Mercurial > repos > blastem
comparison vdp.c @ 34:0e7df84158b1
Improve sprite masking to almost completely pass Nemesis' sprite masking test
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 08 Dec 2012 22:50:14 -0800 |
parents | 8602ad493794 |
children | 233c7737c152 |
comparison
equal
deleted
inserted
replaced
33:2e15fa26fe58 | 34:0e7df84158b1 |
---|---|
86 context->sprite_index = context->vdpmem[address+3] & 0x7F; | 86 context->sprite_index = context->vdpmem[address+3] & 0x7F; |
87 } | 87 } |
88 } | 88 } |
89 } | 89 } |
90 | 90 |
91 #define FLAG_DOT_OFLOW 0x1 | |
92 #define FLAG_CAN_MASK 0x2 | |
91 void read_sprite_x(uint32_t line, vdp_context * context) | 93 void read_sprite_x(uint32_t line, vdp_context * context) |
92 { | 94 { |
93 if ((context->cur_slot >= context->slot_counter) && context->sprite_draws) { | 95 if (context->cur_slot >= context->slot_counter) { |
94 line += 1; | 96 if (context->sprite_draws) { |
95 line &= 0xFF; | 97 line += 1; |
96 //in tiles | 98 line &= 0xFF; |
97 uint8_t width = ((context->sprite_info_list[context->cur_slot].size >> 2) & 0x3) + 1; | 99 //in tiles |
98 //in pixels | 100 uint8_t width = ((context->sprite_info_list[context->cur_slot].size >> 2) & 0x3) + 1; |
99 uint8_t height = ((context->sprite_info_list[context->cur_slot].size & 0x3) + 1) * 8; | 101 //in pixels |
100 uint16_t att_addr = ((context->regs[REG_SAT] & 0x7F) << 9) + context->sprite_info_list[context->cur_slot].index * 8 + 4; | 102 uint8_t height = ((context->sprite_info_list[context->cur_slot].size & 0x3) + 1) * 8; |
101 uint16_t tileinfo = (context->vdpmem[att_addr] << 8) | context->vdpmem[att_addr+1]; | 103 uint16_t att_addr = ((context->regs[REG_SAT] & 0x7F) << 9) + context->sprite_info_list[context->cur_slot].index * 8 + 4; |
102 uint8_t pal_priority = (tileinfo >> 9) & 0x70; | 104 uint16_t tileinfo = (context->vdpmem[att_addr] << 8) | context->vdpmem[att_addr+1]; |
103 uint8_t row; | 105 uint8_t pal_priority = (tileinfo >> 9) & 0x70; |
104 if (tileinfo & MAP_BIT_V_FLIP) { | 106 uint8_t row; |
105 row = (context->sprite_info_list[context->cur_slot].y + height - 1) - line; | 107 if (tileinfo & MAP_BIT_V_FLIP) { |
108 row = (context->sprite_info_list[context->cur_slot].y + height - 1) - line; | |
109 } else { | |
110 row = line-context->sprite_info_list[context->cur_slot].y; | |
111 } | |
112 //uint16_t address = ((tileinfo & 0x7FF) << 5) + (row & 0x7) * 4 + (row & 0x18) * width * 4; | |
113 uint16_t address = ((tileinfo & 0x7FF) << 5) + row * 4; | |
114 int16_t x = ((context->vdpmem[att_addr+ 2] & 0x3) << 8) | context->vdpmem[att_addr + 3]; | |
115 if (x || !(context->flags & (FLAG_CAN_MASK | FLAG_DOT_OFLOW))) { | |
116 //printf("Displaying %d | line: %d, x: %d, flags: %X\n", context->sprite_info_list[context->cur_slot].index, line, x, context->flags); | |
117 if (x) { | |
118 context->flags |= FLAG_CAN_MASK; | |
119 } | |
120 context->flags &= ~FLAG_DOT_OFLOW; | |
121 x -= 128; | |
122 int16_t base_x = x; | |
123 int16_t dir; | |
124 if (tileinfo & MAP_BIT_H_FLIP) { | |
125 x += (width-1) * 8; | |
126 dir = -8; | |
127 } else { | |
128 dir = 8; | |
129 } | |
130 //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); | |
131 for (int16_t i=0; i < width && context->sprite_draws; i++, x += dir) { | |
132 --context->sprite_draws; | |
133 context->sprite_draw_list[context->sprite_draws].address = address + i * height * 4; | |
134 context->sprite_draw_list[context->sprite_draws].x_pos = x; | |
135 context->sprite_draw_list[context->sprite_draws].pal_priority = pal_priority; | |
136 context->sprite_draw_list[context->sprite_draws].h_flip = (tileinfo & MAP_BIT_H_FLIP) ? 1 : 0; | |
137 } | |
138 context->cur_slot--; | |
139 } else { | |
140 //printf("Masking %d | line: %d, x: %d, flags: %X\n", context->sprite_info_list[context->cur_slot].index, line, x, context->flags); | |
141 //sprite masking enabled, no more sprites on this line | |
142 context->cur_slot = -1; | |
143 } | |
106 } else { | 144 } else { |
107 row = line-context->sprite_info_list[context->cur_slot].y; | 145 context->flags |= FLAG_DOT_OFLOW; |
108 } | |
109 //uint16_t address = ((tileinfo & 0x7FF) << 5) + (row & 0x7) * 4 + (row & 0x18) * width * 4; | |
110 uint16_t address = ((tileinfo & 0x7FF) << 5) + row * 4; | |
111 int16_t x = ((context->vdpmem[att_addr+ 2] & 0x3) << 8) | context->vdpmem[att_addr + 3]; | |
112 if (x) { | |
113 x -= 128; | |
114 int16_t base_x = x; | |
115 int16_t dir; | |
116 if (tileinfo & MAP_BIT_H_FLIP) { | |
117 x += (width-1) * 8; | |
118 dir = -8; | |
119 } else { | |
120 dir = 8; | |
121 } | |
122 //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); | |
123 for (int16_t i=0; i < width && context->sprite_draws; i++, x += dir) { | |
124 --context->sprite_draws; | |
125 context->sprite_draw_list[context->sprite_draws].address = address + i * height * 4; | |
126 context->sprite_draw_list[context->sprite_draws].x_pos = x; | |
127 context->sprite_draw_list[context->sprite_draws].pal_priority = pal_priority; | |
128 context->sprite_draw_list[context->sprite_draws].h_flip = (tileinfo & MAP_BIT_H_FLIP) ? 1 : 0; | |
129 } | |
130 context->cur_slot--; | |
131 } else { | |
132 //sprite masking enabled, no more sprites on this line | |
133 context->cur_slot = -1; | |
134 } | 146 } |
135 } | 147 } |
136 } | 148 } |
137 | 149 |
138 void external_slot(vdp_context * context) | 150 void external_slot(vdp_context * context) |
468 //reverse context slot counter so it counts the number of sprite slots | 480 //reverse context slot counter so it counts the number of sprite slots |
469 //filled rather than the number of available slots | 481 //filled rather than the number of available slots |
470 //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter; | 482 //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter; |
471 context->cur_slot = MAX_SPRITES_LINE-1; | 483 context->cur_slot = MAX_SPRITES_LINE-1; |
472 context->sprite_draws = MAX_DRAWS; | 484 context->sprite_draws = MAX_DRAWS; |
485 context->flags &= ~FLAG_CAN_MASK; | |
473 break; | 486 break; |
474 COLUMN_RENDER_BLOCK(2, 48) | 487 COLUMN_RENDER_BLOCK(2, 48) |
475 COLUMN_RENDER_BLOCK(4, 56) | 488 COLUMN_RENDER_BLOCK(4, 56) |
476 COLUMN_RENDER_BLOCK(6, 64) | 489 COLUMN_RENDER_BLOCK(6, 64) |
477 COLUMN_RENDER_BLOCK_REFRESH(8, 72) | 490 COLUMN_RENDER_BLOCK_REFRESH(8, 72) |