* Miscellaneous functions, including savestates and CD-ROM loading.
*/
+#include <stddef.h>
+#include <errno.h>
+#include <assert.h>
#include "misc.h"
#include "cdrom.h"
#include "mdec.h"
#include "gpu.h"
#include "ppf.h"
+#include "psxbios.h"
+#include "database.h"
#include <zlib.h>
char CdromId[10] = "";
char CdromLabel[33] = "";
+int CdromFrontendId; // for frontend use
// PSX Executable types
#define PSX_EXE 1
char name [1];
};
-void mmssdd( char *b, char *p )
+static void mmssdd( char *b, char *p )
{
int m, s, d;
-#if defined(__arm__)
- unsigned char *u = (void *)b;
- int block = (u[3] << 24) | (u[2] << 16) | (u[1] << 8) | u[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; \
+ 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]);
int i;
// only try to scan if a filename is given
- if (!strlen(filename)) return -1;
+ if (filename == INVALID_PTR || !strlen(filename)) return -1;
i = 0;
while (i < 4096) {
return retval;
}
-static const unsigned int gpu_ctl_def[] = {
- 0x00000000, 0x01000000, 0x03000000, 0x04000000,
- 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027,
-};
+static void SetBootRegs(u32 pc, u32 gp, u32 sp)
+{
+ //printf("%s %08x %08x %08x\n", __func__, pc, gp, sp);
+ psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, NULL);
-static const unsigned int gpu_data_def[] = {
- 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
- 0xe5001000, 0xe6000000,
- 0x02000000, 0x00000000, 0x01ff03ff,
-};
+ psxRegs.pc = pc;
+ psxRegs.GPR.n.gp = gp;
+ psxRegs.GPR.n.sp = sp ? sp : 0x801fff00;
+ psxRegs.GPR.n.fp = psxRegs.GPR.n.sp;
-static void fake_bios_gpu_setup(void)
-{
- int i;
+ psxRegs.GPR.n.t0 = psxRegs.GPR.n.sp; // mimic A(43)
+ psxRegs.GPR.n.t3 = pc;
+
+ psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, NULL);
+}
- for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
- GPU_writeStatus(gpu_ctl_def[i]);
+void BiosBootBypass() {
+ assert(psxRegs.pc == 0x80030000);
- for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
- GPU_writeData(gpu_data_def[i]);
+ // skip BIOS logos and region check
+ psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, NULL);
+ psxRegs.pc = psxRegs.GPR.n.ra;
+}
+
+static void getFromCnf(char *buf, const char *key, u32 *val)
+{
+ buf = strstr(buf, key);
+ if (buf)
+ buf = strchr(buf, '=');
+ if (buf) {
+ unsigned long v;
+ errno = 0;
+ v = strtoul(buf + 1, NULL, 16);
+ if (errno == 0)
+ *val = v;
+ }
}
int LoadCdrom() {
- EXE_HEADER tmpHead;
+ union {
+ EXE_HEADER h;
+ u32 d[sizeof(EXE_HEADER) / sizeof(u32)];
+ } tmpHead;
struct iso_directory_record *dir;
u8 time[4], *buf;
u8 mdir[4096];
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 && !Config.SlowBoot) {
- // skip BIOS logos
- psxRegs.pc = psxRegs.GPR.n.ra;
- return 0;
+ u32 cnf_tcb = 4;
+ u32 cnf_event = 16;
+ u32 cnf_stack = 0;
+ u32 t_addr;
+ u32 t_size;
+ u32 sp = 0;
+ int i, ret;
+
+ if (!Config.HLE) {
+ if (psxRegs.pc != 0x80030000) // BiosBootBypass'ed or custom BIOS?
+ return 0;
+ if (Config.SlowBoot)
+ return 0;
}
time[0] = itob(0); time[1] = itob(2); time[2] = itob(0x10);
if (GetCdromFile(mdir, time, "SYSTEM.CNF;1") == -1) {
// if SYSTEM.CNF is missing, start an existing PSX.EXE
if (GetCdromFile(mdir, time, "PSX.EXE;1") == -1) return -1;
+ strcpy(exename, "PSX.EXE;1");
READTRACK();
}
else {
// read the SYSTEM.CNF
READTRACK();
+ buf[1023] = 0;
- sscanf((char *)buf + 12, "BOOT = cdrom:\\%255s", exename);
- if (GetCdromFile(mdir, time, exename) == -1) {
- sscanf((char *)buf + 12, "BOOT = cdrom:%255s", exename);
- if (GetCdromFile(mdir, time, exename) == -1) {
+ ret = sscanf((char *)buf + 12, "BOOT = cdrom:\\%255s", exename);
+ if (ret < 1 || GetCdromFile(mdir, time, exename) == -1) {
+ ret = sscanf((char *)buf + 12, "BOOT = cdrom:%255s", exename);
+ if (ret < 1 || GetCdromFile(mdir, time, exename) == -1) {
char *ptr = strstr((char *)buf + 12, "cdrom:");
if (ptr != NULL) {
ptr += 6;
return -1;
}
}
+ getFromCnf((char *)buf + 12, "TCB", &cnf_tcb);
+ getFromCnf((char *)buf + 12, "EVENT", &cnf_event);
+ getFromCnf((char *)buf + 12, "STACK", &cnf_stack);
+ if (Config.HLE)
+ psxBiosCnfLoaded(cnf_tcb, cnf_event, cnf_stack);
// Read the EXE-Header
READTRACK();
}
memcpy(&tmpHead, buf + 12, sizeof(EXE_HEADER));
+ for (i = 2; i < sizeof(tmpHead.d) / sizeof(tmpHead.d[0]); i++)
+ tmpHead.d[i] = SWAP32(tmpHead.d[i]);
- psxRegs.pc = SWAP32(tmpHead.pc0);
- psxRegs.GPR.n.gp = SWAP32(tmpHead.gp0);
- psxRegs.GPR.n.sp = SWAP32(tmpHead.s_addr);
- if (psxRegs.GPR.n.sp == 0) psxRegs.GPR.n.sp = 0x801fff00;
-
- tmpHead.t_size = SWAP32(tmpHead.t_size);
- tmpHead.t_addr = SWAP32(tmpHead.t_addr);
-
- psxCpu->Clear(tmpHead.t_addr, tmpHead.t_size / 4);
+ SysPrintf("manual booting '%s' pc=%x\n", exename, tmpHead.h.pc0);
+ sp = tmpHead.h.s_addr;
+ if (cnf_stack)
+ sp = cnf_stack;
+ SetBootRegs(tmpHead.h.pc0, tmpHead.h.gp0, sp);
// Read the rest of the main executable
- while (tmpHead.t_size & ~2047) {
- void *ptr = (void *)PSXM(tmpHead.t_addr);
+ for (t_addr = tmpHead.h.t_addr, t_size = tmpHead.h.t_size; t_size & ~2047; ) {
+ void *ptr = (void *)PSXM(t_addr);
incTime();
READTRACK();
- if (ptr != NULL) memcpy(ptr, buf+12, 2048);
+ if (ptr != INVALID_PTR) memcpy(ptr, buf+12, 2048);
- tmpHead.t_size -= 2048;
- tmpHead.t_addr += 2048;
+ t_addr += 2048;
+ t_size -= 2048;
}
+ psxCpu->Clear(tmpHead.h.t_addr, tmpHead.h.t_size / 4);
+ //psxCpu->Reset();
+
+ if (Config.HLE)
+ psxBiosCheckExe(tmpHead.h.t_addr, tmpHead.h.t_size, 0);
+
return 0;
}
u8 time[4],*buf;
u8 mdir[4096];
char exename[256];
+ const char *p1, *p2;
u32 size, addr;
void *mem;
- sscanf(filename, "cdrom:\\%255s", exename);
+ if (filename == INVALID_PTR)
+ return -1;
+
+ p1 = filename;
+ if ((p2 = strchr(p1, ':')))
+ p1 = p2 + 1;
+ while (*p1 == '\\')
+ p1++;
+ snprintf(exename, sizeof(exename), "%s", p1);
time[0] = itob(0); time[1] = itob(2); time[2] = itob(0x10);
READTRACK();
memcpy(head, buf + 12, sizeof(EXE_HEADER));
- size = head->t_size;
- addr = head->t_addr;
+ size = SWAP32(head->t_size);
+ addr = SWAP32(head->t_addr);
psxCpu->Clear(addr, size / 4);
+ //psxCpu->Reset();
while (size & ~2047) {
incTime();
READTRACK();
mem = PSXM(addr);
- if (mem)
+ if (mem != INVALID_PTR)
memcpy(mem, buf + 12, 2048);
size -= 2048;
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
}
if (CdromLabel[0] == ' ') {
- memcpy(CdromLabel, CdromId, 9);
+ strncpy(CdromLabel, CdromId, 9);
}
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();
current = ftell(f);
fseek(f, 0L, SEEK_SET);
- if (fread(&mybuf, sizeof(mybuf), 1, f) != sizeof(mybuf))
+ if (fread(&mybuf, 1, sizeof(mybuf), f) != sizeof(mybuf))
goto io_fail;
fseek(f, current, SEEK_SET);
type = PSXGetFileType(tmpFile);
switch (type) {
case PSX_EXE:
- if (fread(&tmpHead, sizeof(EXE_HEADER), 1, tmpFile) != sizeof(EXE_HEADER))
+ if (fread(&tmpHead, 1, sizeof(EXE_HEADER), tmpFile) != sizeof(EXE_HEADER))
goto fail_io;
section_address = SWAP32(tmpHead.t_addr);
section_size = SWAP32(tmpHead.t_size);
mem = PSXM(section_address);
- if (mem != NULL) {
+ if (mem != INVALID_PTR) {
fseek(tmpFile, 0x800, SEEK_SET);
fread_to_ram(mem, section_size, 1, tmpFile);
psxCpu->Clear(section_address, section_size / 4);
}
- psxRegs.pc = SWAP32(tmpHead.pc0);
- psxRegs.GPR.n.gp = SWAP32(tmpHead.gp0);
- psxRegs.GPR.n.sp = SWAP32(tmpHead.s_addr);
- if (psxRegs.GPR.n.sp == 0)
- psxRegs.GPR.n.sp = 0x801fff00;
+ SetBootRegs(SWAP32(tmpHead.pc0), SWAP32(tmpHead.gp0),
+ SWAP32(tmpHead.s_addr));
retval = 0;
break;
case CPE_EXE:
fseek(tmpFile, 6, SEEK_SET); /* Something tells me we should go to 4 and read the "08 00" here... */
do {
- if (fread(&opcode, sizeof(opcode), 1, tmpFile) != sizeof(opcode))
+ if (fread(&opcode, 1, sizeof(opcode), tmpFile) != sizeof(opcode))
goto fail_io;
switch (opcode) {
case 1: /* Section loading */
- if (fread(§ion_address, sizeof(section_address), 1, tmpFile) != sizeof(section_address))
+ if (fread(§ion_address, 1, sizeof(section_address), tmpFile) != sizeof(section_address))
goto fail_io;
- if (fread(§ion_size, sizeof(section_size), 1, tmpFile) != sizeof(section_size))
+ if (fread(§ion_size, 1, sizeof(section_size), tmpFile) != sizeof(section_size))
goto fail_io;
section_address = SWAPu32(section_address);
section_size = SWAPu32(section_size);
EMU_LOG("Loading %08X bytes from %08X to %08X\n", section_size, ftell(tmpFile), section_address);
#endif
mem = PSXM(section_address);
- if (mem != NULL) {
+ if (mem != INVALID_PTR) {
fread_to_ram(mem, section_size, 1, tmpFile);
psxCpu->Clear(section_address, section_size / 4);
}
break;
case 3: /* register loading (PC only?) */
fseek(tmpFile, 2, SEEK_CUR); /* unknown field */
- if (fread(&psxRegs.pc, sizeof(psxRegs.pc), 1, tmpFile) != sizeof(psxRegs.pc))
+ if (fread(&psxRegs.pc, 1, sizeof(psxRegs.pc), tmpFile) != sizeof(psxRegs.pc))
goto fail_io;
psxRegs.pc = SWAPu32(psxRegs.pc);
break;
CdromLabel[0] = '\0';
}
- fclose(tmpFile);
+ if (tmpFile)
+ fclose(tmpFile);
return retval;
fail_io:
// If you make changes to the savestate version, please increment the value below.
static const u32 SaveVersion = 0x8b410006;
+#define MISC_MAGIC 0x4353494d
+struct misc_save_data {
+ u32 magic;
+ u32 gteBusyCycle;
+ u32 muldivBusyCycle;
+ u32 biuReg;
+ u32 biosBranchCheck;
+ u32 gpuIdleAfter;
+ u32 gpuSr;
+ u32 frame_counter;
+ int CdromFrontendId;
+};
+
int SaveState(const char *file) {
+ struct misc_save_data *misc = (void *)(psxH + 0xf000);
void *f;
- GPUFreeze_t *gpufP;
- SPUFreeze_t *spufP;
+ GPUFreeze_t *gpufP = NULL;
+ SPUFreezeHdr_t spufH;
+ SPUFreeze_t *spufP = NULL;
+ unsigned char *pMem = NULL;
+ int result = -1;
int Size;
- unsigned char *pMem;
+
+ assert(!psxRegs.branching);
+ assert(!psxRegs.cpuInRecursion);
+ assert(!misc->magic);
+ misc->magic = MISC_MAGIC;
+ misc->gteBusyCycle = psxRegs.gteBusyCycle;
+ misc->muldivBusyCycle = psxRegs.muldivBusyCycle;
+ misc->biuReg = psxRegs.biuReg;
+ misc->biosBranchCheck = psxRegs.biosBranchCheck;
+ misc->gpuIdleAfter = psxRegs.gpuIdleAfter;
+ misc->gpuSr = HW_GPU_STATUS;
+ misc->frame_counter = frame_counter;
+ misc->CdromFrontendId = CdromFrontendId;
f = SaveFuncs.open(file, "wb");
if (f == NULL) return -1;
- new_dyna_before_save();
+ psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, NULL);
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;
+ if (pMem == NULL) goto cleanup;
GPU_getScreenPic(pMem);
SaveFuncs.write(f, pMem, 128 * 96 * 3);
free(pMem);
SaveFuncs.write(f, psxM, 0x00200000);
SaveFuncs.write(f, psxR, 0x00080000);
SaveFuncs.write(f, psxH, 0x00010000);
- SaveFuncs.write(f, (void *)&psxRegs, sizeof(psxRegs));
+ // only partial save of psxRegisters to maintain savestate compat
+ SaveFuncs.write(f, &psxRegs, offsetof(psxRegisters, gteBusyCycle));
// gpu
gpufP = (GPUFreeze_t *)malloc(sizeof(GPUFreeze_t));
+ if (gpufP == NULL) goto cleanup;
gpufP->ulFreezeVersion = 1;
GPU_freeze(1, gpufP);
SaveFuncs.write(f, gpufP, sizeof(GPUFreeze_t));
- free(gpufP);
+ free(gpufP); gpufP = NULL;
// spu
- spufP = (SPUFreeze_t *) malloc(16);
- SPU_freeze(2, spufP, psxRegs.cycle);
- Size = spufP->Size; SaveFuncs.write(f, &Size, 4);
- free(spufP);
+ SPU_freeze(2, (SPUFreeze_t *)&spufH, psxRegs.cycle);
+ Size = spufH.Size; SaveFuncs.write(f, &Size, 4);
spufP = (SPUFreeze_t *) malloc(Size);
+ if (spufP == NULL) goto cleanup;
SPU_freeze(1, spufP, psxRegs.cycle);
SaveFuncs.write(f, spufP, Size);
- free(spufP);
+ free(spufP); spufP = NULL;
sioFreeze(f, 1);
cdrFreeze(f, 1);
psxRcntFreeze(f, 1);
mdecFreeze(f, 1);
new_dyna_freeze(f, 1);
+ padFreeze(f, 1);
+ result = 0;
+cleanup:
+ memset(misc, 0, sizeof(*misc));
SaveFuncs.close(f);
-
- new_dyna_after_save();
-
- return 0;
+ return result;
}
int LoadState(const char *file) {
+ struct misc_save_data *misc = (void *)(psxH + 0xf000);
+ u32 biosBranchCheckOld = psxRegs.biosBranchCheck;
void *f;
- GPUFreeze_t *gpufP;
- SPUFreeze_t *spufP;
+ GPUFreeze_t *gpufP = NULL;
+ SPUFreeze_t *spufP = NULL;
int Size;
char header[32];
u32 version;
boolean hle;
+ int result = -1;
f = SaveFuncs.open(file, "rb");
if (f == NULL) return -1;
SaveFuncs.read(f, &hle, sizeof(boolean));
if (strncmp("STv4 PCSX", header, 9) != 0 || version != SaveVersion) {
- SaveFuncs.close(f);
- return -1;
+ SysPrintf("incompatible savestate version %x\n", version);
+ goto cleanup;
}
Config.HLE = hle;
if (Config.HLE)
psxBiosInit();
-#if defined(LIGHTREC)
- if (Config.Cpu != CPU_INTERPRETER)
- psxCpu->Clear(0, UINT32_MAX); //clear all
- else
-#endif
- psxCpu->Reset();
SaveFuncs.seek(f, 128 * 96 * 3, SEEK_CUR);
-
SaveFuncs.read(f, psxM, 0x00200000);
SaveFuncs.read(f, psxR, 0x00080000);
SaveFuncs.read(f, psxH, 0x00010000);
- SaveFuncs.read(f, (void *)&psxRegs, sizeof(psxRegs));
+ 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);
+ if (misc->magic == MISC_MAGIC) {
+ psxRegs.gteBusyCycle = misc->gteBusyCycle;
+ psxRegs.muldivBusyCycle = misc->muldivBusyCycle;
+ psxRegs.biuReg = misc->biuReg;
+ psxRegs.biosBranchCheck = misc->biosBranchCheck;
+ psxRegs.gpuIdleAfter = misc->gpuIdleAfter;
+ HW_GPU_STATUS = misc->gpuSr;
+ frame_counter = misc->frame_counter;
+ CdromFrontendId = misc->CdromFrontendId;
+ }
+
+ psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, NULL);
if (Config.HLE)
psxBiosFreeze(0);
// gpu
gpufP = (GPUFreeze_t *)malloc(sizeof(GPUFreeze_t));
+ if (gpufP == NULL) goto cleanup;
SaveFuncs.read(f, gpufP, sizeof(GPUFreeze_t));
GPU_freeze(0, gpufP);
free(gpufP);
- if (HW_GPU_STATUS == 0)
- HW_GPU_STATUS = GPU_readStatus();
+ gpuSyncPluginSR();
// spu
SaveFuncs.read(f, &Size, 4);
spufP = (SPUFreeze_t *)malloc(Size);
+ if (spufP == NULL) goto cleanup;
SaveFuncs.read(f, spufP, Size);
SPU_freeze(0, spufP, psxRegs.cycle);
free(spufP);
psxRcntFreeze(f, 0);
mdecFreeze(f, 0);
new_dyna_freeze(f, 0);
+ padFreeze(f, 0);
- SaveFuncs.close(f);
+ events_restore();
+ if (Config.HLE)
+ psxBiosCheckExe(biosBranchCheckOld, 0x60, 1);
- return 0;
+ result = 0;
+cleanup:
+ memset(misc, 0, sizeof(*misc));
+ SaveFuncs.close(f);
+ return result;
}
int CheckState(const char *file) {
if (NET_recvData == NULL || NET_sendData == NULL)
return 0;
+ boolean Sio_old = 0;
+ boolean SpuIrq_old = 0;
+ boolean RCntFix_old = 0;
NET_sendData(&Config.Xa, sizeof(Config.Xa), PSE_NET_BLOCKING);
- NET_sendData(&Config.Sio, sizeof(Config.Sio), PSE_NET_BLOCKING);
- NET_sendData(&Config.SpuIrq, sizeof(Config.SpuIrq), PSE_NET_BLOCKING);
- NET_sendData(&Config.RCntFix, sizeof(Config.RCntFix), PSE_NET_BLOCKING);
+ NET_sendData(&Sio_old, sizeof(Sio_old), PSE_NET_BLOCKING);
+ NET_sendData(&SpuIrq_old, sizeof(SpuIrq_old), PSE_NET_BLOCKING);
+ NET_sendData(&RCntFix_old, sizeof(RCntFix_old), PSE_NET_BLOCKING);
NET_sendData(&Config.PsxType, sizeof(Config.PsxType), PSE_NET_BLOCKING);
NET_sendData(&Config.Cpu, sizeof(Config.Cpu), PSE_NET_BLOCKING);
if (NET_recvData == NULL || NET_sendData == NULL)
return 0;
+ boolean Sio_old = 0;
+ boolean SpuIrq_old = 0;
+ boolean RCntFix_old = 0;
NET_recvData(&Config.Xa, sizeof(Config.Xa), PSE_NET_BLOCKING);
- NET_recvData(&Config.Sio, sizeof(Config.Sio), PSE_NET_BLOCKING);
- NET_recvData(&Config.SpuIrq, sizeof(Config.SpuIrq), PSE_NET_BLOCKING);
- NET_recvData(&Config.RCntFix, sizeof(Config.RCntFix), PSE_NET_BLOCKING);
+ NET_recvData(&Sio_old, sizeof(Sio_old), PSE_NET_BLOCKING);
+ NET_recvData(&SpuIrq_old, sizeof(SpuIrq_old), PSE_NET_BLOCKING);
+ NET_recvData(&RCntFix_old, sizeof(RCntFix_old), PSE_NET_BLOCKING);
NET_recvData(&Config.PsxType, sizeof(Config.PsxType), PSE_NET_BLOCKING);
- SysUpdate();
-
tmp = Config.Cpu;
NET_recvData(&Config.Cpu, sizeof(Config.Cpu), PSE_NET_BLOCKING);
if (tmp != Config.Cpu) {
psxCpu->Shutdown();
-#if defined(NEW_DYNAREC) || defined(LIGHTREC)
+#ifndef DRC_DISABLE
if (Config.Cpu == CPU_INTERPRETER) psxCpu = &psxInt;
else psxCpu = &psxRec;
#else
SysClose(); return -1;
}
psxCpu->Reset();
+ psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, NULL);
}
return 0;