cdrom: change pause timing again
[pcsx_rearmed.git] / libpcsxcore / misc.c
index 702f690..889639d 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>
 
 char CdromId[10] = "";
 char CdromLabel[33] = "";
+int  CdromFrontendId; // for frontend use
 
 // PSX Executable types
 #define PSX_EXE     1
@@ -112,7 +115,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) {
@@ -160,12 +163,19 @@ static void SetBootRegs(u32 pc, u32 gp, u32 sp)
        psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, NULL);
 }
 
-void BiosBootBypass() {
+int BiosBootBypass() {
+       struct CdrStat stat = { 0, 0, };
        assert(psxRegs.pc == 0x80030000);
 
+       // no bypass if the lid is open
+       CDR__getStatus(&stat);
+       if (stat.Status & 0x10)
+               return 0;
+
        // skip BIOS logos and region check
        psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, NULL);
        psxRegs.pc = psxRegs.GPR.n.ra;
+       return 1;
 }
 
 static void getFromCnf(char *buf, const char *key, u32 *val)
@@ -173,12 +183,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];
@@ -186,8 +204,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?
@@ -243,43 +263,45 @@ 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' pc=%x\n", exename, SWAP32(tmpHead.pc0));
-       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;
 }
 
-int LoadCdromFile(const char *filename, EXE_HEADER *head) {
+int LoadCdromFile(const char *filename, EXE_HEADER *head, u8 *time_bcd_out) {
        struct iso_directory_record *dir;
        u8 time[4],*buf;
        u8 mdir[4096];
@@ -312,6 +334,7 @@ int LoadCdromFile(const char *filename, EXE_HEADER *head) {
        if (GetCdromFile(mdir, time, exename) == -1) return -1;
 
        READTRACK();
+       incTime();
 
        memcpy(head, buf + 12, sizeof(EXE_HEADER));
        size = SWAP32(head->t_size);
@@ -321,8 +344,8 @@ int LoadCdromFile(const char *filename, EXE_HEADER *head) {
        //psxCpu->Reset();
 
        while (size & ~2047) {
-               incTime();
                READTRACK();
+               incTime();
 
                mem = PSXM(addr);
                if (mem != INVALID_PTR)
@@ -331,12 +354,15 @@ int LoadCdromFile(const char *filename, EXE_HEADER *head) {
                size -= 2048;
                addr += 2048;
        }
+       if (time_bcd_out)
+               memcpy(time_bcd_out, time, 3);
 
        return 0;
 }
 
 int CheckCdrom() {
        struct iso_directory_record *dir;
+       struct CdrStat stat = { 0, 0, };
        unsigned char time[4];
        char *buf;
        unsigned char mdir[4096];
@@ -344,17 +370,22 @@ int CheckCdrom() {
        int i, len, c;
 
        FreePPFCache();
+       memset(CdromLabel, 0, sizeof(CdromLabel));
+       memset(CdromId, 0, sizeof(CdromId));
+       memset(exename, 0, sizeof(exename));
 
        time[0] = itob(0);
        time[1] = itob(2);
        time[2] = itob(0x10);
 
+       if (!Config.HLE && Config.SlowBoot) {
+               // boot to BIOS in case of CDDA ir lid open
+               CDR_getStatus(&stat);
+               if ((stat.Status & 0x10) || stat.Type == 2 || !CDR_readTrack(time))
+                       return 0;
+       }
        READTRACK();
 
-       memset(CdromLabel, 0, sizeof(CdromLabel));
-       memset(CdromId, 0, sizeof(CdromId));
-       memset(exename, 0, sizeof(exename));
-
        strncpy(CdromLabel, buf + 52, 32);
 
        // skip head and sub, and go to the root directory record
@@ -626,7 +657,21 @@ static const char PcsxHeader[32] = "STv4 PCSX v" PCSX_VERSION;
 // 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 = NULL;
        SPUFreezeHdr_t spufH;
@@ -635,9 +680,23 @@ int SaveState(const char *file) {
        int result = -1;
        int Size;
 
+       assert(!psxRegs.branching);
+       assert(!psxRegs.cpuInRecursion);
+       assert(!misc->magic);
+
        f = SaveFuncs.open(file, "wb");
        if (f == NULL) return -1;
 
+       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;
+
        psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, NULL);
 
        SaveFuncs.write(f, (void *)PcsxHeader, 32);
@@ -682,14 +741,18 @@ int SaveState(const char *file) {
        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);
        return result;
 }
 
 int LoadState(const char *file) {
+       struct misc_save_data *misc = (void *)(psxH + 0xf000);
+       u32 biosBranchCheckOld = psxRegs.biosBranchCheck;
        void *f;
        GPUFreeze_t *gpufP = NULL;
        SPUFreeze_t *spufP = NULL;
@@ -721,6 +784,19 @@ int LoadState(const char *file) {
        SaveFuncs.read(f, psxH, 0x00010000);
        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);
 
@@ -733,8 +809,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);
@@ -750,9 +825,15 @@ int LoadState(const char *file) {
        psxRcntFreeze(f, 0);
        mdecFreeze(f, 0);
        new_dyna_freeze(f, 0);
+       padFreeze(f, 0);
+
+       events_restore();
+       if (Config.HLE)
+               psxBiosCheckExe(biosBranchCheckOld, 0x60, 1);
 
        result = 0;
 cleanup:
+       memset(misc, 0, sizeof(*misc));
        SaveFuncs.close(f);
        return result;
 }