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