static INLINE void ChRW(int32 timestamp, uint32 *V) { switch(ch) { default: abort(); case CH_MDEC_IN: MDEC_DMAWrite(*V); break; case CH_MDEC_OUT: *V = MDEC_DMARead(); break; case CH_GPU: if(write_mode) GPU->WriteDMA(*V); else *V = GPU->Read(timestamp, 0); break; case CH_CDC: // 0x1f801018 affects CDC DMA timing. #if 0 if(DMACH[ch].ChanControl & 0x100) // For CDC DMA(at least): When this bit is set, DMA controller doesn't appear to hog the (RAM?) bus. { if(DMACH[ch].ChanControl & 0x00400000) // For CDC DMA(at least): When this bit is set, DMA controller appears to get even less bus time(or has a lower priority??) { DMACH[ch].ClockCounter -= 44 * 20 / 12; } else { DMACH[ch].ClockCounter -= 29 * 20 / 12; } } else { DMACH[ch].ClockCounter -= 23 * 20 / 12; // (23 + 1) = 24. (Though closer to 24.5 or 24.4 on average per tests on a PS1) } #endif *V = CDC->DMARead(); break; case CH_SPU: // 0x1f801014 affects SPU DMA timing. // Wild conjecture about 0x1f801014: // // & 0x0000000F // & 0x000001E0 --- Used if (& 0x20000000) == 0? // & 0x00001000 --- Double total bus cycle time if value == 0? // & 0x0f000000 --- (value << 1) 33MHz cycles, bus cycle extension(added to 4?)? // & 0x20000000 --- // // // TODO?: SPU DMA will "complete" much faster if there's a mismatch between the CHCR read/write mode bit and the SPU control register DMA mode. // // // Investigate: SPU DMA doesn't seem to work right if the value written to 0x1F801DAA doesn't have the upper bit set to 1(0x8000) on a PS1. DMACH[ch].ClockCounter -= 47; // Should be closer to 69, average, but actual timing is...complicated. if(write_mode) SPU->WriteDMA(*V); else *V = SPU->ReadDMA(); break; case CH_OT: if(DMACH[ch].WordCounter == 1) *V = 0xFFFFFF; else *V = (DMACH[ch].CurAddr - 4) & 0x1FFFFF; break; } }
static INLINE void ChRW(const unsigned ch, const uint32_t CRModeCache, uint32_t *V) { unsigned extra_cyc_overhead = 0; switch(ch) { default: abort(); break; case CH_MDEC_IN: if(CRModeCache & 0x1) MDEC_DMAWrite(*V); else *V = 0; break; case CH_MDEC_OUT: if(CRModeCache & 0x1) { } else *V = MDEC_DMARead(); break; case CH_GPU: if(CRModeCache & 0x1) GPU->WriteDMA(*V); else *V = GPU->ReadDMA(); break; case CH_CDC: // 0x1f801018 affects CDC DMA timing. #if 0 if(CRModeCache & 0x100) // For CDC DMA(at least): When this bit is set, DMA controller doesn't appear to hog the (RAM?) bus. { if(CRModeCache & 0x00400000) // For CDC DMA(at least): When this bit is set, DMA controller appears to get even less bus time(or has a lower priority??) { DMACH[ch].ClockCounter -= 44 * 20 / 12; } else { DMACH[ch].ClockCounter -= 29 * 20 / 12; } } else { DMACH[ch].ClockCounter -= 23 * 20 / 12; // (23 + 1) = 24. (Though closer to 24.5 or 24.4 on average per tests on a PS1) } #endif if(CRModeCache & 0x1) { } else { extra_cyc_overhead = 8; // FIXME: Test. *V = CDC->DMARead(); // Note: Legend of Mana's opening movie is sensitive to DMA timing, including CDC. } break; case CH_SPU: // 0x1f801014 affects SPU DMA timing. // Wild conjecture about 0x1f801014: // // & 0x0000000F // & 0x000001E0 --- Used if (& 0x20000000) == 0? // & 0x00001000 --- Double total bus cycle time if value == 0? // & 0x0f000000 --- (value << 1) 33MHz cycles, bus cycle extension(added to 4?)? // & 0x20000000 --- // // // TODO?: SPU DMA will "complete" much faster if there's a mismatch between the CHCR read/write mode bit and the SPU control register DMA mode. // // // Investigate: SPU DMA doesn't seem to work right if the value written to 0x1F801DAA doesn't have the upper bit set to 1(0x8000) on a PS1. extra_cyc_overhead = 47; // Should be closer to 69, average, but actual timing is...complicated. if(CRModeCache & 0x1) SPU->WriteDMA(*V); else *V = SPU->ReadDMA(); break; case CH_FIVE: if(CRModeCache & 0x1) { } else { *V = 0; } break; case CH_OT: if(DMACH[ch].WordCounter == 1) *V = 0xFFFFFF; else *V = (DMACH[ch].CurAddr - 4) & 0x1FFFFF; break; } // GROSS APPROXIMATION, shoehorning multiple effects together, TODO separate(especially SPU and CDC) DMACH[ch].ClockCounter -= std::max<int>(extra_cyc_overhead, (CRModeCache & 0x100) ? 7 : 0); }