diff --git a/index.html b/index.html index bc1515fc..21a45b07 100644 --- a/index.html +++ b/index.html @@ -57,6 +57,7 @@ body { left:0; right:0; background-color: #666; + overflow: hidden;; } div.workspace { background-color:#999; diff --git a/presets/williams-z80/game1.c b/presets/williams-z80/game1.c new file mode 100644 index 00000000..290d3357 --- /dev/null +++ b/presets/williams-z80/game1.c @@ -0,0 +1,447 @@ + +#include + +typedef unsigned char byte; +typedef unsigned short word; + +byte __at (0xc000) palette[16]; +volatile byte __at (0xc800) input0; +volatile byte __at (0xc802) input1; +volatile byte __at (0xc804) input2; +byte __at (0xc900) rom_select; +volatile byte __at (0xcb00) video_counter; +byte __at (0xcbff) watchdog0x39; +byte __at (0xcc00) nvram[0x400]; + +// blitter flags +#define SRCSCREEN 0x1 +#define DSTSCREEN 0x2 +#define ESYNC 0x4 +#define FGONLY 0x8 +#define SOLID 0x10 +#define RSHIFT 0x20 +#define EVENONLY 0x40 +#define ODDONLY 0x80 + +struct { + byte flags; + byte solid; + word sstart; + word dstart; + byte width; + byte height; +} __at (0xca00) blitter; + +byte __at (0x0) vidmem[128][304]; // 256x304x4bpp video memory + +void main(); + +// start routine @ 0x0 +// set stack pointer, enable interrupts +void start() { +__asm + LD SP,#0xc000 + DI +; copy initialized data + LD BC, #l__INITIALIZER + LD A, B + LD DE, #s__INITIALIZED + LD HL, #s__INITIALIZER + LDIR +__endasm; + main(); +} + +const byte palette_data[16] = { + 0x00, 0x03, 0x19, 0x50, 0x52, 0x07, 0x1f, 0x37, 0xe0, 0xa4, 0xfd, 0xff, 0x00, 0x00, 0x00, 0xf8, }; + +const byte sprite1[2+16*16/2] = { +8,16, +0x00,0x09,0x99,0x00,0x00,0x99,0x90,0x00, +0x00,0x94,0x94,0x90,0x09,0x49,0x49,0x00, +0x04,0x49,0x49,0x90,0x09,0x94,0x94,0x90, +0x94,0x99,0x94,0x90,0x09,0x49,0x99,0x49, +0x99,0x99,0x49,0x93,0x39,0x94,0x99,0x99, +0x04,0x49,0x99,0x94,0x49,0x99,0x94,0x90, +0x00,0x94,0x94,0x43,0x34,0x49,0x49,0x00, +0x00,0x09,0x43,0x94,0x49,0x34,0x90,0x00, +0x00,0x90,0x00,0x39,0x93,0x00,0x09,0x00, +0x00,0x09,0x83,0x33,0x33,0x33,0x90,0x00, +0x00,0x09,0x32,0x23,0x32,0x23,0x90,0x00, +0x00,0x03,0x03,0x23,0x82,0x30,0x30,0x00, +0x03,0x30,0x00,0x33,0x33,0x00,0x03,0x30, +0x00,0x30,0x03,0x00,0x00,0x30,0x03,0x00, +0x00,0x00,0x00,0x30,0x03,0x00,0x00,0x00, +0x00,0x09,0x99,0x00,0x00,0x99,0x90,0x00, +}; + +const byte sprite2[2+16*16/2] = { +8,16, +0x00,0x94,0x94,0x90,0x09,0x49,0x49,0x00, +0x04,0x49,0x49,0x90,0x09,0x94,0x94,0x90, +0x94,0x99,0x94,0x90,0x09,0x49,0x99,0x49, +0x99,0x99,0x49,0x93,0x39,0x94,0x99,0x99, +0x04,0x49,0x99,0x94,0x49,0x99,0x94,0x90, +0x00,0x94,0x94,0x43,0x34,0x49,0x49,0x00, +0x00,0x09,0x43,0x94,0x49,0x34,0x90,0x00, +0x00,0x90,0x00,0x39,0x93,0x00,0x09,0x00, +0x00,0x09,0x83,0x33,0x33,0x33,0x90,0x00, +0x00,0x09,0x32,0x23,0x32,0x23,0x90,0x00, +0x00,0x03,0x03,0x23,0x82,0x30,0x30,0x00, +0x03,0x30,0x00,0x33,0x33,0x00,0x03,0x30, +0x00,0x30,0x03,0x00,0x00,0x30,0x03,0x00, +0x00,0x00,0x00,0x30,0x03,0x00,0x00,0x00, +0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00, +}; + +const byte sprite3[2+16*16/2] = { +8,16, +0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00, +0x00,0x00,0x00,0x11,0x11,0x00,0x00,0x00, +0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00, +0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00, +0x00,0x11,0x10,0x01,0x10,0x01,0x11,0x00, +0x11,0x00,0x10,0x11,0x11,0x01,0x00,0x11, +0x10,0x00,0x11,0x11,0x11,0x11,0x00,0x01, +0x10,0x00,0x00,0x11,0x11,0x00,0x00,0x01, +0x00,0x01,0x10,0x11,0x41,0x01,0x10,0x00, +0x00,0x10,0x11,0x11,0x11,0x11,0x01,0x00, +0x01,0x00,0x00,0x51,0x15,0x00,0x00,0x10, +0x01,0x00,0x01,0x10,0x01,0x10,0x00,0x10, +0x01,0x00,0x10,0x00,0x00,0x01,0x00,0x10, +0x00,0x10,0x01,0x00,0x00,0x10,0x01,0x00, +0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x00, +0x00,0x01,0x10,0x00,0x00,0x01,0x10,0x00, +}; + +const byte sprite4[2+16*16/2] = { +8,16, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xbb,0xbb,0x00,0x00,0x00, +0x00,0x00,0x00,0xbb,0xbb,0x00,0x00,0x00, +0x00,0x00,0xbb,0xbb,0xbb,0xbb,0x00,0x00, +0x00,0x0b,0x4b,0xbb,0xbb,0xb4,0xb0,0x00, +0x00,0x0b,0x44,0xbb,0xbb,0x49,0xb0,0x00, +0x00,0xbb,0x99,0x4b,0xb4,0x99,0xbb,0x00, +0x00,0x4b,0xb9,0x9b,0xb4,0x4b,0xb4,0x00, +0x00,0x04,0xbb,0x4b,0xb9,0xbb,0x40,0x00, +0x00,0x00,0x4b,0xbb,0xbb,0xb4,0x00,0x00, +0x11,0x00,0x0b,0xbb,0xbb,0xb0,0x00,0x11, +0x10,0x10,0x0b,0x41,0x14,0xb0,0x01,0x01, +0x10,0x00,0x05,0x11,0x11,0x50,0x00,0x01, +0x01,0x00,0x01,0x51,0x15,0x10,0x00,0x10, +0x00,0x10,0x01,0x10,0x01,0x10,0x01,0x00, +0x01,0x01,0x10,0x10,0x01,0x01,0x10,0x10, +}; + +const byte sprite5[2+16*16/2] = { +8,16, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x22,0x00,0x00,0x22,0x00,0x00, +0x00,0x20,0x20,0x00,0x00,0x02,0x02,0x00, +0x02,0x22,0x12,0x00,0x00,0x21,0x22,0x20, +0x00,0x02,0x11,0x00,0x00,0x11,0x20,0x00, +0x00,0x00,0x02,0x11,0x11,0x20,0x00,0x00, +0x00,0x00,0x02,0x22,0x22,0x20,0x00,0x00, +0x00,0x00,0x21,0x22,0x22,0x12,0x00,0x00, +0x00,0x00,0x22,0x12,0x21,0x22,0x00,0x00, +0x02,0x00,0x22,0x12,0x21,0x22,0x00,0x20, +0x20,0x02,0x21,0x11,0x11,0x12,0x20,0x02, +0x02,0x22,0x15,0x12,0x21,0x51,0x22,0x20, +0x02,0x11,0x15,0x52,0x25,0x51,0x11,0x20, +0x20,0x00,0x22,0x12,0x21,0x22,0x00,0x02, +0x20,0x02,0x20,0x20,0x02,0x02,0x20,0x02, +0x02,0x02,0x00,0x20,0x02,0x00,0x20,0x20, +}; + +const byte sprite6[2+12*16/2] = { +8,12, +0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x00, +0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x40, +0x00,0x00,0x04,0x04,0x49,0x49,0x99,0x44, +0x00,0x00,0x44,0x44,0x99,0x94,0x44,0x40, +0x00,0x04,0x49,0x99,0x94,0x49,0x99,0x40, +0x00,0x44,0x99,0x94,0x49,0x99,0x44,0x00, +0x04,0x49,0x44,0x99,0x99,0x44,0x00,0x00, +0x04,0x44,0x00,0x49,0x44,0x40,0x00,0x00, +0x04,0x40,0x00,0x04,0x00,0x00,0x00,0x00, +0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; + +const byte sprite7[2+16*16/2] = { +8,16, +0x00,0x60,0x00,0x00,0x00,0x00,0x06,0x00, +0x60,0x60,0x00,0x00,0x00,0x00,0x06,0x06, +0x60,0x60,0x50,0x00,0x00,0x05,0x06,0x06, +0x60,0x60,0x06,0x00,0x00,0x60,0x06,0x06, +0x66,0x60,0x06,0x06,0x60,0x60,0x06,0x66, +0x66,0x60,0x66,0x66,0x66,0x66,0x06,0x66, +0x66,0x60,0x6b,0x6b,0xb6,0xb6,0x06,0x66, +0x06,0x66,0x66,0xb6,0x6b,0x66,0x66,0x60, +0x00,0x67,0x66,0x66,0x66,0x66,0x66,0x00, +0x00,0x11,0x11,0x66,0x66,0x11,0x11,0x00, +0x01,0x11,0x21,0x11,0x11,0x12,0x11,0x10, +0x00,0x10,0x01,0x01,0x10,0x10,0x01,0x00, +0x00,0x10,0x11,0x00,0x00,0x11,0x01,0x00, +0x00,0x00,0x10,0x00,0x00,0x01,0x00,0x00, +}; + +const byte sprite8[2+16*16/2] = { +8,16, +0x00,0x00,0x11,0x11,0x11,0x11,0x00,0x00, +0x00,0x01,0x61,0x11,0x21,0x12,0x10,0x00, +0x00,0x11,0x12,0x11,0x61,0x11,0x11,0x00, +0x00,0x11,0x71,0x21,0x61,0x17,0x11,0x00, +0x00,0x11,0x77,0x11,0x12,0x77,0x11,0x00, +0x00,0x11,0x17,0x17,0x71,0x72,0x11,0x00, +0x00,0x16,0x21,0x78,0x87,0x11,0x11,0x00, +0x00,0x01,0x81,0x88,0x88,0x18,0x10,0x00, +0x00,0x08,0x18,0x58,0x85,0x81,0x80,0x00, +0x00,0x88,0x01,0x88,0x88,0x10,0x88,0x00, +0x00,0x08,0x07,0x78,0x87,0x70,0x80,0x00, +0x08,0x80,0x07,0x80,0x08,0x70,0x08,0x80, +0x88,0x00,0x88,0x00,0x00,0x88,0x00,0x88, +0x80,0x00,0x08,0x80,0x08,0x80,0x00,0x08, +0x00,0x00,0x00,0x80,0x08,0x00,0x00,0x00, +}; + +const byte sprite9[2+13*16/2] = { +8,13, +0x00,0x00,0xaa,0x00,0x00,0xaa,0x00,0x00, +0x00,0x00,0xa0,0x0a,0xa0,0x0a,0x00,0x00, +0x0a,0xaa,0xa4,0xaa,0xaa,0x3a,0xaa,0xa0, +0x00,0x0a,0x3a,0x9a,0xa9,0xa3,0xa0,0x00, +0x00,0x0a,0xaa,0x99,0xa4,0xaa,0xa0,0x00, +0x00,0x0a,0xaa,0x99,0x94,0xaa,0xa0,0x00, +0x00,0xaa,0x33,0xaa,0xaa,0x43,0xaa,0x00, +0x0a,0x3a,0xaa,0x3a,0xa3,0xaa,0xa3,0xa0, +0x00,0xaa,0xaa,0x30,0x03,0xaa,0xaa,0x00, +0x00,0x0a,0xa0,0x30,0x03,0x0a,0xa0,0x00, +0x00,0xa3,0xa0,0x00,0x00,0x0a,0x4a,0x00, +0x00,0xaa,0xa0,0x00,0x00,0x0a,0xaa,0x00, +0x00,0x0a,0xa0,0x00,0x00,0x0a,0xa0,0x00, +}; + +const byte* const all_sprites[9] = { + sprite1, + sprite2, + sprite3, + sprite4, + sprite5, + sprite6, + sprite7, + sprite8, + sprite9, +}; + +inline word swapw(word j) { + return ((j << 8) | (j >> 8)); +} + +// x1: 0-151 +// y1: 0-255 +inline void blit_solid(byte x1, byte y1, byte w, byte h, byte color) { + blitter.width = w^4; + blitter.height = h^4; + blitter.dstart = x1+y1*256; // swapped + blitter.solid = color; + blitter.flags = DSTSCREEN|SOLID; +} + +inline void blit_copy(byte x1, byte y1, byte w, byte h, const byte* data) { + blitter.width = w^4; + blitter.height = h^4; + blitter.sstart = swapw((word)data); + blitter.dstart = x1+y1*256; // swapped + blitter.flags = DSTSCREEN|FGONLY; +} + +inline void blit_copy_solid(byte x1, byte y1, byte w, byte h, const byte* data, byte solid) { + blitter.width = w^4; + blitter.height = h^4; + blitter.sstart = swapw((word)data); + blitter.dstart = x1+y1*256; // swapped + blitter.solid = solid; + blitter.flags = DSTSCREEN|FGONLY|SOLID; +} + +inline void draw_sprite(const byte* data, byte x, byte y) { + blitter.width = data[0]^4; + blitter.height = data[1]^4; + blitter.sstart = swapw((word)(data+2)); + blitter.dstart = x+y*256; // swapped + blitter.flags = DSTSCREEN|FGONLY; +} + +inline void draw_sprite_solid(const byte* data, byte x, byte y, byte color) { + blitter.width = data[0]^4; + blitter.height = data[1]^4; + blitter.sstart = swapw((word)(data+2)); + blitter.dstart = x+y*256; // swapped + blitter.solid = color; + blitter.flags = DSTSCREEN|FGONLY|SOLID; +} + +inline void erase_sprite_rect(const byte* data, byte x, byte y) { + blitter.width = data[0]^4; + blitter.height = data[1]^4; + blitter.dstart = x+y*256; // swapped + blitter.solid = 0; + blitter.flags = DSTSCREEN|SOLID; +} + +inline void draw_sprite_strided(const byte* data, byte x, byte y, byte stride) { + const byte* src = data+2; + byte height = data[1]^4; + byte width = data[0]^4; + while (height--) { + blit_copy(x, y, width, 1, src); + y += stride; + src += width; + } +} + +typedef struct Actor* a; + +typedef void ActorUpdateFn(struct Actor* a); +typedef void ActorDrawFn(struct Actor* a); +typedef void ActorEnumerateFn(struct Actor* a); + +typedef struct Actor { + byte grid_index; + byte next_actor; + byte x,y; + byte* shape; + ActorUpdateFn* update; + ActorDrawFn* draw; +} Actor; + +#define GBITS 3 +#define GDIM (1<> (8-GBITS)) | (y & ((GDIM-1) << GBITS)); +} + +void insert_into_grid(byte gi, byte actor_index) { + struct Actor* a = &actors[actor_index]; + a->grid_index = gi; + a->next_actor = grid[gi]; + grid[gi] = actor_index; +} + +void delete_from_grid(byte gi, byte actor_index) { + byte i = grid[gi]; + byte next = actors[actor_index].next_actor; + // is actor to delete at head of list? + if (i == actor_index) { + grid[gi] = next; + } else { + // iterate through the list + do { + byte j = actors[i].next_actor; + if (j == actor_index) { + actors[i].next_actor = next; + break; + } + i = j; + } while (1); // watchdog reset if actor not found to delete + } + actors[actor_index].next_actor = 0; + actors[actor_index].grid_index = 0; +} + +void draw_actor_debug(struct Actor* a) { + draw_sprite_solid(a->shape, a->x, a->y, a->next_actor?0xff:0x66); +} + +byte update_actor(byte actor_index) { + struct Actor* a = &actors[actor_index]; + byte next_actor; + byte gi0,gi1; + if (!a->shape) return 0; // no shape present, ignore + next_actor = a->next_actor; // fetch in case it changes + gi0 = a->grid_index; + draw_sprite_solid(a->shape, a->x, a->y, 0); // erase + if (a->update) a->update(a); // move + if (a->draw) a->draw(a); // draw + gi1 = xy2grid(a->x, a->y); + // has grid bucket changed? + if (gi0 != gi1) { + // remove from old, add to new bucket + delete_from_grid(gi0, actor_index); + insert_into_grid(gi1, actor_index); + } + return next_actor; +} + +// + +word lfsr = 1; + +word rand() { + byte lsb = lfsr & 1; + lfsr >>= 1; + if (lsb) lfsr ^= 0xd400; + return lfsr; +} + +signed char random_dir() { + byte x = rand(); + if (x < 85) return 0; + else if (x < 85*2) return -1; + else return 1; +} + +void random_walk(Actor* a) { + a->x += random_dir(); + a->y += random_dir(); +} + +void update_grid_cell(byte grid_index) { + byte actor_index = grid[grid_index]; + while (actor_index) { + actor_index = update_actor(actor_index); + } +} + +void update_grid_rows(byte row_start, byte row_end) { + byte i0 = row_start * GDIM; + byte i1 = row_end * GDIM; + byte i; + for (i=i0; i!=i1; i++) { + update_grid_cell(i); + } +} + +void main() { + byte i; + byte num_actors = 32; + blit_solid(0, 0, 255, 255, 0); + memset(grid, 0, sizeof(grid)); + memset(actors, 0, sizeof(actors)); + memcpy(palette, palette_data, 16); + for (i=1; ix = (i & 7) * 16 + 16; + a->y = (i / 4) * 24 + 32; + a->shape = (void*) all_sprites[i%9]; + a->update = random_walk; + a->draw = draw_actor_debug; + insert_into_grid(xy2grid(a->x, a->y), i); + watchdog0x39 = 0x39; + } + while (1) { + // update top half while drawing bottom half + while (video_counter < 0x80) ; + update_grid_rows(0,GDIM/2); + // update bottom half while drawing top half + while (video_counter >= 0x80) ; + update_grid_rows(GDIM/2,GDIM); + watchdog0x39 = 0x39; + } +} diff --git a/presets/williams-z80/sprites.c b/presets/williams-z80/sprites.c index 24d22e71..6e525850 100644 --- a/presets/williams-z80/sprites.c +++ b/presets/williams-z80/sprites.c @@ -52,38 +52,6 @@ __endasm; main(); } -#define LOCHAR 0x21 -#define HICHAR 0x5e - -const byte font8x8[HICHAR-LOCHAR+1][8] = { -{ 0x18,0x18,0x18,0x18,0x00,0x00,0x18,0x00 }, { 0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00 }, { 0x66,0x66,0xff,0x66,0xff,0x66,0x66,0x00 }, { 0x18,0x3e,0x60,0x3c,0x06,0x7c,0x18,0x00 }, { 0x62,0x66,0x0c,0x18,0x30,0x66,0x46,0x00 }, { 0x3c,0x66,0x3c,0x38,0x67,0x66,0x3f,0x00 }, { 0x06,0x0c,0x18,0x00,0x00,0x00,0x00,0x00 }, { 0x0c,0x18,0x30,0x30,0x30,0x18,0x0c,0x00 }, { 0x30,0x18,0x0c,0x0c,0x0c,0x18,0x30,0x00 }, { 0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00 }, { 0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30 }, { 0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00 }, { 0x00,0x03,0x06,0x0c,0x18,0x30,0x60,0x00 }, { 0x3c,0x66,0x6e,0x76,0x66,0x66,0x3c,0x00 }, { 0x18,0x18,0x38,0x18,0x18,0x18,0x7e,0x00 }, { 0x3c,0x66,0x06,0x0c,0x30,0x60,0x7e,0x00 }, { 0x3c,0x66,0x06,0x1c,0x06,0x66,0x3c,0x00 }, { 0x06,0x0e,0x1e,0x66,0x7f,0x06,0x06,0x00 }, { 0x7e,0x60,0x7c,0x06,0x06,0x66,0x3c,0x00 }, { 0x3c,0x66,0x60,0x7c,0x66,0x66,0x3c,0x00 }, { 0x7e,0x66,0x0c,0x18,0x18,0x18,0x18,0x00 }, { 0x3c,0x66,0x66,0x3c,0x66,0x66,0x3c,0x00 }, { 0x3c,0x66,0x66,0x3e,0x06,0x66,0x3c,0x00 }, { 0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00 }, { 0x00,0x00,0x18,0x00,0x00,0x18,0x18,0x30 }, { 0x0e,0x18,0x30,0x60,0x30,0x18,0x0e,0x00 }, { 0x00,0x00,0x7e,0x00,0x7e,0x00,0x00,0x00 }, { 0x70,0x18,0x0c,0x06,0x0c,0x18,0x70,0x00 }, { 0x3c,0x66,0x06,0x0c,0x18,0x00,0x18,0x00 }, { 0x3c,0x66,0x6e,0x6e,0x60,0x62,0x3c,0x00 }, { 0x18,0x3c,0x66,0x7e,0x66,0x66,0x66,0x00 }, { 0x7c,0x66,0x66,0x7c,0x66,0x66,0x7c,0x00 }, { 0x3c,0x66,0x60,0x60,0x60,0x66,0x3c,0x00 }, { 0x78,0x6c,0x66,0x66,0x66,0x6c,0x78,0x00 }, { 0x7e,0x60,0x60,0x78,0x60,0x60,0x7e,0x00 }, { 0x7e,0x60,0x60,0x78,0x60,0x60,0x60,0x00 }, { 0x3c,0x66,0x60,0x6e,0x66,0x66,0x3c,0x00 }, { 0x66,0x66,0x66,0x7e,0x66,0x66,0x66,0x00 }, { 0x3c,0x18,0x18,0x18,0x18,0x18,0x3c,0x00 }, { 0x1e,0x0c,0x0c,0x0c,0x0c,0x6c,0x38,0x00 }, { 0x66,0x6c,0x78,0x70,0x78,0x6c,0x66,0x00 }, { 0x60,0x60,0x60,0x60,0x60,0x60,0x7e,0x00 }, { 0x63,0x77,0x7f,0x6b,0x63,0x63,0x63,0x00 }, { 0x66,0x76,0x7e,0x7e,0x6e,0x66,0x66,0x00 }, { 0x3c,0x66,0x66,0x66,0x66,0x66,0x3c,0x00 }, { 0x7c,0x66,0x66,0x7c,0x60,0x60,0x60,0x00 }, { 0x3c,0x66,0x66,0x66,0x66,0x3c,0x0e,0x00 }, { 0x7c,0x66,0x66,0x7c,0x78,0x6c,0x66,0x00 }, { 0x3c,0x66,0x60,0x3c,0x06,0x66,0x3c,0x00 }, { 0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x00 }, { 0x66,0x66,0x66,0x66,0x66,0x66,0x3c,0x00 }, { 0x66,0x66,0x66,0x66,0x66,0x3c,0x18,0x00 }, { 0x63,0x63,0x63,0x6b,0x7f,0x77,0x63,0x00 }, { 0x66,0x66,0x3c,0x18,0x3c,0x66,0x66,0x00 }, { 0x66,0x66,0x66,0x3c,0x18,0x18,0x18,0x00 }, { 0x7e,0x06,0x0c,0x18,0x30,0x60,0x7e,0x00 }, { 0x3c,0x30,0x30,0x30,0x30,0x30,0x3c,0x00 }, { 0x00,0x60,0x30,0x18,0x0c,0x06,0x03,0x00 }, { 0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00 }, { 0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18 } -}; - -static byte font_table[HICHAR-LOCHAR+1][8*4]; - -void fill_char_table_entry(char ch) { - const byte* src = &font8x8[ch-LOCHAR][0]; - byte* data = &font_table[ch-LOCHAR][0]; - int i,j,pixels; - for (i=0; i<8; i++) { - byte b = *src++; - for (j=0; j<4; j++) { - pixels = 0; - if (b & 0x80) pixels |= 0xf0; - if (b & 0x40) pixels |= 0x0f; - *data++ = pixels; - b <<= 2; - } - } -} - -void fill_char_table() { - char ch; - for (ch=LOCHAR; ch<=HICHAR; ch++) { - fill_char_table_entry(ch); - } -} - const byte palette_data[16] = { 0x00, 0x03, 0x19, 0x50, 0x52, 0x07, 0x1f, 0x37, 0xe0, 0xa4, 0xfd, 0xff, 0x00, 0x00, 0x00, 0xf8, }; @@ -333,22 +301,11 @@ inline void draw_sprite_strided(const byte* data, byte x, byte y, byte stride) { } } -inline void draw_char(char ch, byte x, byte y, byte color) { - if (ch < LOCHAR || ch > HICHAR) return; - blit_copy_solid(x, y, 4, 8, font_table[ch - LOCHAR], color); -} - -void draw_string(const char* str, byte x, byte y, byte color) { - while (*str) { - draw_char(*str++, x, y, color); - x += 4; - } -} - typedef struct Actor* a; typedef void ActorUpdateFn(struct Actor* a); typedef void ActorDrawFn(struct Actor* a); +typedef void ActorEnumerateFn(struct Actor* a); typedef struct Actor { byte grid_index; @@ -467,7 +424,6 @@ void main() { memset(grid, 0, sizeof(grid)); memset(actors, 0, sizeof(actors)); memcpy(palette, palette_data, 16); - fill_char_table(); for (i=1; ix = (i & 3) * 16 + 32; diff --git a/src/emu.js b/src/emu.js index 0205c1e7..bdd87417 100644 --- a/src/emu.js +++ b/src/emu.js @@ -32,7 +32,7 @@ function __createCanvas(mainElement, width, height) { var RasterVideo = function(mainElement, width, height, options) { var self = this; var canvas, ctx; - var imageData, buf8, datau32; + var imageData, arraybuf, buf8, datau32; this.create = function() { self.canvas = canvas = __createCanvas(mainElement, width, height); @@ -46,9 +46,13 @@ var RasterVideo = function(mainElement, width, height, options) { } ctx = canvas.getContext('2d'); imageData = ctx.createImageData(width, height); - var buf = new ArrayBuffer(imageData.data.length); - buf8 = new Uint8Array(buf); // TODO: Uint8ClampedArray - datau32 = new Uint32Array(buf); + /* + arraybuf = new ArrayBuffer(imageData.data.length); + buf8 = new Uint8Array(arraybuf); // TODO: Uint8ClampedArray + datau32 = new Uint32Array(arraybuf); + */ + buf8 = imageData.data; + datau32 = new Uint32Array(imageData.data.buffer); } // TODO: common function (canvas) @@ -69,7 +73,7 @@ var RasterVideo = function(mainElement, width, height, options) { } this.updateFrame = function(sx, sy, dx, dy, width, height) { - imageData.data.set(buf8); + //imageData.data.set(buf8); // TODO: slow w/ partial updates if (width && height) ctx.putImageData(imageData, sx, sy, dx, dy, width, height); else diff --git a/src/platform/williams.js b/src/platform/williams.js index 68d37601..27f24d68 100644 --- a/src/platform/williams.js +++ b/src/platform/williams.js @@ -3,6 +3,7 @@ var WILLIAMS_PRESETS = [ {id:'gfxtest.c', name:'Graphics Test'}, {id:'sprites.c', name:'Sprite Test'}, + {id:'game1.c', name:'Game'}, {id:'bitmap_rle.c', name:'RLE Bitmap'}, ]; @@ -64,9 +65,11 @@ var WilliamsPlatform = function(mainElement, proto) { [Keys.VK_RIGHT, 2, 0x2], [Keys.VK_7, 4, 0x1], [Keys.VK_8, 4, 0x2], - [Keys.VK_5, 4, 0x4], + [Keys.VK_6, 4, 0x4], [Keys.VK_9, 4, 0x8], + [Keys.VK_5, 4, 0x10], ]); + // TODO: sound board handshake var palette = []; for (var ii=0; ii<16; ii++) @@ -308,13 +311,13 @@ var WilliamsPlatform = function(mainElement, proto) { cpu.requestInterrupt(); } self.runCPU(cpu, cpuCyclesPerFrame/4); + video.updateFrame(0, 0, quarter*64, 0, 64, 304); } if (screenNeedsRefresh) { for (var i=0; i<0x9800; i++) drawDisplayByte(i, ram.mem[i]); screenNeedsRefresh = false; } - video.updateFrame(); if (watchdog_counter-- <= 0) { console.log("WATCHDOG FIRED, PC =", cpu.getPC().toString(16)); // TODO: alert on video // TODO: self.breakpointHit(cpu.T()); diff --git a/tools/Makefile b/tools/Makefile index f37ab422..1404fff3 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -18,6 +18,8 @@ %.pcx: %.png convert $< -format raw -type palette -compress none -colors 15 +dither $@ +%.4.pcx: %.png + convert $< -format raw -type palette -compress none -colors 4 +dither $@ ship1.pbm: ship1.png convert ship1.png -negate -flop ship1.pbm diff --git a/tools/pcx2will.py b/tools/pcx2will.py index 0c7d7e5f..4f08ccf7 100755 --- a/tools/pcx2will.py +++ b/tools/pcx2will.py @@ -2,6 +2,13 @@ import sys, array, string +col0 = 0 + +def tocolor(x): + if x == 0: + return 0 + else: + return x + col0 def tohex2(v): return '0x%02x'%v @@ -25,13 +32,15 @@ with open(sys.argv[1],'rb') as f: width = (data[9] << 8) + data[8] + 1 height = (data[11] << 8) + data[10] + 1 rowlen = (data[0x43] << 8) + data[0x42] + print "const byte sprite[] = {" print "%d,%d," % ((width+1)/2,height) for y in range(0,height): ofs = 0x80 + y*rowlen output = [] for x in range(0,width,2): - b = (data[ofs] << 4) + (data[ofs+1]) + b = (tocolor(data[ofs]) << 4) + tocolor(data[ofs+1]) output.append(b) ofs += 2 print string.join(map(tohex2,output),',') + ',' - + print "}" +