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