Skip to content

Commit

Permalink
rework gpu busy timing
Browse files Browse the repository at this point in the history
previous implementation caused complications with dynarecs
  • Loading branch information
notaz committed Oct 16, 2023
1 parent 7da5c7a commit f8896d1
Show file tree
Hide file tree
Showing 7 changed files with 18 additions and 17 deletions.
7 changes: 3 additions & 4 deletions libpcsxcore/gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,13 @@ void gpu_state_change(int what)
switch (state)
{
case PGS_VRAM_TRANSFER_START:
HW_GPU_STATUS &= ~SWAP32(PSXGPU_nBUSY);
psxRegs.gpuIdleAfter = psxRegs.cycle + PSXCLK / 50;
break;
case PGS_VRAM_TRANSFER_END:
HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
psxRegs.gpuIdleAfter = psxRegs.cycle;
break;
case PGS_PRIMITIVE_START:
HW_GPU_STATUS &= ~SWAP32(PSXGPU_nBUSY);
set_event(PSXINT_GPUDMA, 200); // see gpuInterrupt
psxRegs.gpuIdleAfter = psxRegs.cycle + 200;
break;
}
}
5 changes: 3 additions & 2 deletions libpcsxcore/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,8 @@ int LoadState(const char *file) {
SaveFuncs.read(f, &psxRegs, offsetof(psxRegisters, gteBusyCycle));
psxRegs.gteBusyCycle = psxRegs.cycle;
psxRegs.biosBranchCheck = ~0;
psxRegs.gpuIdleAfter = psxRegs.cycle - 1;
HW_GPU_STATUS &= SWAP32(~PSXGPU_nBUSY);

psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, NULL);

Expand All @@ -750,8 +752,7 @@ int LoadState(const char *file) {
SaveFuncs.read(f, gpufP, sizeof(GPUFreeze_t));
GPU_freeze(0, gpufP);
free(gpufP);
if (HW_GPU_STATUS == 0)
HW_GPU_STATUS = SWAP32(GPU_readStatus());
gpuSyncPluginSR();

// spu
SaveFuncs.read(f, &Size, 4);
Expand Down
1 change: 0 additions & 1 deletion libpcsxcore/psxbios.c
Original file line number Diff line number Diff line change
Expand Up @@ -3322,7 +3322,6 @@ void psxBiosSetupBootState(void)
GPU_writeStatus(gpu_ctl_def[i]);
for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
GPU_writeData(gpu_data_def[i]);
HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);

// spu
for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
Expand Down
2 changes: 2 additions & 0 deletions libpcsxcore/psxcounters.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,8 @@ void psxRcntUpdate()
}
HW_GPU_STATUS = SWAP32(status);
GPU_vBlank(0, field);
if ((s32)(psxRegs.gpuIdleAfter - psxRegs.cycle) < 0)
psxRegs.gpuIdleAfter = psxRegs.cycle - 1; // prevent overflow

if ((rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset) ||
(rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset2))
Expand Down
10 changes: 4 additions & 6 deletions libpcsxcore/psxdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU
HW_DMA2_MADR = SWAPu32(madr + words_copy * 4);

// careful: gpu_state_change() also messes with this
HW_GPU_STATUS &= SWAP32(~PSXGPU_nBUSY);
psxRegs.gpuIdleAfter = psxRegs.cycle + words / 4 + 16;
// already 32-bit word size ((size * 4) / 4)
set_event(PSXINT_GPUDMA, words / 4);
return;
Expand All @@ -180,7 +180,7 @@ void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU
HW_DMA2_MADR = SWAPu32(madr);

// careful: gpu_state_change() also messes with this
HW_GPU_STATUS &= SWAP32(~PSXGPU_nBUSY);
psxRegs.gpuIdleAfter = psxRegs.cycle + words / 4 + 16;
// already 32-bit word size ((size * 4) / 4)
set_event(PSXINT_GPUDMA, words / 4);
return;
Expand All @@ -199,13 +199,13 @@ void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU
if ((int)size <= 0)
size = gpuDmaChainSize(madr);

HW_GPU_STATUS &= SWAP32(~PSXGPU_nBUSY);
HW_DMA2_MADR = SWAPu32(madr_next);

// Tekken 3 = use 1.0 only (not 1.5x)

// Einhander = parse linked list in pieces (todo)
// Rebel Assault 2 = parse linked list in pieces (todo)
psxRegs.gpuIdleAfter = psxRegs.cycle + size + 16;
set_event(PSXINT_GPUDMA, size);
return;

Expand All @@ -218,14 +218,13 @@ void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU
DMA_INTERRUPT(2);
}

// note: this is also (ab)used for non-dma prim command
// to delay gpu returning to idle state, see gpu_state_change()
void gpuInterrupt() {
if (HW_DMA2_CHCR == SWAP32(0x01000401) && !(HW_DMA2_MADR & SWAP32(0x800000)))
{
u32 size, madr_next = 0xffffff;
size = GPU_dmaChain((u32 *)psxM, HW_DMA2_MADR & 0x1fffff, &madr_next);
HW_DMA2_MADR = SWAPu32(madr_next);
psxRegs.gpuIdleAfter = psxRegs.cycle + size + 64;
set_event(PSXINT_GPUDMA, size);
return;
}
Expand All @@ -234,7 +233,6 @@ void gpuInterrupt() {
HW_DMA2_CHCR &= SWAP32(~0x01000000);
DMA_INTERRUPT(2);
}
HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY); // GPU no longer busy
}

void psxDma6(u32 madr, u32 bcr, u32 chcr) {
Expand Down
7 changes: 4 additions & 3 deletions libpcsxcore/psxhw.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ void psxHwReset() {
mdecInit(); // initialize mdec decoder
cdrReset();
psxRcntInit();
HW_GPU_STATUS = SWAP32(0x14802000);
HW_GPU_STATUS = SWAP32(0x10802000);
psxHwReadGpuSRptr = Config.hacks.gpu_busy_hack
? psxHwReadGpuSRbusyHack : psxHwReadGpuSR;
}
Expand Down Expand Up @@ -91,16 +91,17 @@ void psxHwWriteGpuSR(u32 value)

u32 psxHwReadGpuSR(void)
{
u32 v;
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 & (psxRegs.cycle << 20);
v |= PSXGPU_LCF & (c << 20);
return v;
}

Expand Down
3 changes: 2 additions & 1 deletion libpcsxcore/r3000a.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,8 @@ typedef struct {
u32 dloadVal[2];
u32 biosBranchCheck;
u32 cpuInRecursion;
u32 reserved[2];
u32 gpuIdleAfter;
u32 reserved[1];
// warning: changing anything in psxRegisters requires update of all
// asm in libpcsxcore/new_dynarec/
} psxRegisters;
Expand Down

0 comments on commit f8896d1

Please sign in to comment.