comparison src/vdp.c @ 22:407725d9a02f

Implemented sprite drawing. Added small sprite example.
author Michael Pavone <pavone@retrodev.com>
date Wed, 30 Mar 2016 19:55:48 -0700
parents 91ded3b12d96
children a085f17b79e9
comparison
equal deleted inserted replaced
21:91ded3b12d96 22:407725d9a02f
39 } else { 39 } else {
40 context->drawbuffer = context->linebuffers; 40 context->drawbuffer = context->linebuffers;
41 context->readbuffer = context->linebuffers + 328; 41 context->readbuffer = context->linebuffers + 328;
42 } 42 }
43 context->draw_dest = 0; 43 context->draw_dest = 0;
44 //enable sprite scanning
45 context->status |= VDP_STATUS_SPRITE_SCAN;
46 context->current_draw = 0;
44 } 47 }
45 if (context->draw_counter) { 48 if (context->draw_counter) {
46 context->draw_counter--; 49 context->draw_counter--;
47 uint16_t pixels = context->vram[context->draw_source++]; 50 uint16_t pixels = context->vram[context->draw_source++];
48 for (int i = 0; i < 4; i++) 51 for (int i = 0; i < 4; i++)
68 } 71 }
69 context->palpriority = entry >> 9 & 0x70; 72 context->palpriority = entry >> 9 & 0x70;
70 context->draw_counter = 2; 73 context->draw_counter = 2;
71 //TODO: handle horizontal flip 74 //TODO: handle horizontal flip
72 } 75 }
73 //TODO: Scan sprite table 76 if (context->status & VDP_STATUS_SPRITE_SCAN) {
77 context->status |= VDP_STATUS_SRAM;
78 uint16_t pos = context->sram[context->hcounter];
79 uint16_t y = pos & 0xFF;
80 uint16_t x = pos >> 8;
81 uint16_t atts = context->sram[context->hcounter+1];
82 x |= atts << 2 & 0x100;
83 if (x | y) {
84 uint16_t size = atts & 0x400 ? 16 : 8;
85 if (context->vcounter >= y && context->vcounter < y + size) {
86 uint16_t address = (atts & 0x3F) * 16;
87 if (atts & 0x1000) {
88 address += (size-1) * 2 - (context->vcounter - y) * 2;
89 } else {
90 address += (context->vcounter - y) * 2;
91 }
92 context->sprite_draws[context->current_draw].source = address;
93 context->sprite_draws[context->current_draw].x = x;
94 context->sprite_draws[context->current_draw].hflip = (atts & 0x800) != 0;
95 context->sprite_draws[context->current_draw].palpriority = 0x80 | (atts >> 9 & 0x50);
96 context->current_draw++;
97 if (size == 16) {
98 context->sprite_draws[context->current_draw].source = address + 32;
99 context->sprite_draws[context->current_draw].x = x + 8;
100 context->sprite_draws[context->current_draw].hflip = (atts & 0x800) != 0;
101 context->sprite_draws[context->current_draw].palpriority = 0x80 | (atts >> 9 & 0x50);
102 }
103 context->current_draw++;
104 if (context->current_draw == 40) {
105 //no more rendering capacity
106 context->status &= ~VDP_STATUS_SPRITE_SCAN;
107 context->current_draw = 0;
108 }
109 }
110 } else {
111 //hit sprite list terminator
112 context->status &= ~VDP_STATUS_SPRITE_SCAN;
113 context->current_draw = 0;
114 }
115 }
74 } else { 116 } else {
75 //TODO: Render sprites 117 sprite_draw *draw = context->sprite_draws + (context->current_draw >> 1);
118 if (draw->palpriority) {
119 context->status |= VDP_STATUS_VRAM;
120 uint16_t pixels = context->vram[draw->source + (context->current_draw & 1)];
121 uint16_t x = draw->x - 16 + (context->hscroll & 7);
122 for (int i = 0; i < 4; i++, x++)
123 {
124 //TODO: handle horizontal flip
125 uint8_t pixel = (pixels >> ((3-i) * 4)) & 0xF;
126 if (pixel && x < 328 && ((draw->palpriority & 0x40) || !(context->drawbuffer[x] & 0x40))) {
127 context->drawbuffer[x] = pixel | draw->palpriority;
128 }
129 }
130 if (context->current_draw & 1) {
131 draw->palpriority = 0;
132 } else {
133 draw->x += 4;
134 }
135 }
136 context->current_draw++;
76 } 137 }
77 } 138 }
78 //Draw to framebuffer 139 //Draw to framebuffer
79 if (context->vcounter > 8 && context->vcounter < 249 && context->hcounter < 320) { 140 if (context->vcounter > 8 && context->vcounter < 249 && context->hcounter < 320) {
80 if (!context->hcounter && context->vcounter == 9) { 141 if (!context->hcounter && context->vcounter == 9) {