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