psxbios: don't overwrite ra
[pcsx_rearmed.git] / libpcsxcore / psxbios.c
1 /***************************************************************************
2  *   Copyright (C) 2019 Ryan Schultz, PCSX-df Team, PCSX team, gameblabla, *
3  *       dmitrysmagin, senquack                                                                                            *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA.           *
19  ***************************************************************************/
20
21 /* Gameblabla 2018-2019 :
22  * Numerous changes to bios calls as well as improvements in order to conform to nocash's findings
23  * for the PSX bios calls. Thanks senquack for helping out with some of the changes
24  * and helping to spot issues and refine my patches.
25  * */
26
27 /*
28  * Internal simulated HLE BIOS.
29  */
30
31 // TODO: implement all system calls, count the exact CPU cycles of system calls.
32
33 #include "psxbios.h"
34 #include "psxhw.h"
35 #include "gpu.h"
36 #include "sio.h"
37 #include "psxhle.h"
38 #include "psxinterpreter.h"
39 #include <zlib.h>
40
41 #if (defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)
42 #pragma GCC diagnostic ignored "-Wpointer-sign"
43 #endif
44
45 #ifndef PSXBIOS_LOG
46 //#define PSXBIOS_LOG printf
47 #define PSXBIOS_LOG(...)
48 #endif
49
50 #define PTR_1 (void *)(size_t)1
51
52 char *biosA0n[256] = {
53 // 0x00
54         "open",         "lseek",        "read",         "write",
55         "close",        "ioctl",        "exit",         "sys_a0_07",
56         "getc",         "putc",         "todigit",      "atof",
57         "strtoul",      "strtol",       "abs",          "labs",
58 // 0x10
59         "atoi",         "atol",         "atob",         "setjmp",
60         "longjmp",      "strcat",       "strncat",      "strcmp",
61         "strncmp",      "strcpy",       "strncpy",      "strlen",
62         "index",        "rindex",       "strchr",       "strrchr",
63 // 0x20
64         "strpbrk",      "strspn",       "strcspn",      "strtok",
65         "strstr",       "toupper",      "tolower",      "bcopy",
66         "bzero",        "bcmp",         "memcpy",       "memset",
67         "memmove",      "memcmp",       "memchr",       "rand",
68 // 0x30
69         "srand",        "qsort",        "strtod",       "malloc",
70         "free",         "lsearch",      "bsearch",      "calloc",
71         "realloc",      "InitHeap",     "_exit",        "getchar",
72         "putchar",      "gets",         "puts",         "printf",
73 // 0x40
74         "SystemErrorUnresolvedException", "LoadTest",           "Load",         "Exec",
75         "FlushCache",           "InstallInterruptHandler",      "GPU_dw",       "mem2vram",
76         "SendGPUStatus",        "GPU_cw",                       "GPU_cwb",      "SendPackets",
77         "sys_a0_4c",            "GetGPUStatus",                         "GPU_sync",     "sys_a0_4f",
78 // 0x50
79         "sys_a0_50",            "LoadExec",                             "GetSysSp",             "sys_a0_53",
80         "_96_init()",           "_bu_init()",                   "_96_remove()", "sys_a0_57",
81         "sys_a0_58",            "sys_a0_59",                    "sys_a0_5a",    "dev_tty_init",
82         "dev_tty_open",         "sys_a0_5d",                    "dev_tty_ioctl","dev_cd_open",
83 // 0x60
84         "dev_cd_read",          "dev_cd_close",                 "dev_cd_firstfile",     "dev_cd_nextfile",
85         "dev_cd_chdir",         "dev_card_open",                "dev_card_read",        "dev_card_write",
86         "dev_card_close",       "dev_card_firstfile",   "dev_card_nextfile","dev_card_erase",
87         "dev_card_undelete","dev_card_format",          "dev_card_rename",      "dev_card_6f",
88 // 0x70
89         "_bu_init",                     "_96_init",             "CdRemove",             "sys_a0_73",
90         "sys_a0_74",            "sys_a0_75",    "sys_a0_76",            "sys_a0_77",
91         "_96_CdSeekL",          "sys_a0_79",    "sys_a0_7a",            "sys_a0_7b",
92         "_96_CdGetStatus",      "sys_a0_7d",    "_96_CdRead",           "sys_a0_7f",
93 // 0x80
94         "sys_a0_80",            "sys_a0_81",    "sys_a0_82",            "sys_a0_83",
95         "sys_a0_84",            "_96_CdStop",   "sys_a0_86",            "sys_a0_87",
96         "sys_a0_88",            "sys_a0_89",    "sys_a0_8a",            "sys_a0_8b",
97         "sys_a0_8c",            "sys_a0_8d",    "sys_a0_8e",            "sys_a0_8f",
98 // 0x90
99         "sys_a0_90",            "sys_a0_91",    "sys_a0_92",            "sys_a0_93",
100         "sys_a0_94",            "sys_a0_95",    "AddCDROMDevice",       "AddMemCardDevide",
101         "DisableKernelIORedirection",           "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
102         "SetConf",                      "GetConf",              "sys_a0_9e",            "SetMem",
103 // 0xa0
104         "_boot",                        "SystemError",  "EnqueueCdIntr",        "DequeueCdIntr",
105         "sys_a0_a4",            "ReadSector",   "get_cd_status",        "bufs_cb_0",
106         "bufs_cb_1",            "bufs_cb_2",    "bufs_cb_3",            "_card_info",
107         "_card_load",           "_card_auto",   "bufs_cd_4",            "sys_a0_af",
108 // 0xb0
109         "sys_a0_b0",            "sys_a0_b1",    "do_a_long_jmp",        "sys_a0_b3",
110         "GetSystemInfo",
111 };
112
113 char *biosB0n[256] = {
114 // 0x00
115         "SysMalloc",            "sys_b0_01",    "sys_b0_02",    "sys_b0_03",
116         "sys_b0_04",            "sys_b0_05",    "sys_b0_06",    "DeliverEvent",
117         "OpenEvent",            "CloseEvent",   "WaitEvent",    "TestEvent",
118         "EnableEvent",          "DisableEvent", "OpenTh",               "CloseTh",
119 // 0x10
120         "ChangeTh",                     "sys_b0_11",    "InitPAD",              "StartPAD",
121         "StopPAD",                      "PAD_init",             "PAD_dr",               "ReturnFromExecption",
122         "ResetEntryInt",        "HookEntryInt", "sys_b0_1a",    "sys_b0_1b",
123         "sys_b0_1c",            "sys_b0_1d",    "sys_b0_1e",    "sys_b0_1f",
124 // 0x20
125         "UnDeliverEvent",       "sys_b0_21",    "sys_b0_22",    "sys_b0_23",
126         "sys_b0_24",            "sys_b0_25",    "sys_b0_26",    "sys_b0_27",
127         "sys_b0_28",            "sys_b0_29",    "sys_b0_2a",    "sys_b0_2b",
128         "sys_b0_2c",            "sys_b0_2d",    "sys_b0_2e",    "sys_b0_2f",
129 // 0x30
130         "sys_b0_30",            "sys_b0_31",    "open",                 "lseek",
131         "read",                         "write",                "close",                "ioctl",
132         "exit",                         "sys_b0_39",    "getc",                 "putc",
133         "getchar",                      "putchar",              "gets",                 "puts",
134 // 0x40
135         "cd",                           "format",               "firstfile",    "nextfile",
136         "rename",                       "delete",               "undelete",             "AddDevice",
137         "RemoteDevice",         "PrintInstalledDevices", "InitCARD", "StartCARD",
138         "StopCARD",                     "sys_b0_4d",    "_card_write",  "_card_read",
139 // 0x50
140         "_new_card",            "Krom2RawAdd",  "sys_b0_52",    "sys_b0_53",
141         "_get_errno",           "_get_error",   "GetC0Table",   "GetB0Table",
142         "_card_chan",           "sys_b0_59",    "sys_b0_5a",    "ChangeClearPAD",
143         "_card_status",         "_card_wait",
144 };
145
146 char *biosC0n[256] = {
147 // 0x00
148         "InitRCnt",                       "InitException",              "SysEnqIntRP",          "SysDeqIntRP",
149         "get_free_EvCB_slot", "get_free_TCB_slot",      "ExceptionHandler",     "InstallExeptionHandler",
150         "SysInitMemory",          "SysInitKMem",                "ChangeClearRCnt",      "SystemError",
151         "InitDefInt",             "sys_c0_0d",                  "sys_c0_0e",            "sys_c0_0f",
152 // 0x10
153         "sys_c0_10",              "sys_c0_11",                  "InstallDevices",       "FlushStfInOutPut",
154         "sys_c0_14",              "_cdevinput",                 "_cdevscan",            "_circgetc",
155         "_circputc",              "ioabort",                    "sys_c0_1a",            "KernelRedirect",
156         "PatchAOTable",
157 };
158
159 //#define r0 (psxRegs.GPR.n.r0)
160 #define at (psxRegs.GPR.n.at)
161 #define v0 (psxRegs.GPR.n.v0)
162 #define v1 (psxRegs.GPR.n.v1)
163 #define a0 (psxRegs.GPR.n.a0)
164 #define a1 (psxRegs.GPR.n.a1)
165 #define a2 (psxRegs.GPR.n.a2)
166 #define a3 (psxRegs.GPR.n.a3)
167 #define t0 (psxRegs.GPR.n.t0)
168 #define t1 (psxRegs.GPR.n.t1)
169 #define t2 (psxRegs.GPR.n.t2)
170 #define t3 (psxRegs.GPR.n.t3)
171 #define t4 (psxRegs.GPR.n.t4)
172 #define t5 (psxRegs.GPR.n.t5)
173 #define t6 (psxRegs.GPR.n.t6)
174 #define t7 (psxRegs.GPR.n.t7)
175 #define t8 (psxRegs.GPR.n.t8)
176 #define t9 (psxRegs.GPR.n.t9)
177 #define s0 (psxRegs.GPR.n.s0)
178 #define s1 (psxRegs.GPR.n.s1)
179 #define s2 (psxRegs.GPR.n.s2)
180 #define s3 (psxRegs.GPR.n.s3)
181 #define s4 (psxRegs.GPR.n.s4)
182 #define s5 (psxRegs.GPR.n.s5)
183 #define s6 (psxRegs.GPR.n.s6)
184 #define s7 (psxRegs.GPR.n.s7)
185 #define k0 (psxRegs.GPR.n.k0)
186 #define k1 (psxRegs.GPR.n.k1)
187 #define gp (psxRegs.GPR.n.gp)
188 #define sp (psxRegs.GPR.n.sp)
189 #define fp (psxRegs.GPR.n.fp)
190 #define ra (psxRegs.GPR.n.ra)
191 #define pc0 (psxRegs.pc)
192
193 #define Ra0 ((char *)PSXM(a0))
194 #define Ra1 ((char *)PSXM(a1))
195 #define Ra2 ((char *)PSXM(a2))
196 #define Ra3 ((char *)PSXM(a3))
197 #define Rv0 ((char *)PSXM(v0))
198 #define Rsp ((char *)PSXM(sp))
199
200 typedef struct {
201         u32 class;
202         u32 status;
203         u32 spec;
204         u32 mode;
205         u32 fhandler;
206         u32 unused[2];
207 } EvCB;
208
209 #define EvStUNUSED      0x0000
210 #define EvStDISABLED    0x1000
211 #define EvStACTIVE      0x2000
212 #define EvStALREADY     0x4000
213
214 #define EvMdCALL        0x1000
215 #define EvMdMARK        0x2000
216
217 typedef struct {
218         u32 status;
219         u32 mode;
220         u32 reg[32];
221         u32 epc;
222         u32 hi, lo;
223         u32 sr, cause;
224         u32 unused[9];
225 } TCB;
226
227 typedef struct {
228         u32 _pc0;
229         u32 gp0;
230         u32 t_addr;
231         u32 t_size;
232         u32 d_addr; // 10
233         u32 d_size;
234         u32 b_addr;
235         u32 b_size; // 1c
236         u32 S_addr;
237         u32 s_size;
238         u32 _sp, _fp, _gp, ret, base;
239 } EXEC;
240
241 struct DIRENTRY {
242         char name[20];
243         s32 attr;
244         s32 size;
245         u32 next;
246         s32 head;
247         char system[4];
248 };
249
250 typedef struct {
251         char name[32];
252         u32  mode;
253         u32  offset;
254         u32  size;
255         u32  mcfile;
256 } FileDesc;
257
258 // todo: FileDesc layout is wrong
259 // todo: get rid of these globals
260 static FileDesc FDesc[32];
261 static char ffile[64];
262 static int nfile;
263
264 // fixed RAM offsets, SCPH1001 compatible
265 #define A_TT_ExCB       0x0100
266 #define A_TT_PCB        0x0108
267 #define A_TT_TCB        0x0110
268 #define A_TT_EvCB       0x0120
269 #define A_A0_TABLE      0x0200
270 #define A_B0_TABLE      0x0874
271 #define A_C0_TABLE      0x0674
272 #define A_SYSCALL       0x0650
273 #define A_EXCEPTION     0x0c80
274 #define A_EXC_SP        0x6cf0
275 #define A_EEXIT_DEF     0x6cf4
276 #define A_KMALLOC_PTR   0x7460
277 #define A_KMALLOC_SIZE  0x7464
278 #define A_KMALLOC_END   0x7468
279 #define A_PADCRD_CHN_E  0x74a8  // pad/card irq chain entry, see hleExcPadCard1()
280 #define A_PAD_IRQR_ENA  0x74b8  // pad read on vint irq (nocash 'pad_enable_flag')
281 #define A_CARD_IRQR_ENA 0x74bc  // same for card
282 #define A_PAD_INBUF     0x74c8  // 2x buffers for rx pad data
283 #define A_PAD_OUTBUF    0x74d0  // 2x buffers for tx pad data
284 #define A_PAD_IN_LEN    0x74d8
285 #define A_PAD_OUT_LEN   0x74e0
286 #define A_PAD_DR_DST    0x74c4
287 #define A_CARD_CHAN1    0x7500
288 #define A_PAD_DR_BUF1   0x7570
289 #define A_PAD_DR_BUF2   0x7598
290 #define A_EEXIT_PTR     0x75d0
291 #define A_EXC_STACK     0x85d8  // exception stack top
292 #define A_RCNT_VBL_ACK  0x8600
293 #define A_PAD_ACK_VBL   0x8914  // enable vint ack by pad reading code
294 #define A_HEAP_BASE     0x9000
295 #define A_HEAP_SIZE     0x9004
296 #define A_HEAP_END      0x9008
297 #define A_HEAP_FLAG     0x900c
298 #define A_RND_SEED      0x9010
299 #define A_CONF_TCB      0xb940
300 #define A_CONF_EvCB     0xb944
301 #define A_CONF_SP       0xb948
302 #define A_CD_EVENTS     0xb9b8
303 #define A_EXC_GP        0xf450
304
305 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
306
307 static u32 loadRam32(u32 addr)
308 {
309         assert(!(addr & 0x5f800000));
310         return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
311 }
312
313 static void *castRam8ptr(u32 addr)
314 {
315         assert(!(addr & 0x5f800000));
316         return psxM + (addr & 0x1fffff);
317 }
318
319 static void *castRam32ptr(u32 addr)
320 {
321         assert(!(addr & 0x5f800003));
322         return psxM + (addr & 0x1ffffc);
323 }
324
325 static void *loadRam8ptr(u32 addr)
326 {
327         return castRam8ptr(loadRam32(addr));
328 }
329
330 static void *loadRam32ptr(u32 addr)
331 {
332         return castRam32ptr(loadRam32(addr));
333 }
334
335 static void storeRam8(u32 addr, u8 d)
336 {
337         assert(!(addr & 0x5f800000));
338         *((u8 *)psxM + (addr & 0x1fffff)) = d;
339 }
340
341 static void storeRam32(u32 addr, u32 d)
342 {
343         assert(!(addr & 0x5f800000));
344         *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
345 }
346
347 static void mips_return(u32 val)
348 {
349         v0 = val;
350         pc0 = ra;
351 }
352
353 static void mips_return_void(void)
354 {
355         pc0 = ra;
356 }
357
358 static void use_cycles(u32 cycle)
359 {
360         psxRegs.cycle += cycle * 2;
361 }
362
363 static void mips_return_c(u32 val, u32 cycle)
364 {
365         use_cycles(cycle);
366         mips_return(val);
367 }
368
369 static void mips_return_void_c(u32 cycle)
370 {
371         use_cycles(cycle);
372         pc0 = ra;
373 }
374
375 static int returned_from_exception(void)
376 {
377         // 0x80000080 means it took another exception just after return
378         return pc0 == k0 || pc0 == 0x80000080;
379 }
380
381 static inline void softCall(u32 pc) {
382         u32 sra = ra;
383         u32 ssr = psxRegs.CP0.n.SR;
384         u32 lim = 0;
385         pc0 = pc;
386         ra = 0x80001000;
387         psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
388
389         psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
390
391         while (pc0 != 0x80001000 && ++lim < 1000000)
392                 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
393
394         psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
395
396         if (lim == 1000000)
397                 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
398         ra = sra;
399         psxRegs.CP0.n.SR |= ssr & 0x404;
400 }
401
402 static inline void softCallInException(u32 pc) {
403         u32 sra = ra;
404         u32 lim = 0;
405         pc0 = pc;
406
407         assert(ra != 0x80001000);
408         if (ra == 0x80001000)
409                 return;
410         ra = 0x80001000;
411
412         psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
413
414         while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 1000000)
415                 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
416
417         psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
418
419         if (lim == 1000000)
420                 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
421         if (pc0 == 0x80001000)
422                 ra = sra;
423 }
424
425 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
426 static u32 DeliverEvent(u32 class, u32 spec);
427 static u32 UnDeliverEvent(u32 class, u32 spec);
428 static void CloseEvent(u32 ev);
429
430 /*                                           *
431 //                                           *
432 //                                           *
433 //               System calls A0             */
434
435
436 #define buread(Ra1, mcd, length) { \
437         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); \
438         ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
439         memcpy(Ra1, ptr, length); \
440         psxCpu->Clear(a1, (length + 3) / 4); \
441         if (FDesc[1 + mcd].mode & 0x8000) { \
442         DeliverEvent(0xf0000011, 0x0004); \
443         DeliverEvent(0xf4000001, 0x0004); \
444         v0 = 0; } \
445         else v0 = length; \
446         FDesc[1 + mcd].offset += v0; \
447 }
448
449 #define buwrite(Ra1, mcd, length) { \
450         u32 offset =  + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
451         PSXBIOS_LOG("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
452         ptr = Mcd##mcd##Data + offset; \
453         memcpy(ptr, Ra1, length); \
454         FDesc[1 + mcd].offset += length; \
455         SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
456         if (FDesc[1 + mcd].mode & 0x8000) { \
457         DeliverEvent(0xf0000011, 0x0004); \
458         DeliverEvent(0xf4000001, 0x0004); \
459         v0 = 0; } \
460         else v0 = length; \
461 }
462
463 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
464 /* For some strange reason, the returned character is sign-expanded; */
465 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
466 /* TODO FIX ME : Properly implement this behaviour */
467 void psxBios_getc(void) // 0x03, 0x35
468 {
469         char *ptr;
470         void *pa1 = Ra1;
471 #ifdef PSXBIOS_LOG
472         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
473 #endif
474         v0 = -1;
475
476         if (pa1 != INVALID_PTR) {
477                 switch (a0) {
478                         case 2: buread(pa1, 1, 1); break;
479                         case 3: buread(pa1, 2, 1); break;
480                 }
481         }
482
483         pc0 = ra;
484 }
485
486 /* Copy of psxBios_write, except size is 1. */
487 void psxBios_putc(void) // 0x09, 0x3B
488 {
489         char *ptr;
490         void *pa1 = Ra1;
491 #ifdef PSXBIOS_LOG
492         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
493 #endif
494         v0 = -1;
495         if (pa1 == INVALID_PTR) {
496                 pc0 = ra;
497                 return;
498         }
499
500         if (a0 == 1) { // stdout
501                 char *ptr = (char *)pa1;
502
503                 v0 = a2;
504                 while (a2 > 0) {
505                         printf("%c", *ptr++); a2--;
506                 }
507                 pc0 = ra; return;
508         }
509
510         switch (a0) {
511                 case 2: buwrite(pa1, 1, 1); break;
512                 case 3: buwrite(pa1, 2, 1); break;
513         }
514
515         pc0 = ra;
516 }
517
518 void psxBios_todigit(void) // 0x0a
519 {
520         int c = a0;
521 #ifdef PSXBIOS_LOG
522         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
523 #endif
524         c &= 0xFF;
525         if (c >= 0x30 && c < 0x3A) {
526                 c -= 0x30;
527         }
528         else if (c > 0x60 && c < 0x7B) {
529                 c -= 0x20;
530         }
531         else if (c > 0x40 && c < 0x5B) {
532                 c = c - 0x41 + 10;
533         }
534         else if (c >= 0x80) {
535                 c = -1;
536         }
537         else
538         {
539                 c = 0x0098967F;
540         }
541         v0 = c;
542         pc0 = ra;
543 }
544
545 void psxBios_abs() { // 0x0e
546         if ((s32)a0 < 0) v0 = -(s32)a0;
547         else v0 = a0;
548         pc0 = ra;
549 }
550
551 void psxBios_labs() { // 0x0f
552         psxBios_abs();
553 }
554
555 void psxBios_atoi() { // 0x10
556         s32 n = 0, f = 0;
557         char *p = (char *)Ra0;
558
559         for (;;p++) {
560                 switch (*p) {
561                         case ' ': case '\t': continue;
562                         case '-': f++;
563                         case '+': p++;
564                 }
565                 break;
566         }
567
568         while (*p >= '0' && *p <= '9') {
569                 n = n * 10 + *p++ - '0';
570         }
571
572         v0 = (f ? -n : n);
573         pc0 = ra;
574 }
575
576 void psxBios_atol() { // 0x11
577         psxBios_atoi();
578 }
579
580 struct jmp_buf_ {
581         u32 ra_, sp_, fp_;
582         u32 s[8];
583         u32 gp_;
584 };
585
586 static void psxBios_setjmp() { // 0x13
587         struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
588         int i;
589
590         PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
591
592         jmp_buf->ra_ = SWAP32(ra);
593         jmp_buf->sp_ = SWAP32(sp);
594         jmp_buf->fp_ = SWAP32(fp);
595         for (i = 0; i < 8; i++) // s0-s7
596                 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
597         jmp_buf->gp_ = SWAP32(gp);
598
599         mips_return_c(0, 15);
600 }
601
602 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
603 {
604         int i;
605
606         ra = SWAP32(jmp_buf->ra_);
607         sp = SWAP32(jmp_buf->sp_);
608         fp = SWAP32(jmp_buf->fp_);
609         for (i = 0; i < 8; i++) // s0-s7
610                 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
611         gp = SWAP32(jmp_buf->gp_);;
612 }
613
614 void psxBios_longjmp() { // 0x14
615         struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
616
617         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
618         longjmp_load(jmp_buf);
619         mips_return_c(a1, 15);
620 }
621
622 void psxBios_strcat() { // 0x15
623         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
624
625 #ifdef PSXBIOS_LOG
626         PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
627 #endif
628         if (a0 == 0 || a1 == 0)
629         {
630                 v0 = 0;
631                 pc0 = ra;
632                 return;
633         }
634         while (*p1++);
635         --p1;
636         while ((*p1++ = *p2++) != '\0');
637
638         v0 = a0; pc0 = ra;
639 }
640
641 void psxBios_strncat() { // 0x16
642         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
643         s32 n = a2;
644
645 #ifdef PSXBIOS_LOG
646         PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
647 #endif
648         if (a0 == 0 || a1 == 0)
649         {
650                 v0 = 0;
651                 pc0 = ra;
652                 return;
653         }
654         while (*p1++);
655         --p1;
656         while ((*p1++ = *p2++) != '\0') {
657                 if (--n < 0) {
658                         *--p1 = '\0';
659                         break;
660                 }
661         }
662
663         v0 = a0; pc0 = ra;
664 }
665
666 void psxBios_strcmp() { // 0x17
667         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
668         s32 n=0;
669         if (a0 == 0 && a1 == 0)
670         {
671                 v0 = 0;
672                 pc0 = ra;
673                 return;
674         }
675         else if (a0 == 0 && a1 != 0)
676         {
677                 v0 = -1;
678                 pc0 = ra;
679                 return;
680         }
681         else if (a0 != 0 && a1 == 0)
682         {
683                 v0 = 1;
684                 pc0 = ra;
685                 return;
686         }
687 #ifdef PSXBIOS_LOG
688         PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
689 #endif
690
691         while (*p1 == *p2++) {
692                 n++;
693                 if (*p1++ == '\0') {
694                         v1=n-1;
695                         a0+=n;
696                         a1+=n;
697                         v0 = 0;
698                         pc0 = ra;
699                         return;
700                 }
701         }
702
703         v0 = (*p1 - *--p2);
704         v1 = n;
705         a0+=n;
706         a1+=n;
707         pc0 = ra;
708 }
709
710 void psxBios_strncmp() { // 0x18
711         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
712         s32 n = a2;
713         if (a0 == 0 && a1 == 0)
714         {
715                 v0 = 0;
716                 pc0 = ra;
717                 return;
718         }
719         else if (a0 == 0 && a1 != 0)
720         {
721                 v0 = -1;
722                 pc0 = ra;
723                 return;
724         }
725         else if (a0 != 0 && a1 == 0)
726         {
727                 v0 = 1;
728                 pc0 = ra;
729                 return;
730         }
731 #ifdef PSXBIOS_LOG
732         PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
733 #endif
734
735         while (--n >= 0 && *p1 == *p2++) {
736                 if (*p1++ == '\0') {
737                         v0 = 0;
738                         pc0 = ra;
739                         v1 = a2 - ((a2-n) - 1);
740                         a0 += (a2-n) - 1;
741                         a1 += (a2-n) - 1;
742                         a2 = n;
743                         return;
744                 }
745         }
746
747         v0 = (n < 0 ? 0 : *p1 - *--p2);
748         pc0 = ra;
749         v1 = a2 - ((a2-n) - 1);
750         a0 += (a2-n) - 1;
751         a1 += (a2-n) - 1;
752         a2 = n;
753 }
754
755 void psxBios_strcpy() { // 0x19
756         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
757         if (a0 == 0 || a1 == 0)
758         {
759                 v0 = 0;
760                 pc0 = ra;
761                 return;
762         }
763         while ((*p1++ = *p2++) != '\0');
764
765         v0 = a0; pc0 = ra;
766 }
767
768 void psxBios_strncpy() { // 0x1a
769         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
770         s32 n = a2, i;
771         if (a0 == 0 || a1 == 0)
772         {
773                 v0 = 0;
774                 pc0 = ra;
775                 return;
776         }
777         for (i = 0; i < n; i++) {
778                 if ((*p1++ = *p2++) == '\0') {
779                         while (++i < n) {
780                                 *p1++ = '\0';
781                         }
782                         v0 = a0; pc0 = ra;
783                         return;
784                 }
785         }
786
787         v0 = a0; pc0 = ra;
788 }
789
790 void psxBios_strlen() { // 0x1b
791         char *p = (char *)Ra0;
792         v0 = 0;
793         if (a0 == 0)
794         {
795                 pc0 = ra;
796                 return;
797         }
798         while (*p++) v0++;
799         pc0 = ra;
800 }
801
802 void psxBios_index() { // 0x1c
803         char *p = (char *)Ra0;
804         if (a0 == 0)
805         {
806                 v0 = 0;
807                 pc0 = ra;
808                 return;
809         }
810
811         do {
812                 if (*p == a1) {
813                         v0 = a0 + (p - (char *)Ra0);
814                         pc0 = ra;
815                         return;
816                 }
817         } while (*p++ != '\0');
818
819         v0 = 0; pc0 = ra;
820 }
821
822 void psxBios_rindex() { // 0x1d
823         char *p = (char *)Ra0;
824
825         v0 = 0;
826         if (a0 == 0)
827         {
828                 pc0 = ra;
829                 return;
830         }
831         do {
832                 if (*p == a1)
833                         v0 = a0 + (p - (char *)Ra0);
834         } while (*p++ != '\0');
835
836         pc0 = ra;
837 }
838
839 void psxBios_strchr() { // 0x1e
840         psxBios_index();
841 }
842
843 void psxBios_strrchr() { // 0x1f
844         psxBios_rindex();
845 }
846
847 void psxBios_strpbrk() { // 0x20
848         char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
849
850         while ((c = *p1++) != '\0') {
851                 for (scanp = p2; (sc = *scanp++) != '\0';) {
852                         if (sc == c) {
853                                 v0 = a0 + (p1 - 1 - (char *)Ra0);
854                                 pc0 = ra;
855                                 return;
856                         }
857                 }
858         }
859
860         // BUG: return a0 instead of NULL if not found
861         v0 = a0; pc0 = ra;
862 }
863
864 void psxBios_strspn() { // 0x21
865         char *p1, *p2;
866
867         for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
868                 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
869                 if (*p2 == '\0') break;
870         }
871
872         v0 = p1 - (char *)Ra0; pc0 = ra;
873 }
874
875 void psxBios_strcspn() { // 0x22
876         char *p1, *p2;
877
878         for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
879                 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
880                 if (*p2 != '\0') break;
881         }
882
883         v0 = p1 - (char *)Ra0; pc0 = ra;
884 }
885
886 void psxBios_strtok() { // 0x23
887         char *pcA0 = (char *)Ra0;
888         char *pcRet = strtok(pcA0, (char *)Ra1);
889         if (pcRet)
890                 v0 = a0 + pcRet - pcA0;
891         else
892                 v0 = 0;
893         pc0 = ra;
894 }
895
896 void psxBios_strstr() { // 0x24
897         char *p = (char *)Ra0, *p1, *p2;
898
899         while (*p != '\0') {
900                 p1 = p;
901                 p2 = (char *)Ra1;
902
903                 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
904                         p1++; p2++;
905                 }
906
907                 if (*p2 == '\0') {
908                         v0 = a0 + (p - (char *)Ra0);
909                         pc0 = ra;
910                         return;
911                 }
912
913                 p++;
914         }
915
916         v0 = 0; pc0 = ra;
917 }
918
919 void psxBios_toupper() { // 0x25
920         v0 = (s8)(a0 & 0xff);
921         if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
922         pc0 = ra;
923 }
924
925 void psxBios_tolower() { // 0x26
926         v0 = (s8)(a0 & 0xff);
927         if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
928         pc0 = ra;
929 }
930
931 static void do_memset(u32 dst, u32 v, s32 len)
932 {
933         u32 d = dst;
934         s32 l = len;
935         while (l-- > 0) {
936                 u8 *db = PSXM(d);
937                 if (db != INVALID_PTR)
938                         *db = v;
939                 d++;
940         }
941         psxCpu->Clear(dst, (len + 3) / 4);
942 }
943
944 static void do_memcpy(u32 dst, u32 src, s32 len)
945 {
946         u32 d = dst, s = src;
947         s32 l = len;
948         while (l-- > 0) {
949                 const u8 *sb = PSXM(s);
950                 u8 *db = PSXM(d);
951                 if (db != INVALID_PTR && sb != INVALID_PTR)
952                         *db = *sb;
953                 d++;
954                 s++;
955         }
956         psxCpu->Clear(dst, (len + 3) / 4);
957 }
958
959 static void psxBios_memcpy();
960
961 static void psxBios_bcopy() { // 0x27 - memcpy with args swapped
962         //PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x27], a0, a1, a2);
963         u32 ret = a0, cycles = 0;
964         if (a0 == 0) // ...but it checks src this time
965         {
966                 mips_return_c(0, 4);
967                 return;
968         }
969         v1 = a0;
970         if ((s32)a2 > 0) {
971                 do_memcpy(a1, a0, a2);
972                 cycles = a2 * 6;
973                 a0 += a2;
974                 a1 += a2;
975                 a2 = 0;
976         }
977         mips_return_c(ret, cycles + 5);
978 }
979
980 static void psxBios_bzero() { // 0x28
981         /* Same as memset here (See memset below) */
982         u32 ret = a0, cycles;
983         if (a0 == 0 || (s32)a1 <= 0)
984         {
985                 mips_return_c(0, 6);
986                 return;
987         }
988         do_memset(a0, 0, a1);
989         cycles = a1 * 4;
990         a0 += a1;
991         a1 = 0;
992         // todo: many more cycles due to uncached bios mem
993         mips_return_c(ret, cycles + 5);
994 }
995
996 void psxBios_bcmp() { // 0x29
997         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
998
999         if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
1000
1001         while ((s32)a2-- > 0) {
1002                 if (*p1++ != *p2++) {
1003                         v0 = *p1 - *p2; // BUG: compare the NEXT byte
1004                         pc0 = ra;
1005                         return;
1006                 }
1007         }
1008
1009         v0 = 0; pc0 = ra;
1010 }
1011
1012 static void psxBios_memcpy() { // 0x2a
1013         u32 ret = a0, cycles = 0;
1014         if (a0 == 0)
1015         {
1016                 mips_return_c(0, 4);
1017                 return;
1018         }
1019         v1 = a0;
1020         if ((s32)a2 > 0) {
1021                 do_memcpy(a0, a1, a2);
1022                 cycles = a2 * 6;
1023                 a0 += a2;
1024                 a1 += a2;
1025                 a2 = 0;
1026         }
1027         mips_return_c(ret, cycles + 5);
1028 }
1029
1030 static void psxBios_memset() { // 0x2b
1031         u32 ret = a0, cycles;
1032         if (a0 == 0 || (s32)a2 <= 0)
1033         {
1034                 mips_return_c(0, 6);
1035                 return;
1036         }
1037         do_memset(a0, a1, a2);
1038         cycles = a2 * 4;
1039         a0 += a2;
1040         a2 = 0;
1041         // todo: many more cycles due to uncached bios mem
1042         mips_return_c(ret, cycles + 5);
1043 }
1044
1045 void psxBios_memmove() { // 0x2c
1046         u32 ret = a0, cycles = 0;
1047         if (a0 == 0)
1048         {
1049                 mips_return_c(0, 4);
1050                 return;
1051         }
1052         v1 = a0;
1053         if ((s32)a2 > 0 && a0 > a1 && a0 < a1 + a2) {
1054                 u32 dst = a0, len = a2 + 1;
1055                 a0 += a2;
1056                 a1 += a2;
1057                 while ((s32)a2 >= 0) { // BUG: copies one more byte here
1058                         const u8 *sb = PSXM(a1);
1059                         u8 *db = PSXM(a0);
1060                         if (db != INVALID_PTR && sb != INVALID_PTR)
1061                                 *db = *sb;
1062                         a0--;
1063                         a1--;
1064                         a2--;
1065                 }
1066                 psxCpu->Clear(dst, (len + 3) / 4);
1067                 cycles = 10 + len * 8;
1068         } else if ((s32)a2 > 0) {
1069                 do_memcpy(a0, a1, a2);
1070                 cycles = a2 * 6;
1071                 a0 += a2;
1072                 a1 += a2;
1073                 a2 = 0;
1074         }
1075         mips_return_c(ret, cycles + 5);
1076 }
1077
1078 void psxBios_memcmp() { // 0x2d
1079         psxBios_bcmp();
1080 }
1081
1082 void psxBios_memchr() { // 0x2e
1083         char *p = (char *)Ra0;
1084
1085         if (a0 == 0 || a2 > 0x7FFFFFFF)
1086         {
1087                 pc0 = ra;
1088                 return;
1089         }
1090
1091         while ((s32)a2-- > 0) {
1092                 if (*p++ != (s8)a1) continue;
1093                 v0 = a0 + (p - (char *)Ra0 - 1);
1094                 pc0 = ra;
1095                 return;
1096         }
1097
1098         v0 = 0; pc0 = ra;
1099 }
1100
1101 static void psxBios_rand() { // 0x2f
1102         u32 s = loadRam32(A_RND_SEED) * 1103515245 + 12345;
1103         storeRam32(A_RND_SEED, s);
1104         v1 = s;
1105         mips_return_c((s >> 16) & 0x7fff, 12+37);
1106 }
1107
1108 static void psxBios_srand() { // 0x30
1109         storeRam32(A_RND_SEED, a0);
1110         mips_return_void_c(3);
1111 }
1112
1113 static u32 qscmpfunc, qswidth;
1114
1115 static inline int qscmp(char *a, char *b) {
1116         u32 sa0 = a0;
1117
1118         a0 = sa0 + (a - (char *)PSXM(sa0));
1119         a1 = sa0 + (b - (char *)PSXM(sa0));
1120
1121         softCall(qscmpfunc);
1122
1123         a0 = sa0;
1124         return (s32)v0;
1125 }
1126
1127 static inline void qexchange(char *i, char *j) {
1128         char t;
1129         int n = qswidth;
1130
1131         do {
1132                 t = *i;
1133                 *i++ = *j;
1134                 *j++ = t;
1135         } while (--n);
1136 }
1137
1138 static inline void q3exchange(char *i, char *j, char *k) {
1139         char t;
1140         int n = qswidth;
1141
1142         do {
1143                 t = *i;
1144                 *i++ = *k;
1145                 *k++ = *j;
1146                 *j++ = t;
1147         } while (--n);
1148 }
1149
1150 static void qsort_main(char *a, char *l) {
1151         char *i, *j, *lp, *hp;
1152         int c;
1153         unsigned int n;
1154
1155 start:
1156         if ((n = l - a) <= qswidth)
1157                 return;
1158         n = qswidth * (n / (2 * qswidth));
1159         hp = lp = a + n;
1160         i = a;
1161         j = l - qswidth;
1162         while (TRUE) {
1163                 if (i < lp) {
1164                         if ((c = qscmp(i, lp)) == 0) {
1165                                 qexchange(i, lp -= qswidth);
1166                                 continue;
1167                         }
1168                         if (c < 0) {
1169                                 i += qswidth;
1170                                 continue;
1171                         }
1172                 }
1173
1174 loop:
1175                 if (j > hp) {
1176                         if ((c = qscmp(hp, j)) == 0) {
1177                                 qexchange(hp += qswidth, j);
1178                                 goto loop;
1179                         }
1180                         if (c > 0) {
1181                                 if (i == lp) {
1182                                         q3exchange(i, hp += qswidth, j);
1183                                         i = lp += qswidth;
1184                                         goto loop;
1185                                 }
1186                                 qexchange(i, j);
1187                                 j -= qswidth;
1188                                 i += qswidth;
1189                                 continue;
1190                         }
1191                         j -= qswidth;
1192                         goto loop;
1193                 }
1194
1195                 if (i == lp) {
1196                         if (lp - a >= l - hp) {
1197                                 qsort_main(hp + qswidth, l);
1198                                 l = lp;
1199                         } else {
1200                                 qsort_main(a, lp);
1201                                 a = hp + qswidth;
1202                         }
1203                         goto start;
1204                 }
1205
1206                 q3exchange(j, lp -= qswidth, i);
1207                 j = hp -= qswidth;
1208         }
1209 }
1210
1211 void psxBios_qsort() { // 0x31
1212         qswidth = a2;
1213         qscmpfunc = a3;
1214         qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1215
1216         pc0 = ra;
1217 }
1218
1219 // this isn't how the real bios works, but maybe good enough
1220 static void psxBios_malloc() { // 0x33
1221         u32 *heap_addr, *heap_end;
1222         u32 *chunk, *newchunk = NULL;
1223         unsigned int dsize = 0, csize, cstat;
1224         int colflag;
1225         PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x33], a0);
1226         heap_addr = loadRam32ptr(A_HEAP_BASE);
1227         heap_end = loadRam32ptr(A_HEAP_END);
1228         if (heap_addr >= heap_end) {
1229                 v0 = 0;
1230                 pc0 = ra;
1231                 return;
1232         }
1233
1234         // scan through heap and combine free chunks of space
1235         chunk = heap_addr;
1236         colflag = 0;
1237         while(chunk < heap_end) {
1238                 // get size and status of actual chunk
1239                 csize = ((u32)*chunk) & 0xfffffffc;
1240                 cstat = ((u32)*chunk) & 1;
1241
1242                 // most probably broken heap descriptor
1243                 // this fixes Burning Road
1244                 if (*chunk == 0) {
1245                         newchunk = chunk;
1246                         dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1247                         colflag = 1;
1248                         break;
1249                 }
1250
1251                 // it's a free chunk
1252                 if(cstat == 1) {
1253                         if(colflag == 0) {
1254                                 newchunk = chunk;
1255                                 dsize = csize;
1256                                 colflag = 1;                    // let's begin a new collection of free memory
1257                         }
1258                         else dsize += (csize+4);        // add the new size including header
1259                 }
1260                 // not a free chunk: did we start a collection ?
1261                 else {
1262                         if(colflag == 1) {                      // collection is over
1263                                 colflag = 0;
1264                                 *newchunk = SWAP32(dsize | 1);
1265                         }
1266                 }
1267
1268                 // next chunk
1269                 chunk = (u32*)((uptr)chunk + csize + 4);
1270         }
1271         // if neccessary free memory on end of heap
1272         if (colflag == 1)
1273                 *newchunk = SWAP32(dsize | 1);
1274
1275         chunk = heap_addr;
1276         csize = ((u32)*chunk) & 0xfffffffc;
1277         cstat = ((u32)*chunk) & 1;
1278         dsize = (a0 + 3) & 0xfffffffc;
1279
1280         // exit on uninitialized heap
1281         if (chunk == NULL) {
1282                 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1283                 v0 = 0;
1284                 pc0 = ra;
1285                 return;
1286         }
1287
1288         // search an unused chunk that is big enough until the end of the heap
1289         while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1290                 chunk = (u32*)((uptr)chunk + csize + 4);
1291
1292                         // catch out of memory
1293                         if(chunk >= heap_end) {
1294                                 printf("malloc %x,%x: Out of memory error!\n",
1295                                         v0, a0);
1296                                 v0 = 0; pc0 = ra;
1297                                 return;
1298                         }
1299
1300                 csize = ((u32)*chunk) & 0xfffffffc;
1301                 cstat = ((u32)*chunk) & 1;
1302         }
1303
1304         // allocate memory
1305         if(dsize == csize) {
1306                 // chunk has same size
1307                 *chunk &= 0xfffffffc;
1308         } else if (dsize > csize) {
1309                 v0 = 0; pc0 = ra;
1310                 return;
1311         } else {
1312                 // split free chunk
1313                 *chunk = SWAP32(dsize);
1314                 newchunk = (u32*)((uptr)chunk + dsize + 4);
1315                 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1316         }
1317
1318         // return pointer to allocated memory
1319         v0 = ((uptr)chunk - (uptr)psxM) + 4;
1320         v0|= 0x80000000;
1321         //printf ("malloc %x,%x\n", v0, a0);
1322         pc0 = ra;
1323 }
1324
1325 static void psxBios_free() { // 0x34
1326         PSXBIOS_LOG("psxBios_%s %x (%x bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1327         storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1328         mips_return_void_c(5);
1329 }
1330
1331 static void psxBios_calloc() { // 0x37
1332         u32 ret, size;
1333         PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
1334
1335         a0 = size = a0 * a1;
1336         psxBios_malloc();
1337         ret = v0;
1338         if (ret) {
1339                 a0 = ret; a1 = size;
1340                 psxBios_bzero();
1341         }
1342         mips_return_c(ret, 21);
1343 }
1344
1345 void psxBios_realloc() { // 0x38
1346         u32 block = a0;
1347         u32 size = a1;
1348 #ifdef PSXBIOS_LOG
1349         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1350 #endif
1351
1352         a0 = block;
1353         /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1354         if (block == 0)
1355         {
1356                 psxBios_malloc();
1357         }
1358         /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1359         else if (size == 0)
1360         {
1361                 psxBios_free();
1362         }
1363         /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1364         /* Note that it is not quite implemented this way here. */
1365         else
1366         {
1367                 psxBios_free();
1368                 a0 = size;
1369                 psxBios_malloc();
1370         }
1371 }
1372
1373
1374 /* InitHeap(void *block , int n) */
1375 static void psxBios_InitHeap() { // 0x39
1376         PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
1377
1378         storeRam32(A_HEAP_BASE, a0);
1379         storeRam32(A_HEAP_SIZE, a1);
1380         storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
1381         storeRam32(A_HEAP_FLAG, 0);
1382         storeRam32(a0, 0);
1383
1384         mips_return_void_c(14);
1385 }
1386
1387 void psxBios_getchar() { //0x3b
1388         v0 = getchar(); pc0 = ra;
1389 }
1390
1391 static void psxBios_printf_psxout() { // 0x3f
1392         char tmp[1024];
1393         char tmp2[1024];
1394         u32 save[4];
1395         char *ptmp = tmp;
1396         int n=1, i=0, j;
1397         void *psp;
1398
1399         psp = PSXM(sp);
1400         if (psp != INVALID_PTR) {
1401                 memcpy(save, psp, 4 * 4);
1402                 psxMu32ref(sp) = SWAP32((u32)a0);
1403                 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1404                 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1405                 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1406         }
1407
1408         while (Ra0[i]) {
1409                 switch (Ra0[i]) {
1410                         case '%':
1411                                 j = 0;
1412                                 tmp2[j++] = '%';
1413 _start:
1414                                 switch (Ra0[++i]) {
1415                                         case '.':
1416                                         case 'l':
1417                                                 tmp2[j++] = Ra0[i]; goto _start;
1418                                         default:
1419                                                 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1420                                                         tmp2[j++] = Ra0[i];
1421                                                         goto _start;
1422                                                 }
1423                                                 break;
1424                                 }
1425                                 tmp2[j++] = Ra0[i];
1426                                 tmp2[j] = 0;
1427
1428                                 switch (Ra0[i]) {
1429                                         case 'f': case 'F':
1430                                                 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1431                                         case 'a': case 'A':
1432                                         case 'e': case 'E':
1433                                         case 'g': case 'G':
1434                                                 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1435                                         case 'p':
1436                                         case 'i': case 'u':
1437                                         case 'd': case 'D':
1438                                         case 'o': case 'O':
1439                                         case 'x': case 'X':
1440                                                 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1441                                         case 'c':
1442                                                 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1443                                         case 's':
1444                                                 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1445                                         case '%':
1446                                                 *ptmp++ = Ra0[i]; break;
1447                                 }
1448                                 i++;
1449                                 break;
1450                         default:
1451                                 *ptmp++ = Ra0[i++];
1452                 }
1453         }
1454         *ptmp = 0;
1455
1456         if (psp != INVALID_PTR)
1457                 memcpy(psp, save, 4 * 4);
1458
1459         if (Config.PsxOut)
1460                 SysPrintf("%s", tmp);
1461 }
1462
1463 void psxBios_printf() { // 0x3f
1464         psxBios_printf_psxout();
1465         pc0 = ra;
1466 }
1467
1468 void psxBios_format() { // 0x41
1469         if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1470         {
1471                 CreateMcd(Config.Mcd1);
1472                 LoadMcd(1, Config.Mcd1);
1473                 v0 = 1;
1474         }
1475         else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1476         {
1477                 CreateMcd(Config.Mcd2);
1478                 LoadMcd(2, Config.Mcd2);
1479                 v0 = 1;
1480         }
1481         else
1482         {
1483                 v0 = 0;
1484         }
1485         pc0 = ra;
1486 }
1487
1488 static void psxBios_SystemErrorUnresolvedException() {
1489         if (loadRam32(0xfffc) != 0x12345678) { // prevent log flood
1490                 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1491                 storeRam32(0xfffc, 0x12345678);
1492         }
1493         mips_return_void_c(1000);
1494 }
1495
1496 static void FlushCache() {
1497         psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1498         psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1499         k0 = 0xbfc0193c;
1500         // runs from uncached mem so tons of cycles
1501         use_cycles(500);
1502 }
1503
1504 /*
1505  *      long Load(char *name, struct EXEC *header);
1506  */
1507
1508 void psxBios_Load() { // 0x42
1509         EXE_HEADER eheader;
1510         void *pa1;
1511
1512         pa1 = Ra1;
1513         if (pa1 != INVALID_PTR && LoadCdromFile(Ra0, &eheader) == 0) {
1514                 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1515                 psxCpu->Clear(a1, sizeof(EXEC) / 4);
1516                 FlushCache();
1517                 v0 = 1;
1518         } else v0 = 0;
1519         PSXBIOS_LOG("psxBios_%s: %s, %d -> %d\n", biosA0n[0x42], Ra0, a1, v0);
1520
1521         pc0 = ra;
1522 }
1523
1524 /*
1525  *      int Exec(struct EXEC *header , int argc , char **argv);
1526  */
1527
1528 void psxBios_Exec() { // 43
1529         EXEC *header = (EXEC *)castRam32ptr(a0);
1530         u32 ptr;
1531         s32 len;
1532
1533         PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1534
1535         header->_sp = SWAP32(sp);
1536         header->_fp = SWAP32(fp);
1537         header->_sp = SWAP32(sp);
1538         header->_gp = SWAP32(gp);
1539         header->ret = SWAP32(ra);
1540         header->base = SWAP32(s0);
1541
1542         ptr = SWAP32(header->b_addr);
1543         len = SWAP32(header->b_size);
1544         if (len != 0) do {
1545                 storeRam32(ptr, 0);
1546                 len -= 4; ptr += 4;
1547         } while (len > 0);
1548
1549         if (header->S_addr != 0)
1550                 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1551
1552         gp = SWAP32(header->gp0);
1553
1554         s0 = a0;
1555
1556         a0 = a1;
1557         a1 = a2;
1558
1559         ra = 0x8000;
1560         pc0 = SWAP32(header->_pc0);
1561 }
1562
1563 static void psxBios_FlushCache() { // 44
1564         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1565         FlushCache();
1566         mips_return_void();
1567 }
1568
1569 void psxBios_GPU_dw() { // 0x46
1570         int size;
1571         u32 *ptr;
1572
1573 #ifdef PSXBIOS_LOG
1574         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1575 #endif
1576
1577         GPU_writeData(0xa0000000);
1578         GPU_writeData((a1<<0x10)|(a0&0xffff));
1579         GPU_writeData((a3<<0x10)|(a2&0xffff));
1580         size = (a2*a3)/2;
1581         ptr = (u32*)PSXM(Rsp[4]);  //that is correct?
1582         while(size--)
1583         {
1584                 GPU_writeData(SWAPu32(*ptr++));
1585         } 
1586
1587         pc0 = ra;
1588 }
1589
1590 void psxBios_mem2vram() { // 0x47
1591         int size;
1592         gpuSyncPluginSR(); // flush
1593         GPU_writeData(0xa0000000);
1594         GPU_writeData((a1<<0x10)|(a0&0xffff));
1595         GPU_writeData((a3<<0x10)|(a2&0xffff));
1596         size = ((((a2 * a3) / 2) >> 4) << 16);
1597         GPU_writeStatus(0x04000002);
1598         psxHwWrite32(0x1f8010f4,0);
1599         psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1600         psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1601         psxHwWrite32(0x1f8010a4, size | 0x10);
1602         psxHwWrite32(0x1f8010a8,0x01000201);
1603
1604         pc0 = ra;
1605 }
1606
1607 void psxBios_SendGPU() { // 0x48
1608         GPU_writeStatus(a0);
1609         gpuSyncPluginSR();
1610         pc0 = ra;
1611 }
1612
1613 void psxBios_GPU_cw() { // 0x49
1614         GPU_writeData(a0);
1615         gpuSyncPluginSR();
1616         v0 = HW_GPU_STATUS;
1617         pc0 = ra;
1618 }
1619
1620 void psxBios_GPU_cwb() { // 0x4a
1621         u32 *ptr = (u32*)Ra0;
1622         int size = a1;
1623         gpuSyncPluginSR();
1624         while(size--)
1625         {
1626                 GPU_writeData(SWAPu32(*ptr++));
1627         }
1628
1629         pc0 = ra;
1630 }
1631    
1632 void psxBios_GPU_SendPackets() { //4b:  
1633         gpuSyncPluginSR();
1634         GPU_writeStatus(0x04000002);
1635         psxHwWrite32(0x1f8010f4,0);
1636         psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1637         psxHwWrite32(0x1f8010a0,a0);
1638         psxHwWrite32(0x1f8010a4,0);
1639         psxHwWrite32(0x1f8010a8,0x010000401);
1640         pc0 = ra;
1641 }
1642
1643 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1644         psxHwWrite32(0x1f8010a8,0x00000401);
1645         GPU_writeData(0x0400000);
1646         GPU_writeData(0x0200000);
1647         GPU_writeData(0x0100000);
1648         v0 = 0x1f801814;
1649         pc0 = ra;
1650 }
1651
1652 void psxBios_GPU_GetGPUStatus() { // 0x4d
1653         v0 = GPU_readStatus();
1654         pc0 = ra;
1655 }
1656
1657 #undef s_addr
1658
1659 void psxBios_LoadExec() { // 51
1660         EXEC *header = (EXEC*)PSXM(0xf000);
1661         u32 s_addr, s_size;
1662
1663 #ifdef PSXBIOS_LOG
1664         PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1665 #endif
1666         s_addr = a1; s_size = a2;
1667
1668         a1 = 0xf000;
1669         psxBios_Load();
1670
1671         header->S_addr = s_addr;
1672         header->s_size = s_size;
1673
1674         a0 = 0xf000; a1 = 0; a2 = 0;
1675         psxBios_Exec();
1676 }
1677
1678 void psxBios__bu_init() { // 70
1679 #ifdef PSXBIOS_LOG
1680         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1681 #endif
1682
1683         DeliverEvent(0xf0000011, 0x0004);
1684         DeliverEvent(0xf4000001, 0x0004);
1685
1686         pc0 = ra;
1687 }
1688
1689 void psxBios__96_init() { // 71
1690 #ifdef PSXBIOS_LOG
1691         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1692 #endif
1693
1694         pc0 = ra;
1695 }
1696
1697 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1698 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1699 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1700
1701 static void psxBios_DequeueCdIntr_() {
1702         psxBios_SysDeqIntRP_(0, 0x91d0);
1703         psxBios_SysDeqIntRP_(0, 0x91e0);
1704         use_cycles(16);
1705 }
1706
1707 static void psxBios_DequeueCdIntr() { // a3
1708         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1709         psxBios_DequeueCdIntr_();
1710 }
1711
1712 static void psxBios_CdRemove() { // 56, 72
1713         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1714
1715         CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1716         CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1717         CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1718         CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1719         CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1720         psxBios_DequeueCdIntr_();
1721
1722         // EnterCriticalSection - should be done at the beginning,
1723         // but this way is much easier to implement
1724         a0 = 1;
1725         pc0 = A_SYSCALL;
1726         use_cycles(30);
1727 }
1728
1729 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack);
1730
1731 static void psxBios_SetConf() { // 9c
1732         PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9c], a0, a1, a2);
1733         setup_tt(a1, a0, a2);
1734         psxRegs.CP0.n.SR |= 0x401;
1735         mips_return_void_c(500);
1736 }
1737
1738 static void psxBios_GetConf() { // 9d
1739         PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9d], a0, a1, a2);
1740         storeRam32(a0, loadRam32(A_CONF_EvCB));
1741         storeRam32(a1, loadRam32(A_CONF_TCB));
1742         storeRam32(a2, loadRam32(A_CONF_SP));
1743         mips_return_void_c(10);
1744 }
1745
1746 void psxBios_SetMem() { // 9f
1747         u32 new = psxHu32(0x1060);
1748
1749 #ifdef PSXBIOS_LOG
1750         PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1751 #endif
1752
1753         switch(a0) {
1754                 case 2:
1755                         psxHu32ref(0x1060) = SWAP32(new);
1756                         psxMu32ref(0x060) = a0;
1757                         PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1758                         break;
1759
1760                 case 8:
1761                         psxHu32ref(0x1060) = SWAP32(new | 0x300);
1762                         psxMu32ref(0x060) = a0;
1763                         PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1764
1765                 default:
1766                         PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
1767                 break;
1768         }
1769
1770         pc0 = ra;
1771 }
1772
1773 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1774 static void psxBios_get_cd_status() // a6
1775 {
1776         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
1777         v0 = 1;
1778         pc0 = ra;
1779 }
1780
1781 static void psxBios__card_info() { // ab
1782         PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1783         u32 ret, port;
1784         storeRam32(A_CARD_CHAN1, a0);
1785         port = a0 >> 4;
1786
1787         switch (port) {
1788         case 0x0:
1789         case 0x1:
1790                 ret = 0x0004;
1791                 if (McdDisable[port & 1])
1792                         ret = 0x0100;
1793                 break;
1794         default:
1795                 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
1796                 ret = 0x0302;
1797                 break;
1798         }
1799
1800         if (McdDisable[0] && McdDisable[1])
1801                 ret = 0x0100;
1802
1803         DeliverEvent(0xf0000011, 0x0004);
1804 //      DeliverEvent(0xf4000001, 0x0004);
1805         DeliverEvent(0xf4000001, ret);
1806         v0 = 1; pc0 = ra;
1807 }
1808
1809 void psxBios__card_load() { // ac
1810 #ifdef PSXBIOS_LOG
1811         PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1812 #endif
1813
1814         storeRam32(A_CARD_CHAN1, a0);
1815
1816 //      DeliverEvent(0xf0000011, 0x0004);
1817         DeliverEvent(0xf4000001, 0x0004);
1818
1819         v0 = 1; pc0 = ra;
1820 }
1821
1822 static void psxBios_GetSystemInfo() { // b4
1823         u32 ret = 0;
1824         //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
1825         SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
1826         switch (a0) {
1827         case 0:
1828         case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
1829         case 2: ret = 0xbfc0012c; break;
1830         case 5: ret = loadRam32(0x60) << 10; break;
1831         }
1832         mips_return_c(ret, 20);
1833 }
1834
1835 /* System calls B0 */
1836
1837 static u32 psxBios_SysMalloc_(u32 size);
1838
1839 static void psxBios_SysMalloc() { // B 00
1840         u32 ret = psxBios_SysMalloc_(a0);
1841
1842         PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1843         mips_return_c(ret, 33);
1844 }
1845
1846 void psxBios_SetRCnt() { // 02
1847 #ifdef PSXBIOS_LOG
1848         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1849 #endif
1850
1851         a0&= 0x3;
1852         if (a0 != 3) {
1853                 u32 mode=0;
1854
1855                 psxRcntWtarget(a0, a1);
1856                 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1857                 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1858                 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1859                 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1860                 else         { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1861
1862                 psxRcntWmode(a0, mode);
1863         }
1864         pc0 = ra;
1865 }
1866
1867 void psxBios_GetRCnt() { // 03
1868 #ifdef PSXBIOS_LOG
1869         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1870 #endif
1871
1872         switch (a0 & 0x3)
1873         {
1874         case 0: v0 = psxRcntRcount0(); break;
1875         case 1: v0 = psxRcntRcount1(); break;
1876         case 2: v0 = psxRcntRcount2(); break;
1877         case 3: v0 = 0; break;
1878         }
1879         pc0 = ra;
1880 }
1881
1882 void psxBios_StartRCnt() { // 04
1883 #ifdef PSXBIOS_LOG
1884         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1885 #endif
1886
1887         a0&= 0x3;
1888         if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1889         else psxHu32ref(0x1074)|= SWAPu32(0x1);
1890         v0 = 1; pc0 = ra;
1891 }
1892
1893 void psxBios_StopRCnt() { // 05
1894 #ifdef PSXBIOS_LOG
1895         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1896 #endif
1897
1898         a0&= 0x3;
1899         if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1900         else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1901         pc0 = ra;
1902 }
1903
1904 void psxBios_ResetRCnt() { // 06
1905 #ifdef PSXBIOS_LOG
1906         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1907 #endif
1908
1909         a0&= 0x3;
1910         if (a0 != 3) {
1911                 psxRcntWmode(a0, 0);
1912                 psxRcntWtarget(a0, 0);
1913                 psxRcntWcount(a0, 0);
1914         }
1915         pc0 = ra;
1916 }
1917
1918 static u32 DeliverEvent(u32 class, u32 spec) {
1919         EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1920         u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1921         u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1922         u32 i, lim = evcb_len / 0x1c;
1923
1924         //printf("%s %08x %x\n", __func__, class, spec);
1925         for (i = 0; i < lim; i++, ev++) {
1926                 use_cycles(8);
1927                 if (SWAP32(ev->status) != EvStACTIVE)
1928                         continue;
1929                 use_cycles(4);
1930                 if (SWAP32(ev->class) != class)
1931                         continue;
1932                 use_cycles(4);
1933                 if (SWAP32(ev->spec) != spec)
1934                         continue;
1935                 use_cycles(6);
1936                 ret = SWAP32(ev->mode);
1937                 if (ret == EvMdMARK) {
1938                         ev->status = SWAP32(EvStALREADY);
1939                         continue;
1940                 }
1941                 use_cycles(8);
1942                 if (ret == EvMdCALL) {
1943                         ret = SWAP32(ev->fhandler);
1944                         if (ret) {
1945                                 v0 = ret;
1946                                 softCall(ret);
1947                                 ret = v0;
1948                         }
1949                 }
1950         }
1951         use_cycles(29);
1952         return ret;
1953 }
1954
1955 static u32 UnDeliverEvent(u32 class, u32 spec) {
1956         EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1957         u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1958         u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1959         u32 i, lim = evcb_len / 0x1c;
1960
1961         for (i = 0; i < lim; i++, ev++) {
1962                 use_cycles(8);
1963                 if (SWAP32(ev->status) != EvStALREADY)
1964                         continue;
1965                 use_cycles(4);
1966                 if (SWAP32(ev->class) != class)
1967                         continue;
1968                 use_cycles(4);
1969                 if (SWAP32(ev->spec) != spec)
1970                         continue;
1971                 use_cycles(6);
1972                 if (SWAP32(ev->mode) == EvMdMARK)
1973                         ev->status = SWAP32(EvStACTIVE);
1974         }
1975         use_cycles(28);
1976         return ret;
1977 }
1978
1979 static void psxBios_DeliverEvent() { // 07
1980         u32 ret;
1981         PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
1982
1983         ret = DeliverEvent(a0, a1);
1984         mips_return(ret);
1985 }
1986
1987 static s32 get_free_EvCB_slot() {
1988         EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1989         u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
1990
1991         use_cycles(19);
1992         for (i = 0; i < lim; i++, ev++) {
1993                 use_cycles(8);
1994                 if (ev->status == SWAP32(EvStUNUSED))
1995                         return i;
1996         }
1997         return -1;
1998 }
1999
2000 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
2001         u32 ret = get_free_EvCB_slot();
2002         if ((s32)ret >= 0) {
2003                 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
2004                 ev->class = SWAP32(class);
2005                 ev->status = SWAP32(EvStDISABLED);
2006                 ev->spec = SWAP32(spec);
2007                 ev->mode = SWAP32(mode);
2008                 ev->fhandler = SWAP32(func);
2009                 ret |= 0xf1000000u;
2010         }
2011         return ret;
2012 }
2013
2014 static void psxBios_OpenEvent() { // 08
2015         u32 ret = OpenEvent(a0, a1, a2, a3);
2016         PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
2017                 biosB0n[0x08], a0, a1, a2, a3, ret);
2018         mips_return_c(ret, 36);
2019 }
2020
2021 static void CloseEvent(u32 ev)
2022 {
2023         u32 base = loadRam32(A_TT_EvCB);
2024         storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
2025 }
2026
2027 static void psxBios_CloseEvent() { // 09
2028         PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
2029                 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
2030         CloseEvent(a0);
2031         mips_return_c(1, 10);
2032 }
2033
2034 static void psxBios_WaitEvent() { // 0a
2035         u32 base = loadRam32(A_TT_EvCB);
2036         u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2037         PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
2038
2039         use_cycles(15);
2040         if (status == EvStALREADY) {
2041                 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2042                 mips_return(1);
2043                 return;
2044         }
2045         if (status != EvStACTIVE)
2046         {
2047                 mips_return_c(0, 2);
2048                 return;
2049         }
2050
2051         // retrigger this hlecall after the next emulation event
2052         pc0 -= 4;
2053         if ((s32)(next_interupt - psxRegs.cycle) > 0)
2054                 psxRegs.cycle = next_interupt;
2055         psxBranchTest();
2056 }
2057
2058 static void psxBios_TestEvent() { // 0b
2059         u32 base = loadRam32(A_TT_EvCB);
2060         u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2061         u32 ret = 0;
2062         PSXBIOS_LOG("psxBios_%s    %x %x\n", biosB0n[0x0b], a0, status);
2063         if (status == EvStALREADY) {
2064                 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2065                 ret = 1;
2066         }
2067
2068         mips_return_c(ret, 15);
2069 }
2070
2071 static void psxBios_EnableEvent() { // 0c
2072         u32 base = loadRam32(A_TT_EvCB);
2073         u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2074         PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
2075         if (status != EvStUNUSED)
2076                 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2077
2078         mips_return_c(1, 15);
2079 }
2080
2081 static void psxBios_DisableEvent() { // 0d
2082         u32 base = loadRam32(A_TT_EvCB);
2083         u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2084         PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2085         if (status != EvStUNUSED)
2086                 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2087
2088         mips_return_c(1, 15);
2089 }
2090
2091 /*
2092  *      long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2093  */
2094
2095 void psxBios_OpenTh() { // 0e
2096         TCB *tcb = loadRam32ptr(A_TT_TCB);
2097         u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2098         int th;
2099
2100         for (th = 1; th < limit; th++)
2101         {
2102                 if (tcb[th].status != SWAP32(0x4000)) break;
2103
2104         }
2105         if (th == limit) {
2106                 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2107                 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2108 #ifdef PSXBIOS_LOG
2109                 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2110 #endif
2111                 mips_return_c(0xffffffff, 20);
2112                 return;
2113         }
2114         PSXBIOS_LOG("psxBios_%s -> %x\n", biosB0n[0x0e], 0xff000000 + th);
2115
2116         tcb[th].status  = SWAP32(0x4000);
2117         tcb[th].mode    = SWAP32(0x1000);
2118         tcb[th].epc     = SWAP32(a0);
2119         tcb[th].reg[30] = SWAP32(a1); // fp
2120         tcb[th].reg[29] = SWAP32(a1); // sp
2121         tcb[th].reg[28] = SWAP32(a2); // gp
2122
2123         mips_return_c(0xff000000 + th, 34);
2124 }
2125
2126 /*
2127  *      int CloseTh(long thread);
2128  */
2129
2130 static void psxBios_CloseTh() { // 0f
2131         u32 tcb = loadRam32(A_TT_TCB);
2132         u32 th = a0 & 0xffff;
2133
2134         PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x0f], a0);
2135         // in the usual bios fashion no checks, just write and return 1
2136         storeRam32(tcb + th * sizeof(TCB), 0x1000);
2137
2138         mips_return_c(1, 11);
2139 }
2140
2141 /*
2142  *      int ChangeTh(long thread);
2143  */
2144
2145 void psxBios_ChangeTh() { // 10
2146         u32 tcbBase = loadRam32(A_TT_TCB);
2147         u32 th = a0 & 0xffff;
2148
2149         // this is quite spammy
2150         //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2151
2152         // without doing any argument checks, just issue a syscall
2153         // (like the real bios does)
2154         a0 = 3;
2155         a1 = tcbBase + th * sizeof(TCB);
2156         pc0 = A_SYSCALL;
2157         use_cycles(15);
2158 }
2159
2160 void psxBios_InitPAD() { // 0x12
2161         u32 i, *ram32 = (u32 *)psxM;
2162         PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2163
2164         // printf("%s", "PS-X Control PAD Driver  Ver 3.0");
2165         ram32[A_PAD_DR_DST/4] = 0;
2166         ram32[A_PAD_OUTBUF/4 + 0] = 0;
2167         ram32[A_PAD_OUTBUF/4 + 1] = 0;
2168         ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2169         ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2170         ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2171         ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2172         ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2173         ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2174
2175         for (i = 0; i < a1; i++) {
2176                 use_cycles(4);
2177                 storeRam8(a0 + i, 0);
2178         }
2179         for (i = 0; i < a3; i++) {
2180                 use_cycles(4);
2181                 storeRam8(a2 + i, 0);
2182         }
2183         write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2184
2185         ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2186
2187         mips_return_c(1, 200);
2188 }
2189
2190 void psxBios_StartPAD() { // 13
2191         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2192
2193         psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2194         psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2195         psxHwWrite16(0x1f801070, ~1);
2196         psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2197         storeRam32(A_PAD_ACK_VBL, 1);
2198         storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2199         psxRegs.CP0.n.SR |= 0x401;
2200
2201         mips_return_c(1, 300);
2202 }
2203
2204 void psxBios_StopPAD() { // 14
2205         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2206         storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2207         psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2208         psxRegs.CP0.n.SR |= 0x401;
2209         mips_return_void_c(200);
2210 }
2211
2212 static void psxBios_PAD_init() { // 15
2213         u32 ret = 0;
2214         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2215         if (a0 == 0x20000000 || a0 == 0x20000001)
2216         {
2217                 u32 dst = a1;
2218                 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2219                 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2220                 psxBios_InitPAD();
2221                 psxBios_StartPAD();
2222                 storeRam32(A_PAD_DR_DST, dst);
2223                 ret = 2;
2224         }
2225         mips_return_c(ret, 100);
2226 }
2227
2228 static u32 psxBios_PAD_dr_() {
2229         u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2230         u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2231         u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2232         dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2233         if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2234         {
2235                 dst[0] = buf1[3], dst[1] = buf1[2];
2236                 if (buf1[1] == 0x23) {
2237                         dst[0] |= 0xc7, dst[1] |= 7;
2238                         if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2239                         if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2240                 }
2241         }
2242         if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2243         {
2244                 dst[2] = buf2[3], dst[3] = buf2[2];
2245                 if (buf2[1] == 0x23) {
2246                         dst[2] |= 0xc7, dst[3] |= 7;
2247                         if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2248                         if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2249                 }
2250         }
2251         use_cycles(55);
2252         return SWAP32(*(u32 *)dst);
2253 }
2254
2255 static void psxBios_PAD_dr() { // 16
2256         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2257         u32 ret = psxBios_PAD_dr_();
2258         mips_return(ret);
2259 }
2260
2261 static void psxBios_ReturnFromException() { // 17
2262         u32 tcbPtr = loadRam32(A_TT_PCB);
2263         const TCB *tcb = loadRam32ptr(tcbPtr);
2264         u32 sr;
2265         int i;
2266
2267         for (i = 1; i < 32; i++)
2268                 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2269         psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2270         psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2271         sr = SWAP32(tcb->sr);
2272
2273         //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2274         pc0 = k0 = SWAP32(tcb->epc);
2275
2276         // the interpreter wants to know about sr changes, so do a MTC0
2277         sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2278         MTC0(&psxRegs, 12, sr);
2279
2280         use_cycles(53);
2281         psxBranchTest();
2282 }
2283
2284 void psxBios_ResetEntryInt() { // 18
2285         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2286
2287         storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2288         mips_return_void_c(5);
2289 }
2290
2291 void psxBios_HookEntryInt() { // 19
2292         PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2293
2294         storeRam32(A_EEXIT_PTR, a0);
2295         mips_return_void_c(3);
2296 }
2297
2298 static void psxBios_UnDeliverEvent() { // 0x20
2299         u32 ret;
2300         PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2301
2302         ret = UnDeliverEvent(a0, a1);
2303         mips_return(ret);
2304 }
2305
2306 static void buopen(int mcd, char *ptr, char *cfg)
2307 {
2308         int i;
2309         char *mcd_data = ptr;
2310
2311         strcpy(FDesc[1 + mcd].name, Ra0+5);
2312         FDesc[1 + mcd].offset = 0;
2313         FDesc[1 + mcd].mode   = a1;
2314
2315         for (i=1; i<16; i++) {
2316                 const char *fptr = mcd_data + 128 * i;
2317                 if ((*fptr & 0xF0) != 0x50) continue;
2318                 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2319                 FDesc[1 + mcd].mcfile = i;
2320                 PSXBIOS_LOG("open %s\n", fptr+0xa);
2321                 v0 = 1 + mcd;
2322                 break;
2323         }
2324         if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2325                 for (i=1; i<16; i++) {
2326                         int j, xor, nblk = a1 >> 16;
2327                         char *pptr, *fptr2;
2328                         char *fptr = mcd_data + 128 * i;
2329
2330                         if ((*fptr & 0xF0) != 0xa0) continue;
2331
2332                         FDesc[1 + mcd].mcfile = i;
2333                         fptr[0] = 0x51;
2334                         fptr[4] = 0x00;
2335                         fptr[5] = 0x20 * nblk;
2336                         fptr[6] = 0x00;
2337                         fptr[7] = 0x00;
2338                         strcpy(fptr+0xa, FDesc[1 + mcd].name);
2339                         pptr = fptr2 = fptr;
2340                         for(j=2; j<=nblk; j++) {
2341                                 int k;
2342                                 for(i++; i<16; i++) {
2343                                         fptr2 += 128;
2344
2345                                         memset(fptr2, 0, 128);
2346                                         fptr2[0] = j < nblk ? 0x52 : 0x53;
2347                                         pptr[8] = i - 1;
2348                                         pptr[9] = 0;
2349                                         for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2350                                         pptr[127] = xor;
2351                                         pptr = fptr2;
2352                                         break;
2353                                 }
2354                                 /* shouldn't this return ENOSPC if i == 16? */
2355                         }
2356                         pptr[8] = pptr[9] = 0xff;
2357                         for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2358                         pptr[127] = xor;
2359                         PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2360                         v0 = 1 + mcd;
2361                         /* just go ahead and resave them all */
2362                         SaveMcd(cfg, ptr, 128, 128 * 15);
2363                         break;
2364                 }
2365                 /* shouldn't this return ENOSPC if i == 16? */
2366         }
2367 }
2368
2369 /*
2370  *      int open(char *name , int mode);
2371  */
2372
2373 void psxBios_open() { // 0x32
2374         void *pa0 = Ra0;
2375
2376         PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x32], Ra0, a1);
2377
2378         v0 = -1;
2379
2380         if (pa0 != INVALID_PTR) {
2381                 if (!strncmp(pa0, "bu00", 4)) {
2382                         buopen(1, Mcd1Data, Config.Mcd1);
2383                 }
2384
2385                 if (!strncmp(pa0, "bu10", 4)) {
2386                         buopen(2, Mcd2Data, Config.Mcd2);
2387                 }
2388         }
2389
2390         pc0 = ra;
2391 }
2392
2393 /*
2394  *      int lseek(int fd , int offset , int whence);
2395  */
2396
2397 void psxBios_lseek() { // 0x33
2398 #ifdef PSXBIOS_LOG
2399         PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2400 #endif
2401
2402         switch (a2) {
2403                 case 0: // SEEK_SET
2404                         FDesc[a0].offset = a1;
2405                         v0 = a1;
2406 //                      DeliverEvent(0xf0000011, 0x0004);
2407 //                      DeliverEvent(0xf4000001, 0x0004);
2408                         break;
2409
2410                 case 1: // SEEK_CUR
2411                         FDesc[a0].offset+= a1;
2412                         v0 = FDesc[a0].offset;
2413                         break;
2414         }
2415
2416         pc0 = ra;
2417 }
2418
2419
2420 /*
2421  *      int read(int fd , void *buf , int nbytes);
2422  */
2423
2424 void psxBios_read() { // 0x34
2425         char *ptr;
2426         void *pa1 = Ra1;
2427
2428 #ifdef PSXBIOS_LOG
2429         PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2430 #endif
2431
2432         v0 = -1;
2433
2434         if (pa1 != INVALID_PTR) {
2435                 switch (a0) {
2436                         case 2: buread(pa1, 1, a2); break;
2437                         case 3: buread(pa1, 2, a2); break;
2438                 }
2439         }
2440
2441         pc0 = ra;
2442 }
2443
2444 /*
2445  *      int write(int fd , void *buf , int nbytes);
2446  */
2447
2448 void psxBios_write() { // 0x35/0x03
2449         char *ptr;
2450         void *pa1 = Ra1;
2451
2452         if (a0 != 1) // stdout
2453                 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2454
2455         v0 = -1;
2456         if (pa1 == INVALID_PTR) {
2457                 pc0 = ra;
2458                 return;
2459         }
2460
2461         if (a0 == 1) { // stdout
2462                 char *ptr = pa1;
2463
2464                 v0 = a2;
2465                 if (Config.PsxOut) while (a2 > 0) {
2466                         SysPrintf("%c", *ptr++); a2--;
2467                 }
2468                 pc0 = ra; return;
2469         }
2470
2471         switch (a0) {
2472                 case 2: buwrite(pa1, 1, a2); break;
2473                 case 3: buwrite(pa1, 2, a2); break;
2474         }
2475
2476         pc0 = ra;
2477 }
2478
2479 static void psxBios_write_psxout() {
2480         if (a0 == 1) { // stdout
2481                 const char *ptr = Ra1;
2482                 int len = a2;
2483
2484                 if (ptr != INVALID_PTR)
2485                         while (len-- > 0)
2486                                 SysPrintf("%c", *ptr++);
2487         }
2488 }
2489
2490 static void psxBios_putchar_psxout() { // 3d
2491         SysPrintf("%c", (char)a0);
2492 }
2493
2494 static void psxBios_puts_psxout() { // 3e/3f
2495         SysPrintf("%s", Ra0);
2496 }
2497
2498 /*
2499  *      int close(int fd);
2500  */
2501
2502 void psxBios_close() { // 0x36
2503 #ifdef PSXBIOS_LOG
2504         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2505 #endif
2506
2507         v0 = a0;
2508         pc0 = ra;
2509 }
2510
2511 void psxBios_putchar() { // 3d
2512         if (Config.PsxOut) SysPrintf("%c", (char)a0);
2513         pc0 = ra;
2514 }
2515
2516 void psxBios_puts() { // 3e/3f
2517         if (Config.PsxOut) SysPrintf("%s", Ra0);
2518         pc0 = ra;
2519 }
2520
2521 static void bufile(const u8 *mcd_data, u32 dir_) {
2522         struct DIRENTRY *dir = (struct DIRENTRY *)castRam8ptr(dir_);
2523         const char *pfile = ffile + 5;
2524         const u8 *data = mcd_data;
2525         int i = 0, match = 0;
2526         int blocks = 1;
2527         u32 head = 0;
2528
2529         v0 = 0;
2530         for (; nfile <= 15 && !match; nfile++) {
2531                 const char *name;
2532
2533                 head = nfile * 0x40;
2534                 data = mcd_data + 128 * nfile;
2535                 name = (const char *)data + 0x0a;
2536                 if ((data[0] & 0xF0) != 0x50) continue;
2537                 /* Bug link files show up as free block. */
2538                 if (!name[0]) continue;
2539                 match = 1;
2540                 for (i = 0; i < 20; i++) {
2541                         if (pfile[i] == name[i] || pfile[i] == '?')
2542                                 dir->name[i] = name[i];
2543                         else if (pfile[i] == '*') {
2544                                 int len = strlen(name + i);
2545                                 if (i + len > 20)
2546                                         len = 20 - i;
2547                                 memcpy(dir->name + i, name + i, len + 1);
2548                                 i += len;
2549                                 break;
2550                         }
2551                         else {
2552                                 match = 0;
2553                                 break;
2554                         }
2555                         if (!name[i])
2556                                 break;
2557                 }
2558                 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n",
2559                         nfile, dir->name, pfile, name, match);
2560         }
2561         for (; nfile <= 15; nfile++, blocks++) {
2562                 const u8 *data2 = mcd_data + 128 * nfile;
2563                 const char *name = data2 + 0x0a;
2564                 if ((data2[0] & 0xF0) != 0x50 || name[0])
2565                         break;
2566         }
2567         if (match) {
2568                 // nul char of full lenth name seems to overwrite .attr
2569                 dir->attr = SWAP32(i < 20 ? data[0] & 0xf0 : 0); // ?
2570                 dir->size = 8192 * blocks;
2571                 dir->head = head;
2572                 v0 = dir_;
2573         }
2574         PSXBIOS_LOG("  -> %x '%s' %x %x %x %x\n", v0, v0 ? dir->name : "",
2575                     dir->attr, dir->size, dir->next, dir->head);
2576 }
2577
2578 /*
2579  *      struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2580  */
2581
2582 static void psxBios_firstfile() { // 42
2583         char *pa0 = castRam8ptr(a0);
2584
2585         PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x42], pa0, a1);
2586         v0 = 0;
2587
2588         {
2589                 snprintf(ffile, sizeof(ffile), "%s", pa0);
2590                 if (ffile[5] == 0)
2591                         strcpy(ffile + 5, "*"); // maybe?
2592                 nfile = 1;
2593                 if (!strncmp(pa0, "bu00", 4)) {
2594                         // firstfile() calls _card_read() internally, so deliver it's event
2595                         DeliverEvent(0xf0000011, 0x0004);
2596                         bufile(Mcd1Data, a1);
2597                 } else if (!strncmp(pa0, "bu10", 4)) {
2598                         // firstfile() calls _card_read() internally, so deliver it's event
2599                         DeliverEvent(0xf0000011, 0x0004);
2600                         bufile(Mcd2Data, a1);
2601                 }
2602         }
2603
2604         pc0 = ra;
2605 }
2606
2607 /*
2608  *      struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2609  */
2610
2611 void psxBios_nextfile() { // 43
2612         PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x43], a0);
2613
2614         v0 = 0;
2615         if (!strncmp(ffile, "bu00", 4))
2616                 bufile(Mcd1Data, a0);
2617         else if (!strncmp(ffile, "bu10", 4))
2618                 bufile(Mcd2Data, a0);
2619
2620         pc0 = ra;
2621 }
2622
2623 #define burename(mcd) { \
2624         for (i=1; i<16; i++) { \
2625                 int namelen, j, xor = 0; \
2626                 ptr = Mcd##mcd##Data + 128 * i; \
2627                 if ((*ptr & 0xF0) != 0x50) continue; \
2628                 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2629                 namelen = strlen(Ra1+5); \
2630                 memcpy(ptr+0xa, Ra1+5, namelen); \
2631                 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2632                 for (j=0; j<127; j++) xor^= ptr[j]; \
2633                 ptr[127] = xor; \
2634                 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2635                 v0 = 1; \
2636                 break; \
2637         } \
2638 }
2639
2640 /*
2641  *      int rename(char *old, char *new);
2642  */
2643
2644 void psxBios_rename() { // 44
2645         void *pa0 = Ra0;
2646         void *pa1 = Ra1;
2647         char *ptr;
2648         int i;
2649
2650 #ifdef PSXBIOS_LOG
2651         PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2652 #endif
2653
2654         v0 = 0;
2655
2656         if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2657                 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2658                         burename(1);
2659                 }
2660
2661                 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2662                         burename(2);
2663                 }
2664         }
2665
2666         pc0 = ra;
2667 }
2668
2669
2670 #define budelete(mcd) { \
2671         for (i=1; i<16; i++) { \
2672                 ptr = Mcd##mcd##Data + 128 * i; \
2673                 if ((*ptr & 0xF0) != 0x50) continue; \
2674                 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2675                 *ptr = (*ptr & 0xf) | 0xA0; \
2676                 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2677                 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2678                 v0 = 1; \
2679                 break; \
2680         } \
2681 }
2682
2683 /*
2684  *      int delete(char *name);
2685  */
2686
2687 void psxBios_delete() { // 45
2688         void *pa0 = Ra0;
2689         char *ptr;
2690         int i;
2691
2692 #ifdef PSXBIOS_LOG
2693         PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2694 #endif
2695
2696         v0 = 0;
2697
2698         if (pa0 != INVALID_PTR) {
2699                 if (!strncmp(pa0, "bu00", 4)) {
2700                         budelete(1);
2701                 }
2702
2703                 if (!strncmp(pa0, "bu10", 4)) {
2704                         budelete(2);
2705                 }
2706         }
2707
2708         pc0 = ra;
2709 }
2710
2711 void psxBios_InitCARD() { // 4a
2712         u32 *ram32 = (u32 *)psxM;
2713         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2714         write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2715         // (maybe) todo: early_card_irq, etc
2716
2717         ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2718
2719         psxBios_FlushCache();
2720         mips_return_c(0, 34+13+15+6);
2721 }
2722
2723 void psxBios_StartCARD() { // 4b
2724         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2725         psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2726         psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2727
2728         psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2729         storeRam32(A_PAD_ACK_VBL, 1);
2730         storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2731         storeRam32(A_CARD_IRQR_ENA, 1);
2732         psxRegs.CP0.n.SR |= 0x401;
2733
2734         mips_return_c(1, 200);
2735 }
2736
2737 void psxBios_StopCARD() { // 4c
2738         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2739         storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2740         psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2741         storeRam32(A_CARD_IRQR_ENA, 0);
2742         psxRegs.CP0.n.SR |= 0x401;
2743         mips_return_void_c(200);
2744 }
2745
2746 void psxBios__card_write() { // 0x4e
2747         void *pa2 = Ra2;
2748         int port;
2749
2750 #ifdef PSXBIOS_LOG
2751         PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2752 #endif
2753         /*
2754         Function also accepts sector 400h (a bug).
2755         But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2756         */
2757         if (!(a1 <= 0x3FF))
2758         {
2759                 /* Invalid sectors */
2760                 v0 = 0; pc0 = ra;
2761                 return;
2762         }
2763         storeRam32(A_CARD_CHAN1, a0);
2764         port = a0 >> 4;
2765
2766         if (pa2 != INVALID_PTR) {
2767                 if (port == 0) {
2768                         memcpy(Mcd1Data + a1 * 128, pa2, 128);
2769                         SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2770                 } else {
2771                         memcpy(Mcd2Data + a1 * 128, pa2, 128);
2772                         SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2773                 }
2774         }
2775
2776         DeliverEvent(0xf0000011, 0x0004);
2777 //      DeliverEvent(0xf4000001, 0x0004);
2778
2779         v0 = 1; pc0 = ra;
2780 }
2781
2782 void psxBios__card_read() { // 0x4f
2783         void *pa2 = Ra2;
2784         int port;
2785
2786 #ifdef PSXBIOS_LOG
2787         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2788 #endif
2789         /*
2790         Function also accepts sector 400h (a bug).
2791         But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2792         */
2793         if (!(a1 <= 0x3FF))
2794         {
2795                 /* Invalid sectors */
2796                 v0 = 0; pc0 = ra;
2797                 return;
2798         }
2799         storeRam32(A_CARD_CHAN1, a0);
2800         port = a0 >> 4;
2801
2802         if (pa2 != INVALID_PTR) {
2803                 if (port == 0) {
2804                         memcpy(pa2, Mcd1Data + a1 * 128, 128);
2805                 } else {
2806                         memcpy(pa2, Mcd2Data + a1 * 128, 128);
2807                 }
2808         }
2809
2810         DeliverEvent(0xf0000011, 0x0004);
2811 //      DeliverEvent(0xf4000001, 0x0004);
2812
2813         v0 = 1; pc0 = ra;
2814 }
2815
2816 void psxBios__new_card() { // 0x50
2817 #ifdef PSXBIOS_LOG
2818         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2819 #endif
2820
2821         pc0 = ra;
2822 }
2823
2824 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2825 void psxBios__get_error(void) // 55
2826 {
2827         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2828         v0 = 0;
2829         pc0 = ra;
2830 }
2831
2832 void psxBios_Krom2RawAdd() { // 0x51
2833         int i = 0;
2834
2835         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2836         const u32 table_8140[][2] = {
2837                 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2838                 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2839                 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2840                 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2841                 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2842                 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2843                 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2844                 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2845                 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2846                 {0xffff, 0}
2847         };
2848
2849         const u32 table_889f[][2] = {
2850                 {0x889f, 0x3d68},  {0x8900, 0x40ec},  {0x897f, 0x4fb0},  {0x8a00, 0x56f4},
2851                 {0x8a7f, 0x65b8},  {0x8b00, 0x6cfc},  {0x8b7f, 0x7bc0},  {0x8c00, 0x8304},
2852                 {0x8c7f, 0x91c8},  {0x8d00, 0x990c},  {0x8d7f, 0xa7d0},  {0x8e00, 0xaf14},
2853                 {0x8e7f, 0xbdd8},  {0x8f00, 0xc51c},  {0x8f7f, 0xd3e0},  {0x9000, 0xdb24},
2854                 {0x907f, 0xe9e8},  {0x9100, 0xf12c},  {0x917f, 0xfff0},  {0x9200, 0x10734},
2855                 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2856                 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2857                 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2858                 {0xffff, 0}
2859         };
2860
2861         if (a0 >= 0x8140 && a0 <= 0x84be) {
2862                 while (table_8140[i][0] <= a0) i++;
2863                 a0 -= table_8140[i - 1][0];
2864                 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2865         } else if (a0 >= 0x889f && a0 <= 0x9872) {
2866                 while (table_889f[i][0] <= a0) i++;
2867                 a0 -= table_889f[i - 1][0];
2868                 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2869         } else {
2870                 v0 = 0xffffffff;
2871         }
2872
2873         pc0 = ra;
2874 }
2875
2876 void psxBios_GetC0Table() { // 56
2877         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2878         log_unhandled("GetC0Table @%08x\n", ra);
2879
2880         mips_return_c(A_C0_TABLE, 3);
2881 }
2882
2883 void psxBios_GetB0Table() { // 57
2884         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2885         log_unhandled("GetB0Table @%08x\n", ra);
2886
2887         mips_return_c(A_B0_TABLE, 3);
2888 }
2889
2890 static void psxBios__card_chan() { // 0x58
2891         u32 ret;
2892         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2893
2894         // todo: should return active slot chan
2895         // (active - which was last processed by irq code)
2896         ret = loadRam32(A_CARD_CHAN1);
2897         mips_return_c(ret, 8);
2898 }
2899
2900 static void psxBios_ChangeClearPad() { // 5b
2901         u32 ret;
2902         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2903         ret = loadRam32(A_PAD_ACK_VBL);
2904         storeRam32(A_PAD_ACK_VBL, a0);
2905
2906         mips_return_c(ret, 6);
2907 }
2908
2909 static void psxBios__card_status() { // 5c
2910         PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
2911
2912         v0 = 1; // ready
2913         pc0 = ra;
2914 }
2915
2916 static void psxBios__card_wait() { // 5d
2917         PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
2918
2919         v0 = 1; // ready
2920         pc0 = ra;
2921 }
2922
2923 /* System calls C0 */
2924
2925 static void psxBios_InitRCnt() { // 00
2926         int i;
2927         PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2928         psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2929         for (i = 0; i < 3; i++) {
2930                 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2931                 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2932                 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2933         }
2934         psxBios_SysEnqIntRP_(a0, 0x6d88);
2935         mips_return_c(0, 9);
2936 }
2937
2938 static void psxBios_InitException() { // 01
2939         PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2940         psxBios_SysEnqIntRP_(a0, 0x6da8);
2941         mips_return_c(0, 9);
2942 }
2943
2944 /*
2945  * int SysEnqIntRP(int index , long *queue);
2946  */
2947
2948 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2949         u32 old, base = loadRam32(A_TT_ExCB);
2950
2951         old = loadRam32(base + (priority << 3));
2952         storeRam32(base + (priority << 3), chain_eptr);
2953         storeRam32(chain_eptr, old);
2954         mips_return_c(0, 9);
2955 }
2956
2957 static void psxBios_SysEnqIntRP() { // 02
2958         PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2959         psxBios_SysEnqIntRP_(a0, a1);
2960 }
2961
2962 /*
2963  * int SysDeqIntRP(int index , long *queue);
2964  */
2965
2966 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
2967         u32 ptr, next, base = loadRam32(A_TT_ExCB);
2968         u32 lim = 0, ret = 0;
2969
2970         // as in original: no arg checks of any kind, bug if a1 == 0
2971         ptr = loadRam32(base + (priority << 3));
2972         while (ptr) {
2973                 next = loadRam32(ptr);
2974                 if (ptr == chain_rm_eptr) {
2975                         storeRam32(base + (priority << 3), next);
2976                         ret = ptr;
2977                         use_cycles(6);
2978                         break;
2979                 }
2980                 while (next && next != chain_rm_eptr && lim++ < 100) {
2981                         ptr = next;
2982                         next = loadRam32(ptr);
2983                         use_cycles(8);
2984                 }
2985                 if (next == chain_rm_eptr) {
2986                         next = loadRam32(next);
2987                         storeRam32(ptr, next);
2988                         ret = ptr;
2989                         use_cycles(6);
2990                 }
2991                 break;
2992         }
2993         if (lim == 100)
2994                 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
2995
2996         mips_return_c(ret, 12);
2997 }
2998
2999 static void psxBios_SysDeqIntRP() { // 03
3000         PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
3001         psxBios_SysDeqIntRP_(a0, a1);
3002 }
3003
3004 static void psxBios_get_free_EvCB_slot() { // 04
3005         PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
3006         s32 ret = get_free_EvCB_slot();
3007         mips_return_c(ret, 0);
3008 }
3009         
3010 static void psxBios_SysInitMemory_(u32 base, u32 size) {
3011         storeRam32(base, 0);
3012         storeRam32(A_KMALLOC_PTR, base);
3013         storeRam32(A_KMALLOC_SIZE, size);
3014         storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
3015 }
3016
3017 // this should be much more complicated, but maybe that'll be enough
3018 static u32 psxBios_SysMalloc_(u32 size) {
3019         u32 ptr = loadRam32(A_KMALLOC_PTR);
3020
3021         size = (size + 3) & ~3;
3022         storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
3023         storeRam32(ptr, size);
3024         return ptr + 4;
3025 }
3026
3027 static void psxBios_SysInitMemory() { // 08
3028         PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
3029
3030         psxBios_SysInitMemory_(a0, a1);
3031         mips_return_void_c(12);
3032 }
3033
3034 static void psxBios_ChangeClearRCnt() { // 0a
3035         u32 ret;
3036
3037         PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
3038
3039         ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
3040         storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
3041         mips_return_c(ret, 8);
3042 }
3043
3044 static void psxBios_InitDefInt() { // 0c
3045         PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3046         // should also clear the autoack table
3047         psxBios_SysEnqIntRP_(a0, 0x6d98);
3048         mips_return_c(0, 20 + 6*2);
3049 }
3050
3051 void psxBios_dummy() {
3052         u32 pc = (pc0 & 0x1fffff) - 4;
3053         char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
3054                 : pc == 0xc0 ? biosC0n : NULL;
3055         PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
3056                 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
3057         (void)pc; (void)ntab;
3058         mips_return_c(0, 100);
3059 }
3060
3061 void (*biosA0[256])();
3062 // C0 and B0 overlap (end of C0 is start of B0)
3063 void (*biosC0[256+128])();
3064 void (**biosB0)() = biosC0 + 128;
3065
3066 static void setup_mips_code()
3067 {
3068         u32 *ptr;
3069         ptr = (u32 *)&psxM[A_SYSCALL];
3070         ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3071         ptr[0x04/4] = SWAPu32(0x03e00008); // jr    $ra
3072         ptr[0x08/4] = SWAPu32(0x00000000); // nop
3073
3074         ptr = (u32 *)&psxM[A_EXCEPTION];
3075         memset(ptr, 0, 0xc0);              // nops (to be patched by games sometimes)
3076         ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw    $k0, (0x108)   // PCB
3077         ptr[0x14/4] = SWAPu32(0x00000000); // nop
3078         ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw    $k0, ($k0)     // TCB
3079         ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3080         ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8    // regs
3081         ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw    $ra, 0x7c($k0)
3082         ptr[0x28/4] = SWAPu32(0xaf410004); // sw    $at, 0x04($k0)
3083         ptr[0x2c/4] = SWAPu32(0xaf420008); // sw    $v0, 0x08($k0)
3084         ptr[0x30/4] = SWAPu32(0xaf43000c); // sw    $v1, 0x0c($k0)
3085
3086         ptr[0x60/4] = SWAPu32(0x40037000); // mfc0  $v1, EPC
3087         ptr[0x64/4] = SWAPu32(0x40026800); // mfc0  $v0, Cause
3088         ptr[0x6c/4] = SWAPu32(0xaf430080); // sw    $v1, 0x80($k0)
3089
3090         ptr[0xb0/4] = HLEOP(hleop_exception);
3091 }
3092
3093 static const struct {
3094         u32 addr;
3095         enum hle_op op;
3096 } chainfns[] = {
3097         { 0xbfc050a4, hleop_exc0_0_1 },
3098         { 0xbfc04fbc, hleop_exc0_0_2 },
3099         { 0xbfc0506c, hleop_exc0_1_1 },
3100         { 0xbfc04dec, hleop_exc0_1_2 },
3101         {     0x1a00, hleop_exc0_2_2 },
3102         {     0x19c8, hleop_exc1_0_1 },
3103         {     0x18bc, hleop_exc1_0_2 },
3104         {     0x1990, hleop_exc1_1_1 },
3105         {     0x1858, hleop_exc1_1_2 },
3106         {     0x1958, hleop_exc1_2_1 },
3107         {     0x17f4, hleop_exc1_2_2 },
3108         {     0x1920, hleop_exc1_3_1 },
3109         {     0x1794, hleop_exc1_3_2 },
3110         {     0x2458, hleop_exc3_0_2 },
3111         {     0x49bc, hleop_exc_padcard1 },
3112         {     0x4a4c, hleop_exc_padcard2 },
3113 };
3114
3115 static int chain_hle_op(u32 handler)
3116 {
3117         size_t i;
3118
3119         for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3120                 if (chainfns[i].addr == handler)
3121                         return chainfns[i].op;
3122         return hleop_dummy;
3123 }
3124
3125 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3126 {
3127         d[0] = SWAPu32(next);
3128         d[1] = SWAPu32(handler1);
3129         d[2] = SWAPu32(handler2);
3130
3131         // install the hle traps
3132         if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3133         if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3134 }
3135
3136 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack)
3137 {
3138         u32 *ram32 = (u32 *)psxM;
3139         u32 s_excb = 0x20, s_evcb, s_pcb = 4, s_tcb;
3140         u32 p_excb, p_evcb, p_pcb, p_tcb;
3141         u32 i;
3142
3143         PSXBIOS_LOG("setup: tcb %u, evcb %u\n", tcb_cnt, evcb_cnt);
3144
3145         // the real bios doesn't care, but we just don't
3146         // want to crash in case of garbage parameters
3147         if (tcb_cnt > 1024) tcb_cnt = 1024;
3148         if (evcb_cnt > 1024) evcb_cnt = 1024;
3149         s_evcb = 0x1c * evcb_cnt;
3150         s_tcb = 0xc0 * tcb_cnt;
3151
3152         memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3153         psxBios_SysInitMemory_(0xa000e000, 0x2000);
3154         p_excb = psxBios_SysMalloc_(s_excb);
3155         p_evcb = psxBios_SysMalloc_(s_evcb);
3156         p_pcb  = psxBios_SysMalloc_(s_pcb);
3157         p_tcb  = psxBios_SysMalloc_(s_tcb);
3158
3159         // "table of tables". Some games modify it
3160         assert(A_TT_ExCB == 0x0100);
3161         ram32[0x0100/4] = SWAPu32(p_excb);  // ExCB - exception chains
3162         ram32[0x0104/4] = SWAPu32(s_excb);  // ExCB size
3163         ram32[0x0108/4] = SWAPu32(p_pcb);   // PCB - process control
3164         ram32[0x010c/4] = SWAPu32(s_pcb);   // PCB size
3165         ram32[0x0110/4] = SWAPu32(p_tcb);   // TCB - thread control
3166         ram32[0x0114/4] = SWAPu32(s_tcb);   // TCB size
3167         ram32[0x0120/4] = SWAPu32(p_evcb);  // EvCB - event control
3168         ram32[0x0124/4] = SWAPu32(s_evcb);  // EvCB size
3169         ram32[0x0140/4] = SWAPu32(0x8648);  // FCB - file control
3170         ram32[0x0144/4] = SWAPu32(0x02c0);  // FCB size
3171         ram32[0x0150/4] = SWAPu32(0x6ee0);  // DCB - device control
3172         ram32[0x0154/4] = SWAPu32(0x0320);  // DCB size
3173
3174         storeRam32(p_excb + 0*4, 0x91e0);   // chain0
3175         storeRam32(p_excb + 2*4, 0x6d88);   // chain1
3176         storeRam32(p_excb + 4*4, 0x0000);   // chain2
3177         storeRam32(p_excb + 6*4, 0x6d98);   // chain3
3178
3179         storeRam32(p_pcb, p_tcb);
3180         storeRam32(p_tcb, 0x4000);          // first TCB
3181         for (i = 1; i < tcb_cnt; i++)
3182                 storeRam32(p_tcb + sizeof(TCB) * i, 0x1000);
3183
3184         // default events
3185         storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3186         storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3187         storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3188         storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3189         storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3190
3191         storeRam32(A_CONF_EvCB, evcb_cnt);
3192         storeRam32(A_CONF_TCB, tcb_cnt);
3193         storeRam32(A_CONF_SP, stack);
3194 }
3195
3196 static const u32 gpu_ctl_def[] = {
3197         0x00000000, 0x01000000, 0x03000000, 0x04000000,
3198         0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3199 };
3200
3201 static const u32 gpu_data_def[] = {
3202         0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3203         0xe5001000, 0xe6000000,
3204         0x02000000, 0x00000000, 0x01ff03ff
3205 };
3206
3207 // from 1f801d80
3208 static const u16 spu_config[] = {
3209         0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3210         0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3211         0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3212         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3213         0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3214         0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3215         0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3216         0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3217 };
3218
3219 void psxBiosSetupBootState(void)
3220 {
3221         boolean hle = Config.HLE;
3222         u32 *hw = (u32 *)psxH;
3223         int i;
3224
3225         // see also SetBootRegs()
3226         if (hle) {
3227                 v0 = 1; v1 = 4;
3228                 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3229                 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3230                 s0 = 0xa000b870;
3231                 k0 = 0xbfc0d968; k1 = 0xf1c;
3232                 ra = 0xf0001234; // just to easily detect attempts to return
3233                 psxRegs.CP0.n.Cause = 0x20;
3234                 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3235
3236                 hw[0x1000/4] = SWAP32(0x1f000000);
3237                 hw[0x1004/4] = SWAP32(0x1f802000);
3238                 hw[0x1008/4] = SWAP32(0x0013243f);
3239                 hw[0x100c/4] = SWAP32(0x00003022);
3240                 hw[0x1010/4] = SWAP32(0x0013243f);
3241                 hw[0x1014/4] = SWAP32(0x200931e1);
3242                 hw[0x1018/4] = SWAP32(0x00020943);
3243                 hw[0x101c/4] = SWAP32(0x00070777);
3244                 hw[0x1020/4] = SWAP32(0x0000132c);
3245                 hw[0x1060/4] = SWAP32(0x00000b88);
3246                 hw[0x1070/4] = SWAP32(0x00000001);
3247                 hw[0x1074/4] = SWAP32(0x0000000c);
3248                 hw[0x2040/4] = SWAP32(0x00000900);
3249         }
3250
3251         hw[0x10a0/4] = SWAP32(0x00ffffff);
3252         hw[0x10a8/4] = SWAP32(0x00000401);
3253         hw[0x10b0/4] = SWAP32(0x0008b000);
3254         hw[0x10b4/4] = SWAP32(0x00010200);
3255         hw[0x10e0/4] = SWAP32(0x000eccf4);
3256         hw[0x10e4/4] = SWAP32(0x00000400);
3257         hw[0x10e8/4] = SWAP32(0x00000002);
3258         hw[0x10f0/4] = SWAP32(0x00009099);
3259         hw[0x10f4/4] = SWAP32(0x8c8c0000);
3260
3261         if (hle) {
3262                 psxRcntWmode(0, 0);
3263                 psxRcntWmode(1, 0);
3264                 psxRcntWmode(2, 0);
3265         }
3266
3267         // gpu
3268         for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3269                 GPU_writeStatus(gpu_ctl_def[i]);
3270         for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3271                 GPU_writeData(gpu_data_def[i]);
3272         HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
3273
3274         // spu
3275         for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3276                 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3277 }
3278
3279 #include "sjisfont.h"
3280
3281 void psxBiosInit() {
3282         u32 *ptr, *ram32, *rom32;
3283         int i;
3284         uLongf len;
3285
3286         memset(psxM, 0, 0x10000);
3287         for(i = 0; i < 256; i++) {
3288                 biosA0[i] = NULL;
3289                 biosB0[i] = NULL;
3290                 biosC0[i] = NULL;
3291         }
3292         biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3293         biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3294         biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3295         biosA0[0x3f] = psxBios_printf_psxout;
3296
3297         if (!Config.HLE) return;
3298
3299         for(i = 0; i < 256; i++) {
3300                 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3301                 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3302                 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3303         }
3304
3305         biosA0[0x00] = psxBios_open;
3306         biosA0[0x01] = psxBios_lseek;
3307         biosA0[0x02] = psxBios_read;
3308         biosA0[0x03] = psxBios_write;
3309         biosA0[0x04] = psxBios_close;
3310         //biosA0[0x05] = psxBios_ioctl;
3311         //biosA0[0x06] = psxBios_exit;
3312         //biosA0[0x07] = psxBios_sys_a0_07;
3313         biosA0[0x08] = psxBios_getc;
3314         biosA0[0x09] = psxBios_putc;
3315         biosA0[0x0a] = psxBios_todigit;
3316         //biosA0[0x0b] = psxBios_atof;
3317         //biosA0[0x0c] = psxBios_strtoul;
3318         //biosA0[0x0d] = psxBios_strtol;
3319         biosA0[0x0e] = psxBios_abs;
3320         biosA0[0x0f] = psxBios_labs;
3321         biosA0[0x10] = psxBios_atoi;
3322         biosA0[0x11] = psxBios_atol;
3323         //biosA0[0x12] = psxBios_atob;
3324         biosA0[0x13] = psxBios_setjmp;
3325         biosA0[0x14] = psxBios_longjmp;
3326         biosA0[0x15] = psxBios_strcat;
3327         biosA0[0x16] = psxBios_strncat;
3328         biosA0[0x17] = psxBios_strcmp;
3329         biosA0[0x18] = psxBios_strncmp;
3330         biosA0[0x19] = psxBios_strcpy;
3331         biosA0[0x1a] = psxBios_strncpy;
3332         biosA0[0x1b] = psxBios_strlen;
3333         biosA0[0x1c] = psxBios_index;
3334         biosA0[0x1d] = psxBios_rindex;
3335         biosA0[0x1e] = psxBios_strchr;
3336         biosA0[0x1f] = psxBios_strrchr;
3337         biosA0[0x20] = psxBios_strpbrk;
3338         biosA0[0x21] = psxBios_strspn;
3339         biosA0[0x22] = psxBios_strcspn;
3340         biosA0[0x23] = psxBios_strtok;
3341         biosA0[0x24] = psxBios_strstr;
3342         biosA0[0x25] = psxBios_toupper;
3343         biosA0[0x26] = psxBios_tolower;
3344         biosA0[0x27] = psxBios_bcopy;
3345         biosA0[0x28] = psxBios_bzero;
3346         biosA0[0x29] = psxBios_bcmp;
3347         biosA0[0x2a] = psxBios_memcpy;
3348         biosA0[0x2b] = psxBios_memset;
3349         biosA0[0x2c] = psxBios_memmove;
3350         biosA0[0x2d] = psxBios_memcmp;
3351         biosA0[0x2e] = psxBios_memchr;
3352         biosA0[0x2f] = psxBios_rand;
3353         biosA0[0x30] = psxBios_srand;
3354         biosA0[0x31] = psxBios_qsort;
3355         //biosA0[0x32] = psxBios_strtod;
3356         biosA0[0x33] = psxBios_malloc;
3357         biosA0[0x34] = psxBios_free;
3358         //biosA0[0x35] = psxBios_lsearch;
3359         //biosA0[0x36] = psxBios_bsearch;
3360         biosA0[0x37] = psxBios_calloc;
3361         biosA0[0x38] = psxBios_realloc;
3362         biosA0[0x39] = psxBios_InitHeap;
3363         //biosA0[0x3a] = psxBios__exit;
3364         biosA0[0x3b] = psxBios_getchar;
3365         biosA0[0x3c] = psxBios_putchar;
3366         //biosA0[0x3d] = psxBios_gets;
3367         biosA0[0x3e] = psxBios_puts;
3368         biosA0[0x3f] = psxBios_printf;
3369         biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3370         //biosA0[0x41] = psxBios_LoadTest;
3371         biosA0[0x42] = psxBios_Load;
3372         biosA0[0x43] = psxBios_Exec;
3373         biosA0[0x44] = psxBios_FlushCache;
3374         //biosA0[0x45] = psxBios_InstallInterruptHandler;
3375         biosA0[0x46] = psxBios_GPU_dw;
3376         biosA0[0x47] = psxBios_mem2vram;
3377         biosA0[0x48] = psxBios_SendGPU;
3378         biosA0[0x49] = psxBios_GPU_cw;
3379         biosA0[0x4a] = psxBios_GPU_cwb;
3380         biosA0[0x4b] = psxBios_GPU_SendPackets;
3381         biosA0[0x4c] = psxBios_sys_a0_4c;
3382         biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3383         //biosA0[0x4e] = psxBios_GPU_sync;
3384         //biosA0[0x4f] = psxBios_sys_a0_4f;
3385         //biosA0[0x50] = psxBios_sys_a0_50;
3386         biosA0[0x51] = psxBios_LoadExec;
3387         //biosA0[0x52] = psxBios_GetSysSp;
3388         //biosA0[0x53] = psxBios_sys_a0_53;
3389         //biosA0[0x54] = psxBios__96_init_a54;
3390         //biosA0[0x55] = psxBios__bu_init_a55;
3391         biosA0[0x56] = psxBios_CdRemove;
3392         //biosA0[0x57] = psxBios_sys_a0_57;
3393         //biosA0[0x58] = psxBios_sys_a0_58;
3394         //biosA0[0x59] = psxBios_sys_a0_59;
3395         //biosA0[0x5a] = psxBios_sys_a0_5a;
3396         //biosA0[0x5b] = psxBios_dev_tty_init;
3397         //biosA0[0x5c] = psxBios_dev_tty_open;
3398         //biosA0[0x5d] = psxBios_sys_a0_5d;
3399         //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3400         //biosA0[0x5f] = psxBios_dev_cd_open;
3401         //biosA0[0x60] = psxBios_dev_cd_read;
3402         //biosA0[0x61] = psxBios_dev_cd_close;
3403         //biosA0[0x62] = psxBios_dev_cd_firstfile;
3404         //biosA0[0x63] = psxBios_dev_cd_nextfile;
3405         //biosA0[0x64] = psxBios_dev_cd_chdir;
3406         //biosA0[0x65] = psxBios_dev_card_open;
3407         //biosA0[0x66] = psxBios_dev_card_read;
3408         //biosA0[0x67] = psxBios_dev_card_write;
3409         //biosA0[0x68] = psxBios_dev_card_close;
3410         //biosA0[0x69] = psxBios_dev_card_firstfile;
3411         //biosA0[0x6a] = psxBios_dev_card_nextfile;
3412         //biosA0[0x6b] = psxBios_dev_card_erase;
3413         //biosA0[0x6c] = psxBios_dev_card_undelete;
3414         //biosA0[0x6d] = psxBios_dev_card_format;
3415         //biosA0[0x6e] = psxBios_dev_card_rename;
3416         //biosA0[0x6f] = psxBios_dev_card_6f;
3417         biosA0[0x70] = psxBios__bu_init;
3418         biosA0[0x71] = psxBios__96_init;
3419         biosA0[0x72] = psxBios_CdRemove;
3420         //biosA0[0x73] = psxBios_sys_a0_73;
3421         //biosA0[0x74] = psxBios_sys_a0_74;
3422         //biosA0[0x75] = psxBios_sys_a0_75;
3423         //biosA0[0x76] = psxBios_sys_a0_76;
3424         //biosA0[0x77] = psxBios_sys_a0_77;
3425         //biosA0[0x78] = psxBios__96_CdSeekL;
3426         //biosA0[0x79] = psxBios_sys_a0_79;
3427         //biosA0[0x7a] = psxBios_sys_a0_7a;
3428         //biosA0[0x7b] = psxBios_sys_a0_7b;
3429         //biosA0[0x7c] = psxBios__96_CdGetStatus;
3430         //biosA0[0x7d] = psxBios_sys_a0_7d;
3431         //biosA0[0x7e] = psxBios__96_CdRead;
3432         //biosA0[0x7f] = psxBios_sys_a0_7f;
3433         //biosA0[0x80] = psxBios_sys_a0_80;
3434         //biosA0[0x81] = psxBios_sys_a0_81;
3435         //biosA0[0x82] = psxBios_sys_a0_82;
3436         //biosA0[0x83] = psxBios_sys_a0_83;
3437         //biosA0[0x84] = psxBios_sys_a0_84;
3438         //biosA0[0x85] = psxBios__96_CdStop;
3439         //biosA0[0x86] = psxBios_sys_a0_86;
3440         //biosA0[0x87] = psxBios_sys_a0_87;
3441         //biosA0[0x88] = psxBios_sys_a0_88;
3442         //biosA0[0x89] = psxBios_sys_a0_89;
3443         //biosA0[0x8a] = psxBios_sys_a0_8a;
3444         //biosA0[0x8b] = psxBios_sys_a0_8b;
3445         //biosA0[0x8c] = psxBios_sys_a0_8c;
3446         //biosA0[0x8d] = psxBios_sys_a0_8d;
3447         //biosA0[0x8e] = psxBios_sys_a0_8e;
3448         //biosA0[0x8f] = psxBios_sys_a0_8f;
3449         biosA0[0x90] = hleExc0_1_2;
3450         biosA0[0x91] = hleExc0_0_2;
3451         biosA0[0x92] = hleExc0_1_1;
3452         biosA0[0x93] = hleExc0_0_1;
3453         //biosA0[0x94] = psxBios_sys_a0_94;
3454         //biosA0[0x95] = psxBios_sys_a0_95;
3455         //biosA0[0x96] = psxBios_AddCDROMDevice;
3456         //biosA0[0x97] = psxBios_AddMemCardDevide;
3457         //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3458         //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3459         //biosA0[0x9a] = psxBios_sys_a0_9a;
3460         //biosA0[0x9b] = psxBios_sys_a0_9b;
3461         biosA0[0x9c] = psxBios_SetConf;
3462         biosA0[0x9d] = psxBios_GetConf;
3463         //biosA0[0x9e] = psxBios_sys_a0_9e;
3464         biosA0[0x9f] = psxBios_SetMem;
3465         //biosA0[0xa0] = psxBios__boot;
3466         //biosA0[0xa1] = psxBios_SystemError;
3467         //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3468         biosA0[0xa3] = psxBios_DequeueCdIntr;
3469         //biosA0[0xa4] = psxBios_sys_a0_a4;
3470         //biosA0[0xa5] = psxBios_ReadSector;
3471         biosA0[0xa6] = psxBios_get_cd_status;
3472         //biosA0[0xa7] = psxBios_bufs_cb_0;
3473         //biosA0[0xa8] = psxBios_bufs_cb_1;
3474         //biosA0[0xa9] = psxBios_bufs_cb_2;
3475         //biosA0[0xaa] = psxBios_bufs_cb_3;
3476         biosA0[0xab] = psxBios__card_info;
3477         biosA0[0xac] = psxBios__card_load;
3478         //biosA0[0axd] = psxBios__card_auto;
3479         //biosA0[0xae] = psxBios_bufs_cd_4;
3480         //biosA0[0xaf] = psxBios_sys_a0_af;
3481         //biosA0[0xb0] = psxBios_sys_a0_b0;
3482         //biosA0[0xb1] = psxBios_sys_a0_b1;
3483         //biosA0[0xb2] = psxBios_do_a_long_jmp
3484         //biosA0[0xb3] = psxBios_sys_a0_b3;
3485         biosA0[0xb4] = psxBios_GetSystemInfo;
3486 //*******************B0 CALLS****************************
3487         biosB0[0x00] = psxBios_SysMalloc;
3488         //biosB0[0x01] = psxBios_sys_b0_01;
3489         biosB0[0x02] = psxBios_SetRCnt;
3490         biosB0[0x03] = psxBios_GetRCnt;
3491         biosB0[0x04] = psxBios_StartRCnt;
3492         biosB0[0x05] = psxBios_StopRCnt;
3493         biosB0[0x06] = psxBios_ResetRCnt;
3494         biosB0[0x07] = psxBios_DeliverEvent;
3495         biosB0[0x08] = psxBios_OpenEvent;
3496         biosB0[0x09] = psxBios_CloseEvent;
3497         biosB0[0x0a] = psxBios_WaitEvent;
3498         biosB0[0x0b] = psxBios_TestEvent;
3499         biosB0[0x0c] = psxBios_EnableEvent;
3500         biosB0[0x0d] = psxBios_DisableEvent;
3501         biosB0[0x0e] = psxBios_OpenTh;
3502         biosB0[0x0f] = psxBios_CloseTh;
3503         biosB0[0x10] = psxBios_ChangeTh;
3504         //biosB0[0x11] = psxBios_psxBios_b0_11;
3505         biosB0[0x12] = psxBios_InitPAD;
3506         biosB0[0x13] = psxBios_StartPAD;
3507         biosB0[0x14] = psxBios_StopPAD;
3508         biosB0[0x15] = psxBios_PAD_init;
3509         biosB0[0x16] = psxBios_PAD_dr;
3510         biosB0[0x17] = psxBios_ReturnFromException;
3511         biosB0[0x18] = psxBios_ResetEntryInt;
3512         biosB0[0x19] = psxBios_HookEntryInt;
3513         //biosB0[0x1a] = psxBios_sys_b0_1a;
3514         //biosB0[0x1b] = psxBios_sys_b0_1b;
3515         //biosB0[0x1c] = psxBios_sys_b0_1c;
3516         //biosB0[0x1d] = psxBios_sys_b0_1d;
3517         //biosB0[0x1e] = psxBios_sys_b0_1e;
3518         //biosB0[0x1f] = psxBios_sys_b0_1f;
3519         biosB0[0x20] = psxBios_UnDeliverEvent;
3520         //biosB0[0x21] = psxBios_sys_b0_21;
3521         //biosB0[0x22] = psxBios_sys_b0_22;
3522         //biosB0[0x23] = psxBios_sys_b0_23;
3523         //biosB0[0x24] = psxBios_sys_b0_24;
3524         //biosB0[0x25] = psxBios_sys_b0_25;
3525         //biosB0[0x26] = psxBios_sys_b0_26;
3526         //biosB0[0x27] = psxBios_sys_b0_27;
3527         //biosB0[0x28] = psxBios_sys_b0_28;
3528         //biosB0[0x29] = psxBios_sys_b0_29;
3529         //biosB0[0x2a] = psxBios_sys_b0_2a;
3530         //biosB0[0x2b] = psxBios_sys_b0_2b;
3531         //biosB0[0x2c] = psxBios_sys_b0_2c;
3532         //biosB0[0x2d] = psxBios_sys_b0_2d;
3533         //biosB0[0x2e] = psxBios_sys_b0_2e;
3534         //biosB0[0x2f] = psxBios_sys_b0_2f;
3535         //biosB0[0x30] = psxBios_sys_b0_30;
3536         //biosB0[0x31] = psxBios_sys_b0_31;
3537         biosB0[0x32] = psxBios_open;
3538         biosB0[0x33] = psxBios_lseek;
3539         biosB0[0x34] = psxBios_read;
3540         biosB0[0x35] = psxBios_write;
3541         biosB0[0x36] = psxBios_close;
3542         //biosB0[0x37] = psxBios_ioctl;
3543         //biosB0[0x38] = psxBios_exit;
3544         //biosB0[0x39] = psxBios_sys_b0_39;
3545         //biosB0[0x3a] = psxBios_getc;
3546         //biosB0[0x3b] = psxBios_putc;
3547         biosB0[0x3c] = psxBios_getchar;
3548         biosB0[0x3d] = psxBios_putchar;
3549         //biosB0[0x3e] = psxBios_gets;
3550         biosB0[0x3f] = psxBios_puts;
3551         //biosB0[0x40] = psxBios_cd;
3552         biosB0[0x41] = psxBios_format;
3553         biosB0[0x42] = psxBios_firstfile;
3554         biosB0[0x43] = psxBios_nextfile;
3555         biosB0[0x44] = psxBios_rename;
3556         biosB0[0x45] = psxBios_delete;
3557         //biosB0[0x46] = psxBios_undelete;
3558         //biosB0[0x47] = psxBios_AddDevice;
3559         //biosB0[0x48] = psxBios_RemoteDevice;
3560         //biosB0[0x49] = psxBios_PrintInstalledDevices;
3561         biosB0[0x4a] = psxBios_InitCARD;
3562         biosB0[0x4b] = psxBios_StartCARD;
3563         biosB0[0x4c] = psxBios_StopCARD;
3564         //biosB0[0x4d] = psxBios_sys_b0_4d;
3565         biosB0[0x4e] = psxBios__card_write;
3566         biosB0[0x4f] = psxBios__card_read;
3567         biosB0[0x50] = psxBios__new_card;
3568         biosB0[0x51] = psxBios_Krom2RawAdd;
3569         //biosB0[0x52] = psxBios_sys_b0_52;
3570         //biosB0[0x53] = psxBios_sys_b0_53;
3571         //biosB0[0x54] = psxBios__get_errno;
3572         biosB0[0x55] = psxBios__get_error;
3573         biosB0[0x56] = psxBios_GetC0Table;
3574         biosB0[0x57] = psxBios_GetB0Table;
3575         biosB0[0x58] = psxBios__card_chan;
3576         //biosB0[0x59] = psxBios_sys_b0_59;
3577         //biosB0[0x5a] = psxBios_sys_b0_5a;
3578         biosB0[0x5b] = psxBios_ChangeClearPad;
3579         biosB0[0x5c] = psxBios__card_status;
3580         biosB0[0x5d] = psxBios__card_wait;
3581 //*******************C0 CALLS****************************
3582         biosC0[0x00] = psxBios_InitRCnt;
3583         biosC0[0x01] = psxBios_InitException;
3584         biosC0[0x02] = psxBios_SysEnqIntRP;
3585         biosC0[0x03] = psxBios_SysDeqIntRP;
3586         biosC0[0x04] = psxBios_get_free_EvCB_slot;
3587         //biosC0[0x05] = psxBios_get_free_TCB_slot;
3588         //biosC0[0x06] = psxBios_ExceptionHandler;
3589         //biosC0[0x07] = psxBios_InstallExeptionHandler;
3590         biosC0[0x08] = psxBios_SysInitMemory;
3591         //biosC0[0x09] = psxBios_SysInitKMem;
3592         biosC0[0x0a] = psxBios_ChangeClearRCnt;
3593         //biosC0[0x0b] = psxBios_SystemError;
3594         biosC0[0x0c] = psxBios_InitDefInt;
3595         //biosC0[0x0d] = psxBios_sys_c0_0d;
3596         //biosC0[0x0e] = psxBios_sys_c0_0e;
3597         //biosC0[0x0f] = psxBios_sys_c0_0f;
3598         //biosC0[0x10] = psxBios_sys_c0_10;
3599         //biosC0[0x11] = psxBios_sys_c0_11;
3600         //biosC0[0x12] = psxBios_InstallDevices;
3601         //biosC0[0x13] = psxBios_FlushStfInOutPut;
3602         //biosC0[0x14] = psxBios_sys_c0_14;
3603         //biosC0[0x15] = psxBios__cdevinput;
3604         //biosC0[0x16] = psxBios__cdevscan;
3605         //biosC0[0x17] = psxBios__circgetc;
3606         //biosC0[0x18] = psxBios__circputc;
3607         //biosC0[0x19] = psxBios_ioabort;
3608         //biosC0[0x1a] = psxBios_sys_c0_1a
3609         //biosC0[0x1b] = psxBios_KernelRedirect;
3610         //biosC0[0x1c] = psxBios_PatchAOTable;
3611 //************** THE END ***************************************
3612 /**/
3613
3614         memset(FDesc, 0, sizeof(FDesc));
3615
3616         // somewhat pretend to be a SCPH1001 BIOS
3617         // some games look for these and take an exception if they're missing
3618         rom32 = (u32 *)psxR;
3619         rom32[0x100/4] = SWAP32(0x19951204);
3620         rom32[0x104/4] = SWAP32(3);
3621         strcpy(psxR + 0x108, "PCSX authors");
3622         strcpy(psxR + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3623         strcpy(psxR + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3624         strcpy(psxR + 0x7ff54, "GPL-2.0-or-later");
3625
3626         // fonts
3627         len = 0x80000 - 0x66000;
3628         uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3629         len = 0x80000 - 0x69d68;
3630         uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3631
3632         // trap attempts to call bios directly
3633         rom32[0x00000/4] = HLEOP(hleop_dummy);
3634         rom32[0x00180/4] = HLEOP(hleop_dummy);
3635         rom32[0x3fffc/4] = HLEOP(hleop_dummy);
3636         rom32[0x65ffc/4] = HLEOP(hleop_dummy);
3637         rom32[0x7ff2c/4] = HLEOP(hleop_dummy);
3638
3639         /*      Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3640                 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3641                 Here are some examples of games not working with this fix in place :
3642                 R-type won't get past the Irem logo if not implemented.
3643                 Crash Team Racing will softlock after the Sony logo.
3644         */
3645
3646         ram32 = (u32 *)psxM;
3647         ram32[0x0000/4] = SWAPu32(0x00000003); // lui   $k0, 0  (overwritten by 3)
3648         ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3649         ram32[0x0008/4] = SWAPu32(0x03400008); // jr    $k0
3650         ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3651
3652         ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3653         ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3654
3655         ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui   $k0, 0  // exception vector
3656         ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3657         ram32[0x0088/4] = SWAPu32(0x03400008); // jr    $k0
3658         ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3659
3660         ram32[0x00a0/4] = HLEOP(hleop_a0);
3661         ram32[0x00b0/4] = HLEOP(hleop_b0);
3662         ram32[0x00c0/4] = HLEOP(hleop_c0);
3663
3664         setup_tt(4, 16, 0x801fff00);
3665         DeliverEvent(0xf0000003, 0x0010);
3666
3667         ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3668         strcpy((char *)&ram32[0xeff0/4], "bu");
3669
3670         // default exception handler chains
3671         write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3672         write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3673         write_chain(&ram32[0x6da8/4],      0,          0,     0x1a00); // chain0.e2
3674         write_chain(&ram32[0x6d88/4], 0x6d78,     0x19c8,     0x18bc); // chain1.e0
3675         write_chain(&ram32[0x6d78/4], 0x6d68,     0x1990,     0x1858); // chain1.e1
3676         write_chain(&ram32[0x6d68/4], 0x6d58,     0x1958,     0x17f4); // chain1.e2
3677         write_chain(&ram32[0x6d58/4],      0,     0x1920,     0x1794); // chain1.e3
3678         write_chain(&ram32[0x6d98/4],      0,          0,     0x2458); // chain3.e0
3679
3680         setup_mips_code();
3681
3682         // fill the api jumptables with fake entries as some games patch them
3683         // (or rather the funcs listed there)
3684         ptr = (u32 *)&psxM[A_A0_TABLE];
3685         for (i = 0; i < 256; i++)
3686                 ptr[i] = SWAP32(0x1000);
3687
3688         ptr = (u32 *)&psxM[A_B0_TABLE];
3689         for (i = 0; i < 256; i++)
3690                 ptr[i] = SWAP32(0x2000);
3691         // B(5b) is special because games patch (sometimes even jump to)
3692         // code at fixed offsets from it, nocash lists offsets:
3693         //  patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3694         //  call:  +7a0=4b70, +884=4c54, +894=4c64
3695         ptr[0x5b] = SWAP32(0x43d0);
3696         ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3697
3698         ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3699         ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3700         ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3701
3702         ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3703         ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3704
3705         ptr = (u32 *)&psxM[A_C0_TABLE];
3706         for (i = 0; i < 256/2; i++)
3707                 ptr[i] = SWAP32(0x3000);
3708         ptr[6] = SWAP32(A_EXCEPTION);
3709
3710         // more HLE traps
3711         ram32[0x1000/4] = HLEOP(hleop_dummy);
3712         ram32[0x2000/4] = HLEOP(hleop_dummy);
3713         ram32[0x3000/4] = HLEOP(hleop_dummy);
3714         ram32[0x8000/4] = HLEOP(hleop_execret);
3715
3716         ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3717         ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3718         ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3719         ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3720         ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3721         ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3722         ram32[A_RND_SEED/4] = SWAPu32(0x24040001); // was 0xac20cc00
3723 }
3724
3725 void psxBiosShutdown() {
3726 }
3727
3728 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 stack) {
3729         if (stack == 0)
3730                 stack = 0x801FFF00;
3731         if (tcb_cnt != 4 || evcb_cnt != 16) {
3732                 setup_tt(tcb_cnt, evcb_cnt, stack);
3733                 DeliverEvent(0xf0000003, 0x0010);
3734         }
3735         storeRam32(A_CONF_SP, stack);
3736 }
3737
3738 #define psxBios_PADpoll(pad) { \
3739         PAD##pad##_startPoll(pad); \
3740         pad_buf##pad[0] = 0; \
3741         pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3742         if (!(pad_buf##pad[1] & 0x0f)) { \
3743                 bufcount = 32; \
3744         } else { \
3745                 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3746         } \
3747         PAD##pad##_poll(0); \
3748         i = 2; \
3749         while (bufcount--) { \
3750                 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3751         } \
3752 }
3753
3754 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3755 {
3756         use_cycles(10);
3757         if (enable) {
3758                 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3759                 psxBios_ReturnFromException();
3760         }
3761         else
3762                 pc0 = ra;
3763 }
3764
3765 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3766 // so this is only partially implemented
3767 void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3768 {
3769         u32 cdrom_dma_ack_enable = 1; // a000b93c
3770         handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3771 }
3772
3773 void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3774 {
3775         u32 ret = 0;
3776         //PSXBIOS_LOG("%s\n", __func__);
3777
3778         if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3779                 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3780                 //if (--cdrom_irq_counter == 0) // 0xa0009180
3781                 //      DeliverEvent(0xf0000003, 0x10);
3782                 use_cycles(22);
3783                 ret = 1;
3784         }
3785         mips_return_c(ret, 20);
3786 }
3787
3788 void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3789 {
3790         u32 cdrom_irq_ack_enable = 1; // a000b938
3791         handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3792 }
3793
3794 void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3795 {
3796         u32 ret = 0;
3797         if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3798                 PSXBIOS_LOG("%s TODO\n", __func__);
3799                 ret = 1;
3800         }
3801         mips_return_c(ret, 20);
3802 }
3803
3804 void hleExc0_2_2_syscall() // not in any A/B/C table
3805 {
3806         u32 tcbPtr = loadRam32(A_TT_PCB);
3807         TCB *tcb = loadRam32ptr(tcbPtr);
3808         u32 code = (SWAP32(tcb->cause) & 0x3c) >> 2;
3809
3810         if (code != R3000E_Syscall) {
3811                 if (code != 0) {
3812                         DeliverEvent(0xf0000010, 0x1000);
3813                         //psxBios_SystemErrorUnresolvedException();
3814                 }
3815                 mips_return_c(0, 17);
3816                 return;
3817         }
3818
3819         //printf("%s c=%d a0=%d\n", __func__, code, SWAP32(tcb->reg[4]));
3820         tcb->epc += SWAP32(4);
3821         switch (SWAP32(tcb->reg[4])) { // a0
3822                 case 0: // noop
3823                         break;
3824
3825                 case 1: { // EnterCritical - disable irqs
3826                         u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3827                         tcb->reg[2] = SWAP32(was_enabled);
3828                         tcb->sr &= SWAP32(~0x404);
3829                         break;
3830                 }
3831                 case 2: // ExitCritical - enable irqs
3832                         tcb->sr |= SWAP32(0x404);
3833                         break;
3834
3835                 case 3: { // ChangeThreadSubFunction
3836                         u32 tcbPtr = loadRam32(A_TT_PCB);
3837                         storeRam32(tcbPtr, SWAP32(tcb->reg[5])); // a1
3838                         break;
3839                 }
3840                 default:
3841                         DeliverEvent(0xf0000010, 0x4000);
3842                         break;
3843         }
3844         use_cycles(30);
3845         psxBios_ReturnFromException();
3846 }
3847
3848 void hleExc1_0_1(void)
3849 {
3850         u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3851         handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3852 }
3853
3854 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3855 {
3856         u32 ret = 0;
3857         if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3858                 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3859                 ret = 1;
3860         }
3861         mips_return_c(ret, 22);
3862 }
3863
3864 void hleExc1_0_2(void)
3865 {
3866         handle_chain_1_x_2(3, 0); // IRQ0 vblank
3867 }
3868
3869 void hleExc1_1_1(void)
3870 {
3871         u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3872         handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3873 }
3874
3875 void hleExc1_1_2(void)
3876 {
3877         handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3878 }
3879
3880 void hleExc1_2_1(void)
3881 {
3882         u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3883         handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3884 }
3885
3886 void hleExc1_2_2(void)
3887 {
3888         handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3889 }
3890
3891 void hleExc1_3_1(void)
3892 {
3893         u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3894         handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3895 }
3896
3897 void hleExc1_3_2(void)
3898 {
3899         handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3900 }
3901
3902 void hleExc3_0_2_defint(void)
3903 {
3904         static const struct {
3905                 u8 ev, irqbit;
3906         } tab[] = {
3907                 {  3,  2 }, // cdrom
3908                 {  9,  9 }, // spu
3909                 {  2,  1 }, // gpu
3910                 { 10, 10 }, // io
3911                 { 11,  8 }, // sio
3912                 {  1,  0 }, // vbl
3913                 {  5,  4 }, // rcnt0
3914                 {  6,  5 }, // rcnt1
3915                 {  6,  6 }, // rcnt2 (bug)
3916                 {  8,  7 }, // sio rx
3917                 {  4,  3 }, // sio
3918         };
3919         size_t i;
3920         for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3921                 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3922                         DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3923                         use_cycles(7);
3924                 }
3925
3926         }
3927         mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3928 }
3929
3930 void hleExcPadCard1(void)
3931 {
3932         if (loadRam32(A_PAD_IRQR_ENA)) {
3933                 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3934                 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
3935                 int i, bufcount;
3936
3937                 psxBios_PADpoll(1);
3938                 psxBios_PADpoll(2);
3939                 use_cycles(100);
3940                 if (loadRam32(A_PAD_DR_DST))
3941                         psxBios_PAD_dr_();
3942         }
3943         if (loadRam32(A_PAD_ACK_VBL))
3944                 psxHwWrite16(0x1f801070, ~1);
3945         if (loadRam32(A_CARD_IRQR_ENA)) {
3946                 // todo, maybe
3947         }
3948
3949         mips_return_c(0, 18);
3950 }
3951
3952 void hleExcPadCard2(void)
3953 {
3954         u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
3955         mips_return_c(ret, 15);
3956 }
3957
3958 void psxBiosException() {
3959         u32 tcbPtr = loadRam32(A_TT_PCB);
3960         u32 *chains = loadRam32ptr(A_TT_ExCB);
3961         TCB *tcb = loadRam32ptr(tcbPtr);
3962         u32 ptr, *chain;
3963         int c, lim;
3964         int i;
3965
3966         // save the regs
3967         // $at, $v0, $v1, $ra already saved by the mips code at A_EXCEPTION
3968         for (i = 4; i < 31; i++) {
3969                 if (i == 26) // $k0
3970                         continue;
3971                 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
3972         }
3973         tcb->lo = SWAP32(psxRegs.GPR.n.lo);
3974         tcb->hi = SWAP32(psxRegs.GPR.n.hi);
3975         //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
3976         tcb->sr = SWAP32(psxRegs.CP0.n.SR);
3977         tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
3978         sp = fp = loadRam32(A_EXC_SP);
3979         gp = A_EXC_GP;
3980         use_cycles(46);
3981
3982         // do the chains (always 4)
3983         for (c = lim = 0; c < 4; c++) {
3984                 if (chains[c * 2] == 0)
3985                         continue;
3986                 ptr = SWAP32(chains[c * 2]);
3987                 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
3988                         chain = castRam32ptr(ptr);
3989                         use_cycles(14);
3990                         lim++;
3991                         if (chain[2] == 0)
3992                                 continue;
3993                         softCallInException(SWAP32(chain[2]));
3994                         if (returned_from_exception())
3995                                 return;
3996
3997                         if (v0 == 0 || chain[1] == 0)
3998                                 continue;
3999                         softCallInException(SWAP32(chain[1]));
4000                         if (returned_from_exception())
4001                                 return;
4002                 }
4003         }
4004         assert(lim < 100);
4005
4006         // return from exception (custom or default)
4007         use_cycles(23);
4008         ptr = loadRam32(A_EEXIT_PTR);
4009         if (ptr != A_EEXIT_DEF) {
4010                 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
4011                 longjmp_load(jmp_buf);
4012                 v0 = 1;
4013                 pc0 = ra;
4014                 return;
4015         }
4016         psxBios_ReturnFromException();
4017 }
4018
4019 #define bfreeze(ptr, size) { \
4020         if (Mode == 1) memcpy(&psxR[base], ptr, size); \
4021         if (Mode == 0) memcpy(ptr, &psxR[base], size); \
4022         base += size; \
4023 }
4024
4025 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
4026 #define bfreezel(ptr) bfreeze(ptr, sizeof(*(ptr)))
4027
4028 void psxBiosFreeze(int Mode) {
4029         u32 base = 0x40000;
4030
4031         bfreezes(FDesc);
4032         bfreezes(ffile);
4033         bfreezel(&nfile);
4034 }