megadrive_test2

changeset 5:ea70f3da150f

color cycling tunnel
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 20 Jun 2017 06:08:58 +0300
parents 72ab63f262bf
children df2c6b3c6f2e
files .hgignore Makefile src/intr.s src/main.c src/vdp.c src/vdp.h tools/ppm2md.c tools/tunnel.c
diffstat 8 files changed, 212 insertions(+), 82 deletions(-) [+]
line diff
     1.1 --- a/.hgignore	Mon Jun 19 08:02:51 2017 +0300
     1.2 +++ b/.hgignore	Tue Jun 20 06:08:58 2017 +0300
     1.3 @@ -4,3 +4,7 @@
     1.4  \.map$
     1.5  \.elf$
     1.6  \.bin$
     1.7 +tools/ppm2md$
     1.8 +tools/tunnel$
     1.9 +\.ppm$
    1.10 +tun_data\.h$
     2.1 --- a/Makefile	Mon Jun 19 08:02:51 2017 +0300
     2.2 +++ b/Makefile	Tue Jun 20 06:08:58 2017 +0300
     2.3 @@ -9,8 +9,9 @@
     2.4  
     2.5  warn = -pedantic -Wall
     2.6  dbg = -g
     2.7 +opt = -O2
     2.8  def = -DGAMENAME=\"testgame\" -DVERSTR=\"01\" -D__NO_CTYPE
     2.9 -inc = -Isrc -Isrc/libc
    2.10 +inc = -I. -Isrc -Isrc/libc
    2.11  
    2.12  tool_prefix = m68k-linux-gnu-
    2.13  
    2.14 @@ -28,12 +29,18 @@
    2.15  $(bin): $(elf)
    2.16  	$(OBJCOPY) -O binary $< $@
    2.17  
    2.18 -$(elf): $(obj)
    2.19 +$(elf): tun_data.h $(obj)
    2.20  	$(LD) -o $@ $(obj) -Map link.map $(LDFLAGS)
    2.21  
    2.22 +tun_data.h: tunnel.ppm
    2.23 +	cat $< | tools/ppm2md tun_ >$@
    2.24 +
    2.25 +tunnel.ppm:
    2.26 +	tools/tunnel >$@
    2.27 +
    2.28  .PHONY: clean
    2.29  clean:
    2.30 -	rm -f $(obj) $(elf) $(bin)
    2.31 +	rm -f $(obj) $(elf) $(bin) tun_data.h tunnel.ppm
    2.32  
    2.33  .PHONY: run
    2.34  run: $(bin)
     3.1 --- a/src/intr.s	Mon Jun 19 08:02:51 2017 +0300
     3.2 +++ b/src/intr.s	Tue Jun 20 06:08:58 2017 +0300
     3.3 @@ -102,5 +102,5 @@
     3.4  	rte
     3.5  
     3.6  intr_vblank:
     3.7 -	|jsr vblank_handler
     3.8 +	jsr vblank_handler
     3.9  	rte
     4.1 --- a/src/main.c	Mon Jun 19 08:02:51 2017 +0300
     4.2 +++ b/src/main.c	Tue Jun 20 06:08:58 2017 +0300
     4.3 @@ -1,41 +1,29 @@
     4.4  #include <stdint.h>
     4.5  #include "vdp.h"
     4.6 +#include "tun_data.h"
     4.7  
     4.8 -uint32_t pat0[] = {
     4.9 -	0x00000000,
    4.10 -	0x00000000,
    4.11 -	0x00000000,
    4.12 -	0x00010000,
    4.13 -	0x00000000,
    4.14 -	0x00000000,
    4.15 -	0x00000000,
    4.16 -	0x00000000
    4.17 +#define NAMETAB_A	6
    4.18 +#define NAMETAB_B	6
    4.19 +
    4.20 +void load_pattern(int idx, void *data);
    4.21 +void set_tile(int nametab_idx, int x, int y, int tile_idx, int palidx);
    4.22 +
    4.23 +#define CYCLE_BEG	1
    4.24 +#define CYCLE_END	14
    4.25 +static uint16_t pal[16] = {
    4.26 +	VDP_PACK_RGB(0, 0, 0),	/* 0: fixed */
    4.27 +	VDP_PACK_RGB(0, 0, 0),	/* 1: cycle start */
    4.28 +	VDP_PACK_RGB(0, 0, 0), VDP_PACK_RGB(0, 0, 0),
    4.29 +	VDP_PACK_RGB(0, 0, 0), VDP_PACK_RGB(0, 0, 0),
    4.30 +	VDP_PACK_RGB(0, 0, 0), VDP_PACK_RGB(0, 0, 0),
    4.31 +	VDP_PACK_RGB(0, 0, 0), VDP_PACK_RGB(0, 0, 0),
    4.32 +	VDP_PACK_RGB(0, 0, 0), VDP_PACK_RGB(0, 0, 0),
    4.33 +	VDP_PACK_RGB(0, 0, 0),	/* 12: \            */
    4.34 +	VDP_PACK_RGB(7, 0, 3),	/* 13:  > beam      */
    4.35 +	VDP_PACK_RGB(0, 0, 0),	/* 14: /  cycle end */
    4.36 +	VDP_PACK_RGB(7, 0, 3)		/* 15: fixed */
    4.37  };
    4.38  
    4.39 -uint32_t pat1[] = {
    4.40 -	0x11111111,
    4.41 -	0x11000011,
    4.42 -	0x10100101,
    4.43 -	0x10011001,
    4.44 -	0x10011001,
    4.45 -	0x10100101,
    4.46 -	0x11000011,
    4.47 -	0x11111111
    4.48 -};
    4.49 -
    4.50 -uint32_t pat2[] = {
    4.51 -	0x11111111,
    4.52 -	0x10011001,
    4.53 -	0x10011001,
    4.54 -	0x11111111,
    4.55 -	0x11111111,
    4.56 -	0x10011001,
    4.57 -	0x10011001,
    4.58 -	0x11111111
    4.59 -};
    4.60 -
    4.61 -void load_pattern(int idx, void *data);
    4.62 -void set_tile(int x, int y, int tile_idx, int palidx);
    4.63  
    4.64  int main(void)
    4.65  {
    4.66 @@ -43,39 +31,35 @@
    4.67  
    4.68  	vdp_init();
    4.69  
    4.70 -	vdp_set_pal_entry(0, 0, 0, 0, 0);
    4.71 -	vdp_set_pal_entry(0, 1, 7, 1, 3);
    4.72 +	vdp_setreg(VDP_REG_MODE2, vdp_getreg(VDP_REG_MODE2) | VDP_MODE2_V30CELL);
    4.73 +
    4.74 +	vdp_begin_palette(0, 0);
    4.75 +	for(i=0; i<16; i++) {
    4.76 +		VDP_PORT_DATA = pal[i];
    4.77 +	}
    4.78  	vdp_set_bgcolor(0, 0);
    4.79  
    4.80 -	load_pattern(0, pat0);
    4.81 -	load_pattern(1, pat1);
    4.82 -	load_pattern(2, pat2);
    4.83 +	for(i=0; i<tun_xtiles * tun_ytiles; i++) {
    4.84 +		load_pattern(i, tun_tiles[i]);
    4.85 +	}
    4.86  
    4.87 -	vdp_set_nametab_idx(VDP_PLANE_A, 6);
    4.88 +	vdp_set_nametab_idx(VDP_PLANE_A, NAMETAB_A);
    4.89 +	vdp_set_nametab_idx(VDP_PLANE_B, NAMETAB_B);
    4.90  
    4.91 -	for(i=0; i<20; i++) {
    4.92 -		for(j=0; j<20; j++) {
    4.93 -			set_tile(j, i, 1, 0);
    4.94 +	for(i=0; i<tun_ytiles; i++) {
    4.95 +		for(j=0; j<tun_xtiles; j++) {
    4.96 +			set_tile(NAMETAB_A, j, i, i * tun_xtiles + j, 0);
    4.97  		}
    4.98  	}
    4.99  
   4.100  	//vdp_enable_hintr(12);
   4.101 -	//vdp_enable_vintr();
   4.102 +	vdp_enable_vintr();
   4.103  
   4.104  	for(;;);
   4.105  
   4.106  	return 0;
   4.107  }
   4.108  
   4.109 -/*
   4.110 -uint16_t testcol = 0x00c0;
   4.111 -
   4.112 -void vblank_handler(void)
   4.113 -{
   4.114 -	testcol = 0x00c0;
   4.115 -}
   4.116 -*/
   4.117 -
   4.118  void load_pattern(int idx, void *data)
   4.119  {
   4.120  	int i;
   4.121 @@ -88,13 +72,28 @@
   4.122  	}
   4.123  }
   4.124  
   4.125 -void set_tile(int x, int y, int tile_idx, int palidx)
   4.126 +void set_tile(int nametab_idx, int x, int y, int tile_idx, int palidx)
   4.127  {
   4.128  	uint16_t tile_ent, addr;
   4.129  
   4.130  	tile_ent = vdp_nametab_entry(tile_idx, palidx, VDP_TILE_LOW_PRIO);
   4.131  
   4.132 -	addr = vdp_nametab_addr(6) + (y * 64 + x) * 2;
   4.133 +	addr = vdp_nametab_addr(nametab_idx) + (y * 64 + x) * 2;
   4.134  	vdp_setup_access(addr, VDP_MEM_WRITE, VDP_MEM_VRAM);
   4.135  	VDP_PORT_DATA = tile_ent;
   4.136  }
   4.137 +
   4.138 +void vblank_handler(void)
   4.139 +{
   4.140 +	int idx = CYCLE_BEG;
   4.141 +	uint16_t first = pal[idx];
   4.142 +
   4.143 +	vdp_begin_palette(0, idx);
   4.144 +	while(idx < CYCLE_END) {
   4.145 +		pal[idx] = pal[idx + 1];
   4.146 +		VDP_PORT_DATA = pal[idx];
   4.147 +		++idx;
   4.148 +	}
   4.149 +	pal[idx] = first;
   4.150 +	VDP_PORT_DATA = pal[idx];
   4.151 +}
     5.1 --- a/src/vdp.c	Mon Jun 19 08:02:51 2017 +0300
     5.2 +++ b/src/vdp.c	Tue Jun 20 06:08:58 2017 +0300
     5.3 @@ -2,8 +2,31 @@
     5.4  
     5.5  void vdp_init(void)
     5.6  {
     5.7 +	int i;
     5.8 +
     5.9  	vdp_setreg(VDP_REG_MODE1, VDP_MODE1_BASE);
    5.10  	vdp_setreg(VDP_REG_MODE2, VDP_MODE2_BASE | VDP_MODE2_DISP);
    5.11  
    5.12 +	vdp_set_nametab_addr(VDP_PLANE_A, 0xc000);
    5.13 +	vdp_set_nametab_addr(VDP_PLANE_B, 0xe000);
    5.14 +	vdp_disable_layer(VDP_PLANE_WIN);
    5.15 +	vdp_set_scroll_table(0xd000);
    5.16 +	vdp_set_sprite_table(0xd400);
    5.17 +
    5.18 +	vdp_setreg(VDP_REG_MODE3, VDP_MODE3_BASE);
    5.19 +	vdp_setreg(VDP_REG_MODE4, VDP_MODE4_BASE | VDP_MODE4_H40CELL);
    5.20 +	vdp_setreg(VDP_REG_SCROLL_SIZE, VDP_SCROLL_H64 | VDP_SCROLL_V32);
    5.21 +
    5.22  	vdp_set_autoinc(2);
    5.23 +	vdp_set_bgcolor(0, 0);
    5.24 +
    5.25 +	vdp_setreg(VDP_REG_HINTR, 0);
    5.26 +	vdp_setreg(VDP_REG_WIN_XPOS, 0);
    5.27 +	vdp_setreg(VDP_REG_WIN_YPOS, 0);
    5.28 +
    5.29 +	/* clear vmem at the planes A/B name tables, scroll table, and sprite table */
    5.30 +	vdp_setup_access(0xd000, VDP_MEM_WRITE, VDP_MEM_VRAM);
    5.31 +	for(i=0xd000; i<65536; i++) {
    5.32 +		VDP_PORT_DATA = 0;
    5.33 +	}
    5.34  }
     6.1 --- a/src/vdp.h	Mon Jun 19 08:02:51 2017 +0300
     6.2 +++ b/src/vdp.h	Tue Jun 20 06:08:58 2017 +0300
     6.3 @@ -157,11 +157,15 @@
     6.4  	vdp_setreg(VDP_REG_AUTOINC, stride);
     6.5  }
     6.6  
     6.7 +static inline void vdp_begin_palette(int pidx, int cidx)
     6.8 +{
     6.9 +	uint16_t paddr = (pidx << 5) | (cidx << 1);
    6.10 +	vdp_setup_access(paddr, VDP_MEM_WRITE, VDP_MEM_CRAM);
    6.11 +}
    6.12 +
    6.13  static inline void vdp_set_pal_entry(int pidx, int cidx, int r, int g, int b)
    6.14  {
    6.15 -	uint16_t paddr = (pidx << 5) | (cidx << 1);
    6.16 -
    6.17 -	vdp_setup_access(paddr, VDP_MEM_WRITE, VDP_MEM_CRAM);
    6.18 +	vdp_begin_palette(pidx, cidx);
    6.19  	VDP_PORT_DATA = VDP_PACK_RGB(r, g, b);
    6.20  }
    6.21  
    6.22 @@ -188,22 +192,18 @@
    6.23  
    6.24  static inline void vdp_set_nametab_addr(int plane, uint16_t addr)
    6.25  {
    6.26 -	int reg;
    6.27  	switch(plane) {
    6.28  	case VDP_PLANE_A:
    6.29 -		reg = VDP_REG_NAMETAB_A;
    6.30 +		vdp_setreg(VDP_REG_NAMETAB_A, (addr >> 10) & 0x38);
    6.31  		break;
    6.32  	case VDP_PLANE_B:
    6.33 -		reg = VDP_REG_NAMETAB_B;
    6.34 +		vdp_setreg(VDP_REG_NAMETAB_B, (addr >> 13) & 7);
    6.35  		break;
    6.36  	case VDP_PLANE_WIN:
    6.37 -		reg = VDP_REG_NAMETAB_WIN;
    6.38 +		vdp_setreg(VDP_REG_NAMETAB_WIN, (addr >> 10) & 0x7e);
    6.39 +	default:
    6.40  		break;
    6.41 -	default:
    6.42 -		return;
    6.43  	}
    6.44 -
    6.45 -	vdp_setreg(reg, (addr >> 10) & 0x38);
    6.46  }
    6.47  
    6.48  static inline uint16_t vdp_nametab_addr(int idx)
    6.49 @@ -216,11 +216,37 @@
    6.50  	vdp_set_nametab_addr(plane, vdp_nametab_addr(idx));
    6.51  }
    6.52  
    6.53 +static inline void vdp_disable_layer(int plane)
    6.54 +{
    6.55 +	switch(plane) {
    6.56 +	case VDP_PLANE_A:
    6.57 +		vdp_setreg(VDP_REG_NAMETAB_A, 0x40);
    6.58 +		break;
    6.59 +	case VDP_PLANE_B:
    6.60 +		vdp_setreg(VDP_REG_NAMETAB_B, 0x08);
    6.61 +		break;
    6.62 +	case VDP_PLANE_WIN:
    6.63 +		vdp_setreg(VDP_REG_NAMETAB_WIN, 0x40);
    6.64 +	default:
    6.65 +		break;
    6.66 +	}
    6.67 +}
    6.68 +
    6.69  static inline uint16_t vdp_nametab_entry(int tileidx, int palidx, uint16_t flags)
    6.70  {
    6.71  	return tileidx | (((uint16_t)palidx & 0x3) << 13) | flags;
    6.72  }
    6.73  
    6.74 +static inline void vdp_set_sprite_table(uint16_t addr)
    6.75 +{
    6.76 +	vdp_setreg(VDP_REG_SPRITE_TAB, addr >> 9);
    6.77 +}
    6.78 +
    6.79 +static inline void vdp_set_scroll_table(uint16_t addr)
    6.80 +{
    6.81 +	vdp_setreg(VDP_REG_SCROLL_TAB, addr >> 10);
    6.82 +}
    6.83 +
    6.84  void vdp_init(void);
    6.85  
    6.86  #endif	/* VDP_H_ */
     7.1 --- a/tools/ppm2md.c	Mon Jun 19 08:02:51 2017 +0300
     7.2 +++ b/tools/ppm2md.c	Tue Jun 20 06:08:58 2017 +0300
     7.3 @@ -3,26 +3,92 @@
     7.4  #include <string.h>
     7.5  #include <ctype.h>
     7.6  
     7.7 +#define RODATA_STR	"__attribute__((section(\".rodata\")))"
     7.8 +
     7.9  unsigned char *read_image(int *xsz, int *ysz, int *maxval);
    7.10  
    7.11 -int main(void)
    7.12 +int main(int argc, char **argv)
    7.13  {
    7.14 -	int i, j, width, height, maxval;
    7.15 -	unsigned char *pixels;
    7.16 +	int i, j, width, height, xtiles, ytiles, maxval;
    7.17 +	unsigned char *pixels, *tiles, *src, *dest;
    7.18 +	const char *prefix = "img_";
    7.19 +
    7.20 +	if(argv[1]) {
    7.21 +		prefix = argv[1];
    7.22 +	}
    7.23  
    7.24  	if(!(pixels = read_image(&width, &height, &maxval))) {
    7.25  		return 1;
    7.26  	}
    7.27  	fprintf(stderr, "read image %dx%d (maxval: %d)\n", width, height, maxval);
    7.28  
    7.29 -	/* reduce colors */
    7.30 +	xtiles = width / 8;
    7.31 +	ytiles = height / 8;
    7.32 +	/* each tile is 32 bytes, 8 rows of 4 bytes each */
    7.33 +	if(!(tiles = malloc(xtiles * ytiles * 32))) {
    7.34 +		free(pixels);
    7.35 +		return 1;
    7.36 +	}
    7.37  
    7.38 -	/* slice tiles */
    7.39 -	for(i=0; i<height / 8; i++) {
    7.40 -		for(j=0; j<width / 8; j++) {
    7.41 +	/* if we have 15 as max val, we'll assume they are straight palette indices
    7.42 +	 * otherwise, do color quantization and palette allocation
    7.43 +	 */
    7.44 +	if(maxval == 15) {
    7.45 +		/* just drop green/blue components in-place, keep red as index */
    7.46 +		dest = src = pixels;
    7.47 +		for(i=0; i<width * height; i++) {
    7.48 +			*dest++ = *src;
    7.49 +			src += 3;
    7.50 +		}
    7.51 +	} else {
    7.52 +		/* TODO */
    7.53 +	}
    7.54 +
    7.55 +	/* after processing, we have 1 color index per byte */
    7.56 +
    7.57 +	/* slice tiles and pack indices as nibbles */
    7.58 +	dest = tiles;
    7.59 +	for(i=0; i<ytiles; i++) {
    7.60 +		for(j=0; j<xtiles; j++) {
    7.61 +			int x, y;
    7.62 +			int tilestart = (i * xtiles * 8 + j) * 8;
    7.63 +
    7.64 +			for(y=0; y<8; y++) {
    7.65 +				for(x=0; x<4; x++) {
    7.66 +					src = pixels + tilestart + y * width + x * 2;
    7.67 +					*dest++ = (src[0] << 4) | (src[1] & 0xf);
    7.68 +				}
    7.69 +			}
    7.70 +
    7.71  		}
    7.72  	}
    7.73  
    7.74 +	/* output as C array */
    7.75 +	printf("/* generated by ppm2md */\n");
    7.76 +	printf("int %sxtiles " RODATA_STR " = %d;\n", prefix, xtiles);
    7.77 +	printf("int %sytiles " RODATA_STR " = %d;\n", prefix, ytiles);
    7.78 +	printf("unsigned char %stiles[][32] " RODATA_STR " = {", prefix);
    7.79 +
    7.80 +	src = tiles;
    7.81 +	for(i=0; i<xtiles * ytiles; i++) {
    7.82 +		if(i > 0) {
    7.83 +			printf(",\n");
    7.84 +		} else {
    7.85 +			putchar('\n');
    7.86 +		}
    7.87 +		printf("\t{");
    7.88 +		for(j=0; j<32; j++) {
    7.89 +			if(j == 0) {
    7.90 +				printf("%u", (unsigned int)*src++);
    7.91 +			} else {
    7.92 +				printf(", %u", (unsigned int)*src++);
    7.93 +			}
    7.94 +		}
    7.95 +		printf(" }");
    7.96 +	}
    7.97 +	printf("\n};\n");
    7.98 +
    7.99 +
   7.100  	return 0;
   7.101  }
   7.102  
     8.1 --- a/tools/tunnel.c	Mon Jun 19 08:02:51 2017 +0300
     8.2 +++ b/tools/tunnel.c	Tue Jun 20 06:08:58 2017 +0300
     8.3 @@ -2,13 +2,14 @@
     8.4  #include <stdlib.h>
     8.5  #include <math.h>
     8.6  
     8.7 -#define XSZ		512
     8.8 -#define YSZ		512
     8.9 +#define XSZ		320
    8.10 +#define YSZ		240
    8.11  
    8.12  int main(void)
    8.13  {
    8.14  	int i, j;
    8.15  	unsigned char *pixels, *pptr;
    8.16 +	float aspect = (float)XSZ / (float)YSZ;
    8.17  
    8.18  	pixels = malloc(XSZ * YSZ);
    8.19  	pptr = pixels;
    8.20 @@ -16,15 +17,19 @@
    8.21  	for(i=0; i<YSZ; i++) {
    8.22  		float y = 2.0 * (float)i / (float)YSZ - 1.0;
    8.23  		for(j=0; j<XSZ; j++) {
    8.24 -			float x = 2.0 * (float)j / (float)XSZ - 1.0;
    8.25 +			float x = aspect * (2.0 * (float)j / (float)XSZ - 1.0);
    8.26  			float tu = atan2(y, x) / M_PI * 0.5 + 0.5;
    8.27  			float d = sqrt(x * x + y * y);
    8.28 -			float tv = d == 0.0 ? 0.0 : 1.0 / d;
    8.29 +			float tv = d == 0.0 ? 0.0 : 0.5 / d;
    8.30  
    8.31 -			int ty = (int)(tv * 64.0) & 0xf;
    8.32 +			int ty = (int)(tv * 64.0) % 14 + 1;
    8.33  			int tx = (int)(tu * 256.0) & 0xf;
    8.34  
    8.35 -			*pptr++ = tx ? ty : 0;
    8.36 +			if(d < 0.2) {
    8.37 +				*pptr++ = 0;
    8.38 +			} else {
    8.39 +				*pptr++ = tx ? ty : 0xf;
    8.40 +			}
    8.41  		}
    8.42  	}
    8.43