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)