overwrite dynarec related code with upstream version
[pcsx_rearmed.git] / libpcsxcore / misc.c
index a27f60f..be501a2 100644 (file)
 * 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] = "";
@@ -73,7 +75,7 @@ void mmssdd( char *b, char *p )
 
        m = ((m / 10) << 4) | m % 10;
        s = ((s / 10) << 4) | s % 10;
-       d = ((d / 10) << 4) | d % 10;   
+       d = ((d / 10) << 4) | d % 10;
 
        p[0] = m;
        p[1] = s;
@@ -180,7 +182,7 @@ int LoadCdrom() {
        // is just below, do it here
        fake_bios_gpu_setup();
 
-       if (!Config.HLE) {
+       if (!Config.HLE && !Config.SlowBoot) {
                // skip BIOS logos
                psxRegs.pc = psxRegs.GPR.n.ra;
                return 0;
@@ -191,7 +193,7 @@ int LoadCdrom() {
        READTRACK();
 
        // skip head and sub, and go to the root directory record
-       dir = (struct iso_directory_record*) &buf[12+156]; 
+       dir = (struct iso_directory_record*) &buf[12+156];
 
        mmssdd(dir->extent, (char*)time);
 
@@ -208,9 +210,9 @@ int LoadCdrom() {
                // 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((char *)buf + 12, "cdrom:");
                                if (ptr != NULL) {
@@ -236,13 +238,14 @@ int LoadCdrom() {
 
        psxRegs.pc = SWAP32(tmpHead.pc0);
        psxRegs.GPR.n.gp = SWAP32(tmpHead.gp0);
-       psxRegs.GPR.n.sp = SWAP32(tmpHead.s_addr); 
+       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);
+       psxCpu->Reset();
 
        // Read the rest of the main executable
        while (tmpHead.t_size & ~2047) {
@@ -268,14 +271,14 @@ int LoadCdromFile(const char *filename, EXE_HEADER *head) {
        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);
 
        READTRACK();
 
        // skip head and sub, and go to the root directory record
-       dir = (struct iso_directory_record *)&buf[12 + 156]; 
+       dir = (struct iso_directory_record *)&buf[12 + 156];
 
        mmssdd(dir->extent, (char*)time);
 
@@ -290,6 +293,7 @@ int LoadCdromFile(const char *filename, EXE_HEADER *head) {
        addr = head->t_addr;
 
        psxCpu->Clear(addr, size / 4);
+       psxCpu->Reset();
 
        while (size & ~2047) {
                incTime();
@@ -312,7 +316,7 @@ int CheckCdrom() {
        char *buf;
        unsigned char mdir[4096];
        char exename[256];
-       int i, c;
+       int i, len, c;
 
        FreePPFCache();
 
@@ -322,13 +326,14 @@ int CheckCdrom() {
 
        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);
 
        // skip head and sub, and go to the root directory record
-       dir = (struct iso_directory_record *)&buf[12 + 156]; 
+       dir = (struct iso_directory_record *)&buf[12 + 156];
 
        mmssdd(dir->extent, (char *)time);
 
@@ -337,9 +342,9 @@ int CheckCdrom() {
        if (GetCdromFile(mdir, time, "SYSTEM.CNF;1") != -1) {
                READTRACK();
 
-               sscanf(buf + 12, "BOOT = cdrom:\\%256s", exename);
+               sscanf(buf + 12, "BOOT = cdrom:\\%255s", exename);
                if (GetCdromFile(mdir, time, exename) == -1) {
-                       sscanf(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) {
@@ -356,6 +361,14 @@ int CheckCdrom() {
                                        return -1;
                        }
                }
+               /* Workaround for Wild Arms EU/US which has non-standard string causing incorrect region detection */
+               if (exename[0] == 'E' && exename[1] == 'X' && exename[2] == 'E' && exename[3] == '\\') {
+                       size_t offset = 4;
+                       size_t i, len = strlen(exename) - offset;
+                       for (i = 0; i < len; i++)
+                               exename[i] = exename[i + offset];
+                       exename[i] = '\0';
+               }
        } else if (GetCdromFile(mdir, time, "PSX.EXE;1") != -1) {
                strcpy(exename, "PSX.EXE;1");
                strcpy(CdromId, "SLUS99999");
@@ -363,14 +376,13 @@ int CheckCdrom() {
                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];
                }
        }
 
@@ -378,7 +390,13 @@ int CheckCdrom() {
                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
        }
@@ -388,6 +406,9 @@ int CheckCdrom() {
        }
        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();
 
@@ -402,7 +423,9 @@ static int PSXGetFileType(FILE *f) {
 
        current = ftell(f);
        fseek(f, 0L, SEEK_SET);
-       fread(mybuf, 2048, 1, f);
+       if (fread(&mybuf, sizeof(mybuf), 1, f) != sizeof(mybuf))
+               goto io_fail;
+       
        fseek(f, current, SEEK_SET);
 
        exe_hdr = (EXE_HEADER *)mybuf;
@@ -417,6 +440,12 @@ static int PSXGetFileType(FILE *f) {
                return COFF_EXE;
 
        return INVALID_EXE;
+
+io_fail:
+#ifndef NDEBUG
+       SysPrintf(_("File IO error in <%s:%s>.\n"), __FILE__, __func__);
+#endif
+       return INVALID_EXE;
 }
 
 // temporary pandora workaround..
@@ -425,7 +454,7 @@ 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);
@@ -444,8 +473,8 @@ int Load(const char *ExePath) {
        u32 section_address, section_size;
        void *mem;
 
-       strncpy(CdromId, "SLUS99999", 9);
-       strncpy(CdromLabel, "SLUS_999.99", 11);
+       strcpy(CdromId, "SLUS99999");
+       strcpy(CdromLabel, "SLUS_999.99");
 
        tmpFile = fopen(ExePath, "rb");
        if (tmpFile == NULL) {
@@ -455,19 +484,19 @@ int Load(const char *ExePath) {
                type = PSXGetFileType(tmpFile);
                switch (type) {
                        case PSX_EXE:
-                               fread(&tmpHead,sizeof(EXE_HEADER),1,tmpFile);
+                               if (fread(&tmpHead, sizeof(EXE_HEADER), 1, 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) {
-                                       fseek(tmpFile, 0x800, SEEK_SET);                
+                                       fseek(tmpFile, 0x800, SEEK_SET);
                                        fread_to_ram(mem, section_size, 1, tmpFile);
                                        psxCpu->Clear(section_address, section_size / 4);
                                }
-                               fclose(tmpFile);
                                psxRegs.pc = SWAP32(tmpHead.pc0);
                                psxRegs.GPR.n.gp = SWAP32(tmpHead.gp0);
-                               psxRegs.GPR.n.sp = SWAP32(tmpHead.s_addr); 
+                               psxRegs.GPR.n.sp = SWAP32(tmpHead.s_addr);
                                if (psxRegs.GPR.n.sp == 0)
                                        psxRegs.GPR.n.sp = 0x801fff00;
                                retval = 0;
@@ -475,11 +504,14 @@ int Load(const char *ExePath) {
                        case CPE_EXE:
                                fseek(tmpFile, 6, SEEK_SET); /* Something tells me we should go to 4 and read the "08 00" here... */
                                do {
-                                       fread(&opcode, 1, 1, tmpFile);
+                                       if (fread(&opcode, sizeof(opcode), 1, tmpFile) != sizeof(opcode))
+                                               goto fail_io;
                                        switch (opcode) {
                                                case 1: /* Section loading */
-                                                       fread(&section_address, 4, 1, tmpFile);
-                                                       fread(&section_size, 4, 1, tmpFile);
+                                                       if (fread(&section_address, sizeof(section_address), 1, tmpFile) != sizeof(section_address))
+                                                               goto fail_io;
+                                                       if (fread(&section_size, sizeof(section_size), 1, tmpFile) != sizeof(section_size))
+                                                               goto fail_io;
                                                        section_address = SWAPu32(section_address);
                                                        section_size = SWAPu32(section_size);
 #ifdef EMU_LOG
@@ -493,7 +525,8 @@ int Load(const char *ExePath) {
                                                        break;
                                                case 3: /* register loading (PC only?) */
                                                        fseek(tmpFile, 2, SEEK_CUR); /* unknown field */
-                                                       fread(&psxRegs.pc, 4, 1, tmpFile);
+                                                       if (fread(&psxRegs.pc, sizeof(psxRegs.pc), 1, tmpFile) != sizeof(psxRegs.pc))
+                                                               goto fail_io;
                                                        psxRegs.pc = SWAPu32(psxRegs.pc);
                                                        break;
                                                case 0: /* End of file */
@@ -522,7 +555,15 @@ int Load(const char *ExePath) {
                CdromLabel[0] = '\0';
        }
 
+       fclose(tmpFile);
        return retval;
+
+fail_io:
+#ifndef NDEBUG
+       SysPrintf(_("File IO error in <%s:%s>.\n"), __FILE__, __func__);
+#endif
+       fclose(tmpFile);
+       return -1;
 }
 
 // STATES
@@ -556,7 +597,7 @@ struct PcsxSaveFuncs SaveFuncs = {
        zlib_open, zlib_read, zlib_write, zlib_seek, zlib_close
 };
 
-static const char PcsxHeader[32] = "STv4 PCSX v" PACKAGE_VERSION;
+static const char PcsxHeader[32] = "STv4 PCSX v" PCSX_VERSION;
 
 // Savestate Versioning!
 // If you make changes to the savestate version, please increment the value below.
@@ -572,7 +613,7 @@ int SaveState(const char *file) {
        f = SaveFuncs.open(file, "wb");
        if (f == NULL) return -1;
 
-       new_dyna_save();
+       new_dyna_before_save();
 
        SaveFuncs.write(f, (void *)PcsxHeader, 32);
        SaveFuncs.write(f, (void *)&SaveVersion, sizeof(u32));
@@ -590,7 +631,8 @@ int SaveState(const char *file) {
        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));
@@ -601,11 +643,11 @@ int SaveState(const char *file) {
 
        // spu
        spufP = (SPUFreeze_t *) malloc(16);
-       SPU_freeze(2, spufP);
+       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);
+       SPU_freeze(1, spufP, psxRegs.cycle);
        SaveFuncs.write(f, spufP, Size);
        free(spufP);
 
@@ -614,6 +656,7 @@ int SaveState(const char *file) {
        psxHwFreeze(f, 1);
        psxRcntFreeze(f, 1);
        mdecFreeze(f, 1);
+       new_dyna_freeze(f, 1);
 
        SaveFuncs.close(f);
 
@@ -647,13 +690,19 @@ int LoadState(const char *file) {
        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;
 
        if (Config.HLE)
                psxBiosFreeze(0);
@@ -670,7 +719,7 @@ int LoadState(const char *file) {
        SaveFuncs.read(f, &Size, 4);
        spufP = (SPUFreeze_t *)malloc(Size);
        SaveFuncs.read(f, spufP, Size);
-       SPU_freeze(0, spufP);
+       SPU_freeze(0, spufP, psxRegs.cycle);
        free(spufP);
 
        sioFreeze(f, 0);
@@ -678,9 +727,9 @@ int LoadState(const char *file) {
        psxHwFreeze(f, 0);
        psxRcntFreeze(f, 0);
        mdecFreeze(f, 0);
+       new_dyna_freeze(f, 0);
 
        SaveFuncs.close(f);
-       new_dyna_restore();
 
        return 0;
 }
@@ -740,7 +789,7 @@ int RecvPcsxInfo() {
        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