X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libpcsxcore%2Fpsxhw.c;h=4811f99babbcbf7e4bf949026f742cd8eca10806;hb=f8896d181bd26ef6fd18af17f01c77b73ae17a68;hp=10a2695f437bd31bcf087f23a957212300451aaf;hpb=906b1599387d4ecbf225282ba5123f83444c88fb;p=pcsx_rearmed.git diff --git a/libpcsxcore/psxhw.c b/libpcsxcore/psxhw.c index 10a2695f..4811f99b 100644 --- a/libpcsxcore/psxhw.c +++ b/libpcsxcore/psxhw.c @@ -22,6 +22,7 @@ */ #include "psxhw.h" +#include "psxevents.h" #include "mdec.h" #include "cdrom.h" #include "gpu.h" @@ -32,13 +33,88 @@ #define PAD_LOG(...) #endif +static u32 (*psxHwReadGpuSRptr)(void) = psxHwReadGpuSR; + void psxHwReset() { memset(psxH, 0, 0x10000); mdecInit(); // initialize mdec decoder cdrReset(); psxRcntInit(); - HW_GPU_STATUS = SWAP32(0x14802000); + HW_GPU_STATUS = SWAP32(0x10802000); + psxHwReadGpuSRptr = Config.hacks.gpu_busy_hack + ? psxHwReadGpuSRbusyHack : psxHwReadGpuSR; +} + +void psxHwWriteIstat(u32 value) +{ + u32 stat = psxHu16(0x1070) & value; + psxHu16ref(0x1070) = SWAPu16(stat); + + psxRegs.CP0.n.Cause &= ~0x400; + if (stat & psxHu16(0x1074)) + psxRegs.CP0.n.Cause |= 0x400; +} + +void psxHwWriteImask(u32 value) +{ + u32 stat = psxHu16(0x1070); + psxHu16ref(0x1074) = SWAPu16(value); + if (stat & value) { + //if ((psxRegs.CP0.n.SR & 0x401) == 0x401) + // log_unhandled("irq on unmask @%08x\n", psxRegs.pc); + set_event(PSXINT_NEWDRC_CHECK, 1); + } + psxRegs.CP0.n.Cause &= ~0x400; + if (stat & value) + psxRegs.CP0.n.Cause |= 0x400; +} + +void psxHwWriteDmaIcr32(u32 value) +{ + u32 tmp = value & 0x00ff803f; + tmp |= (SWAPu32(HW_DMA_ICR) & ~value) & 0x7f000000; + if ((tmp & HW_DMA_ICR_GLOBAL_ENABLE && tmp & 0x7f000000) + || tmp & HW_DMA_ICR_BUS_ERROR) { + if (!(SWAPu32(HW_DMA_ICR) & HW_DMA_ICR_IRQ_SENT)) + psxHu32ref(0x1070) |= SWAP32(8); + tmp |= HW_DMA_ICR_IRQ_SENT; + } + HW_DMA_ICR = SWAPu32(tmp); +} + +void psxHwWriteGpuSR(u32 value) +{ + GPU_writeStatus(value); + gpuSyncPluginSR(); +} + +u32 psxHwReadGpuSR(void) +{ + u32 v, c = psxRegs.cycle; + + // meh2, syncing for img bit, might want to avoid it.. + gpuSyncPluginSR(); + v = SWAP32(HW_GPU_STATUS); + v |= ((s32)(psxRegs.gpuIdleAfter - c) >> 31) & PSXGPU_nBUSY; + + // XXX: because of large timeslices can't use hSyncCount, using rough + // approximization instead. Perhaps better use hcounter code here or something. + if (hSyncCount < 240 && (v & PSXGPU_ILACE_BITS) != PSXGPU_ILACE_BITS) + v |= PSXGPU_LCF & (c << 20); + return v; +} + +// a hack due to poor timing of gpu idle bit +// to get rid of this, GPU draw times, DMAs, cpu timing has to fall within +// certain timing window or else games like "ToHeart" softlock +u32 psxHwReadGpuSRbusyHack(void) +{ + u32 v = psxHwReadGpuSR(); + static u32 hack; + if (!(hack++ & 3)) + v &= ~PSXGPU_nBUSY; + return v; } u8 psxHwRead8(u32 add) { @@ -83,8 +159,11 @@ u8 psxHwRead8(u32 add) { log_unhandled("unhandled r8 %08x @%08x\n", add, psxRegs.pc); // falthrough default: - if (0x1f801c00 <= add && add < 0x1f802000) - log_unhandled("spu r8 %02x @%08x\n", add, psxRegs.pc); + if (0x1f801c00 <= add && add < 0x1f802000) { + u16 val = SPU_readRegister(add & ~1, psxRegs.cycle); + hard = (add & 1) ? val >> 8 : val; + break; + } hard = psxHu8(add); #ifdef PSXHW_LOG PSXHW_LOG("*Unkwnown 8bit read at address %x\n", add); @@ -138,7 +217,7 @@ u16 psxHwRead16(u32 add) { return 0x80; case 0x1f801100: - hard = psxRcntRcount(0); + hard = psxRcntRcount0(); #ifdef PSXHW_LOG PSXHW_LOG("T0 count read16: %x\n", hard); #endif @@ -156,7 +235,7 @@ u16 psxHwRead16(u32 add) { #endif return hard; case 0x1f801110: - hard = psxRcntRcount(1); + hard = psxRcntRcount1(); #ifdef PSXHW_LOG PSXHW_LOG("T1 count read16: %x\n", hard); #endif @@ -174,7 +253,7 @@ u16 psxHwRead16(u32 add) { #endif return hard; case 0x1f801120: - hard = psxRcntRcount(2); + hard = psxRcntRcount2(); #ifdef PSXHW_LOG PSXHW_LOG("T2 count read16: %x\n", hard); #endif @@ -216,7 +295,7 @@ u16 psxHwRead16(u32 add) { // falthrough default: if (0x1f801c00 <= add && add < 0x1f802000) - return SPU_readRegister(add); + return SPU_readRegister(add, psxRegs.cycle); hard = psxHu16(add); #ifdef PSXHW_LOG PSXHW_LOG("*Unkwnown 16bit read at address %x\n", add); @@ -262,10 +341,7 @@ u32 psxHwRead32(u32 add) { #endif return hard; case 0x1f801814: - gpuSyncPluginSR(); - hard = SWAP32(HW_GPU_STATUS); - if (hSyncCount < 240 && (hard & PSXGPU_ILACE_BITS) != PSXGPU_ILACE_BITS) - hard |= PSXGPU_LCF & (psxRegs.cycle << 20); + hard = psxHwReadGpuSRptr(); #ifdef PSXHW_LOG PSXHW_LOG("GPU STATUS 32bit read %x\n", hard); #endif @@ -309,7 +385,7 @@ u32 psxHwRead32(u32 add) { // time for rootcounters :) case 0x1f801100: - hard = psxRcntRcount(0); + hard = psxRcntRcount0(); #ifdef PSXHW_LOG PSXHW_LOG("T0 count read32: %x\n", hard); #endif @@ -327,7 +403,7 @@ u32 psxHwRead32(u32 add) { #endif return hard; case 0x1f801110: - hard = psxRcntRcount(1); + hard = psxRcntRcount1(); #ifdef PSXHW_LOG PSXHW_LOG("T1 count read32: %x\n", hard); #endif @@ -345,7 +421,7 @@ u32 psxHwRead32(u32 add) { #endif return hard; case 0x1f801120: - hard = psxRcntRcount(2); + hard = psxRcntRcount2(); #ifdef PSXHW_LOG PSXHW_LOG("T2 count read32: %x\n", hard); #endif @@ -374,8 +450,8 @@ u32 psxHwRead32(u32 add) { // falthrough default: if (0x1f801c00 <= add && add < 0x1f802000) { - hard = SPU_readRegister(add); - hard |= SPU_readRegister(add + 2) << 16; + hard = SPU_readRegister(add, psxRegs.cycle); + hard |= SPU_readRegister(add + 2, psxRegs.cycle) << 16; return hard; } hard = psxHu32(add); @@ -476,19 +552,14 @@ void psxHwWrite16(u32 add, u16 value) { #ifdef PSXHW_LOG PSXHW_LOG("IREG 16bit write %x\n", value); #endif - psxHu16ref(0x1070) &= SWAPu16(value); + psxHwWriteIstat(value); return; case 0x1f801074: #ifdef PSXHW_LOG PSXHW_LOG("IMASK 16bit write %x\n", value); #endif - psxHu16ref(0x1074) = SWAPu16(value); - if (psxHu16ref(0x1070) & SWAPu16(value)) { - //if ((psxRegs.CP0.n.SR & 0x401) == 0x401) - // log_unhandled("irq on unmask @%08x\n", psxRegs.pc); - new_dyna_set_event(PSXINT_NEWDRC_CHECK, 1); - } + psxHwWriteImask(value); return; case 0x1f801100: @@ -607,18 +678,13 @@ void psxHwWrite32(u32 add, u32 value) { #ifdef PSXHW_LOG PSXHW_LOG("IREG 32bit write %x\n", value); #endif - psxHu32ref(0x1070) &= SWAPu32(value); + psxHwWriteIstat(value); return; case 0x1f801074: #ifdef PSXHW_LOG PSXHW_LOG("IMASK 32bit write %x\n", value); #endif - psxHu32ref(0x1074) = SWAPu32(value); - if (psxHu32ref(0x1070) & SWAPu32(value)) { - if ((psxRegs.CP0.n.SR & 0x401) == 0x401) - log_unhandled("irq on unmask @%08x\n", psxRegs.pc); - new_dyna_set_event(PSXINT_NEWDRC_CHECK, 1); - } + psxHwWriteImask(value); return; #ifdef PSXHW_LOG @@ -729,18 +795,8 @@ void psxHwWrite32(u32 add, u32 value) { #ifdef PSXHW_LOG PSXHW_LOG("DMA ICR 32bit write %x\n", value); #endif - { - u32 tmp = value & 0x00ff803f; - tmp |= (SWAPu32(HW_DMA_ICR) & ~value) & 0x7f000000; - if ((tmp & HW_DMA_ICR_GLOBAL_ENABLE && tmp & 0x7f000000) - || tmp & HW_DMA_ICR_BUS_ERROR) { - if (!(SWAPu32(HW_DMA_ICR) & HW_DMA_ICR_IRQ_SENT)) - psxHu32ref(0x1070) |= SWAP32(8); - tmp |= HW_DMA_ICR_IRQ_SENT; - } - HW_DMA_ICR = SWAPu32(tmp); + psxHwWriteDmaIcr32(value); return; - } case 0x1f801810: #ifdef PSXHW_LOG @@ -751,8 +807,7 @@ void psxHwWrite32(u32 add, u32 value) { #ifdef PSXHW_LOG PSXHW_LOG("GPU STATUS 32bit write %x\n", value); #endif - GPU_writeStatus(value); - gpuSyncPluginSR(); + psxHwWriteGpuSR(value); return; case 0x1f801820: