Chrono Cross interlace fix (ePSXe version)

GameShark Lite needs GPUSTATUS_READYFORVRAM off when not IDLE. Also fixes CDROM swapping.
- Enable 'Fake GPU Busy States' to work
- Perhaps we should fix PEOPS GPU to turn off READYFORVRAM instead of gpu.c (my temp solution)

Please add gpu.c / gpu.h to your makefiles.


git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@56824 e17a0e51-4ae3-4d35-97c3-1a29b211df97
This commit is contained in:
SND\shalma_cp 2010-09-05 01:11:09 +00:00
parent 37edbb7d48
commit dcc46e2d30
6 changed files with 213 additions and 70 deletions

View File

@ -573,9 +573,14 @@ void cdrInterrupt() {
// case now open
if (stat.Status & 0x10) {
cdr.Stat = DiskError;
if( Irq != CdlNop )
{
cdr.Stat = DiskError;
cdr.Result[0] |= 0x01;
}
cdr.Result[0] |= 0x11;
// GameShark Lite: Wants -exactly- $10
cdr.Result[0] |= 0x10;
cdr.Result[0] &= ~0x02;
}
// case now closed
@ -583,6 +588,9 @@ void cdrInterrupt() {
cdr.StatP &= ~0x11;
cdr.Result[0] |= 0x2;
// GameShark Lite: Wants -exactly- $42, then $02
cdr.Result[0] |= 0x40;
CheckCdrom();
}
}

198
libpcsxcore/gpu.c Normal file
View File

@ -0,0 +1,198 @@
#include "psxhw.h"
#include "gpu.h"
#include "psxdma.h"
extern unsigned int hSyncCount;
#define GPUSTATUS_ODDLINES 0x80000000
#define GPUSTATUS_DMABITS 0x60000000 // Two bits
#define GPUSTATUS_READYFORCOMMANDS 0x10000000
#define GPUSTATUS_READYFORVRAM 0x08000000
#define GPUSTATUS_IDLE 0x04000000
#define GPUSTATUS_DISPLAYDISABLED 0x00800000
#define GPUSTATUS_INTERLACED 0x00400000
#define GPUSTATUS_RGB24 0x00200000
#define GPUSTATUS_PAL 0x00100000
#define GPUSTATUS_DOUBLEHEIGHT 0x00080000
#define GPUSTATUS_WIDTHBITS 0x00070000 // Three bits
#define GPUSTATUS_MASKENABLED 0x00001000
#define GPUSTATUS_MASKDRAWN 0x00000800
#define GPUSTATUS_DRAWINGALLOWED 0x00000400
#define GPUSTATUS_DITHER 0x00000200
// Taken from PEOPS SOFTGPU
unsigned long lUsedAddr[3];
char CheckForEndlessLoop(unsigned long laddr)
{
if(laddr==lUsedAddr[1]) return 1;
if(laddr==lUsedAddr[2]) return 1;
if(laddr<lUsedAddr[0]) lUsedAddr[1]=laddr;
else lUsedAddr[2]=laddr;
lUsedAddr[0]=laddr;
return 0;
}
long gpuDmaChain(unsigned long *baseAddrL, unsigned long addr)
{
unsigned long dmaMem;
unsigned char *baseAddrB;
short count;unsigned int DMACommandCounter = 0;
int size;
size = 0;
lUsedAddr[0]=lUsedAddr[1]=lUsedAddr[2]=0xffffff;
baseAddrB = (unsigned char*) baseAddrL;
do
{
// Only Zinc = 1024
//if(iGPUHeight==512) addr&=0x1FFFFC;
addr&=0x1FFFFC;
if(DMACommandCounter++ > 2000000) break;
if(CheckForEndlessLoop(addr)) break;
count = baseAddrB[addr+3];
size += 4;
size += count;
dmaMem=addr+4;
//if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count);
addr = baseAddrL[addr>>2]&0xffffff;
}
while (addr != 0xffffff);
return size;
}
int gpuReadStatus()
{
int hard;
// GPU plugin
hard = GPU_readStatus();
// ePSXe 1.7.0 - Chrono Cross interlace hack
if (hard & 0x400000) {
switch (Config.PsxType) {
case PSX_TYPE_NTSC:
if (hSyncCount > 262 - 240) hard ^= 0x80000000;
break;
case PSX_TYPE_PAL:
if (hSyncCount > 312 - 256) hard ^= 0x80000000;
break;
}
}
// NOTE:
// Backup option when plugins fail to simulate 'busy gpu'
// TODO:
// Check this with
// - Hot wheels turbo racing
// - Dukes of Hazzard
#if 1
if( HW_DMA2_CHCR & 0x01000000 )
{
hard &= ~GPUSTATUS_IDLE;
hard &= ~GPUSTATUS_READYFORCOMMANDS;
}
#endif
// Gameshark Lite - wants to see VRAM busy
// - Must enable GPU 'Fake Busy States' hack
if( (hard & GPUSTATUS_IDLE) == 0 )
hard &= ~GPUSTATUS_READYFORVRAM;
return hard;
}
void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU
u32 *ptr;
u32 size;
switch(chcr) {
case 0x01000200: // vram2mem
#ifdef PSXDMA_LOG
PSXDMA_LOG("*** DMA2 GPU - vram2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
#endif
ptr = (u32 *)PSXM(madr);
if (ptr == NULL) {
#ifdef CPU_LOG
CPU_LOG("*** DMA2 GPU - vram2mem *** NULL Pointer!!!\n");
#endif
break;
}
size = (bcr >> 16) * (bcr & 0xffff);
GPU_readDataMem(ptr, size);
psxCpu->Clear(madr, size);
GPUDMA_INT( size / 4 );
return;
case 0x01000201: // mem2vram
#ifdef PSXDMA_LOG
PSXDMA_LOG("*** DMA 2 - GPU mem2vram *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
#endif
ptr = (u32 *)PSXM(madr);
if (ptr == NULL) {
#ifdef CPU_LOG
CPU_LOG("*** DMA2 GPU - mem2vram *** NULL Pointer!!!\n");
#endif
break;
}
size = (bcr >> 16) * (bcr & 0xffff);
GPU_writeDataMem(ptr, size);
GPUDMA_INT( size / 4 );
return;
case 0x01000401: // dma chain
#ifdef PSXDMA_LOG
PSXDMA_LOG("*** DMA 2 - GPU dma chain *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
#endif
GPU_dmaChain((u32 *)psxM, madr & 0x1fffff);
// FIXME!! GPU DMA chain walking
GPUDMA_INT( 0x4000 / 4 );
return;
#ifdef PSXDMA_LOG
default:
PSXDMA_LOG("*** DMA 2 - GPU unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
break;
#endif
}
HW_DMA2_CHCR &= SWAP32(~0x01000000);
DMA_INTERRUPT(2);
}
void gpuInterrupt() {
HW_DMA2_CHCR &= SWAP32(~0x01000000);
DMA_INTERRUPT(2);
}

1
libpcsxcore/gpu.h Normal file
View File

@ -0,0 +1 @@
int gpuReadStatus();

View File

@ -75,7 +75,7 @@ static const s32 VerboseLevel = 0;
static Rcnt rcnts[ CounterQuantity ];
static u32 hSyncCount = 0;
u32 hSyncCount = 0;
static u32 spuSyncCount = 0;
u32 psxNextCounter = 0, psxNextsCounter = 0;

View File

@ -80,72 +80,7 @@ void psxDma4(u32 madr, u32 bcr, u32 chcr) { // SPU
DMA_INTERRUPT(4);
}
void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU
u32 *ptr;
u32 size;
switch(chcr) {
case 0x01000200: // vram2mem
#ifdef PSXDMA_LOG
PSXDMA_LOG("*** DMA2 GPU - vram2mem *** %x addr = %x size = %x\n", chcr, madr, bcr);
#endif
ptr = (u32 *)PSXM(madr);
if (ptr == NULL) {
#ifdef CPU_LOG
CPU_LOG("*** DMA2 GPU - vram2mem *** NULL Pointer!!!\n");
#endif
break;
}
size = (bcr >> 16) * (bcr & 0xffff);
GPU_readDataMem(ptr, size);
psxCpu->Clear(madr, size);
GPUDMA_INT(size / 4);
return;
case 0x01000201: // mem2vram
#ifdef PSXDMA_LOG
PSXDMA_LOG("*** DMA 2 - GPU mem2vram *** %x addr = %x size = %x\n", chcr, madr, bcr);
#endif
ptr = (u32 *)PSXM(madr);
if (ptr == NULL) {
#ifdef CPU_LOG
CPU_LOG("*** DMA2 GPU - mem2vram *** NULL Pointer!!!\n");
#endif
break;
}
size = (bcr >> 16) * (bcr & 0xffff);
GPU_writeDataMem(ptr, size);
GPUDMA_INT(size / 4);
return;
case 0x01000401: // dma chain
#ifdef PSXDMA_LOG
PSXDMA_LOG("*** DMA 2 - GPU dma chain *** %x addr = %x size = %x\n", chcr, madr, bcr);
#endif
GPU_dmaChain((u32 *)psxM, madr & 0x1fffff);
// FIXME!!! Walk through DMA chain and add the cycles
GPUDMA_INT( 0x4000 / 4 );
return;
#ifdef PSXDMA_LOG
default:
PSXDMA_LOG("*** DMA 2 - GPU unknown *** %x addr = %x size = %x\n", chcr, madr, bcr);
break;
#endif
}
HW_DMA2_CHCR &= SWAP32(~0x01000000);
DMA_INTERRUPT(2);
}
void gpuInterrupt() {
HW_DMA2_CHCR &= SWAP32(~0x01000000);
DMA_INTERRUPT(2);
}
void psxDma6(u32 madr, u32 bcr, u32 chcr) {
u32 *mem = (u32 *)PSXM(madr);
@ -169,7 +104,7 @@ void psxDma6(u32 madr, u32 bcr, u32 chcr) {
}
mem++; *mem = 0xffffff;
RAMDMA_INT( size / BIAS);
RAMDMA_INT( size );
return;
}
#ifdef PSXDMA_LOG

View File

@ -24,6 +24,7 @@
#include "psxhw.h"
#include "mdec.h"
#include "cdrom.h"
#include "gpu.h"
void psxHwReset() {
if (Config.Sio) psxHu32ref(0x1070) |= SWAP32(0x80);
@ -235,7 +236,7 @@ u32 psxHwRead32(u32 add) {
#endif
return hard;
case 0x1f801814:
hard = GPU_readStatus();
hard = gpuReadStatus();
#ifdef PSXHW_LOG
PSXHW_LOG("GPU STATUS 32bit read %x\n", hard);
#endif