Mercurial > repos > blastem
comparison vdp.c @ 21:72ce60cb1711
Sprites somewhat less broken
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 08 Dec 2012 11:12:17 -0800 |
parents | f664eeb55cb4 |
children | f090a98ccb7e |
comparison
equal
deleted
inserted
replaced
20:f664eeb55cb4 | 21:72ce60cb1711 |
---|---|
21 context->linebuf = malloc(LINEBUF_SIZE + 48); | 21 context->linebuf = malloc(LINEBUF_SIZE + 48); |
22 context->tmp_buf_a = context->linebuf + LINEBUF_SIZE; | 22 context->tmp_buf_a = context->linebuf + LINEBUF_SIZE; |
23 context->tmp_buf_b = context->tmp_buf_a + 24; | 23 context->tmp_buf_b = context->tmp_buf_a + 24; |
24 } | 24 } |
25 | 25 |
26 void render_sprite_cells(uint32_t linecyc, vdp_context * context) | 26 void render_sprite_cells(vdp_context * context) |
27 { | 27 { |
28 if (linecyc < context->sprite_draws) { | 28 if (context->cur_slot >= context->sprite_draws) { |
29 sprite_draw * d = context->sprite_draw_list + linecyc; | 29 sprite_draw * d = context->sprite_draw_list + context->cur_slot; |
30 context->cur_slot--; | |
30 uint16_t dir; | 31 uint16_t dir; |
31 int16_t x; | 32 int16_t x; |
32 if (d->h_flip) { | 33 if (d->h_flip) { |
33 x = d->x_pos + 7; | 34 x = d->x_pos + 7; |
34 dir = -1; | 35 dir = -1; |
52 void scan_sprite_table(uint32_t line, vdp_context * context) | 53 void scan_sprite_table(uint32_t line, vdp_context * context) |
53 { | 54 { |
54 if (context->sprite_index && context->slot_counter) { | 55 if (context->sprite_index && context->slot_counter) { |
55 line += 1; | 56 line += 1; |
56 line &= 0xFF; | 57 line &= 0xFF; |
57 line += 128; | |
58 context->sprite_index &= 0x7F; | 58 context->sprite_index &= 0x7F; |
59 //TODO: Read from SAT cache rather than from VRAM | 59 //TODO: Read from SAT cache rather than from VRAM |
60 uint16_t sat_address = (context->regs[REG_SAT] & 0x7F) << 9; | 60 uint16_t sat_address = (context->regs[REG_SAT] & 0x7F) << 9; |
61 uint16_t address = context->sprite_index * 8 + sat_address; | 61 uint16_t address = context->sprite_index * 8 + sat_address; |
62 uint16_t y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) - 128; | 62 int16_t y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) - 128; |
63 uint8_t height = ((context->vdpmem[address+2] & 0x3) + 1) * 8; | 63 uint8_t height = ((context->vdpmem[address+2] & 0x3) + 1) * 8; |
64 if (y >= line && (y + height) < line) { | 64 //printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height); |
65 if (y <= line && line < (y + height)) { | |
66 printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line); | |
65 context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2]; | 67 context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2]; |
66 context->sprite_info_list[context->slot_counter].index = context->sprite_index; | 68 context->sprite_info_list[context->slot_counter].index = context->sprite_index; |
67 context->sprite_info_list[context->slot_counter].y = y; | 69 context->sprite_info_list[context->slot_counter].y = y; |
68 } | 70 } |
69 context->sprite_index = context->vdpmem[address+3] & 0x7F; | 71 context->sprite_index = context->vdpmem[address+3] & 0x7F; |
70 if (context->sprite_index && context->slot_counter) | 72 if (context->sprite_index && context->slot_counter) |
71 { | 73 { |
72 address = context->sprite_index * 8 + sat_address; | 74 address = context->sprite_index * 8 + sat_address; |
73 y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) - 128; | 75 y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) - 128; |
74 height = ((context->vdpmem[address+2] & 0x3) + 1) * 8; | 76 height = ((context->vdpmem[address+2] & 0x3) + 1) * 8; |
75 if (y >= line && y < (line + height)) { | 77 if (y <= line && line < (y + height)) { |
78 printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line); | |
76 context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2]; | 79 context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2]; |
77 context->sprite_info_list[context->slot_counter].index = context->sprite_index; | 80 context->sprite_info_list[context->slot_counter].index = context->sprite_index; |
78 context->sprite_info_list[context->slot_counter].y = y; | 81 context->sprite_info_list[context->slot_counter].y = y; |
79 } | 82 } |
83 context->sprite_index = context->vdpmem[address+3] & 0x7F; | |
80 } | 84 } |
81 } | 85 } |
82 } | 86 } |
83 | 87 |
84 void read_sprite_x(uint32_t line, vdp_context * context) | 88 void read_sprite_x(uint32_t line, vdp_context * context) |
85 { | 89 { |
86 if (context->slot_counter && context->sprite_draws) { | 90 if ((context->cur_slot >= context->slot_counter) && context->sprite_draws) { |
87 context->slot_counter--; | 91 line += 1; |
88 uint8_t width = (context->sprite_info_list[context->slot_counter].size & 0x3) + 1; | 92 line &= 0xFF; |
89 uint8_t height = (((context->sprite_info_list[context->slot_counter].size >> 2) & 0x3) + 1) * 8; | 93 //in tiles |
90 uint16_t att_addr = ((context->regs[REG_SAT] & 0x7F) << 9) + context->sprite_info_list[context->slot_counter].index * 8 + 4; | 94 uint8_t width = ((context->sprite_info_list[context->cur_slot].size >> 2) & 0x3) + 1; |
95 //in pixels | |
96 uint8_t height = ((context->sprite_info_list[context->cur_slot].size & 0x3) + 1) * 8; | |
97 uint16_t att_addr = ((context->regs[REG_SAT] & 0x7F) << 9) + context->sprite_info_list[context->cur_slot].index * 8 + 4; | |
91 uint16_t tileinfo = (context->vdpmem[att_addr] << 8) | context->vdpmem[att_addr+1]; | 98 uint16_t tileinfo = (context->vdpmem[att_addr] << 8) | context->vdpmem[att_addr+1]; |
92 uint8_t pal_priority = (tileinfo >> 9) & 0x70; | 99 uint8_t pal_priority = (tileinfo >> 9) & 0x70; |
93 uint8_t row; | 100 uint8_t row; |
94 if (tileinfo & MAP_BIT_V_FLIP) { | 101 if (tileinfo & MAP_BIT_V_FLIP) { |
95 row = (context->sprite_info_list[context->slot_counter].y + height - 1) - line; | 102 row = (context->sprite_info_list[context->cur_slot].y + height - 1) - line; |
96 } else { | 103 } else { |
97 row = line-context->sprite_info_list[context->slot_counter].y; | 104 row = line-context->sprite_info_list[context->cur_slot].y; |
98 } | 105 } |
99 uint16_t address = ((tileinfo & 0x7FF) << 5) + row * width * 4; | 106 uint16_t address = ((tileinfo & 0x7FF) << 5) + (row & 0x7) * 4 + (row & 0x18) * width * 4; |
100 int16_t x = ((context->vdpmem[att_addr+ 6] & 0x3) << 8) | context->vdpmem[att_addr + 7]; | 107 int16_t x = ((context->vdpmem[att_addr+ 2] & 0x3) << 8) | context->vdpmem[att_addr + 3]; |
101 if (x) { | 108 if (x) { |
102 x -= 128; | 109 x -= 128; |
103 for (;width && context->sprite_draws; --width, --context->sprite_draws, address += 4, x += 8) { | 110 printf("Sprite %d | x: %d, y: %d, width: %d, height: %d, pal_priority: %X, row: %d, tile addr: %X\n", context->sprite_info_list[context->cur_slot].index, x, context->sprite_info_list[context->cur_slot].y, width, height, pal_priority, row, address); |
111 for (;width && context->sprite_draws; --width, --context->sprite_draws, address += 32, x += 8) { | |
104 context->sprite_draw_list[context->sprite_draws].address = address; | 112 context->sprite_draw_list[context->sprite_draws].address = address; |
105 context->sprite_draw_list[context->sprite_draws].x_pos = x; | 113 context->sprite_draw_list[context->sprite_draws].x_pos = x; |
106 context->sprite_draw_list[context->sprite_draws].pal_priority = pal_priority; | 114 context->sprite_draw_list[context->sprite_draws].pal_priority = pal_priority; |
107 context->sprite_draw_list[context->sprite_draws].h_flip = (tileinfo & MAP_BIT_H_FLIP) ? 1 : 0; | 115 context->sprite_draw_list[context->sprite_draws].h_flip = (tileinfo & MAP_BIT_H_FLIP) ? 1 : 0; |
108 } | 116 } |
117 context->cur_slot--; | |
109 } else { | 118 } else { |
110 //sprite masking enabled, no more sprites on this line | 119 //sprite masking enabled, no more sprites on this line |
111 context->slot_counter = 0; | 120 context->cur_slot = -1; |
112 } | 121 } |
113 } | 122 } |
114 } | 123 } |
115 | 124 |
116 void external_slot(vdp_context * context) | 125 void external_slot(vdp_context * context) |
243 } else {*/ | 252 } else {*/ |
244 end = dst + 16; | 253 end = dst + 16; |
245 //} | 254 //} |
246 for (; dst < end; ++plane_a, ++plane_b, ++sprite_buf, ++dst) { | 255 for (; dst < end; ++plane_a, ++plane_b, ++sprite_buf, ++dst) { |
247 uint8_t pixel; | 256 uint8_t pixel; |
248 if (*sprite_buf & BUF_BIT_PRIORITY) { | 257 if (*sprite_buf & BUF_BIT_PRIORITY && *sprite_buf & 0xF) { |
249 pixel = *sprite_buf; | 258 pixel = *sprite_buf; |
250 } else if (*plane_a & BUF_BIT_PRIORITY) { | 259 } else if (*plane_a & BUF_BIT_PRIORITY && *plane_a & 0xF) { |
251 pixel = *plane_a; | 260 pixel = *plane_a; |
252 } else if (*plane_b & BUF_BIT_PRIORITY) { | 261 } else if (*plane_b & BUF_BIT_PRIORITY && *plane_b & 0xF) { |
253 pixel = *plane_b; | 262 pixel = *plane_b; |
254 } else if (*sprite_buf & 0xF) { | 263 } else if (*sprite_buf & 0xF) { |
255 pixel = *sprite_buf; | 264 pixel = *sprite_buf; |
256 } else if (*plane_a & 0xF) { | 265 } else if (*plane_a & 0xF) { |
257 pixel = *plane_a; | 266 pixel = *plane_a; |
333 uint32_t mask; | 342 uint32_t mask; |
334 switch(linecyc) | 343 switch(linecyc) |
335 { | 344 { |
336 //sprite render to line buffer starts | 345 //sprite render to line buffer starts |
337 case 0: | 346 case 0: |
347 context->cur_slot = MAX_DRAWS; | |
338 memset(context->linebuf, 0, LINEBUF_SIZE); | 348 memset(context->linebuf, 0, LINEBUF_SIZE); |
339 render_sprite_cells(linecyc, context); | 349 render_sprite_cells(context); |
340 break; | 350 break; |
341 case 1: | 351 case 1: |
342 case 2: | 352 case 2: |
343 case 3: | 353 case 3: |
344 render_sprite_cells(linecyc, context); | 354 render_sprite_cells(context); |
345 break; | 355 break; |
346 //sprite attribute table scan starts | 356 //sprite attribute table scan starts |
347 case 4: | 357 case 4: |
348 render_sprite_cells(linecyc, context); | 358 render_sprite_cells( context); |
349 context->sprite_index = 0x80; | 359 context->sprite_index = 0x80; |
350 context->slot_counter = MAX_SPRITES_LINE; | 360 context->slot_counter = MAX_SPRITES_LINE; |
351 scan_sprite_table(line, context); | 361 scan_sprite_table(line, context); |
352 break; | 362 break; |
353 case 5: | 363 case 5: |
367 case 19: | 377 case 19: |
368 case 20: | 378 case 20: |
369 //!HSYNC asserted | 379 //!HSYNC asserted |
370 case 21: | 380 case 21: |
371 case 22: | 381 case 22: |
372 render_sprite_cells(linecyc, context); | 382 render_sprite_cells(context); |
373 scan_sprite_table(line, context); | 383 scan_sprite_table(line, context); |
374 break; | 384 break; |
375 case 23: | 385 case 23: |
376 external_slot(context); | 386 external_slot(context); |
377 break; | 387 break; |
384 case 30: | 394 case 30: |
385 case 31: | 395 case 31: |
386 case 32: | 396 case 32: |
387 case 33: | 397 case 33: |
388 case 34: | 398 case 34: |
389 render_sprite_cells(linecyc, context); | 399 render_sprite_cells(context); |
390 scan_sprite_table(line, context); | 400 scan_sprite_table(line, context); |
391 break; | 401 break; |
392 case 35: | 402 case 35: |
393 address = (context->regs[REG_HSCROLL] & 0x3F) << 10; | 403 address = (context->regs[REG_HSCROLL] & 0x3F) << 10; |
394 mask = 0; | 404 mask = 0; |
407 case 36: | 417 case 36: |
408 //!HSYNC high | 418 //!HSYNC high |
409 case 37: | 419 case 37: |
410 case 38: | 420 case 38: |
411 case 39: | 421 case 39: |
412 render_sprite_cells(linecyc, context); | 422 render_sprite_cells(context); |
413 scan_sprite_table(line, context); | 423 scan_sprite_table(line, context); |
414 break; | 424 break; |
415 case 40: | 425 case 40: |
416 read_map_scroll_a(0, line, context); | 426 read_map_scroll_a(0, line, context); |
417 break; | 427 break; |
418 case 41: | 428 case 41: |
419 render_sprite_cells(linecyc, context); | 429 render_sprite_cells(context); |
420 scan_sprite_table(line, context); | 430 scan_sprite_table(line, context); |
421 break; | 431 break; |
422 case 42: | 432 case 42: |
423 render_map_1(context); | 433 render_map_1(context); |
424 scan_sprite_table(line, context);//Just a guess | 434 scan_sprite_table(line, context);//Just a guess |
429 break; | 439 break; |
430 case 44: | 440 case 44: |
431 read_map_scroll_b(0, line, context); | 441 read_map_scroll_b(0, line, context); |
432 break; | 442 break; |
433 case 45: | 443 case 45: |
434 render_sprite_cells(linecyc, context); | 444 render_sprite_cells(context); |
435 scan_sprite_table(line, context); | 445 scan_sprite_table(line, context); |
436 break; | 446 break; |
437 case 46: | 447 case 46: |
438 render_map_3(context); | 448 render_map_3(context); |
439 scan_sprite_table(line, context);//Just a guess | 449 scan_sprite_table(line, context);//Just a guess |
441 case 47: | 451 case 47: |
442 render_map_output(line, 0, context); | 452 render_map_output(line, 0, context); |
443 scan_sprite_table(line, context);//Just a guess | 453 scan_sprite_table(line, context);//Just a guess |
444 //reverse context slot counter so it counts the number of sprite slots | 454 //reverse context slot counter so it counts the number of sprite slots |
445 //filled rather than the number of available slots | 455 //filled rather than the number of available slots |
446 context->slot_counter = MAX_SPRITES_LINE - context->slot_counter; | 456 //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter; |
457 context->cur_slot = MAX_SPRITES_LINE-1; | |
447 context->sprite_draws = MAX_DRAWS; | 458 context->sprite_draws = MAX_DRAWS; |
448 break; | 459 break; |
449 COLUMN_RENDER_BLOCK(2, 48) | 460 COLUMN_RENDER_BLOCK(2, 48) |
450 COLUMN_RENDER_BLOCK(4, 56) | 461 COLUMN_RENDER_BLOCK(4, 56) |
451 COLUMN_RENDER_BLOCK(6, 64) | 462 COLUMN_RENDER_BLOCK(6, 64) |