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