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