megadrive_test1

changeset 6:862f8a034cae

expanding the megadrive code
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 11 Feb 2017 08:56:42 +0200
parents f99eab59e7dc
children 8253942b0a1a
files Makefile src/io.c src/io.h src/libc/ctype.c src/libc/printf.c src/libc/stdlib.c src/libc/string.c src/main.c src/misc.c src/misc.h src/startup.s src/vdp.c src/vdp.h
diffstat 13 files changed, 775 insertions(+), 11 deletions(-) [+]
line diff
     1.1 --- a/Makefile	Wed Feb 01 14:40:19 2017 +0200
     1.2 +++ b/Makefile	Sat Feb 11 08:56:42 2017 +0200
     1.3 @@ -1,4 +1,4 @@
     1.4 -csrc = $(wildcard src/*.c)
     1.5 +csrc = $(wildcard src/*.c) $(wildcard src/libc/*.c)
     1.6  asrc = $(wildcard src/*.s)
     1.7  aSsrc = $(wildcard src/*.S)
     1.8  obj = $(asrc:.s=.o) $(aSsrc:.S=.o) $(csrc:.c=.o)
     1.9 @@ -9,7 +9,8 @@
    1.10  
    1.11  warn = -pedantic -Wall
    1.12  dbg = -g
    1.13 -def = -DGAMENAME=\"testgame\" -DVERSTR=\"01\"
    1.14 +def = -DGAMENAME=\"testgame\" -DVERSTR=\"01\" -D__NO_CTYPE
    1.15 +inc = -Isrc/libc
    1.16  
    1.17  tool_prefix = m68k-linux-gnu-
    1.18  
    1.19 @@ -18,16 +19,17 @@
    1.20  LD = $(tool_prefix)ld
    1.21  OBJCOPY = $(tool_prefix)objcopy
    1.22  
    1.23 -CFLAGS = -m68000 -fno-builtin $(warn) $(dbg) $(opt) $(def)
    1.24 +CFLAGS = -m68000 -ffreestanding -fno-builtin $(warn) $(dbg) $(opt) $(def) $(inc)
    1.25  CPPFLAGS = $(def)
    1.26  ASFLAGS = -m68000
    1.27 -LDFLAGS = -T megadrive.ldscript -print-gc-sections
    1.28 +LDFLAGS = -T megadrive.ldscript -print-gc-sections \
    1.29 +		  -L/usr/lib/gcc-cross/m68k-linux-gnu/6 -lgcc
    1.30  
    1.31  $(bin): $(elf)
    1.32  	$(OBJCOPY) -O binary $< $@
    1.33  
    1.34  $(elf): $(obj)
    1.35 -	$(LD) -o $@ $(LDFLAGS) $(obj) -Map link.map
    1.36 +	$(LD) -o $@ $(obj) -Map link.map $(LDFLAGS)
    1.37  
    1.38  .PHONY: clean
    1.39  clean:
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/src/io.c	Sat Feb 11 08:56:42 2017 +0200
     2.3 @@ -0,0 +1,11 @@
     2.4 +#include "io.h"
     2.5 +
     2.6 +int mdg_version(void)
     2.7 +{
     2.8 +	return IO_VERSION & IO_VER_MASK;
     2.9 +}
    2.10 +
    2.11 +int mdg_ispal(void)
    2.12 +{
    2.13 +	return IO_VERSION & IO_VER_VMOD;
    2.14 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/io.h	Sat Feb 11 08:56:42 2017 +0200
     3.3 @@ -0,0 +1,16 @@
     3.4 +#ifndef IO_H_
     3.5 +#define IO_H_
     3.6 +
     3.7 +#define IO_VERSION		(*(unsigned char*)0xa10001)
     3.8 +
     3.9 +#define IO_VER_MASK		0x0f
    3.10 +#define IO_VER_DISK		0x20
    3.11 +#define IO_VER_VMOD		0x40
    3.12 +#define IO_VER_MODE_BIT	0x80
    3.13 +
    3.14 +#define IO_Z80_MEM_START	0xa00000
    3.15 +
    3.16 +int mdg_version(void);
    3.17 +int mdg_ispal(void);
    3.18 +
    3.19 +#endif	/* IO_H_ */
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/libc/ctype.c	Sat Feb 11 08:56:42 2017 +0200
     4.3 @@ -0,0 +1,60 @@
     4.4 +int isalpha(int c);
     4.5 +int isdigit(int c);
     4.6 +int islower(int c);
     4.7 +int isupper(int c);
     4.8 +
     4.9 +
    4.10 +int isalnum(int c)
    4.11 +{
    4.12 +	return isalpha(c) || isdigit(c);
    4.13 +}
    4.14 +
    4.15 +int isalpha(int c)
    4.16 +{
    4.17 +	return isupper(c) || islower(c);
    4.18 +}
    4.19 +
    4.20 +int isblank(int c)
    4.21 +{
    4.22 +	return c == ' ' || c == '\t';
    4.23 +}
    4.24 +
    4.25 +int isdigit(int c)
    4.26 +{
    4.27 +	return c >= '0' && c <= '9';
    4.28 +}
    4.29 +
    4.30 +int isupper(int c)
    4.31 +{
    4.32 +	return c >= 'A' && c <= 'Z';
    4.33 +}
    4.34 +
    4.35 +int islower(int c)
    4.36 +{
    4.37 +	return c >= 'a' && c <= 'z';
    4.38 +}
    4.39 +
    4.40 +int isgraph(int c)
    4.41 +{
    4.42 +	return c > ' ' && c <= '~';
    4.43 +}
    4.44 +
    4.45 +int isprint(int c)
    4.46 +{
    4.47 +	return isgraph(c) || c == ' ';
    4.48 +}
    4.49 +
    4.50 +int isspace(int c)
    4.51 +{
    4.52 +	return isblank(c) || c == '\f' || c == '\n' || c == '\r' || c == '\v';
    4.53 +}
    4.54 +
    4.55 +int toupper(int c)
    4.56 +{
    4.57 +	return islower(c) ? (c + ('A' - 'a')) : c;
    4.58 +}
    4.59 +
    4.60 +int tolower(int c)
    4.61 +{
    4.62 +	return isupper(c) ? (c + ('A' - 'a')) : c;
    4.63 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/libc/printf.c	Sat Feb 11 08:56:42 2017 +0200
     5.3 @@ -0,0 +1,323 @@
     5.4 +#include <stdio.h>
     5.5 +#include <string.h>
     5.6 +#include <stdlib.h>
     5.7 +#include <ctype.h>
     5.8 +#include <stdarg.h>
     5.9 +
    5.10 +static void bwrite(char *buf, size_t buf_sz, char *str, int sz);
    5.11 +static int intern_printf(char *buf, size_t sz, const char *fmt, va_list ap);
    5.12 +static void itoa(int val, char *buf, int base);
    5.13 +static void utoa(unsigned int val, char *buf, int base);
    5.14 +
    5.15 +
    5.16 +int putchar(int c)
    5.17 +{
    5.18 +	/* TODO */
    5.19 +	return c;
    5.20 +}
    5.21 +
    5.22 +int puts(const char *s)
    5.23 +{
    5.24 +	while(*s) {
    5.25 +		putchar(*s++);
    5.26 +	}
    5.27 +	putchar('\n');
    5.28 +	return 0;
    5.29 +}
    5.30 +
    5.31 +/* -- printf and friends -- */
    5.32 +
    5.33 +static char *convc = "dioxXucsfeEgGpn%";
    5.34 +
    5.35 +#define IS_CONV(c)	strchr(convc, c)
    5.36 +
    5.37 +int printf(const char *fmt, ...)
    5.38 +{
    5.39 +	int res;
    5.40 +	va_list ap;
    5.41 +
    5.42 +	va_start(ap, fmt);
    5.43 +	res = intern_printf(0, 0, fmt, ap);
    5.44 +	va_end(ap);
    5.45 +	return res;
    5.46 +}
    5.47 +
    5.48 +int vprintf(const char *fmt, va_list ap)
    5.49 +{
    5.50 +	return intern_printf(0, 0, fmt, ap);
    5.51 +}
    5.52 +
    5.53 +int sprintf(char *buf, const char *fmt, ...)
    5.54 +{
    5.55 +	int res;
    5.56 +	va_list ap;
    5.57 +
    5.58 +	va_start(ap, fmt);
    5.59 +	res = intern_printf(buf, 0, fmt, ap);
    5.60 +	va_end(ap);
    5.61 +	return res;
    5.62 +}
    5.63 +
    5.64 +int vsprintf(char *buf, const char *fmt, va_list ap)
    5.65 +{
    5.66 +	return intern_printf(buf, 0, fmt, ap);
    5.67 +}
    5.68 +
    5.69 +int snprintf(char *buf, size_t sz, const char *fmt, ...)
    5.70 +{
    5.71 +	int res;
    5.72 +	va_list ap;
    5.73 +
    5.74 +	va_start(ap, fmt);
    5.75 +	res = intern_printf(buf, sz, fmt, ap);
    5.76 +	va_end(ap);
    5.77 +	return res;
    5.78 +}
    5.79 +
    5.80 +int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap)
    5.81 +{
    5.82 +	return intern_printf(buf, sz, fmt, ap);
    5.83 +}
    5.84 +
    5.85 +
    5.86 +/* intern_printf provides all the functionality needed by all the printf
    5.87 + * variants.
    5.88 + * - buf: optional buffer onto which the formatted results are written. If null
    5.89 + *   then the output goes to the terminal through putchar calls. This is used
    5.90 + *   by the (v)sprintf variants which write to an array of char.
    5.91 + * - sz: optional maximum size of the output, 0 means unlimited. This is used
    5.92 + *   by the (v)snprintf variants to avoid buffer overflows.
    5.93 + * The rest are obvious, format string and variable argument list.
    5.94 + */
    5.95 +
    5.96 +#define BUF(x)	((x) ? (x) + cnum : (x))
    5.97 +#define SZ(x)	((x) ? (x) - cnum : (x))
    5.98 +
    5.99 +static int intern_printf(char *buf, size_t sz, const char *fmt, va_list ap)
   5.100 +{
   5.101 +	char conv_buf[32];
   5.102 +	char *str;
   5.103 +	int i, slen;
   5.104 +	const char *fstart = 0;
   5.105 +
   5.106 +	/* state */
   5.107 +	int cnum = 0;
   5.108 +	int base = 10;
   5.109 +	int alt = 0;
   5.110 +	int fwidth = 0;
   5.111 +	int padc = ' ';
   5.112 +	int sign = 0;
   5.113 +	int left_align = 0;	/* not implemented yet */
   5.114 +	int hex_caps = 0;
   5.115 +	int unsig = 0;
   5.116 +
   5.117 +	while(*fmt) {
   5.118 +		if(*fmt == '%') {
   5.119 +			fstart = fmt++;
   5.120 +			continue;
   5.121 +		}
   5.122 +
   5.123 +		if(fstart) {
   5.124 +			if(IS_CONV(*fmt)) {
   5.125 +				switch(*fmt) {
   5.126 +				case 'X':
   5.127 +					hex_caps = 1;
   5.128 +
   5.129 +				case 'x':
   5.130 +				case 'p':
   5.131 +					base = 16;
   5.132 +
   5.133 +					if(alt) {
   5.134 +						bwrite(BUF(buf), SZ(sz), "0x", 2);
   5.135 +					}
   5.136 +
   5.137 +				case 'u':
   5.138 +					unsig = 1;
   5.139 +
   5.140 +					if(0) {
   5.141 +				case 'o':
   5.142 +						base = 8;
   5.143 +
   5.144 +						if(alt) {
   5.145 +							bwrite(BUF(buf), SZ(sz), "0", 1);
   5.146 +						}
   5.147 +					}
   5.148 +
   5.149 +				case 'd':
   5.150 +				case 'i':
   5.151 +					if(unsig) {
   5.152 +						utoa(va_arg(ap, unsigned int), conv_buf, base);
   5.153 +					} else {
   5.154 +						itoa(va_arg(ap, int), conv_buf, base);
   5.155 +					}
   5.156 +					if(hex_caps) {
   5.157 +						for(i=0; conv_buf[i]; i++) {
   5.158 +							conv_buf[i] = toupper(conv_buf[i]);
   5.159 +						}
   5.160 +					}
   5.161 +
   5.162 +					slen = strlen(conv_buf);
   5.163 +					for(i=slen; i<fwidth; i++) {
   5.164 +						bwrite(BUF(buf), SZ(sz), (char*)&padc, 1);
   5.165 +						cnum++;
   5.166 +					}
   5.167 +
   5.168 +					bwrite(BUF(buf), SZ(sz), conv_buf, strlen(conv_buf));
   5.169 +					cnum += slen;
   5.170 +					break;
   5.171 +
   5.172 +				case 'c':
   5.173 +					{
   5.174 +						char c = va_arg(ap, int);
   5.175 +						bwrite(BUF(buf), SZ(sz), &c, 1);
   5.176 +						cnum++;
   5.177 +					}
   5.178 +					break;
   5.179 +
   5.180 +				case 's':
   5.181 +					str = va_arg(ap, char*);
   5.182 +					slen = strlen(str);
   5.183 +
   5.184 +					for(i=slen; i<fwidth; i++) {
   5.185 +						bwrite(BUF(buf), SZ(sz), (char*)&padc, 1);
   5.186 +						cnum++;
   5.187 +					}
   5.188 +					bwrite(BUF(buf), SZ(sz), str, slen);
   5.189 +					cnum += slen;
   5.190 +					break;
   5.191 +
   5.192 +				case 'n':
   5.193 +					*va_arg(ap, int*) = cnum;
   5.194 +					break;
   5.195 +
   5.196 +				default:
   5.197 +					break;
   5.198 +				}
   5.199 +
   5.200 +				/* restore default conversion state */
   5.201 +				base = 10;
   5.202 +				alt = 0;
   5.203 +				fwidth = 0;
   5.204 +				padc = ' ';
   5.205 +				hex_caps = 0;
   5.206 +
   5.207 +				fstart = 0;
   5.208 +				fmt++;
   5.209 +			} else {
   5.210 +				switch(*fmt) {
   5.211 +				case '#':
   5.212 +					alt = 1;
   5.213 +					break;
   5.214 +
   5.215 +				case '+':
   5.216 +					sign = 1;
   5.217 +					break;
   5.218 +
   5.219 +				case '-':
   5.220 +					left_align = 1;
   5.221 +					break;
   5.222 +
   5.223 +				case 'l':
   5.224 +				case 'L':
   5.225 +					break;
   5.226 +
   5.227 +				case '0':
   5.228 +					padc = '0';
   5.229 +					break;
   5.230 +
   5.231 +				default:
   5.232 +					if(isdigit(*fmt)) {
   5.233 +						const char *fw = fmt;
   5.234 +						while(*fmt && isdigit(*fmt)) fmt++;
   5.235 +
   5.236 +						fwidth = atoi(fw);
   5.237 +						continue;
   5.238 +					}
   5.239 +				}
   5.240 +				fmt++;
   5.241 +			}
   5.242 +		} else {
   5.243 +			bwrite(BUF(buf), SZ(sz), (char*)fmt++, 1);
   5.244 +			cnum++;
   5.245 +		}
   5.246 +	}
   5.247 +
   5.248 +	return 0;
   5.249 +}
   5.250 +
   5.251 +
   5.252 +/* bwrite is called by intern_printf to transparently handle writing into a
   5.253 + * buffer (if buf is non-null) or to the terminal (if buf is null).
   5.254 + */
   5.255 +static void bwrite(char *buf, size_t buf_sz, char *str, int sz)
   5.256 +{
   5.257 +	if(buf) {
   5.258 +		if(buf_sz && buf_sz <= sz) sz = buf_sz - 1;
   5.259 +		memcpy(buf, str, sz);
   5.260 +
   5.261 +		buf[sz] = 0;
   5.262 +	} else {
   5.263 +		int i;
   5.264 +		for(i=0; i<sz; i++) {
   5.265 +			putchar(*str++);
   5.266 +		}
   5.267 +	}
   5.268 +}
   5.269 +
   5.270 +
   5.271 +static void itoa(int val, char *buf, int base)
   5.272 +{
   5.273 +	static char rbuf[16];
   5.274 +	char *ptr = rbuf;
   5.275 +	int neg = 0;
   5.276 +
   5.277 +	if(val < 0) {
   5.278 +		neg = 1;
   5.279 +		val = -val;
   5.280 +	}
   5.281 +
   5.282 +	if(val == 0) {
   5.283 +		*ptr++ = '0';
   5.284 +	}
   5.285 +
   5.286 +	while(val) {
   5.287 +		int digit = val % base;
   5.288 +		*ptr++ = digit < 10 ? (digit + '0') : (digit - 10 + 'a');
   5.289 +		val /= base;
   5.290 +	}
   5.291 +
   5.292 +	if(neg) {
   5.293 +		*ptr++ = '-';
   5.294 +	}
   5.295 +
   5.296 +	ptr--;
   5.297 +
   5.298 +	while(ptr >= rbuf) {
   5.299 +		*buf++ = *ptr--;
   5.300 +	}
   5.301 +	*buf = 0;
   5.302 +}
   5.303 +
   5.304 +static void utoa(unsigned int val, char *buf, int base)
   5.305 +{
   5.306 +	static char rbuf[16];
   5.307 +	char *ptr = rbuf;
   5.308 +
   5.309 +	if(val == 0) {
   5.310 +		*ptr++ = '0';
   5.311 +	}
   5.312 +
   5.313 +	while(val) {
   5.314 +		unsigned int digit = val % base;
   5.315 +		*ptr++ = digit < 10 ? (digit + '0') : (digit - 10 + 'a');
   5.316 +		val /= base;
   5.317 +	}
   5.318 +
   5.319 +	ptr--;
   5.320 +
   5.321 +	while(ptr >= rbuf) {
   5.322 +		*buf++ = *ptr--;
   5.323 +	}
   5.324 +	*buf = 0;
   5.325 +}
   5.326 +
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/libc/stdlib.c	Sat Feb 11 08:56:42 2017 +0200
     6.3 @@ -0,0 +1,62 @@
     6.4 +#include <stdlib.h>
     6.5 +#include <ctype.h>
     6.6 +
     6.7 +int atoi(const char *str)
     6.8 +{
     6.9 +	return strtol(str, 0, 10);
    6.10 +}
    6.11 +
    6.12 +long atol(const char *str)
    6.13 +{
    6.14 +	return strtol(str, 0, 10);
    6.15 +}
    6.16 +
    6.17 +long strtol(const char *str, char **endp, int base)
    6.18 +{
    6.19 +	long acc = 0;
    6.20 +	int sign = 1;
    6.21 +
    6.22 +	while(isspace(*str)) str++;
    6.23 +
    6.24 +	if(base == 0) {
    6.25 +		if(str[0] == '0') {
    6.26 +			if(str[1] == 'x' || str[1] == 'X') {
    6.27 +				base = 16;
    6.28 +			} else {
    6.29 +				base = 8;
    6.30 +			}
    6.31 +		} else {
    6.32 +			base = 10;
    6.33 +		}
    6.34 +	}
    6.35 +
    6.36 +	if(*str == '+') {
    6.37 +		str++;
    6.38 +	} else if(*str == '-') {
    6.39 +		sign = -1;
    6.40 +		str++;
    6.41 +	}
    6.42 +
    6.43 +	while(*str) {
    6.44 +		long val;
    6.45 +		char c = tolower(*str);
    6.46 +
    6.47 +		if(isdigit(c)) {
    6.48 +			val = *str - '0';
    6.49 +		} else if(c >= 'a' || c <= 'f') {
    6.50 +			val = 10 + c - 'a';
    6.51 +		}
    6.52 +		if(val >= base) {
    6.53 +			break;
    6.54 +		}
    6.55 +
    6.56 +		acc = acc * base + val;
    6.57 +		str++;
    6.58 +	}
    6.59 +
    6.60 +	if(endp) {
    6.61 +		*endp = (char*)str;
    6.62 +	}
    6.63 +
    6.64 +	return sign > 0 ? acc : -acc;
    6.65 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/libc/string.c	Sat Feb 11 08:56:42 2017 +0200
     7.3 @@ -0,0 +1,107 @@
     7.4 +#include <string.h>
     7.5 +
     7.6 +void *memset(void *s, int c, size_t n)
     7.7 +{
     7.8 +	char *ptr = s;
     7.9 +	while(n--) {
    7.10 +		*ptr++ = c;
    7.11 +	}
    7.12 +	return s;
    7.13 +}
    7.14 +
    7.15 +void *memcpy(void *dest, const void *src, size_t n)
    7.16 +{
    7.17 +	char *dptr = dest;
    7.18 +	const char *sptr = src;
    7.19 +
    7.20 +	while(n--) {
    7.21 +		*dptr++ = *sptr++;
    7.22 +	}
    7.23 +	return dest;
    7.24 +}
    7.25 +
    7.26 +void *memmove(void *dest, const void *src, size_t n)
    7.27 +{
    7.28 +	int i;
    7.29 +	char *dptr;
    7.30 +	const char *sptr;
    7.31 +
    7.32 +	if(dest <= src) {
    7.33 +		/* forward copy */
    7.34 +		dptr = dest;
    7.35 +		sptr = src;
    7.36 +		for(i=0; i<n; i++) {
    7.37 +			*dptr++ = *sptr++;
    7.38 +		}
    7.39 +	} else {
    7.40 +		/* backwards copy */
    7.41 +		dptr = (char*)dest + n - 1;
    7.42 +		sptr = (char*)src + n - 1;
    7.43 +		for(i=0; i<n; i++) {
    7.44 +			*dptr-- = *sptr--;
    7.45 +		}
    7.46 +	}
    7.47 +
    7.48 +	return dest;
    7.49 +}
    7.50 +
    7.51 +size_t strlen(const char *s)
    7.52 +{
    7.53 +	size_t len = 0;
    7.54 +	while(*s++) len++;
    7.55 +	return len;
    7.56 +}
    7.57 +
    7.58 +char *strchr(const char *s, int c)
    7.59 +{
    7.60 +	while(*s) {
    7.61 +		if(*s == c) {
    7.62 +			return (char*)s;
    7.63 +		}
    7.64 +		s++;
    7.65 +	}
    7.66 +	return 0;
    7.67 +}
    7.68 +
    7.69 +char *strrchr(const char *s, int c)
    7.70 +{
    7.71 +	const char *ptr = s;
    7.72 +
    7.73 +	/* find the end */
    7.74 +	while(*ptr) ptr++;
    7.75 +
    7.76 +	/* go back checking for c */
    7.77 +	while(--ptr >= s) {
    7.78 +		if(*ptr == c) {
    7.79 +			return (char*)ptr;
    7.80 +		}
    7.81 +	}
    7.82 +	return 0;
    7.83 +}
    7.84 +
    7.85 +char *strstr(const char *str, const char *substr)
    7.86 +{
    7.87 +	while(*str) {
    7.88 +		const char *s1 = str;
    7.89 +		const char *s2 = substr;
    7.90 +
    7.91 +		while(*s1 && *s1 == *s2) {
    7.92 +			s1++;
    7.93 +			s2++;
    7.94 +		}
    7.95 +		if(!*s2) {
    7.96 +			return (char*)str;
    7.97 +		}
    7.98 +		str++;
    7.99 +	}
   7.100 +	return 0;
   7.101 +}
   7.102 +
   7.103 +int strcmp(const char *s1, const char *s2)
   7.104 +{
   7.105 +	while(*s1 && *s1 == *s2) {
   7.106 +		s1++;
   7.107 +		s2++;
   7.108 +	}
   7.109 +	return *s1 - *s2;
   7.110 +}
     8.1 --- a/src/main.c	Wed Feb 01 14:40:19 2017 +0200
     8.2 +++ b/src/main.c	Sat Feb 11 08:56:42 2017 +0200
     8.3 @@ -1,12 +1,32 @@
     8.4  #include "vdp.h"
     8.5  
     8.6 +static const unsigned char pal[][3] = {
     8.7 +	{0, 0, 0}, {64, 128, 255}, {255, 128, 32}, {255, 255, 255}
     8.8 +};
     8.9 +
    8.10 +static const unsigned char pat[8] = {
    8.11 +	0, 0, 0, 0,					/* 0 0 0 0 0 0 0 0 */
    8.12 +	1, 0x11, 0x11, 0x11,		/* 0 1 1 1 1 1 1 1 */
    8.13 +	1, 0x11, 0x11, 0x11,		/* 0 1 1 1 1 1 1 1 */
    8.14 +	1, 0x11, 0x11, 0x12,		/* 0 1 1 1 1 1 1 2 */
    8.15 +	1, 0x11, 0x12, 0x22,		/* 0 1 1 1 1 2 2 2 */
    8.16 +	1, 0x11, 0x22, 0x22,		/* 0 1 1 1 2 2 2 2 */
    8.17 +	1, 0x11, 0x22, 0x22,		/* 0 1 1 1 2 2 2 2 */
    8.18 +	1, 0x12, 0x22, 0x22			/* 0 1 1 2 2 2 2 2 */
    8.19 +};
    8.20 +
    8.21  int main(void)
    8.22  {
    8.23 -	VDP_SET_CRAM_ADDR(0);
    8.24 -	VDP_SET_CRAM_RGB24(64, 128, 255);
    8.25 +	unsigned char *tmap;
    8.26 +
    8.27 +	vdp_init();
    8.28 +
    8.29 +	vdp_setpal(0, sizeof pal / sizeof *pal, (unsigned char*)pal);
    8.30  	VDP_SET_BGCOLOR(0, 0);
    8.31 -	/* enable display */
    8.32 -	VDP_SET_REG(0, VDP_REG0_BASE);
    8.33 -	VDP_SET_REG(1, VDP_REG1_BASE | VDP_REG1_DISP_BIT);
    8.34 +
    8.35 +	vdp_set_tilemap_slot(VDP_PLANE_A, 0);
    8.36 +	tmap = vdp_tilemap_ptr(VDP_PLANE_A);
    8.37 +
    8.38 +
    8.39  	return 0;
    8.40  }
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/misc.c	Sat Feb 11 08:56:42 2017 +0200
     9.3 @@ -0,0 +1,17 @@
     9.4 +#include <stdio.h>
     9.5 +#include <stdarg.h>
     9.6 +#include "misc.h"
     9.7 +
     9.8 +void panic(const char *fmt, ...)
     9.9 +{
    9.10 +	va_list ap;
    9.11 +
    9.12 +	printf("~~~~ panic ~~~~\n");
    9.13 +	va_start(ap, fmt);
    9.14 +	vprintf(fmt, ap);
    9.15 +	va_end(ap);
    9.16 +
    9.17 +	/*printf("registers:\n");*/
    9.18 +
    9.19 +	halt_cpu();
    9.20 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/misc.h	Sat Feb 11 08:56:42 2017 +0200
    10.3 @@ -0,0 +1,9 @@
    10.4 +#ifndef MISC_H_
    10.5 +#define MISC_H_
    10.6 +
    10.7 +void panic(const char *fmt, ...);
    10.8 +
    10.9 +/* defined in startup.s */
   10.10 +void halt_cpu(void);
   10.11 +
   10.12 +#endif	/* MISC_H_ */
    11.1 --- a/src/startup.s	Wed Feb 01 14:40:19 2017 +0200
    11.2 +++ b/src/startup.s	Sat Feb 11 08:56:42 2017 +0200
    11.3 @@ -2,6 +2,7 @@
    11.4  	.extern main
    11.5  
    11.6  	.global start
    11.7 +	.global halt_cpu
    11.8  start:
    11.9  	| copy .data section from ROM to RAM
   11.10  	move.l #_data_lma, %a0
   11.11 @@ -24,4 +25,5 @@
   11.12  	bne.s 0b
   11.13  1:
   11.14  	jsr main
   11.15 +halt_cpu:
   11.16  	stop #0x2700
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/vdp.c	Sat Feb 11 08:56:42 2017 +0200
    12.3 @@ -0,0 +1,85 @@
    12.4 +#include <stdint.h>
    12.5 +#include "vdp.h"
    12.6 +#include "io.h"
    12.7 +#include "misc.h"
    12.8 +
    12.9 +static void *tilemap_ptr[3];
   12.10 +
   12.11 +int vdp_init(void)
   12.12 +{
   12.13 +	unsigned int mode1_flags = VDP_REG1_DISP_BIT;
   12.14 +
   12.15 +	if(mdg_ispal()) {
   12.16 +		mode1_flags |= VDP_REG1_30CELL_BIT;
   12.17 +	}
   12.18 +
   12.19 +	VDP_SET_REG(0, VDP_REG0_BASE);
   12.20 +	VDP_SET_REG(1, VDP_REG1_BASE | mode1_flags);
   12.21 +
   12.22 +	return 0;
   12.23 +}
   12.24 +
   12.25 +void vdp_set_tilemap_slot(int plane, int slot)
   12.26 +{
   12.27 +	switch(plane) {
   12.28 +	case VDP_PLANE_A:
   12.29 +		VDP_SET_REG(VDP_REG_PADDR_A, (slot & 7) << 3);
   12.30 +		tilemap_ptr[VDP_PLANE_A] = (void*)((uint32_t)slot << 13);
   12.31 +		break;
   12.32 +
   12.33 +	case VDP_PLANE_WIN:
   12.34 +		VDP_SET_REG(VDP_REG_PADDR_WIN, (slot & 0x1f) << 1);
   12.35 +		tilemap_ptr[VDP_PLANE_WIN] = (void*)((uint32_t)slot << 11);
   12.36 +		break;
   12.37 +
   12.38 +	case VDP_PLANE_B:
   12.39 +		VDP_SET_REG(VDP_REG_PADDR_B, slot & 7);
   12.40 +		tilemap_ptr[VDP_PLANE_B] = (void*)((uint32_t)slot << 13);
   12.41 +		break;
   12.42 +	}
   12.43 +}
   12.44 +
   12.45 +void *vdp_tilemap_ptr(int plane)
   12.46 +{
   12.47 +	return tilemap_ptr[plane];
   12.48 +}
   12.49 +
   12.50 +void vdp_setpal_rgb24(int idx, int r, int g, int b)
   12.51 +{
   12.52 +	VDP_SET_CRAM_ADDR(idx);
   12.53 +	VDP_SET_CRAM_RGB24(r, g, b);
   12.54 +}
   12.55 +
   12.56 +void vdp_setpal(int idx0, int count, unsigned char *pal)
   12.57 +{
   12.58 +	int i;
   12.59 +
   12.60 +	VDP_SET_CRAM_ADDR(idx0);
   12.61 +	for(i=0; i<count; i++) {
   12.62 +		VDP_SET_CRAM_RGB24(pal[0], pal[1], pal[2]);
   12.63 +		pal += 3;
   12.64 +	}
   12.65 +}
   12.66 +
   12.67 +#define SCROLLSIZE(x)	\
   12.68 +	do { \
   12.69 +		switch(xtiles) { \
   12.70 +		case 32: \
   12.71 +		case 64: \
   12.72 +			(x) >>= 6; \
   12.73 +			break; \
   12.74 +		case 128: \
   12.75 +			(x) = 3; \
   12.76 +			break; \
   12.77 +		default: \
   12.78 +			panic("invalid argument to %s: %d\n", (x), __func__); \
   12.79 +		} \
   12.80 +	} while(0)
   12.81 +
   12.82 +void vdp_set_scroll_size(int xtiles, int ytiles)
   12.83 +{
   12.84 +	SCROLLSIZE(xtiles);
   12.85 +	SCROLLSIZE(ytiles);
   12.86 +
   12.87 +	VDP_SET_REG(VDP_REG_SCROLL_SIZE, (ytiles << 4) | xtiles);
   12.88 +}
    13.1 --- a/src/vdp.h	Wed Feb 01 14:40:19 2017 +0200
    13.2 +++ b/src/vdp.h	Sat Feb 11 08:56:42 2017 +0200
    13.3 @@ -10,6 +10,28 @@
    13.4  #define VDP_PORT_HVCOUNT	(*(volatile uint16_t*)0xc00008)
    13.5  #define VDP_PORT_PSG		(*(volatile uint16_t*)0xc00010)
    13.6  
    13.7 +/* registers */
    13.8 +#define VDP_REG_MODE1			0
    13.9 +#define VDP_REG_MODE2			1
   13.10 +#define VDP_REG_PADDR_A			2
   13.11 +#define VDP_REG_PADDR_WIN		3
   13.12 +#define VDP_REG_PADDR_B			4
   13.13 +#define VDP_REG_SPRITE			5
   13.14 +#define VDP_REG_BGCOLOR			7
   13.15 +#define VDP_REG_HINT			10
   13.16 +#define VDP_REG_MODE3			11
   13.17 +#define VDP_REG_MODE4			12
   13.18 +#define VDP_REG_HSCROLL			13
   13.19 +#define VDP_REG_AUTOINC			15
   13.20 +#define VDP_REG_SCROLL_SIZE		16
   13.21 +#define VDP_REG_WINXPOS			17
   13.22 +#define VDP_REG_WINYPOS			18
   13.23 +#define VDP_REG_DMALEN_LOW		19
   13.24 +#define VDP_REG_DMALEN_HIGH		20
   13.25 +#define VDP_REG_DMA_SADDR_LOW	21
   13.26 +#define VDP_REG_DMA_SADDR_MID	22
   13.27 +#define VDP_REG_DMA_SADDR_HIGH	23
   13.28 +
   13.29  /* control register read flags */
   13.30  #define VDP_CTL_PAL_BIT			0x0001
   13.31  #define VDP_CTL_HBLANK_BIT		0x0002
   13.32 @@ -42,12 +64,17 @@
   13.33  #define VDP_REG1_DMA_BIT	0x10
   13.34  #define VDP_REG1_VINTR_BIT	0x20
   13.35  #define VDP_REG1_DISP_BIT	0x40
   13.36 +#define VDP_REG1_XVRAM_BIT	0x80
   13.37  
   13.38  #define VDP_MODE_WR_BIT		1
   13.39  
   13.40  #define VDP_VRAM_WR		1
   13.41  #define VDP_CRAM_WR		3
   13.42  
   13.43 +#define VDP_DMA_MEM_TO_VRAM		0
   13.44 +#define VDP_DMA_VRAM_FILL		2
   13.45 +#define VDP_DMA_VRAM_COPY		3
   13.46 +
   13.47  #define VDP_ADDRSET(addr, mode) /* TODO */
   13.48  
   13.49  #define VDP_CRAM_ADDR32(addr) (0xc0000000 | ((uint32_t)(addr) << 16))
   13.50 @@ -55,15 +82,38 @@
   13.51  #define VDP_SET_CRAM_ADDR(addr) \
   13.52  	do { VDP_PORT_CTL32 = VDP_CRAM_ADDR32(addr); } while(0)
   13.53  
   13.54 +#define VDP_RGB(r, g, b) \
   13.55 +	((((uint16_t)(r) << 1) & 0xe) | \
   13.56 +	 (((uint16_t)(g) << 5) & 0xe0) | \
   13.57 +	 (((uint16_t)(b) << 9) & 0xe00))
   13.58 +
   13.59  #define VDP_RGB24(r, g, b) \
   13.60  	((((uint16_t)(r) >> 4) & 0xe) | \
   13.61  	 ((uint16_t)(g) & 0xe0) | \
   13.62  	 (((uint16_t)(b) << 4) & 0xe00))
   13.63  
   13.64 +#define VDP_SET_CRAM_RGB(r, g, b) \
   13.65 +	do { VDP_PORT_DATA = VDP_RGB(r, g, b); } while(0)
   13.66 +
   13.67  #define VDP_SET_CRAM_RGB24(r, g, b) \
   13.68  	do { VDP_PORT_DATA = VDP_RGB24(r, g, b); } while(0)
   13.69  
   13.70  #define VDP_SET_BGCOLOR(pal, col) \
   13.71 -	do { VDP_SET_REG(7, ((pal) << 4) | (col)); } while(0)
   13.72 +	do { VDP_SET_REG(VDP_REG_BGCOLOR, ((pal) << 4) | (col)); } while(0)
   13.73 +
   13.74 +/* arguments to vdp_tilemap_slot */
   13.75 +#define VDP_PLANE_A		0
   13.76 +#define VDP_PLANE_WIN	1
   13.77 +#define VDP_PLANE_B		2
   13.78 +
   13.79 +int vdp_init(void);
   13.80 +void vdp_set_tilemap_slot(int plane, int slot);
   13.81 +void *vdp_tilemap_ptr(int plane);
   13.82 +void vdp_setpal_rgb24(int idx, int r, int g, int b);
   13.83 +void vdp_setpal(int idx0, int count, unsigned char *pal);
   13.84 +/* TODO vdp_setpal_dma */
   13.85 +
   13.86 +/* xtiles and ytiles can only be 32, 64, or 128 */
   13.87 +void vdp_set_scroll_size(int xtiles, int ytiles);
   13.88  
   13.89  #endif	/* VDP_H_ */