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