* Miscellaneous functions, including savestates and CD-ROM loading.
*/
+#include <stddef.h>
#include "misc.h"
#include "cdrom.h"
#include "mdec.h"
+#include "gpu.h"
#include "ppf.h"
+#include "database.h"
+#include <zlib.h>
char CdromId[10] = "";
char CdromLabel[33] = "";
char name [1];
};
-void mmssdd( char *b, char *p )
+static void mmssdd( char *b, char *p )
{
int m, s, d;
-#if defined(__arm__)
- int block = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0];
-#elif defined(__BIGENDIAN__)
- int block = (b[0] & 0xff) | ((b[1] & 0xff) << 8) | ((b[2] & 0xff) << 16) | (b[3] << 24);
-#else
- int block = *((int*)b);
-#endif
+ unsigned char *ub = (void *)b;
+ int block = (ub[3] << 24) | (ub[2] << 16) | (ub[1] << 8) | ub[0];
block += 150;
m = block / 4500; // minutes
time[0] = itob(time[0]); time[1] = itob(time[1]); time[2] = itob(time[2]);
#define READTRACK() \
- if (CDR_readTrack(time) == -1) return -1; \
- buf = CDR_getBuffer(); \
- if (buf == NULL) return -1; else CheckPPFCache(buf, time[0], time[1], time[2]);
+ if (!CDR_readTrack(time)) return -1; \
+ buf = (void *)CDR_getBuffer(); \
+ if (buf == NULL) return -1; \
+ else CheckPPFCache((u8 *)buf, time[0], time[1], time[2]);
#define READDIR(_dir) \
READTRACK(); \
READTRACK(); \
memcpy(_dir + 2048, buf + 12, 2048);
-int GetCdromFile(u8 *mdir, u8 *time, s8 *filename) {
+int GetCdromFile(u8 *mdir, u8 *time, char *filename) {
struct iso_directory_record *dir;
- char ddir[4096];
+ int retval = -1;
+ u8 ddir[4096];
u8 *buf;
int i;
if (dir->length[0] == 0) {
return -1;
}
- i += dir->length[0];
+ i += (u8)dir->length[0];
if (dir->flags[0] & 0x2) { // it's a dir
if (!strnicmp((char *)&dir->name[0], filename, dir->name_len[0])) {
} else {
if (!strnicmp((char *)&dir->name[0], filename, strlen(filename))) {
mmssdd(dir->extent, (char *)time);
+ retval = 0;
break;
}
}
}
- return 0;
+ return retval;
+}
+
+static const unsigned int gpu_ctl_def[] = {
+ 0x00000000, 0x01000000, 0x03000000, 0x04000000,
+ 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027,
+};
+
+static const unsigned int gpu_data_def[] = {
+ 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
+ 0xe5001000, 0xe6000000,
+ 0x02000000, 0x00000000, 0x01ff03ff,
+};
+
+static void fake_bios_gpu_setup(void)
+{
+ int i;
+
+ for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
+ 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]);
}
int LoadCdrom() {
struct iso_directory_record *dir;
u8 time[4], *buf;
u8 mdir[4096];
- s8 exename[256];
+ char exename[256];
+
+ // not the best place to do it, but since BIOS boot logo killer
+ // is just below, do it here
+ fake_bios_gpu_setup();
if (!Config.HLE) {
+ // skip BIOS logos
psxRegs.pc = psxRegs.GPR.n.ra;
return 0;
}
// read the SYSTEM.CNF
READTRACK();
- sscanf((char *)buf + 12, "BOOT = cdrom:\\%256s", exename);
+ sscanf((char *)buf + 12, "BOOT = cdrom:\\%255s", exename);
if (GetCdromFile(mdir, time, exename) == -1) {
- sscanf((char *)buf + 12, "BOOT = cdrom:%256s", exename);
+ sscanf((char *)buf + 12, "BOOT = cdrom:%255s", exename);
if (GetCdromFile(mdir, time, exename) == -1) {
- char *ptr = strstr(buf + 12, "cdrom:");
+ char *ptr = strstr((char *)buf + 12, "cdrom:");
if (ptr != NULL) {
ptr += 6;
while (*ptr == '\\' || *ptr == '/') ptr++;
tmpHead.t_addr = SWAP32(tmpHead.t_addr);
psxCpu->Clear(tmpHead.t_addr, tmpHead.t_size / 4);
+ psxCpu->Reset();
// Read the rest of the main executable
while (tmpHead.t_size & ~2047) {
int LoadCdromFile(const char *filename, EXE_HEADER *head) {
struct iso_directory_record *dir;
u8 time[4],*buf;
- u8 mdir[4096], exename[256];
+ u8 mdir[4096];
+ char exename[256];
u32 size, addr;
+ void *mem;
- sscanf(filename, "cdrom:\\%256s", exename);
+ sscanf(filename, "cdrom:\\%255s", exename);
time[0] = itob(0); time[1] = itob(2); time[2] = itob(0x10);
addr = head->t_addr;
psxCpu->Clear(addr, size / 4);
+ psxCpu->Reset();
while (size & ~2047) {
incTime();
READTRACK();
- memcpy((void *)PSXM(addr), buf + 12, 2048);
+ mem = PSXM(addr);
+ if (mem)
+ memcpy(mem, buf + 12, 2048);
size -= 2048;
addr += 2048;
int CheckCdrom() {
struct iso_directory_record *dir;
- unsigned char time[4], *buf;
+ unsigned char time[4];
+ char *buf;
unsigned char mdir[4096];
char exename[256];
- int i, c;
+ int i, len, c;
FreePPFCache();
READTRACK();
- CdromLabel[0] = '\0';
- CdromId[0] = '\0';
+ memset(CdromLabel, 0, sizeof(CdromLabel));
+ memset(CdromId, 0, sizeof(CdromId));
+ memset(exename, 0, sizeof(exename));
strncpy(CdromLabel, buf + 52, 32);
if (GetCdromFile(mdir, time, "SYSTEM.CNF;1") != -1) {
READTRACK();
- sscanf((char *)buf + 12, "BOOT = cdrom:\\%256s", exename);
+ sscanf(buf + 12, "BOOT = cdrom:\\%255s", exename);
if (GetCdromFile(mdir, time, exename) == -1) {
- sscanf((char *)buf + 12, "BOOT = cdrom:%256s", exename);
+ sscanf(buf + 12, "BOOT = cdrom:%255s", exename);
if (GetCdromFile(mdir, time, exename) == -1) {
char *ptr = strstr(buf + 12, "cdrom:"); // possibly the executable is in some subdir
if (ptr != NULL) {
return -1; // SYSTEM.CNF and PSX.EXE not found
if (CdromId[0] == '\0') {
- i = strlen(exename);
- if (i >= 2) {
- if (exename[i - 2] == ';') i-= 2;
- c = 8; i--;
- while (i >= 0 && c >= 0) {
- if (isalnum(exename[i])) CdromId[c--] = exename[i];
- i--;
- }
+ len = strlen(exename);
+ c = 0;
+ for (i = 0; i < len; ++i) {
+ if (exename[i] == ';' || c >= sizeof(CdromId) - 1)
+ break;
+ if (isalnum(exename[i]))
+ CdromId[c++] = exename[i];
}
}
+ if (CdromId[0] == '\0')
+ strcpy(CdromId, "SLUS99999");
+
if (Config.PsxAuto) { // autodetect system (pal or ntsc)
- if (CdromId[2] == 'e' || CdromId[2] == 'E')
+ if (
+ /* Make sure Wild Arms SCUS-94608 is not detected as a PAL game. */
+ ((CdromId[0] == 's' || CdromId[0] == 'S') && (CdromId[2] == 'e' || CdromId[2] == 'E')) ||
+ !strncmp(CdromId, "DTLS3035", 8) ||
+ !strncmp(CdromId, "PBPX95001", 9) || // according to redump.org, these PAL
+ !strncmp(CdromId, "PBPX95007", 9) || // discs have a non-standard ID;
+ !strncmp(CdromId, "PBPX95008", 9)) // add more serials if they are discovered.
Config.PsxType = PSX_TYPE_PAL; // pal
else Config.PsxType = PSX_TYPE_NTSC; // ntsc
}
}
SysPrintf(_("CD-ROM Label: %.32s\n"), CdromLabel);
SysPrintf(_("CD-ROM ID: %.9s\n"), CdromId);
+ SysPrintf(_("CD-ROM EXE Name: %.255s\n"), exename);
+
+ Apply_Hacks_Cdrom();
BuildPPFCache();
return INVALID_EXE;
}
+// temporary pandora workaround..
+// FIXME: remove
+size_t fread_to_ram(void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+ void *tmp;
+ size_t ret = 0;
+
+ tmp = malloc(size * nmemb);
+ if (tmp) {
+ ret = fread(tmp, size, nmemb, stream);
+ memcpy(ptr, tmp, size * nmemb);
+ free(tmp);
+ }
+ return ret;
+}
+
int Load(const char *ExePath) {
FILE *tmpFile;
EXE_HEADER tmpHead;
mem = PSXM(section_address);
if (mem != NULL) {
fseek(tmpFile, 0x800, SEEK_SET);
- fread(mem, section_size, 1, tmpFile);
+ fread_to_ram(mem, section_size, 1, tmpFile);
psxCpu->Clear(section_address, section_size / 4);
}
fclose(tmpFile);
#endif
mem = PSXM(section_address);
if (mem != NULL) {
- fread(mem, section_size, 1, tmpFile);
+ fread_to_ram(mem, section_size, 1, tmpFile);
psxCpu->Clear(section_address, section_size / 4);
}
break;
retval = -1;
break;
case INVALID_EXE:
- SysPrintf(_("This file does not appear to be a valid PSX file.\n"));
+ SysPrintf(_("This file does not appear to be a valid PSX EXE file.\n"));
+ SysPrintf(_("(did you forget -cdfile ?)\n"));
retval = -1;
break;
}
// STATES
+static void *zlib_open(const char *name, const char *mode)
+{
+ return gzopen(name, mode);
+}
+
+static int zlib_read(void *file, void *buf, u32 len)
+{
+ return gzread(file, buf, len);
+}
+
+static int zlib_write(void *file, const void *buf, u32 len)
+{
+ return gzwrite(file, buf, len);
+}
+
+static long zlib_seek(void *file, long offs, int whence)
+{
+ return gzseek(file, offs, whence);
+}
+
+static void zlib_close(void *file)
+{
+ gzclose(file);
+}
+
+struct PcsxSaveFuncs SaveFuncs = {
+ zlib_open, zlib_read, zlib_write, zlib_seek, zlib_close
+};
+
static const char PcsxHeader[32] = "STv4 PCSX v" PACKAGE_VERSION;
// Savestate Versioning!
static const u32 SaveVersion = 0x8b410006;
int SaveState(const char *file) {
- gzFile f;
+ void *f;
GPUFreeze_t *gpufP;
SPUFreeze_t *spufP;
int Size;
unsigned char *pMem;
- f = gzopen(file, "wb");
+ f = SaveFuncs.open(file, "wb");
if (f == NULL) return -1;
- new_dyna_save();
+ new_dyna_before_save();
- gzwrite(f, (void *)PcsxHeader, 32);
- gzwrite(f, (void *)&SaveVersion, sizeof(u32));
- gzwrite(f, (void *)&Config.HLE, sizeof(boolean));
+ SaveFuncs.write(f, (void *)PcsxHeader, 32);
+ SaveFuncs.write(f, (void *)&SaveVersion, sizeof(u32));
+ SaveFuncs.write(f, (void *)&Config.HLE, sizeof(boolean));
pMem = (unsigned char *)malloc(128 * 96 * 3);
if (pMem == NULL) return -1;
GPU_getScreenPic(pMem);
- gzwrite(f, pMem, 128 * 96 * 3);
+ SaveFuncs.write(f, pMem, 128 * 96 * 3);
free(pMem);
if (Config.HLE)
psxBiosFreeze(1);
- gzwrite(f, psxM, 0x00200000);
- gzwrite(f, psxR, 0x00080000);
- gzwrite(f, psxH, 0x00010000);
- gzwrite(f, (void *)&psxRegs, sizeof(psxRegs));
+ SaveFuncs.write(f, psxM, 0x00200000);
+ SaveFuncs.write(f, psxR, 0x00080000);
+ SaveFuncs.write(f, psxH, 0x00010000);
+ // only partial save of psxRegisters to maintain savestate compat
+ SaveFuncs.write(f, &psxRegs, offsetof(psxRegisters, gteBusyCycle));
// gpu
gpufP = (GPUFreeze_t *)malloc(sizeof(GPUFreeze_t));
gpufP->ulFreezeVersion = 1;
GPU_freeze(1, gpufP);
- gzwrite(f, gpufP, sizeof(GPUFreeze_t));
+ SaveFuncs.write(f, gpufP, sizeof(GPUFreeze_t));
free(gpufP);
// spu
spufP = (SPUFreeze_t *) malloc(16);
- SPU_freeze(2, spufP);
- Size = spufP->Size; gzwrite(f, &Size, 4);
+ SPU_freeze(2, spufP, psxRegs.cycle);
+ Size = spufP->Size; SaveFuncs.write(f, &Size, 4);
free(spufP);
spufP = (SPUFreeze_t *) malloc(Size);
- SPU_freeze(1, spufP);
- gzwrite(f, spufP, Size);
+ SPU_freeze(1, spufP, psxRegs.cycle);
+ SaveFuncs.write(f, spufP, Size);
free(spufP);
sioFreeze(f, 1);
psxHwFreeze(f, 1);
psxRcntFreeze(f, 1);
mdecFreeze(f, 1);
+ new_dyna_freeze(f, 1);
+
+ SaveFuncs.close(f);
- gzclose(f);
+ new_dyna_after_save();
return 0;
}
int LoadState(const char *file) {
- gzFile f;
+ void *f;
GPUFreeze_t *gpufP;
SPUFreeze_t *spufP;
int Size;
u32 version;
boolean hle;
- f = gzopen(file, "rb");
+ f = SaveFuncs.open(file, "rb");
if (f == NULL) return -1;
- gzread(f, header, sizeof(header));
- gzread(f, &version, sizeof(u32));
- gzread(f, &hle, sizeof(boolean));
+ SaveFuncs.read(f, header, sizeof(header));
+ SaveFuncs.read(f, &version, sizeof(u32));
+ SaveFuncs.read(f, &hle, sizeof(boolean));
if (strncmp("STv4 PCSX", header, 9) != 0 || version != SaveVersion) {
- gzclose(f);
+ SaveFuncs.close(f);
return -1;
}
Config.HLE = hle;
psxBiosInit();
psxCpu->Reset();
- gzseek(f, 128 * 96 * 3, SEEK_CUR);
+ SaveFuncs.seek(f, 128 * 96 * 3, SEEK_CUR);
- gzread(f, psxM, 0x00200000);
- gzread(f, psxR, 0x00080000);
- gzread(f, psxH, 0x00010000);
- gzread(f, (void *)&psxRegs, sizeof(psxRegs));
+ SaveFuncs.read(f, psxM, 0x00200000);
+ SaveFuncs.read(f, psxR, 0x00080000);
+ SaveFuncs.read(f, psxH, 0x00010000);
+ SaveFuncs.read(f, &psxRegs, offsetof(psxRegisters, gteBusyCycle));
+ psxRegs.gteBusyCycle = psxRegs.cycle;
if (Config.HLE)
psxBiosFreeze(0);
// gpu
gpufP = (GPUFreeze_t *)malloc(sizeof(GPUFreeze_t));
- gzread(f, gpufP, sizeof(GPUFreeze_t));
+ SaveFuncs.read(f, gpufP, sizeof(GPUFreeze_t));
GPU_freeze(0, gpufP);
free(gpufP);
+ if (HW_GPU_STATUS == 0)
+ HW_GPU_STATUS = SWAP32(GPU_readStatus());
// spu
- gzread(f, &Size, 4);
+ SaveFuncs.read(f, &Size, 4);
spufP = (SPUFreeze_t *)malloc(Size);
- gzread(f, spufP, Size);
- SPU_freeze(0, spufP);
+ SaveFuncs.read(f, spufP, Size);
+ SPU_freeze(0, spufP, psxRegs.cycle);
free(spufP);
sioFreeze(f, 0);
psxHwFreeze(f, 0);
psxRcntFreeze(f, 0);
mdecFreeze(f, 0);
+ new_dyna_freeze(f, 0);
- gzclose(f);
- new_dyna_restore();
+ SaveFuncs.close(f);
return 0;
}
int CheckState(const char *file) {
- gzFile f;
+ void *f;
char header[32];
u32 version;
boolean hle;
- f = gzopen(file, "rb");
+ f = SaveFuncs.open(file, "rb");
if (f == NULL) return -1;
- gzread(f, header, sizeof(header));
- gzread(f, &version, sizeof(u32));
- gzread(f, &hle, sizeof(boolean));
+ SaveFuncs.read(f, header, sizeof(header));
+ SaveFuncs.read(f, &version, sizeof(u32));
+ SaveFuncs.read(f, &hle, sizeof(boolean));
- gzclose(f);
+ SaveFuncs.close(f);
if (strncmp("STv4 PCSX", header, 9) != 0 || version != SaveVersion)
return -1;
NET_recvData(&Config.Cpu, sizeof(Config.Cpu), PSE_NET_BLOCKING);
if (tmp != Config.Cpu) {
psxCpu->Shutdown();
-#ifdef PSXREC
+#ifndef DRC_DISABLE
if (Config.Cpu == CPU_INTERPRETER) psxCpu = &psxInt;
else psxCpu = &psxRec;
#else