# HG changeset patch # User Michael Pavone # Date 1459392948 25200 # Node ID 407725d9a02f925976e574700e07ef9c9badef2b # Parent 91ded3b12d96e3363b39d371ab2ea1acffa02276 Implemented sprite drawing. Added small sprite example. diff -r 91ded3b12d96 -r 407725d9a02f sprites.s16 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sprites.s16 Wed Mar 30 19:55:48 2016 -0700 @@ -0,0 +1,143 @@ + + ;write palette entries to CRAM + ldim 0, r0 + ldimh $FF, r0 + outi 14, r0 + ldim colors, r0 + ldimh colors, r0 + ldim $80, r1 + ldimh $0, r1 + ldim 0, r2 +cloop: + ld16 r0, r2, r3 + outi 15, r3 + addi 2, r2 + cmp r1, r2 + bne cloop + + ;write tile to VRAM + ldim 0, r2 + outi 14, r2 + ldim tile, r0 + ldim $A0, r1 + ldimh $0, r1 +tloop: + ld16 r0, r2, r3 + outi 15, r3 + addi 2, r2 + cmp r1, r2 + bne tloop + + ;write name table entries to VRAM + ldim 0, r2 + ldimh $60, r2 + outi 14, r2 + ;current entry + ldim 0, r0 + ;increment + ldimh $8, r2 + ;counter + ldim $00, r1 + ldimh $7, r1 +nloop: + outi 15, r0 + add r2, r0, r0 + addi -1, r1 + bne nloop + + ;setup writes to sprite list + ldim 0, r0 + ldimh $FE, r0 + outi 14, r0 + + ;write first sprite + ldim $15, r0 + ldimh $35, r0 + outi 15, r0 + ldim 1, r1 + ldimh $84, r1 + outi 15, r1 + + ;write second sprite + ldim $8A, r0 + ldimh $8A, r0 + outi 15, r0 + ldimh $A4, r1 + outi 15, r1 + + + ;write vscroll register + ldim $0, r0 + ldimh $E6, r0 + outi $C, r0 + ;write hscroll register to enable display + ldimh $80, r0 + outi $D, r0 +forever: + bra forever +tile: + dc.l $000FFFFF + dc.l $E111EEEE + dc.l $DD222DDD + dc.l $CCC333CC + dc.l $BBBB444B + dc.l $AAAAA555 + dc.l $99996669 + dc.l $88877788 + + dc.l $00000088 + dc.l $00000889 + dc.l $0000889A + dc.l $000889AB + dc.l $00889ABC + dc.l $0889ABCD + dc.l $889ABCDE + dc.l $889ABCEF + + dc.l $889ABCEF + dc.l $889ABCDE + dc.l $0889ABCD + dc.l $00889ABC + dc.l $000889AB + dc.l $0000889A + dc.l $00000889 + dc.l $00000088 + + dc.l $88000000 + dc.l $98800000 + dc.l $A9880000 + dc.l $BA988000 + dc.l $CBA98800 + dc.l $DCBA9880 + dc.l $EDCBA988 + dc.l $FECBA988 + + dc.l $FECBA988 + dc.l $EDCBA988 + dc.l $DCBA9880 + dc.l $CBA98800 + dc.l $BA988000 + dc.l $A9880000 + dc.l $98800000 + dc.l $88000000 +colors: + dc.w $0000, $0001, $0002, $0003 + dc.w $0004, $0005, $0006, $0007 + dc.w $0008, $0009, $000A, $000B + dc.w $000C, $000D, $000E, $000F + + dc.w $0000, $0010, $0020, $0030 + dc.w $0040, $0050, $0060, $0070 + dc.w $0080, $0090, $00A0, $00B0 + dc.w $00C0, $00D0, $00E0, $00F0 + + dc.w $0000, $0100, $0200, $0300 + dc.w $0400, $0500, $0600, $0700 + dc.w $0800, $0900, $0A00, $0B00 + dc.w $0C00, $0D00, $0E00, $0F00 + + dc.w $0000, $0111, $0222, $0333 + dc.w $0444, $0555, $0666, $0777 + dc.w $0888, $0999, $0AAA, $0BBB + dc.w $0CCC, $0DDD, $0EEE, $0FFF + diff -r 91ded3b12d96 -r 407725d9a02f src/vdp.c --- a/src/vdp.c Tue Mar 29 19:59:26 2016 -0700 +++ b/src/vdp.c Wed Mar 30 19:55:48 2016 -0700 @@ -41,6 +41,9 @@ context->readbuffer = context->linebuffers + 328; } context->draw_dest = 0; + //enable sprite scanning + context->status |= VDP_STATUS_SPRITE_SCAN; + context->current_draw = 0; } if (context->draw_counter) { context->draw_counter--; @@ -70,9 +73,67 @@ context->draw_counter = 2; //TODO: handle horizontal flip } - //TODO: Scan sprite table + if (context->status & VDP_STATUS_SPRITE_SCAN) { + context->status |= VDP_STATUS_SRAM; + uint16_t pos = context->sram[context->hcounter]; + uint16_t y = pos & 0xFF; + uint16_t x = pos >> 8; + uint16_t atts = context->sram[context->hcounter+1]; + x |= atts << 2 & 0x100; + if (x | y) { + uint16_t size = atts & 0x400 ? 16 : 8; + if (context->vcounter >= y && context->vcounter < y + size) { + uint16_t address = (atts & 0x3F) * 16; + if (atts & 0x1000) { + address += (size-1) * 2 - (context->vcounter - y) * 2; + } else { + address += (context->vcounter - y) * 2; + } + context->sprite_draws[context->current_draw].source = address; + context->sprite_draws[context->current_draw].x = x; + context->sprite_draws[context->current_draw].hflip = (atts & 0x800) != 0; + context->sprite_draws[context->current_draw].palpriority = 0x80 | (atts >> 9 & 0x50); + context->current_draw++; + if (size == 16) { + context->sprite_draws[context->current_draw].source = address + 32; + context->sprite_draws[context->current_draw].x = x + 8; + context->sprite_draws[context->current_draw].hflip = (atts & 0x800) != 0; + context->sprite_draws[context->current_draw].palpriority = 0x80 | (atts >> 9 & 0x50); + } + context->current_draw++; + if (context->current_draw == 40) { + //no more rendering capacity + context->status &= ~VDP_STATUS_SPRITE_SCAN; + context->current_draw = 0; + } + } + } else { + //hit sprite list terminator + context->status &= ~VDP_STATUS_SPRITE_SCAN; + context->current_draw = 0; + } + } } else { - //TODO: Render sprites + sprite_draw *draw = context->sprite_draws + (context->current_draw >> 1); + if (draw->palpriority) { + context->status |= VDP_STATUS_VRAM; + uint16_t pixels = context->vram[draw->source + (context->current_draw & 1)]; + uint16_t x = draw->x - 16 + (context->hscroll & 7); + for (int i = 0; i < 4; i++, x++) + { + //TODO: handle horizontal flip + uint8_t pixel = (pixels >> ((3-i) * 4)) & 0xF; + if (pixel && x < 328 && ((draw->palpriority & 0x40) || !(context->drawbuffer[x] & 0x40))) { + context->drawbuffer[x] = pixel | draw->palpriority; + } + } + if (context->current_draw & 1) { + draw->palpriority = 0; + } else { + draw->x += 4; + } + } + context->current_draw++; } } //Draw to framebuffer diff -r 91ded3b12d96 -r 407725d9a02f src/vdp.h --- a/src/vdp.h Tue Mar 29 19:59:26 2016 -0700 +++ b/src/vdp.h Wed Mar 30 19:55:48 2016 -0700 @@ -2,6 +2,13 @@ #define VDP_H_ typedef struct { + uint16_t source; + uint16_t x; + uint8_t hflip; + uint8_t palpriority; +} sprite_draw; + +typedef struct { uint16_t *framebuffer; uint8_t *drawbuffer; uint8_t *readbuffer; @@ -22,14 +29,18 @@ uint16_t draw_source; uint16_t draw_dest; + uint16_t vram[32*512]; uint8_t linebuffers[328*2]; uint16_t sram[64*2]; uint16_t cram[64]; + sprite_draw sprite_draws[40]; + uint8_t fifo_dest; uint8_t draw_counter; uint8_t palpriority; + uint8_t current_draw; } vdp; enum { @@ -39,10 +50,11 @@ FIFO_DEST_CRAM }; -#define VDP_STATUS_FIFO 1 -#define VDP_STATUS_VRAM 2 -#define VDP_STATUS_SRAM 4 -#define VDP_STATUS_ENABLED 8 +#define VDP_STATUS_FIFO 1 +#define VDP_STATUS_VRAM 2 +#define VDP_STATUS_SRAM 4 +#define VDP_STATUS_ENABLED 8 +#define VDP_STATUS_SPRITE_SCAN 16 void vdp_init(vdp *context, uint32_t clock_div); void vdp_run(vdp *context, uint32_t target);