diff 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
line wrap: on
line diff
--- 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