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