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;