Mercurial > repos > blastem
comparison vdp.c @ 998:bf63cbf1d7bb
Implement SAT cache. Causes some graphical corruption in Overdrive due to an unrelated bug.
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 30 Apr 2016 15:31:48 -0700 |
parents | 2bc27415565b |
children | 238141756e67 |
comparison
equal
deleted
inserted
replaced
997:560da2e455c2 | 998:bf63cbf1d7bb |
---|---|
208 uint16_t sat_address = (context->regs[REG_SAT] & 0x7F) << 9; | 208 uint16_t sat_address = (context->regs[REG_SAT] & 0x7F) << 9; |
209 uint16_t current_index = 0; | 209 uint16_t current_index = 0; |
210 uint8_t count = 0; | 210 uint8_t count = 0; |
211 do { | 211 do { |
212 uint16_t address = current_index * 8 + sat_address; | 212 uint16_t address = current_index * 8 + sat_address; |
213 uint8_t height = ((context->vdpmem[address+2] & 0x3) + 1) * 8; | 213 uint16_t cache_address = current_index * 4; |
214 uint8_t width = (((context->vdpmem[address+2] >> 2) & 0x3) + 1) * 8; | 214 uint8_t height = ((context->sat_cache[cache_address+2] & 0x3) + 1) * 8; |
215 int16_t y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) & 0x1FF; | 215 uint8_t width = (((context->sat_cache[cache_address+2] >> 2) & 0x3) + 1) * 8; |
216 int16_t y = ((context->sat_cache[cache_address] & 0x3) << 8 | context->sat_cache[cache_address+1]) & 0x1FF; | |
216 int16_t x = ((context->vdpmem[address+ 6] & 0x3) << 8 | context->vdpmem[address + 7]) & 0x1FF; | 217 int16_t x = ((context->vdpmem[address+ 6] & 0x3) << 8 | context->vdpmem[address + 7]) & 0x1FF; |
217 uint16_t link = context->vdpmem[address+3] & 0x7F; | 218 uint16_t link = context->sat_cache[cache_address+3] & 0x7F; |
218 uint8_t pal = context->vdpmem[address + 4] >> 5 & 0x3; | 219 uint8_t pal = context->vdpmem[address + 4] >> 5 & 0x3; |
219 uint8_t pri = context->vdpmem[address + 4] >> 7; | 220 uint8_t pri = context->vdpmem[address + 4] >> 7; |
220 uint16_t pattern = ((context->vdpmem[address + 4] << 8 | context->vdpmem[address + 5]) & 0x7FF) << 5; | 221 uint16_t pattern = ((context->vdpmem[address + 4] << 8 | context->vdpmem[address + 5]) & 0x7FF) << 5; |
221 printf("Sprite %d: X=%d(%d), Y=%d(%d), Width=%u, Height=%u, Link=%u, Pal=%u, Pri=%u, Pat=%X\n", current_index, x, x-128, y, y-128, width, height, link, pal, pri, pattern); | 222 printf("Sprite %d: X=%d(%d), Y=%d(%d), Width=%u, Height=%u, Link=%u, Pal=%u, Pri=%u, Pat=%X\n", current_index, x, x-128, y, y-128, width, height, link, pal, pri, pattern); |
222 current_index = link; | 223 current_index = link; |
372 } | 373 } |
373 } else if(context->sprite_index >= MAX_SPRITES_FRAME_H32) { | 374 } else if(context->sprite_index >= MAX_SPRITES_FRAME_H32) { |
374 context->sprite_index = 0; | 375 context->sprite_index = 0; |
375 return; | 376 return; |
376 } | 377 } |
377 //TODO: Read from SAT cache rather than from VRAM | 378 uint16_t address = context->sprite_index * 4; |
378 uint16_t sat_address = (context->regs[REG_SAT] & 0x7F) << 9; | |
379 uint16_t address = context->sprite_index * 8 + sat_address; | |
380 line += ymin; | 379 line += ymin; |
381 uint16_t y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) & ymask; | 380 uint16_t y = ((context->sat_cache[address] & 0x3) << 8 | context->sat_cache[address+1]) & ymask; |
382 uint8_t height = ((context->vdpmem[address+2] & 0x3) + 1) * height_mult; | 381 uint8_t height = ((context->sat_cache[address+2] & 0x3) + 1) * height_mult; |
383 //printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height); | 382 //printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height); |
384 if (y <= line && line < (y + height)) { | 383 if (y <= line && line < (y + height)) { |
385 //printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line); | 384 //printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line); |
386 context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2]; | 385 context->sprite_info_list[--(context->slot_counter)].size = context->sat_cache[address+2]; |
387 context->sprite_info_list[context->slot_counter].index = context->sprite_index; | 386 context->sprite_info_list[context->slot_counter].index = context->sprite_index; |
388 context->sprite_info_list[context->slot_counter].y = y-ymin; | 387 context->sprite_info_list[context->slot_counter].y = y-ymin; |
389 } | 388 } |
390 context->sprite_index = context->vdpmem[address+3] & 0x7F; | 389 context->sprite_index = context->sat_cache[address+3] & 0x7F; |
391 if (context->sprite_index && context->slot_counter) | 390 if (context->sprite_index && context->slot_counter) |
392 { | 391 { |
393 address = context->sprite_index * 8 + sat_address; | 392 if (context->regs[REG_MODE_4] & BIT_H40) { |
394 y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) & ymask; | 393 if (context->sprite_index >= MAX_SPRITES_FRAME) { |
395 height = ((context->vdpmem[address+2] & 0x3) + 1) * height_mult; | 394 context->sprite_index = 0; |
395 return; | |
396 } | |
397 } else if(context->sprite_index >= MAX_SPRITES_FRAME_H32) { | |
398 context->sprite_index = 0; | |
399 return; | |
400 } | |
401 address = context->sprite_index * 4; | |
402 y = ((context->sat_cache[address] & 0x3) << 8 | context->sat_cache[address+1]) & ymask; | |
403 height = ((context->sat_cache[address+2] & 0x3) + 1) * height_mult; | |
396 //printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height); | 404 //printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height); |
397 if (y <= line && line < (y + height)) { | 405 if (y <= line && line < (y + height)) { |
398 //printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line); | 406 //printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line); |
399 context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2]; | 407 context->sprite_info_list[--(context->slot_counter)].size = context->sat_cache[address+2]; |
400 context->sprite_info_list[context->slot_counter].index = context->sprite_index; | 408 context->sprite_info_list[context->slot_counter].index = context->sprite_index; |
401 context->sprite_info_list[context->slot_counter].y = y-ymin; | 409 context->sprite_info_list[context->slot_counter].y = y-ymin; |
402 } | 410 } |
403 context->sprite_index = context->vdpmem[address+3] & 0x7F; | 411 context->sprite_index = context->sat_cache[address+3] & 0x7F; |
404 } | 412 } |
405 } | 413 } |
406 } | 414 } |
407 | 415 |
408 void read_sprite_x(uint32_t line, vdp_context * context) | 416 void read_sprite_x(uint32_t line, vdp_context * context) |
507 context->flags &= ~FLAG_DMA_RUN; | 515 context->flags &= ~FLAG_DMA_RUN; |
508 context->cd &= 0xF; | 516 context->cd &= 0xF; |
509 } | 517 } |
510 } | 518 } |
511 | 519 |
520 void write_vram_byte(vdp_context *context, uint16_t address, uint8_t value) | |
521 { | |
522 if (!(address & 4)) { | |
523 uint16_t sat_address = (context->regs[REG_SAT] & 0x7F) << 9; | |
524 if(address >= sat_address && address <= sat_address + SAT_CACHE_SIZE*2) { | |
525 context->sat_cache[(address & 3) | (address >> 1 & 0x1FC)] = value; | |
526 } | |
527 } | |
528 context->vdpmem[address] = value; | |
529 } | |
530 | |
512 void external_slot(vdp_context * context) | 531 void external_slot(vdp_context * context) |
513 { | 532 { |
514 if ((context->flags & FLAG_DMA_RUN) && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80 && context->fifo_read < 0) { | 533 if ((context->flags & FLAG_DMA_RUN) && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80 && context->fifo_read < 0) { |
515 context->fifo_read = (context->fifo_write-1) & (FIFO_SIZE-1); | 534 context->fifo_read = (context->fifo_write-1) & (FIFO_SIZE-1); |
516 fifo_entry * cur = context->fifo + context->fifo_read; | 535 fifo_entry * cur = context->fifo + context->fifo_read; |
524 switch (start->cd & 0xF) | 543 switch (start->cd & 0xF) |
525 { | 544 { |
526 case VRAM_WRITE: | 545 case VRAM_WRITE: |
527 if (start->partial) { | 546 if (start->partial) { |
528 //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); | 547 //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); |
529 context->vdpmem[start->address ^ 1] = start->partial == 2 ? start->value >> 8 : start->value; | 548 write_vram_byte(context, start->address ^ 1, start->partial == 2 ? start->value >> 8 : start->value); |
530 } else { | 549 } else { |
531 //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); | 550 //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); |
532 context->vdpmem[start->address] = start->value >> 8; | 551 write_vram_byte(context, start->address, start->value >> 8); |
533 start->partial = 1; | 552 start->partial = 1; |
534 //skip auto-increment and removal of entry from fifo | 553 //skip auto-increment and removal of entry from fifo |
535 return; | 554 return; |
536 } | 555 } |
537 break; | 556 break; |
555 } | 574 } |
556 context->fifo_read = -1; | 575 context->fifo_read = -1; |
557 } | 576 } |
558 } else if ((context->flags & FLAG_DMA_RUN) && (context->regs[REG_DMASRC_H] & 0xC0) == 0xC0) { | 577 } else if ((context->flags & FLAG_DMA_RUN) && (context->regs[REG_DMASRC_H] & 0xC0) == 0xC0) { |
559 if (context->flags & FLAG_READ_FETCHED) { | 578 if (context->flags & FLAG_READ_FETCHED) { |
560 context->vdpmem[context->address ^ 1] = context->prefetch; | 579 write_vram_byte(context, context->address ^ 1, context->prefetch); |
561 | 580 |
562 //Update DMA state | 581 //Update DMA state |
563 vdp_advance_dma(context); | 582 vdp_advance_dma(context); |
564 | 583 |
565 context->flags &= ~FLAG_READ_FETCHED; | 584 context->flags &= ~FLAG_READ_FETCHED; |