eliminate event code duplication
[pcsx_rearmed.git] / libpcsxcore / misc.c
index 252e1c8..f332f43 100644 (file)
 */
 
 #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>
 
@@ -112,7 +114,7 @@ int GetCdromFile(u8 *mdir, u8 *time, char *filename) {
        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) {
@@ -144,30 +146,6 @@ int GetCdromFile(u8 *mdir, u8 *time, char *filename) {
        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,
-};
-
-void BiosLikeGPUSetup()
-{
-       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]);
-
-       HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
-}
-
 static void SetBootRegs(u32 pc, u32 gp, u32 sp)
 {
        //printf("%s %08x %08x %08x\n", __func__, pc, gp, sp);
@@ -176,6 +154,10 @@ static void SetBootRegs(u32 pc, u32 gp, u32 sp)
        psxRegs.pc = pc;
        psxRegs.GPR.n.gp = gp;
        psxRegs.GPR.n.sp = sp ? sp : 0x801fff00;
+       psxRegs.GPR.n.fp = psxRegs.GPR.n.sp;
+
+       psxRegs.GPR.n.t0 = psxRegs.GPR.n.sp; // mimic A(43)
+       psxRegs.GPR.n.t3 = pc;
 
        psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, NULL);
 }
@@ -193,12 +175,20 @@ static void getFromCnf(char *buf, const char *key, u32 *val)
        buf = strstr(buf, key);
        if (buf)
                buf = strchr(buf, '=');
-       if (buf)
-               *val = strtol(buf + 1, NULL, 16);
+       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];
@@ -206,8 +196,10 @@ int LoadCdrom() {
        u32 cnf_tcb = 4;
        u32 cnf_event = 16;
        u32 cnf_stack = 0;
+       u32 t_addr;
+       u32 t_size;
        u32 sp = 0;
-       int ret;
+       int i, ret;
 
        if (!Config.HLE) {
                if (psxRegs.pc != 0x80030000) // BiosBootBypass'ed or custom BIOS?
@@ -263,39 +255,41 @@ int LoadCdrom() {
                getFromCnf((char *)buf + 12, "EVENT", &cnf_event);
                getFromCnf((char *)buf + 12, "STACK", &cnf_stack);
                if (Config.HLE)
-                       psxBiosCnfLoaded(cnf_tcb, cnf_event);
+                       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]);
 
-       SysPrintf("manual booting '%s'\n", exename);
-       sp = SWAP32(tmpHead.s_addr);
+       SysPrintf("manual booting '%s' pc=%x\n", exename, tmpHead.h.pc0);
+       sp = tmpHead.h.s_addr;
        if (cnf_stack)
                sp = cnf_stack;
-       SetBootRegs(SWAP32(tmpHead.pc0), SWAP32(tmpHead.gp0), sp);
-
-       tmpHead.t_size = SWAP32(tmpHead.t_size);
-       tmpHead.t_addr = SWAP32(tmpHead.t_addr);
-
-       psxCpu->Clear(tmpHead.t_addr, tmpHead.t_size / 4);
-       psxCpu->Reset();
+       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 != 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;
 }
 
@@ -304,10 +298,19 @@ int LoadCdromFile(const char *filename, EXE_HEADER *head) {
        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);
 
@@ -325,11 +328,11 @@ int LoadCdromFile(const char *filename, EXE_HEADER *head) {
        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();
+       //psxCpu->Reset();
 
        while (size & ~2047) {
                incTime();
@@ -639,11 +642,12 @@ static const u32 SaveVersion = 0x8b410006;
 
 int SaveState(const char *file) {
        void *f;
-       GPUFreeze_t *gpufP;
-       SPUFreezeHdr_t *spufH;
-       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;
 
        f = SaveFuncs.open(file, "wb");
        if (f == NULL) return -1;
@@ -655,7 +659,7 @@ int SaveState(const char *file) {
        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);
@@ -671,20 +675,20 @@ int SaveState(const char *file) {
 
        // 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
-       spufH = malloc(sizeof(*spufH));
-       SPU_freeze(2, (SPUFreeze_t *)spufH, psxRegs.cycle);
-       Size = spufH->Size; SaveFuncs.write(f, &Size, 4);
-       free(spufH);
+       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);
@@ -692,20 +696,24 @@ int SaveState(const char *file) {
        psxRcntFreeze(f, 1);
        mdecFreeze(f, 1);
        new_dyna_freeze(f, 1);
+       padFreeze(f, 1);
 
+       result = 0;
+cleanup:
        SaveFuncs.close(f);
-
-       return 0;
+       return result;
 }
 
 int LoadState(const char *file) {
+       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;
@@ -715,8 +723,8 @@ int LoadState(const char *file) {
        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;
 
@@ -729,6 +737,7 @@ int LoadState(const char *file) {
        SaveFuncs.read(f, psxH, 0x00010000);
        SaveFuncs.read(f, &psxRegs, offsetof(psxRegisters, gteBusyCycle));
        psxRegs.gteBusyCycle = psxRegs.cycle;
+       psxRegs.biosBranchCheck = ~0;
 
        psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, NULL);
 
@@ -737,6 +746,7 @@ int LoadState(const char *file) {
 
        // 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);
@@ -746,6 +756,7 @@ int LoadState(const char *file) {
        // 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);
@@ -756,10 +767,16 @@ int LoadState(const char *file) {
        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:
+       SaveFuncs.close(f);
+       return result;
 }
 
 int CheckState(const char *file) {