psxbios: unbreak bcopy
[pcsx_rearmed.git] / libpcsxcore / psxbios.c
index 313bc50..17d5044 100644 (file)
 #include "gpu.h"
 #include "sio.h"
 #include "psxhle.h"
+#include "psxinterpreter.h"
 #include <zlib.h>
 
 #if (defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)
 #pragma GCC diagnostic ignored "-Wpointer-sign"
 #endif
 
-#undef SysPrintf
-#define SysPrintf if (Config.PsxOut) printf
+#ifndef PSXBIOS_LOG
+//#define PSXBIOS_LOG printf
+#define PSXBIOS_LOG(...)
+#endif
 
 char *biosA0n[256] = {
 // 0x00
@@ -66,9 +69,9 @@ char *biosA0n[256] = {
        "realloc",      "InitHeap",     "_exit",        "getchar",
        "putchar",      "gets",         "puts",         "printf",
 // 0x40
-       "sys_a0_40",            "LoadTest",                                     "Load",         "Exec",
+       "SystemErrorUnresolvedException", "LoadTest",           "Load",         "Exec",
        "FlushCache",           "InstallInterruptHandler",      "GPU_dw",       "mem2vram",
-       "SendGPUStatus",        "GPU_cw",                                       "GPU_cwb",      "SendPackets",
+       "SendGPUStatus",        "GPU_cw",                       "GPU_cwb",      "SendPackets",
        "sys_a0_4c",            "GetGPUStatus",                         "GPU_sync",     "sys_a0_4f",
 // 0x50
        "sys_a0_50",            "LoadExec",                             "GetSysSp",             "sys_a0_53",
@@ -102,7 +105,7 @@ char *biosA0n[256] = {
        "_card_load",           "_card_auto",   "bufs_cd_4",            "sys_a0_af",
 // 0xb0
        "sys_a0_b0",            "sys_a0_b1",    "do_a_long_jmp",        "sys_a0_b3",
-       "?? sub_function",
+       "GetSystemInfo",
 };
 
 char *biosB0n[256] = {
@@ -181,7 +184,7 @@ char *biosC0n[256] = {
 #define k1 (psxRegs.GPR.n.k1)
 #define gp (psxRegs.GPR.n.gp)
 #define sp (psxRegs.GPR.n.sp)
-#define fp (psxRegs.GPR.n.s8)
+#define fp (psxRegs.GPR.n.fp)
 #define ra (psxRegs.GPR.n.ra)
 #define pc0 (psxRegs.pc)
 
@@ -224,10 +227,10 @@ typedef struct {
        u32 gp0;
        u32 t_addr;
        u32 t_size;
-       u32 d_addr;
+       u32 d_addr; // 10
        u32 d_size;
        u32 b_addr;
-       u32 b_size;
+       u32 b_size; // 1c
        u32 S_addr;
        u32 s_size;
        u32 _sp, _fp, _gp, ret, base;
@@ -250,12 +253,11 @@ typedef struct {
        u32  mcfile;
 } FileDesc;
 
-static int *pad_buf = NULL;
-static u32 heap_size = 0;
-static u32 *heap_addr = NULL;
-static u32 *heap_end = NULL;
+// todo: FileDesc layout is wrong
+// todo: get rid of these globals
 static FileDesc FDesc[32];
-static u32 card_active_chan = 0;
+static char ffile[64], *pfile;
+static int nfile;
 
 // fixed RAM offsets, SCPH1001 compatible
 #define A_TT_ExCB       0x0100
@@ -272,17 +274,25 @@ static u32 card_active_chan = 0;
 #define A_KMALLOC_PTR   0x7460
 #define A_KMALLOC_SIZE  0x7464
 #define A_KMALLOC_END   0x7468
-#define A_PADCRD_CHN_E  0x74a8  // pad/card irq chain entry
+#define A_PADCRD_CHN_E  0x74a8  // pad/card irq chain entry, see hleExcPadCard1()
 #define A_PAD_IRQR_ENA  0x74b8  // pad read on vint irq (nocash 'pad_enable_flag')
 #define A_CARD_IRQR_ENA 0x74bc  // same for card
 #define A_PAD_INBUF     0x74c8  // 2x buffers for rx pad data
 #define A_PAD_OUTBUF    0x74d0  // 2x buffers for tx pad data
 #define A_PAD_IN_LEN    0x74d8
 #define A_PAD_OUT_LEN   0x74e0
+#define A_PAD_DR_DST    0x74c4
+#define A_CARD_CHAN1    0x7500
+#define A_PAD_DR_BUF1   0x7570
+#define A_PAD_DR_BUF2   0x7598
 #define A_EEXIT_PTR     0x75d0
 #define A_EXC_STACK     0x85d8  // exception stack top
 #define A_RCNT_VBL_ACK  0x8600
 #define A_PAD_ACK_VBL   0x8914  // enable vint ack by pad reading code
+#define A_HEAP_BASE     0x9000
+#define A_HEAP_SIZE     0x9004
+#define A_HEAP_END      0x9008
+#define A_HEAP_FLAG     0x900c
 #define A_CD_EVENTS     0xb9b8
 #define A_EXC_GP        0xf450
 
@@ -360,25 +370,31 @@ static int returned_from_exception(void)
 static inline void softCall(u32 pc) {
        u32 sra = ra;
        u32 ssr = psxRegs.CP0.n.SR;
+       u32 lim = 0;
        pc0 = pc;
        ra = 0x80001000;
        psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
 
-       while (pc0 != 0x80001000)
+       while (pc0 != 0x80001000 && ++lim < 1000000)
                psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
 
+       if (lim == 1000000)
+               PSXBIOS_LOG("softCall @%x hit lim\n", pc);
        ra = sra;
-       psxRegs.CP0.n.SR = ssr;
+       psxRegs.CP0.n.SR |= ssr & 0x404;
 }
 
 static inline void softCallInException(u32 pc) {
        u32 sra = ra;
+       u32 lim = 0;
        pc0 = pc;
        ra = 0x80001000;
 
-       while (!returned_from_exception() && pc0 != 0x80001000)
+       while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 1000000)
                psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
 
+       if (lim == 1000000)
+               PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
        if (pc0 == 0x80001000)
                ra = sra;
 }
@@ -395,9 +411,10 @@ static void CloseEvent(u32 ev);
 
 
 #define buread(Ra1, mcd, length) { \
-       SysPrintf("read %d: %x,%x (%s)\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2, Mcd##mcd##Data + 128 * FDesc[1 + mcd].mcfile + 0xa); \
+       PSXBIOS_LOG("read %d: %x,%x (%s)\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2, Mcd##mcd##Data + 128 * FDesc[1 + mcd].mcfile + 0xa); \
        ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
        memcpy(Ra1, ptr, length); \
+       psxCpu->Clear(a1, (length + 3) / 4); \
        if (FDesc[1 + mcd].mode & 0x8000) { \
        DeliverEvent(0xf0000011, 0x0004); \
        DeliverEvent(0xf4000001, 0x0004); \
@@ -408,7 +425,7 @@ static void CloseEvent(u32 ev);
 
 #define buwrite(Ra1, mcd, length) { \
        u32 offset =  + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
-       SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
+       PSXBIOS_LOG("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
        ptr = Mcd##mcd##Data + offset; \
        memcpy(ptr, Ra1, length); \
        FDesc[1 + mcd].offset += length; \
@@ -420,11 +437,6 @@ static void CloseEvent(u32 ev);
        else v0 = length; \
 }
 
-#ifndef PSXBIOS_LOG
-//#define PSXBIOS_LOG printf
-#define PSXBIOS_LOG(...)
-#endif
-
 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
 /* For some strange reason, the returned character is sign-expanded; */
 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
@@ -893,37 +905,69 @@ void psxBios_tolower() { // 0x26
        pc0 = ra;
 }
 
-void psxBios_bcopy() { // 0x27
-       char *p1 = (char *)Ra1, *p2 = (char *)Ra0;
-       v0 = a0;
-       if (a0 == 0 || a2 > 0x7FFFFFFF)
-       {
-               pc0 = ra;
-               return;
+static void do_memset(u32 dst, u32 v, s32 len)
+{
+       u32 d = dst;
+       s32 l = len;
+       while (l-- > 0) {
+               u8 *db = PSXM(d);
+               if (db != INVALID_PTR)
+                       *db = v;
+               d++;
        }
-       while ((s32)a2-- > 0) *p1++ = *p2++;
-       a2 = 0;
-       pc0 = ra;
+       psxCpu->Clear(dst, (len + 3) / 4);
 }
 
-void psxBios_bzero() { // 0x28
-       char *p = (char *)Ra0;
-       v0 = a0;
-       /* Same as memset here (See memset below) */
-       if (a1 > 0x7FFFFFFF || a1 == 0)
+static void do_memcpy(u32 dst, u32 src, s32 len)
+{
+       u32 d = dst, s = src;
+       s32 l = len;
+       while (l-- > 0) {
+               const u8 *sb = PSXM(s);
+               u8 *db = PSXM(d);
+               if (db != INVALID_PTR && sb != INVALID_PTR)
+                       *db = *sb;
+               d++;
+               s++;
+       }
+       psxCpu->Clear(dst, (len + 3) / 4);
+}
+
+static void psxBios_memcpy();
+
+static void psxBios_bcopy() { // 0x27 - memcpy with args swapped
+       //PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x27], a0, a1, a2);
+       u32 ret = a0, cycles = 0;
+       if (a0 == 0) // ...but it checks src this time
        {
-               v0 = 0;
-               pc0 = ra;
+               mips_return_c(0, 4);
                return;
        }
-       else if (a0 == 0)
+       v1 = a0;
+       if ((s32)a2 > 0) {
+               do_memcpy(a1, a0, a2);
+               cycles = a2 * 6;
+               a0 += a2;
+               a1 += a2;
+               a2 = 0;
+       }
+       mips_return_c(ret, cycles + 5);
+}
+
+static void psxBios_bzero() { // 0x28
+       /* Same as memset here (See memset below) */
+       u32 ret = a0, cycles;
+       if (a0 == 0 || (s32)a1 <= 0)
        {
-               pc0 = ra;
+               mips_return_c(0, 6);
                return;
        }
-       while ((s32)a1-- > 0) *p++ = '\0';
+       do_memset(a0, 0, a1);
+       cycles = a1 * 4;
+       a0 += a1;
        a1 = 0;
-       pc0 = ra;
+       // todo: many more cycles due to uncached bios mem
+       mips_return_c(ret, cycles + 5);
 }
 
 void psxBios_bcmp() { // 0x29
@@ -942,57 +986,70 @@ void psxBios_bcmp() { // 0x29
        v0 = 0; pc0 = ra;
 }
 
-void psxBios_memcpy() { // 0x2a
-       char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
-       v0 = a0;
-       if (a0 == 0 || a2 > 0x7FFFFFFF)
+static void psxBios_memcpy() { // 0x2a
+       u32 ret = a0, cycles = 0;
+       if (a0 == 0)
        {
-               pc0 = ra;
+               mips_return_c(0, 4);
                return;
        }
-       while ((s32)a2-- > 0) {
-               *p1++ = *p2++;
+       if ((s32)a2 > 0) {
+               do_memcpy(a0, a1, a2);
+               cycles = a2 * 6;
+               v1 = a0;
+               a0 += a2;
+               a1 += a2;
+               a2 = 0;
        }
-       a2 = 0;
-       pc0 = ra;
+       mips_return_c(ret, cycles + 5);
 }
 
-void psxBios_memset() { // 0x2b
-       char *p = (char *)Ra0;
-       v0 = a0;
-       if (a2 > 0x7FFFFFFF || a2 == 0)
-       {
-               v0 = 0;
-               pc0 = ra;
-               return;
-       }
-       if (a0 == 0)
+static void psxBios_memset() { // 0x2b
+       u32 ret = a0, cycles;
+       if (a0 == 0 || (s32)a2 <= 0)
        {
-               pc0 = ra;
+               mips_return_c(0, 6);
                return;
        }
-       while ((s32)a2-- > 0) *p++ = (char)a1;
+       do_memset(a0, a1, a2);
+       cycles = a2 * 4;
+       a0 += a2;
        a2 = 0;
-       v0 = a0; pc0 = ra;
+       // todo: many more cycles due to uncached bios mem
+       mips_return_c(ret, cycles + 5);
 }
 
 void psxBios_memmove() { // 0x2c
-       char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
-       v0 = a0;
-       if (a0 == 0 || a2 > 0x7FFFFFFF)
+       u32 ret = a0, cycles = 0;
+       if (a0 == 0)
        {
-               pc0 = ra;
+               mips_return_c(0, 4);
                return;
        }
-       if (p2 <= p1 && p2 + a2 > p1) {
-               a2++; // BUG: copy one more byte here
-               p1 += a2;
-               p2 += a2;
-               while ((s32)a2-- > 0) *--p1 = *--p2;
-       } else {
-               while ((s32)a2-- > 0) *p1++ = *p2++;
+       v1 = a0;
+       if ((s32)a2 > 0 && a0 > a1 && a0 < a1 + a2) {
+               u32 dst = a0, len = a2 + 1;
+               a0 += a2;
+               a1 += a2;
+               while ((s32)a2 >= 0) { // BUG: copies one more byte here
+                       const u8 *sb = PSXM(a1);
+                       u8 *db = PSXM(a0);
+                       if (db != INVALID_PTR && sb != INVALID_PTR)
+                               *db = *sb;
+                       a0--;
+                       a1--;
+                       a2--;
+               }
+               psxCpu->Clear(dst, (len + 3) / 4);
+               cycles = 10 + len * 8;
+       } else if ((s32)a2 > 0) {
+               do_memcpy(a0, a1, a2);
+               cycles = a2 * 6;
+               a0 += a2;
+               a1 += a2;
+               a2 = 0;
        }
-       pc0 = ra;
+       mips_return_c(ret, cycles + 5);
 }
 
 void psxBios_memcmp() { // 0x2d
@@ -1136,14 +1193,16 @@ void psxBios_qsort() { // 0x31
        pc0 = ra;
 }
 
-void psxBios_malloc() { // 0x33
+// this isn't how the real bios works, but maybe good enough
+static void psxBios_malloc() { // 0x33
+       u32 *heap_addr, *heap_end;
        u32 *chunk, *newchunk = NULL;
        unsigned int dsize = 0, csize, cstat;
        int colflag;
-#ifdef PSXBIOS_LOG
-       PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]);
-#endif
-       if (!a0 || (!heap_size || !heap_addr)) {
+       PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x33], a0);
+       heap_addr = loadRam32ptr(A_HEAP_BASE);
+       heap_end = loadRam32ptr(A_HEAP_END);
+       if (heap_addr >= heap_end) {
                v0 = 0;
                pc0 = ra;
                return;
@@ -1240,30 +1299,24 @@ void psxBios_malloc() { // 0x33
        pc0 = ra;
 }
 
-void psxBios_free() { // 0x34
-
-#ifdef PSXBIOS_LOG
-       PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x34]);
-#endif
-
-       SysPrintf("free %x: %x bytes\n", a0, *(u32*)(Ra0-4));
-
-       if (a0)
-               *(u32*)(Ra0-4) |= 1;    // set chunk to free
-       pc0 = ra;
+static void psxBios_free() { // 0x34
+       PSXBIOS_LOG("psxBios_%s %x (%x bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
+       storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
+       mips_return_void_c(5);
 }
 
-void psxBios_calloc() { // 0x37
-       void *pv0;
-#ifdef PSXBIOS_LOG
-       PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]);
-#endif
+static void psxBios_calloc() { // 0x37
+       u32 ret, size;
+       PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
 
-       a0 = a0 * a1;
+       a0 = size = a0 * a1;
        psxBios_malloc();
-       pv0 = Rv0;
-       if (pv0)
-               memset(pv0, 0, a0);
+       ret = v0;
+       if (ret) {
+               a0 = ret; a1 = size;
+               psxBios_bzero();
+       }
+       mips_return_c(ret, 21);
 }
 
 void psxBios_realloc() { // 0x38
@@ -1296,27 +1349,16 @@ void psxBios_realloc() { // 0x38
 
 
 /* InitHeap(void *block , int n) */
-void psxBios_InitHeap() { // 0x39
-       unsigned int size;
-
-#ifdef PSXBIOS_LOG
-       PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x39]);
-#endif
+static void psxBios_InitHeap() { // 0x39
+       PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
 
-       if (((a0 & 0x1fffff) + a1)>= 0x200000) size = 0x1ffffc - (a0 & 0x1fffff);
-       else size = a1;
+       storeRam32(A_HEAP_BASE, a0);
+       storeRam32(A_HEAP_SIZE, a1);
+       storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
+       storeRam32(A_HEAP_FLAG, 0);
+       storeRam32(a0, 0);
 
-       size &= 0xfffffffc;
-
-       heap_addr = (u32 *)Ra0;
-       heap_size = size;
-       heap_end = (u32 *)((u8 *)heap_addr + heap_size);
-       /* HACKFIX: Commenting out this line fixes GTA2 crash */
-       //*heap_addr = SWAP32(size | 1);
-
-       SysPrintf("InitHeap %x,%x : %x %x\n",a0,a1, (int)((uptr)heap_addr-(uptr)psxM), size);
-
-       pc0 = ra;
+       mips_return_void_c(14);
 }
 
 void psxBios_getchar() { //0x3b
@@ -1391,7 +1433,8 @@ _start:
        if (psp != INVALID_PTR)
                memcpy(psp, save, 4 * 4);
 
-       SysPrintf("%s", tmp);
+       if (Config.PsxOut)
+               SysPrintf("%s", tmp);
 }
 
 void psxBios_printf() { // 0x3f
@@ -1421,7 +1464,7 @@ void psxBios_format() { // 0x41
 
 static void psxBios_SystemErrorUnresolvedException() {
        if (loadRam32(0xfffc) != 0x12345678) { // prevent log flood
-               SysPrintf("psxBios_%s\n", biosA0n[0x40]);
+               SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
                storeRam32(0xfffc, 0x12345678);
        }
        mips_return_void_c(1000);
@@ -1436,8 +1479,9 @@ void psxBios_Load() { // 0x42
        void *pa1;
 
        pa1 = Ra1;
-       if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
+       if (pa1 != INVALID_PTR && LoadCdromFile(Ra0, &eheader) == 0) {
                memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
+               psxCpu->Clear(a1, sizeof(EXEC) / 4);
                v0 = 1;
        } else v0 = 0;
        PSXBIOS_LOG("psxBios_%s: %s, %d -> %d\n", biosA0n[0x42], Ra0, a1, v0);
@@ -1450,27 +1494,30 @@ void psxBios_Load() { // 0x42
  */
 
 void psxBios_Exec() { // 43
-       EXEC *header = (EXEC*)Ra0;
-       u32 tmp;
+       EXEC *header = (EXEC *)castRam32ptr(a0);
+       u32 ptr;
+       s32 len;
 
-#ifdef PSXBIOS_LOG
        PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
-#endif
 
-       header->_sp = sp;
-       header->_fp = fp;
-       header->_sp = sp;
-       header->_gp = gp;
-       header->ret = ra;
-       header->base = s0;
+       header->_sp = SWAP32(sp);
+       header->_fp = SWAP32(fp);
+       header->_sp = SWAP32(sp);
+       header->_gp = SWAP32(gp);
+       header->ret = SWAP32(ra);
+       header->base = SWAP32(s0);
 
-       if (header->S_addr != 0) {
-               tmp = header->S_addr + header->s_size;
-               sp = tmp;
-               fp = sp;
-       }
+       ptr = SWAP32(header->b_addr);
+       len = SWAP32(header->b_size);
+       if (len != 0) do {
+               storeRam32(ptr, 0);
+               len -= 4; ptr += 4;
+       } while (len > 0);
 
-       gp = header->gp0;
+       if (header->S_addr != 0)
+               sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
+
+       gp = SWAP32(header->gp0);
 
        s0 = a0;
 
@@ -1478,7 +1525,7 @@ void psxBios_Exec() { // 43
        a1 = a2;
 
        ra = 0x8000;
-       pc0 = header->_pc0;
+       pc0 = SWAP32(header->_pc0);
 }
 
 void psxBios_FlushCache() { // 44
@@ -1661,16 +1708,16 @@ void psxBios_SetMem() { // 9f
                case 2:
                        psxHu32ref(0x1060) = SWAP32(new);
                        psxMu32ref(0x060) = a0;
-                       SysPrintf("Change effective memory : %d MBytes\n",a0);
+                       PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
                        break;
 
                case 8:
                        psxHu32ref(0x1060) = SWAP32(new | 0x300);
                        psxMu32ref(0x060) = a0;
-                       SysPrintf("Change effective memory : %d MBytes\n",a0);
+                       PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
 
                default:
-                       SysPrintf("Effective memory must be 2/8 MBytes\n");
+                       PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
                break;
        }
 
@@ -1678,19 +1725,18 @@ void psxBios_SetMem() { // 9f
 }
 
 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
-void psxBios_get_cd_status(void) //a6
+static void psxBios_get_cd_status() // a6
 {
+       PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
        v0 = 1;
        pc0 = ra;
 }
 
-void psxBios__card_info() { // ab
-#ifdef PSXBIOS_LOG
+static void psxBios__card_info() { // ab
        PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
-#endif
        u32 ret, port;
-       card_active_chan = a0;
-       port = card_active_chan >> 4;
+       storeRam32(A_CARD_CHAN1, a0);
+       port = a0 >> 4;
 
        switch (port) {
        case 0x0:
@@ -1700,9 +1746,7 @@ void psxBios__card_info() { // ab
                        ret = 0x0100;
                break;
        default:
-#ifdef PSXBIOS_LOG
-               PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
-#endif
+               PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
                ret = 0x0302;
                break;
        }
@@ -1721,7 +1765,7 @@ void psxBios__card_load() { // ac
        PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
 #endif
 
-       card_active_chan = a0;
+       storeRam32(A_CARD_CHAN1, a0);
 
 //     DeliverEvent(0xf0000011, 0x0004);
        DeliverEvent(0xf4000001, 0x0004);
@@ -1729,6 +1773,19 @@ void psxBios__card_load() { // ac
        v0 = 1; pc0 = ra;
 }
 
+static void psxBios_GetSystemInfo() { // b4
+       u32 ret = 0;
+       //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
+       SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
+       switch (a0) {
+       case 0:
+       case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
+       case 2: ret = 0xbfc0012c; break;
+       case 5: ret = loadRam32(0x60) << 10; break;
+       }
+       mips_return_c(ret, 20);
+}
+
 /* System calls B0 */
 
 static u32 psxBios_SysMalloc_(u32 size);
@@ -2044,9 +2101,9 @@ void psxBios_ChangeTh() { // 10
        u32 tcbBase = loadRam32(A_TT_TCB);
        u32 th = a0 & 0xffff;
 
-#ifdef PSXBIOS_LOG
-//     PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
-#endif
+       // this is quite spammy
+       //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
+
        // without doing any argument checks, just issue a syscall
        // (like the real bios does)
        a0 = 3;
@@ -2060,7 +2117,7 @@ void psxBios_InitPAD() { // 0x12
        PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
 
        // printf("%s", "PS-X Control PAD Driver  Ver 3.0");
-       // PAD_dr_enable = 0;
+       ram32[A_PAD_DR_DST/4] = 0;
        ram32[A_PAD_OUTBUF/4 + 0] = 0;
        ram32[A_PAD_OUTBUF/4 + 1] = 0;
        ram32[A_PAD_OUT_LEN/4 + 0] = 0;
@@ -2107,47 +2164,74 @@ void psxBios_StopPAD() { // 14
        mips_return_void_c(200);
 }
 
-void psxBios_PAD_init() { // 15
-#ifdef PSXBIOS_LOG
+static void psxBios_PAD_init() { // 15
+       u32 ret = 0;
        PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
-#endif
-       if (!(a0 == 0x20000000 || a0 == 0x20000001))
+       if (a0 == 0x20000000 || a0 == 0x20000001)
        {
-               v0 = 0;
-               pc0 = ra;
-               return;
+               u32 dst = a1;
+               a0 = A_PAD_DR_BUF1; a1 = 0x22;
+               a2 = A_PAD_DR_BUF2; a3 = 0x22;
+               psxBios_InitPAD();
+               psxBios_StartPAD();
+               storeRam32(A_PAD_DR_DST, dst);
+               ret = 2;
+       }
+       mips_return_c(ret, 100);
+}
+
+static u32 psxBios_PAD_dr_() {
+       u8 *dst = loadRam32ptr(A_PAD_DR_DST);
+       u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
+       u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
+       dst[0] = dst[1] = dst[2] = dst[3] = ~0;
+       if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
+       {
+               dst[0] = buf1[3], dst[1] = buf1[2];
+               if (buf1[1] == 0x23) {
+                       dst[0] |= 0xc7, dst[1] |= 7;
+                       if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
+                       if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
+               }
        }
-       psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
-       pad_buf = (int *)Ra1;
-       *pad_buf = -1;
-       psxRegs.CP0.n.SR |= 0x401;
-       v0 = 2;
-       pc0 = ra;
+       if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
+       {
+               dst[2] = buf2[3], dst[3] = buf2[2];
+               if (buf2[1] == 0x23) {
+                       dst[2] |= 0xc7, dst[3] |= 7;
+                       if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
+                       if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
+               }
+       }
+       use_cycles(55);
+       return SWAP32(*(u32 *)dst);
 }
 
-void psxBios_PAD_dr() { // 16
-#ifdef PSXBIOS_LOG
+static void psxBios_PAD_dr() { // 16
        PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
-#endif
-
-       v0 = -1; pc0 = ra;
+       u32 ret = psxBios_PAD_dr_();
+       mips_return(ret);
 }
 
 static void psxBios_ReturnFromException() { // 17
        u32 tcbPtr = loadRam32(A_TT_PCB);
        const TCB *tcb = loadRam32ptr(tcbPtr);
+       u32 sr;
        int i;
 
        for (i = 1; i < 32; i++)
                psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
        psxRegs.GPR.n.lo = SWAP32(tcb->lo);
        psxRegs.GPR.n.hi = SWAP32(tcb->hi);
-       psxRegs.CP0.n.SR = SWAP32(tcb->sr);
+       sr = SWAP32(tcb->sr);
 
        //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
        pc0 = k0 = SWAP32(tcb->epc);
 
-       psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
+       // the interpreter wants to know about sr changes, so do a MTC0
+       sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
+       MTC0(&psxRegs, 12, sr);
+
        use_cycles(53);
        psxBranchTest();
 }
@@ -2174,9 +2258,6 @@ static void psxBios_UnDeliverEvent() { // 0x20
        mips_return(ret);
 }
 
-char ffile[64], *pfile;
-int nfile;
-
 static void buopen(int mcd, char *ptr, char *cfg)
 {
        int i;
@@ -2191,7 +2272,7 @@ static void buopen(int mcd, char *ptr, char *cfg)
                if ((*fptr & 0xF0) != 0x50) continue;
                if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
                FDesc[1 + mcd].mcfile = i;
-               SysPrintf("open %s\n", fptr+0xa);
+               PSXBIOS_LOG("open %s\n", fptr+0xa);
                v0 = 1 + mcd;
                break;
        }
@@ -2230,7 +2311,7 @@ static void buopen(int mcd, char *ptr, char *cfg)
                        pptr[8] = pptr[9] = 0xff;
                        for (j=0, xor=0; j<127; j++) xor^= pptr[j];
                        pptr[127] = xor;
-                       SysPrintf("openC %s %d\n", ptr, nblk);
+                       PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
                        v0 = 1 + mcd;
                        /* just go ahead and resave them all */
                        SaveMcd(cfg, ptr, 128, 128 * 15);
@@ -2325,9 +2406,8 @@ void psxBios_write() { // 0x35/0x03
        char *ptr;
        void *pa1 = Ra1;
 
-#ifdef PSXBIOS_LOG
-       PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
-#endif
+       if (a0 != 1) // stdout
+               PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
 
        v0 = -1;
        if (pa1 == INVALID_PTR) {
@@ -2339,7 +2419,7 @@ void psxBios_write() { // 0x35/0x03
                char *ptr = pa1;
 
                v0 = a2;
-               while (a2 > 0) {
+               if (Config.PsxOut) while (a2 > 0) {
                        SysPrintf("%c", *ptr++); a2--;
                }
                pc0 = ra; return;
@@ -2386,12 +2466,12 @@ void psxBios_close() { // 0x36
 }
 
 void psxBios_putchar() { // 3d
-       SysPrintf("%c", (char)a0);
+       if (Config.PsxOut) SysPrintf("%c", (char)a0);
        pc0 = ra;
 }
 
 void psxBios_puts() { // 3e/3f
-       SysPrintf("%s", Ra0);
+       if (Config.PsxOut) SysPrintf("%s", Ra0);
        pc0 = ra;
 }
 
@@ -2428,7 +2508,7 @@ static size_t strlen_internal(char* p)
                                strcpy(dir->name+i, ptr+i); break; } \
                        match = 0; break; \
                } \
-               SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
+               PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
                if (match == 0) { continue; } \
                dir->size = 8192; \
                v0 = _dir; \
@@ -2552,7 +2632,7 @@ void psxBios_rename() { // 44
                if (strcmp(Ra0+5, ptr+0xa)) continue; \
                *ptr = (*ptr & 0xf) | 0xA0; \
                SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
-               SysPrintf("delete %s\n", ptr+0xa); \
+               PSXBIOS_LOG("delete %s\n", ptr+0xa); \
                v0 = 1; \
                break; \
        } \
@@ -2637,7 +2717,7 @@ void psxBios__card_write() { // 0x4e
                v0 = 0; pc0 = ra;
                return;
        }
-       card_active_chan = a0;
+       storeRam32(A_CARD_CHAN1, a0);
        port = a0 >> 4;
 
        if (pa2 != INVALID_PTR) {
@@ -2673,7 +2753,7 @@ void psxBios__card_read() { // 0x4f
                v0 = 0; pc0 = ra;
                return;
        }
-       card_active_chan = a0;
+       storeRam32(A_CARD_CHAN1, a0);
        port = a0 >> 4;
 
        if (pa2 != INVALID_PTR) {
@@ -2764,13 +2844,14 @@ void psxBios_GetB0Table() { // 57
        mips_return_c(A_B0_TABLE, 3);
 }
 
-void psxBios__card_chan() { // 0x58
-#ifdef PSXBIOS_LOG
+static void psxBios__card_chan() { // 0x58
+       u32 ret;
        PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
-#endif
 
-       v0 = card_active_chan;
-       pc0 = ra;
+       // todo: should return active slot chan
+       // (active - which was last processed by irq code)
+       ret = loadRam32(A_CARD_CHAN1);
+       mips_return_c(ret, 8);
 }
 
 static void psxBios_ChangeClearPad() { // 5b
@@ -2782,21 +2863,17 @@ static void psxBios_ChangeClearPad() { // 5b
        mips_return_c(ret, 6);
 }
 
-void psxBios__card_status() { // 5c
-#ifdef PSXBIOS_LOG
-       PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
-#endif
+static void psxBios__card_status() { // 5c
+       PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
 
-       v0 = card_active_chan;
+       v0 = 1; // ready
        pc0 = ra;
 }
 
-void psxBios__card_wait() { // 5d
-#ifdef PSXBIOS_LOG
-       PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
-#endif
+static void psxBios__card_wait() { // 5d
+       PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
 
-       v0 = 1;
+       v0 = 1; // ready
        pc0 = ra;
 }
 
@@ -2943,9 +3020,7 @@ void (*biosA0[256])();
 void (*biosC0[256+128])();
 void (**biosB0)() = biosC0 + 128;
 
-#include "sjisfont.h"
-
-void setup_mips_code()
+static void setup_mips_code()
 {
        u32 *ptr;
        ptr = (u32 *)&psxM[A_SYSCALL];
@@ -2967,7 +3042,6 @@ void setup_mips_code()
 
        ptr[0x60/4] = SWAPu32(0x40037000); // mfc0  $v1, EPC
        ptr[0x64/4] = SWAPu32(0x40026800); // mfc0  $v0, Cause
-       ptr[0x68/4] = SWAPu32(0x24630004); // addiu $v1, $v1, 4
        ptr[0x6c/4] = SWAPu32(0xaf430080); // sw    $v1, 0x80($k0)
 
        ptr[0xb0/4] = HLEOP(hleop_exception);
@@ -3062,6 +3136,91 @@ static void setup_tt(u32 tcb_cnt, u32 evcb_cnt)
        DeliverEvent(0xf0000003, 0x0010);
 }
 
+static const u32 gpu_ctl_def[] = {
+       0x00000000, 0x01000000, 0x03000000, 0x04000000,
+       0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
+};
+
+static const u32 gpu_data_def[] = {
+       0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
+       0xe5001000, 0xe6000000,
+       0x02000000, 0x00000000, 0x01ff03ff
+};
+
+// from 1f801d80
+static const u16 spu_config[] = {
+       0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
+       0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
+       0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
+       0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+       0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
+       0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
+       0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
+       0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
+};
+
+void psxBiosSetupBootState(void)
+{
+       boolean hle = Config.HLE;
+       u32 *hw = (u32 *)psxH;
+       int i;
+
+       // see also SetBootRegs()
+       if (hle) {
+               v0 = 1; v1 = 4;
+               a0 = 1; a2 = a3 = 0; a3 = 0x2a;
+               t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
+               s0 = 0xa000b870;
+               k0 = 0xbfc0d968; k1 = 0xf1c;
+               ra = 0xf0001234; // just to easily detect attempts to return
+               psxRegs.CP0.n.Cause = 0x20;
+               psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
+
+               hw[0x1000/4] = SWAP32(0x1f000000);
+               hw[0x1004/4] = SWAP32(0x1f802000);
+               hw[0x1008/4] = SWAP32(0x0013243f);
+               hw[0x100c/4] = SWAP32(0x00003022);
+               hw[0x1010/4] = SWAP32(0x0013243f);
+               hw[0x1014/4] = SWAP32(0x200931e1);
+               hw[0x1018/4] = SWAP32(0x00020943);
+               hw[0x101c/4] = SWAP32(0x00070777);
+               hw[0x1020/4] = SWAP32(0x0000132c);
+               hw[0x1060/4] = SWAP32(0x00000b88);
+               hw[0x1070/4] = SWAP32(0x00000001);
+               hw[0x1074/4] = SWAP32(0x0000000c);
+               hw[0x2040/4] = SWAP32(0x00000900);
+       }
+
+       hw[0x10a0/4] = SWAP32(0x00ffffff);
+       hw[0x10a8/4] = SWAP32(0x00000401);
+       hw[0x10b0/4] = SWAP32(0x0008b000);
+       hw[0x10b4/4] = SWAP32(0x00010200);
+       hw[0x10e0/4] = SWAP32(0x000eccf4);
+       hw[0x10e4/4] = SWAP32(0x00000400);
+       hw[0x10e8/4] = SWAP32(0x00000002);
+       hw[0x10f0/4] = SWAP32(0x00009099);
+       hw[0x10f4/4] = SWAP32(0x8c8c0000);
+
+       if (hle) {
+               psxRcntWmode(0, 0);
+               psxRcntWmode(1, 0);
+               psxRcntWmode(2, 0);
+       }
+
+       // gpu
+       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);
+
+       // spu
+       for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
+               SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
+}
+
+#include "sjisfont.h"
+
 void psxBiosInit() {
        u32 *ptr, *ram32, *rom32;
        int i;
@@ -3148,6 +3307,8 @@ void psxBiosInit() {
        biosA0[0x3b] = psxBios_getchar;
        biosA0[0x3c] = psxBios_putchar;
        //biosA0[0x3d] = psxBios_gets;
+       biosA0[0x3e] = psxBios_puts;
+       biosA0[0x3f] = psxBios_printf;
        biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
        //biosA0[0x41] = psxBios_LoadTest;
        biosA0[0x42] = psxBios_Load;
@@ -3264,7 +3425,7 @@ void psxBiosInit() {
        //biosA0[0xb1] = psxBios_sys_a0_b1;
        //biosA0[0xb2] = psxBios_do_a_long_jmp
        //biosA0[0xb3] = psxBios_sys_a0_b3;
-       //biosA0[0xb4] = psxBios_sub_function;
+       biosA0[0xb4] = psxBios_GetSystemInfo;
 //*******************B0 CALLS****************************
        biosB0[0x00] = psxBios_SysMalloc;
        //biosB0[0x01] = psxBios_sys_b0_01;
@@ -3327,7 +3488,9 @@ void psxBiosInit() {
        //biosB0[0x3a] = psxBios_getc;
        //biosB0[0x3b] = psxBios_putc;
        biosB0[0x3c] = psxBios_getchar;
+       biosB0[0x3d] = psxBios_putchar;
        //biosB0[0x3e] = psxBios_gets;
+       biosB0[0x3f] = psxBios_puts;
        //biosB0[0x40] = psxBios_cd;
        biosB0[0x41] = psxBios_format;
        biosB0[0x42] = psxBios_firstfile;
@@ -3391,21 +3554,20 @@ void psxBiosInit() {
 //************** THE END ***************************************
 /**/
 
-       pad_buf = NULL;
-       heap_addr = NULL;
-       heap_end = NULL;
-       heap_size = 0;
        memset(FDesc, 0, sizeof(FDesc));
-       card_active_chan = 0;
 
        // initial RNG seed
        psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
 
+       // somewhat pretend to be a SCPH1001 BIOS
+       // some games look for these and take an exception if they're missing
        rom32 = (u32 *)psxR;
        rom32[0x100/4] = SWAP32(0x19951204);
        rom32[0x104/4] = SWAP32(3);
        strcpy(psxR + 0x108, "PCSX authors");
-       strcpy(psxR + 0x12c, "PCSX HLE");
+       strcpy(psxR + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
+       strcpy(psxR + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
+       strcpy(psxR + 0x7ff54, "GPL-2.0-or-later");
 
        // fonts
        len = 0x80000 - 0x66000;
@@ -3413,9 +3575,6 @@ void psxBiosInit() {
        len = 0x80000 - 0x69d68;
        uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
 
-       // memory size 2 MB
-       psxHu32ref(0x1060) = SWAPu32(0x00000b88);
-
        /*      Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
                See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
                Here are some examples of games not working with this fix in place :
@@ -3525,40 +3684,6 @@ void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt) {
        } \
 }
 
-static void biosPadHLE() {
-       if (pad_buf != NULL) {
-               u32 *buf = (u32*)pad_buf;
-
-               PAD1_startPoll(1);
-               if (PAD1_poll(0x42) == 0x23) {
-                       PAD1_poll(0);
-                       *buf = PAD1_poll(0) << 8;
-                       *buf |= PAD1_poll(0);
-                       PAD1_poll(0);
-                       *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
-                       *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
-               } else {
-                       PAD1_poll(0);
-                       *buf = PAD1_poll(0) << 8;
-                       *buf|= PAD1_poll(0);
-               }
-
-               PAD2_startPoll(2);
-               if (PAD2_poll(0x42) == 0x23) {
-                       PAD2_poll(0);
-                       *buf |= PAD2_poll(0) << 24;
-                       *buf |= PAD2_poll(0) << 16;
-                       PAD2_poll(0);
-                       *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
-                       *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
-               } else {
-                       PAD2_poll(0);
-                       *buf |= PAD2_poll(0) << 24;
-                       *buf |= PAD2_poll(0) << 16;
-               }
-       }
-}
-
 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
 {
        use_cycles(10);
@@ -3618,7 +3743,7 @@ void hleExc0_2_2_syscall() // not in any A/B/C table
        if (code != R3000E_Syscall) {
                if (code != 0) {
                        DeliverEvent(0xf0000010, 0x1000);
-                       psxBios_SystemErrorUnresolvedException();
+                       //psxBios_SystemErrorUnresolvedException();
                }
                mips_return_c(0, 17);
                return;
@@ -3744,8 +3869,9 @@ void hleExcPadCard1(void)
 
                psxBios_PADpoll(1);
                psxBios_PADpoll(2);
-               biosPadHLE();
                use_cycles(100);
+               if (loadRam32(A_PAD_DR_DST))
+                       psxBios_PAD_dr_();
        }
        if (loadRam32(A_PAD_ACK_VBL))
                psxHwWrite16(0x1f801070, ~1);
@@ -3779,7 +3905,7 @@ void psxBiosException() {
        }
        tcb->lo = SWAP32(psxRegs.GPR.n.lo);
        tcb->hi = SWAP32(psxRegs.GPR.n.hi);
-       tcb->epc = SWAP32(psxRegs.CP0.n.EPC);
+       //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
        tcb->sr = SWAP32(psxRegs.CP0.n.SR);
        tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
        sp = fp = loadRam32(A_EXC_SP);
@@ -3846,9 +3972,5 @@ void psxBiosException() {
 void psxBiosFreeze(int Mode) {
        u32 base = 0x40000;
 
-       bfreezepsxMptr(pad_buf, int);
-       bfreezepsxMptr(heap_addr, u32);
        bfreezes(FDesc);
-       bfreezel(&card_active_chan);
-       bfreezel(&heap_size);
 }