diff options
author | Michael Pavone <pavone@retrodev.com> | 2016-04-30 15:31:48 -0700 |
---|---|---|
committer | Michael Pavone <pavone@retrodev.com> | 2016-04-30 15:31:48 -0700 |
commit | 020f7a650838ab52be6113232b70e012a73f5c81 (patch) | |
tree | b415bcd8ce7e3d61403ec5010b90bd6323d808c8 /vdp.c | |
parent | f57bfb8aede525c24315b7dd07b8291795b8b547 (diff) |
Implement SAT cache. Causes some graphical corruption in Overdrive due to an unrelated bug.
Diffstat (limited to 'vdp.c')
-rw-r--r-- | vdp.c | 57 |
1 files changed, 38 insertions, 19 deletions
@@ -210,11 +210,12 @@ void vdp_print_sprite_table(vdp_context * context) uint8_t count = 0; do { uint16_t address = current_index * 8 + sat_address; - uint8_t height = ((context->vdpmem[address+2] & 0x3) + 1) * 8; - uint8_t width = (((context->vdpmem[address+2] >> 2) & 0x3) + 1) * 8; - int16_t y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) & 0x1FF; + uint16_t cache_address = current_index * 4; + uint8_t height = ((context->sat_cache[cache_address+2] & 0x3) + 1) * 8; + uint8_t width = (((context->sat_cache[cache_address+2] >> 2) & 0x3) + 1) * 8; + int16_t y = ((context->sat_cache[cache_address] & 0x3) << 8 | context->sat_cache[cache_address+1]) & 0x1FF; int16_t x = ((context->vdpmem[address+ 6] & 0x3) << 8 | context->vdpmem[address + 7]) & 0x1FF; - uint16_t link = context->vdpmem[address+3] & 0x7F; + uint16_t link = context->sat_cache[cache_address+3] & 0x7F; uint8_t pal = context->vdpmem[address + 4] >> 5 & 0x3; uint8_t pri = context->vdpmem[address + 4] >> 7; uint16_t pattern = ((context->vdpmem[address + 4] << 8 | context->vdpmem[address + 5]) & 0x7FF) << 5; @@ -374,33 +375,40 @@ void scan_sprite_table(uint32_t line, vdp_context * context) context->sprite_index = 0; return; } - //TODO: Read from SAT cache rather than from VRAM - uint16_t sat_address = (context->regs[REG_SAT] & 0x7F) << 9; - uint16_t address = context->sprite_index * 8 + sat_address; + uint16_t address = context->sprite_index * 4; line += ymin; - uint16_t y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) & ymask; - uint8_t height = ((context->vdpmem[address+2] & 0x3) + 1) * height_mult; + uint16_t y = ((context->sat_cache[address] & 0x3) << 8 | context->sat_cache[address+1]) & ymask; + uint8_t height = ((context->sat_cache[address+2] & 0x3) + 1) * height_mult; //printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height); if (y <= line && line < (y + height)) { //printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line); - context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2]; + context->sprite_info_list[--(context->slot_counter)].size = context->sat_cache[address+2]; context->sprite_info_list[context->slot_counter].index = context->sprite_index; context->sprite_info_list[context->slot_counter].y = y-ymin; } - context->sprite_index = context->vdpmem[address+3] & 0x7F; + context->sprite_index = context->sat_cache[address+3] & 0x7F; if (context->sprite_index && context->slot_counter) { - address = context->sprite_index * 8 + sat_address; - y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) & ymask; - height = ((context->vdpmem[address+2] & 0x3) + 1) * height_mult; + if (context->regs[REG_MODE_4] & BIT_H40) { + if (context->sprite_index >= MAX_SPRITES_FRAME) { + context->sprite_index = 0; + return; + } + } else if(context->sprite_index >= MAX_SPRITES_FRAME_H32) { + context->sprite_index = 0; + return; + } + address = context->sprite_index * 4; + y = ((context->sat_cache[address] & 0x3) << 8 | context->sat_cache[address+1]) & ymask; + height = ((context->sat_cache[address+2] & 0x3) + 1) * height_mult; //printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height); if (y <= line && line < (y + height)) { //printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line); - context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2]; + context->sprite_info_list[--(context->slot_counter)].size = context->sat_cache[address+2]; context->sprite_info_list[context->slot_counter].index = context->sprite_index; context->sprite_info_list[context->slot_counter].y = y-ymin; } - context->sprite_index = context->vdpmem[address+3] & 0x7F; + context->sprite_index = context->sat_cache[address+3] & 0x7F; } } } @@ -509,6 +517,17 @@ void vdp_advance_dma(vdp_context * context) } } +void write_vram_byte(vdp_context *context, uint16_t address, uint8_t value) +{ + if (!(address & 4)) { + uint16_t sat_address = (context->regs[REG_SAT] & 0x7F) << 9; + if(address >= sat_address && address <= sat_address + SAT_CACHE_SIZE*2) { + context->sat_cache[(address & 3) | (address >> 1 & 0x1FC)] = value; + } + } + context->vdpmem[address] = value; +} + void external_slot(vdp_context * context) { if ((context->flags & FLAG_DMA_RUN) && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80 && context->fifo_read < 0) { @@ -526,10 +545,10 @@ void external_slot(vdp_context * context) case VRAM_WRITE: if (start->partial) { //printf("VRAM Write: %X to %X at %d (line %d, slot %d)\n", start->value, start->address ^ 1, context->cycles, context->cycles/MCLKS_LINE, (context->cycles%MCLKS_LINE)/16); - context->vdpmem[start->address ^ 1] = start->partial == 2 ? start->value >> 8 : start->value; + write_vram_byte(context, start->address ^ 1, start->partial == 2 ? start->value >> 8 : start->value); } else { //printf("VRAM Write High: %X to %X at %d (line %d, slot %d)\n", start->value >> 8, start->address, context->cycles, context->cycles/MCLKS_LINE, (context->cycles%MCLKS_LINE)/16); - context->vdpmem[start->address] = start->value >> 8; + write_vram_byte(context, start->address, start->value >> 8); start->partial = 1; //skip auto-increment and removal of entry from fifo return; @@ -557,7 +576,7 @@ void external_slot(vdp_context * context) } } else if ((context->flags & FLAG_DMA_RUN) && (context->regs[REG_DMASRC_H] & 0xC0) == 0xC0) { if (context->flags & FLAG_READ_FETCHED) { - context->vdpmem[context->address ^ 1] = context->prefetch; + write_vram_byte(context, context->address ^ 1, context->prefetch); //Update DMA state vdp_advance_dma(context); |