merge from libretro fork
[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 <zlib.h>
38
39 #if (defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)
40 #pragma GCC diagnostic ignored "-Wpointer-sign"
41 #endif
42
43 #undef SysPrintf
44 #define SysPrintf if (Config.PsxOut) printf
45
46 char *biosA0n[256] = {
47 // 0x00
48         "open",         "lseek",        "read",         "write",
49         "close",        "ioctl",        "exit",         "sys_a0_07",
50         "getc",         "putc",         "todigit",      "atof",
51         "strtoul",      "strtol",       "abs",          "labs",
52 // 0x10
53         "atoi",         "atol",         "atob",         "setjmp",
54         "longjmp",      "strcat",       "strncat",      "strcmp",
55         "strncmp",      "strcpy",       "strncpy",      "strlen",
56         "index",        "rindex",       "strchr",       "strrchr",
57 // 0x20
58         "strpbrk",      "strspn",       "strcspn",      "strtok",
59         "strstr",       "toupper",      "tolower",      "bcopy",
60         "bzero",        "bcmp",         "memcpy",       "memset",
61         "memmove",      "memcmp",       "memchr",       "rand",
62 // 0x30
63         "srand",        "qsort",        "strtod",       "malloc",
64         "free",         "lsearch",      "bsearch",      "calloc",
65         "realloc",      "InitHeap",     "_exit",        "getchar",
66         "putchar",      "gets",         "puts",         "printf",
67 // 0x40
68         "sys_a0_40",            "LoadTest",                                     "Load",         "Exec",
69         "FlushCache",           "InstallInterruptHandler",      "GPU_dw",       "mem2vram",
70         "SendGPUStatus",        "GPU_cw",                                       "GPU_cwb",      "SendPackets",
71         "sys_a0_4c",            "GetGPUStatus",                         "GPU_sync",     "sys_a0_4f",
72 // 0x50
73         "sys_a0_50",            "LoadExec",                             "GetSysSp",             "sys_a0_53",
74         "_96_init()",           "_bu_init()",                   "_96_remove()", "sys_a0_57",
75         "sys_a0_58",            "sys_a0_59",                    "sys_a0_5a",    "dev_tty_init",
76         "dev_tty_open",         "sys_a0_5d",                    "dev_tty_ioctl","dev_cd_open",
77 // 0x60
78         "dev_cd_read",          "dev_cd_close",                 "dev_cd_firstfile",     "dev_cd_nextfile",
79         "dev_cd_chdir",         "dev_card_open",                "dev_card_read",        "dev_card_write",
80         "dev_card_close",       "dev_card_firstfile",   "dev_card_nextfile","dev_card_erase",
81         "dev_card_undelete","dev_card_format",          "dev_card_rename",      "dev_card_6f",
82 // 0x70
83         "_bu_init",                     "_96_init",             "_96_remove",           "sys_a0_73",
84         "sys_a0_74",            "sys_a0_75",    "sys_a0_76",            "sys_a0_77",
85         "_96_CdSeekL",          "sys_a0_79",    "sys_a0_7a",            "sys_a0_7b",
86         "_96_CdGetStatus",      "sys_a0_7d",    "_96_CdRead",           "sys_a0_7f",
87 // 0x80
88         "sys_a0_80",            "sys_a0_81",    "sys_a0_82",            "sys_a0_83",
89         "sys_a0_84",            "_96_CdStop",   "sys_a0_86",            "sys_a0_87",
90         "sys_a0_88",            "sys_a0_89",    "sys_a0_8a",            "sys_a0_8b",
91         "sys_a0_8c",            "sys_a0_8d",    "sys_a0_8e",            "sys_a0_8f",
92 // 0x90
93         "sys_a0_90",            "sys_a0_91",    "sys_a0_92",            "sys_a0_93",
94         "sys_a0_94",            "sys_a0_95",    "AddCDROMDevice",       "AddMemCardDevide",
95         "DisableKernelIORedirection",           "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
96         "SetConf",                      "GetConf",              "sys_a0_9e",            "SetMem",
97 // 0xa0
98         "_boot",                        "SystemError",  "EnqueueCdIntr",        "DequeueCdIntr",
99         "sys_a0_a4",            "ReadSector",   "get_cd_status",        "bufs_cb_0",
100         "bufs_cb_1",            "bufs_cb_2",    "bufs_cb_3",            "_card_info",
101         "_card_load",           "_card_auto",   "bufs_cd_4",            "sys_a0_af",
102 // 0xb0
103         "sys_a0_b0",            "sys_a0_b1",    "do_a_long_jmp",        "sys_a0_b3",
104         "?? sub_function",
105 };
106
107 char *biosB0n[256] = {
108 // 0x00
109         "SysMalloc",            "sys_b0_01",    "sys_b0_02",    "sys_b0_03",
110         "sys_b0_04",            "sys_b0_05",    "sys_b0_06",    "DeliverEvent",
111         "OpenEvent",            "CloseEvent",   "WaitEvent",    "TestEvent",
112         "EnableEvent",          "DisableEvent", "OpenTh",               "CloseTh",
113 // 0x10
114         "ChangeTh",                     "sys_b0_11",    "InitPAD",              "StartPAD",
115         "StopPAD",                      "PAD_init",             "PAD_dr",               "ReturnFromExecption",
116         "ResetEntryInt",        "HookEntryInt", "sys_b0_1a",    "sys_b0_1b",
117         "sys_b0_1c",            "sys_b0_1d",    "sys_b0_1e",    "sys_b0_1f",
118 // 0x20
119         "UnDeliverEvent",       "sys_b0_21",    "sys_b0_22",    "sys_b0_23",
120         "sys_b0_24",            "sys_b0_25",    "sys_b0_26",    "sys_b0_27",
121         "sys_b0_28",            "sys_b0_29",    "sys_b0_2a",    "sys_b0_2b",
122         "sys_b0_2c",            "sys_b0_2d",    "sys_b0_2e",    "sys_b0_2f",
123 // 0x30
124         "sys_b0_30",            "sys_b0_31",    "open",                 "lseek",
125         "read",                         "write",                "close",                "ioctl",
126         "exit",                         "sys_b0_39",    "getc",                 "putc",
127         "getchar",                      "putchar",              "gets",                 "puts",
128 // 0x40
129         "cd",                           "format",               "firstfile",    "nextfile",
130         "rename",                       "delete",               "undelete",             "AddDevice",
131         "RemoteDevice",         "PrintInstalledDevices", "InitCARD", "StartCARD",
132         "StopCARD",                     "sys_b0_4d",    "_card_write",  "_card_read",
133 // 0x50
134         "_new_card",            "Krom2RawAdd",  "sys_b0_52",    "sys_b0_53",
135         "_get_errno",           "_get_error",   "GetC0Table",   "GetB0Table",
136         "_card_chan",           "sys_b0_59",    "sys_b0_5a",    "ChangeClearPAD",
137         "_card_status",         "_card_wait",
138 };
139
140 char *biosC0n[256] = {
141 // 0x00
142         "InitRCnt",                       "InitException",              "SysEnqIntRP",          "SysDeqIntRP",
143         "get_free_EvCB_slot", "get_free_TCB_slot",      "ExceptionHandler",     "InstallExeptionHandler",
144         "SysInitMemory",          "SysInitKMem",                "ChangeClearRCnt",      "SystemError",
145         "InitDefInt",             "sys_c0_0d",                  "sys_c0_0e",            "sys_c0_0f",
146 // 0x10
147         "sys_c0_10",              "sys_c0_11",                  "InstallDevices",       "FlushStfInOutPut",
148         "sys_c0_14",              "_cdevinput",                 "_cdevscan",            "_circgetc",
149         "_circputc",              "ioabort",                    "sys_c0_1a",            "KernelRedirect",
150         "PatchAOTable",
151 };
152
153 //#define r0 (psxRegs.GPR.n.r0)
154 #define at (psxRegs.GPR.n.at)
155 #define v0 (psxRegs.GPR.n.v0)
156 #define v1 (psxRegs.GPR.n.v1)
157 #define a0 (psxRegs.GPR.n.a0)
158 #define a1 (psxRegs.GPR.n.a1)
159 #define a2 (psxRegs.GPR.n.a2)
160 #define a3 (psxRegs.GPR.n.a3)
161 #define t0 (psxRegs.GPR.n.t0)
162 #define t1 (psxRegs.GPR.n.t1)
163 #define t2 (psxRegs.GPR.n.t2)
164 #define t3 (psxRegs.GPR.n.t3)
165 #define t4 (psxRegs.GPR.n.t4)
166 #define t5 (psxRegs.GPR.n.t5)
167 #define t6 (psxRegs.GPR.n.t6)
168 #define t7 (psxRegs.GPR.n.t7)
169 #define t8 (psxRegs.GPR.n.t8)
170 #define t9 (psxRegs.GPR.n.t9)
171 #define s0 (psxRegs.GPR.n.s0)
172 #define s1 (psxRegs.GPR.n.s1)
173 #define s2 (psxRegs.GPR.n.s2)
174 #define s3 (psxRegs.GPR.n.s3)
175 #define s4 (psxRegs.GPR.n.s4)
176 #define s5 (psxRegs.GPR.n.s5)
177 #define s6 (psxRegs.GPR.n.s6)
178 #define s7 (psxRegs.GPR.n.s7)
179 #define k0 (psxRegs.GPR.n.k0)
180 #define k1 (psxRegs.GPR.n.k1)
181 #define gp (psxRegs.GPR.n.gp)
182 #define sp (psxRegs.GPR.n.sp)
183 #define fp (psxRegs.GPR.n.s8)
184 #define ra (psxRegs.GPR.n.ra)
185 #define pc0 (psxRegs.pc)
186
187 #define Ra0 ((char *)PSXM(a0))
188 #define Ra1 ((char *)PSXM(a1))
189 #define Ra2 ((char *)PSXM(a2))
190 #define Ra3 ((char *)PSXM(a3))
191 #define Rv0 ((char *)PSXM(v0))
192 #define Rsp ((char *)PSXM(sp))
193
194 typedef struct {
195         u32 desc;
196         s32 status;
197         s32 mode;
198         u32 fhandler;
199 } EvCB[32];
200
201 #define EvStUNUSED      0x0000
202 #define EvStWAIT        0x1000
203 #define EvStACTIVE      0x2000
204 #define EvStALREADY 0x4000
205
206 #define EvMdINTR        0x1000
207 #define EvMdNOINTR      0x2000
208
209 /*
210 typedef struct {
211         s32 next;
212         s32 func1;
213         s32 func2;
214         s32 pad;
215 } SysRPst;
216 */
217
218 typedef struct {
219         s32 status;
220         s32 mode;
221         u32 reg[32];
222         u32 func;
223 } TCB;
224
225 typedef struct {
226         u32 _pc0;
227         u32 gp0;
228         u32 t_addr;
229         u32 t_size;
230         u32 d_addr;
231         u32 d_size;
232         u32 b_addr;
233         u32 b_size;
234         u32 S_addr;
235         u32 s_size;
236         u32 _sp, _fp, _gp, ret, base;
237 } EXEC;
238
239 struct DIRENTRY {
240         char name[20];
241         s32 attr;
242         s32 size;
243         u32 next;
244         s32 head;
245         char system[4];
246 };
247
248 typedef struct {
249         char name[32];
250         u32  mode;
251         u32  offset;
252         u32  size;
253         u32  mcfile;
254 } FileDesc;
255
256 static u32 *jmp_int = NULL;
257 static int *pad_buf = NULL;
258 static char *pad_buf1 = NULL, *pad_buf2 = NULL;
259 static int pad_buf1len, pad_buf2len;
260 static int pad_stopped = 0;
261
262 static u32 regs[35];
263 static EvCB *EventCB;
264 static EvCB *HwEV; // 0xf0
265 static EvCB *EvEV; // 0xf1
266 static EvCB *RcEV; // 0xf2
267 static EvCB *UeEV; // 0xf3
268 static EvCB *SwEV; // 0xf4
269 static EvCB *ThEV; // 0xff
270 static u32 heap_size = 0;
271 static u32 *heap_addr = NULL;
272 static u32 *heap_end = NULL;
273 static u32 SysIntRP[8];
274 static int CardState = -1;
275 static TCB ThreadCB[8];
276 static int CurThread = 0;
277 static FileDesc FDesc[32];
278 static u32 card_active_chan = 0;
279
280 boolean hleSoftCall = FALSE;
281
282 static inline void softCall(u32 pc) {
283         pc0 = pc;
284         ra = 0x80001000;
285
286         hleSoftCall = TRUE;
287
288         while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
289
290         hleSoftCall = FALSE;
291 }
292
293 static inline void softCall2(u32 pc) {
294         u32 sra = ra;
295         pc0 = pc;
296         ra = 0x80001000;
297
298         hleSoftCall = TRUE;
299
300         while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
301         ra = sra;
302
303         hleSoftCall = FALSE;
304 }
305
306 static inline void DeliverEvent(u32 ev, u32 spec) {
307         if (EventCB[ev][spec].status != EvStACTIVE) return;
308
309 //      EventCB[ev][spec].status = EvStALREADY;
310         if (EventCB[ev][spec].mode == EvMdINTR) {
311                 softCall2(EventCB[ev][spec].fhandler);
312         } else EventCB[ev][spec].status = EvStALREADY;
313 }
314
315 static unsigned interrupt_r26=0x8004E8B0;
316
317 static inline void SaveRegs() {
318         memcpy(regs, psxRegs.GPR.r, 32*4);
319         regs[32] = psxRegs.GPR.n.lo;
320         regs[33] = psxRegs.GPR.n.hi;
321         regs[34] = psxRegs.pc;
322 }
323
324 static inline void LoadRegs() {
325         memcpy(psxRegs.GPR.r, regs, 32*4);
326         psxRegs.GPR.n.lo = regs[32];
327         psxRegs.GPR.n.hi = regs[33];
328 }
329
330 /*                                           *
331 //                                           *
332 //                                           *
333 //               System calls A0             */
334
335
336 #define buread(Ra1, mcd, length) { \
337         SysPrintf("read %d: %x,%x (%s)\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2, Mcd##mcd##Data + 128 * FDesc[1 + mcd].mcfile + 0xa); \
338         ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
339         memcpy(Ra1, ptr, length); \
340         if (FDesc[1 + mcd].mode & 0x8000) { \
341         DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
342         DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
343         v0 = 0; } \
344         else v0 = length; \
345         FDesc[1 + mcd].offset += v0; \
346 }
347
348 #define buwrite(Ra1, mcd, length) { \
349         u32 offset =  + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
350         SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
351         ptr = Mcd##mcd##Data + offset; \
352         memcpy(ptr, Ra1, length); \
353         FDesc[1 + mcd].offset += length; \
354         SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
355         if (FDesc[1 + mcd].mode & 0x8000) { \
356         DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
357         DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
358         v0 = 0; } \
359         else v0 = length; \
360 }
361
362
363 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
364 /* For some strange reason, the returned character is sign-expanded; */
365 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
366 /* TODO FIX ME : Properly implement this behaviour */
367 void psxBios_getc(void) // 0x03, 0x35
368 {
369         char *ptr;
370         void *pa1 = Ra1;
371 #ifdef PSXBIOS_LOG
372         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
373 #endif
374         v0 = -1;
375
376         if (pa1 != INVALID_PTR) {
377                 switch (a0) {
378                         case 2: buread(pa1, 1, 1); break;
379                         case 3: buread(pa1, 2, 1); break;
380                 }
381         }
382
383         pc0 = ra;
384 }
385
386 /* Copy of psxBios_write, except size is 1. */
387 void psxBios_putc(void) // 0x09, 0x3B
388 {
389         char *ptr;
390         void *pa1 = Ra1;
391 #ifdef PSXBIOS_LOG
392         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
393 #endif
394         v0 = -1;
395         if (pa1 == INVALID_PTR) {
396                 pc0 = ra;
397                 return;
398         }
399
400         if (a0 == 1) { // stdout
401                 char *ptr = (char *)pa1;
402
403                 v0 = a2;
404                 while (a2 > 0) {
405                         printf("%c", *ptr++); a2--;
406                 }
407                 pc0 = ra; return;
408         }
409
410         switch (a0) {
411                 case 2: buwrite(pa1, 1, 1); break;
412                 case 3: buwrite(pa1, 2, 1); break;
413         }
414
415         pc0 = ra;
416 }
417
418 void psxBios_todigit(void) // 0x0a
419 {
420         int c = a0;
421 #ifdef PSXBIOS_LOG
422         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
423 #endif
424         c &= 0xFF;
425         if (c >= 0x30 && c < 0x3A) {
426                 c -= 0x30;
427         }
428         else if (c > 0x60 && c < 0x7B) {
429                 c -= 0x20;
430         }
431         else if (c > 0x40 && c < 0x5B) {
432                 c = c - 0x41 + 10;
433         }
434         else if (c >= 0x80) {
435                 c = -1;
436         }
437         else
438         {
439                 c = 0x0098967F;
440         }
441         v0 = c;
442         pc0 = ra;
443 }
444
445 void psxBios_abs() { // 0x0e
446         if ((s32)a0 < 0) v0 = -(s32)a0;
447         else v0 = a0;
448         pc0 = ra;
449 }
450
451 void psxBios_labs() { // 0x0f
452         psxBios_abs();
453 }
454
455 void psxBios_atoi() { // 0x10
456         s32 n = 0, f = 0;
457         char *p = (char *)Ra0;
458
459         for (;;p++) {
460                 switch (*p) {
461                         case ' ': case '\t': continue;
462                         case '-': f++;
463                         case '+': p++;
464                 }
465                 break;
466         }
467
468         while (*p >= '0' && *p <= '9') {
469                 n = n * 10 + *p++ - '0';
470         }
471
472         v0 = (f ? -n : n);
473         pc0 = ra;
474 }
475
476 void psxBios_atol() { // 0x11
477         psxBios_atoi();
478 }
479
480 void psxBios_setjmp() { // 0x13
481         u32 *jmp_buf = (u32 *)Ra0;
482         int i;
483
484 #ifdef PSXBIOS_LOG
485         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x13]);
486 #endif
487
488         jmp_buf[0] = ra;
489         jmp_buf[1] = sp;
490         jmp_buf[2] = fp;
491         for (i = 0; i < 8; i++) // s0-s7
492                 jmp_buf[3 + i] = psxRegs.GPR.r[16 + i];
493         jmp_buf[11] = gp;
494
495         v0 = 0; pc0 = ra;
496 }
497
498 void psxBios_longjmp() { // 0x14
499         u32 *jmp_buf = (u32 *)Ra0;
500         int i;
501
502 #ifdef PSXBIOS_LOG
503         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
504 #endif
505
506         ra = jmp_buf[0]; /* ra */
507         sp = jmp_buf[1]; /* sp */
508         fp = jmp_buf[2]; /* fp */
509         for (i = 0; i < 8; i++) // s0-s7
510                 psxRegs.GPR.r[16 + i] = jmp_buf[3 + i];
511         gp = jmp_buf[11]; /* gp */
512
513         v0 = a1; pc0 = ra;
514 }
515
516 void psxBios_strcat() { // 0x15
517         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
518
519 #ifdef PSXBIOS_LOG
520         PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
521 #endif
522         if (a0 == 0 || a1 == 0)
523         {
524                 v0 = 0;
525                 pc0 = ra;
526                 return;
527         }
528         while (*p1++);
529         --p1;
530         while ((*p1++ = *p2++) != '\0');
531
532         v0 = a0; pc0 = ra;
533 }
534
535 void psxBios_strncat() { // 0x16
536         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
537         s32 n = a2;
538
539 #ifdef PSXBIOS_LOG
540         PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
541 #endif
542         if (a0 == 0 || a1 == 0)
543         {
544                 v0 = 0;
545                 pc0 = ra;
546                 return;
547         }
548         while (*p1++);
549         --p1;
550         while ((*p1++ = *p2++) != '\0') {
551                 if (--n < 0) {
552                         *--p1 = '\0';
553                         break;
554                 }
555         }
556
557         v0 = a0; pc0 = ra;
558 }
559
560 void psxBios_strcmp() { // 0x17
561         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
562         s32 n=0;
563         if (a0 == 0 && a1 == 0)
564         {
565                 v0 = 0;
566                 pc0 = ra;
567                 return;
568         }
569         else if (a0 == 0 && a1 != 0)
570         {
571                 v0 = -1;
572                 pc0 = ra;
573                 return;
574         }
575         else if (a0 != 0 && a1 == 0)
576         {
577                 v0 = 1;
578                 pc0 = ra;
579                 return;
580         }
581 #ifdef PSXBIOS_LOG
582         PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
583 #endif
584
585         while (*p1 == *p2++) {
586                 n++;
587                 if (*p1++ == '\0') {
588                         v1=n-1;
589                         a0+=n;
590                         a1+=n;
591                         v0 = 0;
592                         pc0 = ra;
593                         return;
594                 }
595         }
596
597         v0 = (*p1 - *--p2);
598         v1 = n;
599         a0+=n;
600         a1+=n;
601         pc0 = ra;
602 }
603
604 void psxBios_strncmp() { // 0x18
605         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
606         s32 n = a2;
607         if (a0 == 0 && a1 == 0)
608         {
609                 v0 = 0;
610                 pc0 = ra;
611                 return;
612         }
613         else if (a0 == 0 && a1 != 0)
614         {
615                 v0 = -1;
616                 pc0 = ra;
617                 return;
618         }
619         else if (a0 != 0 && a1 == 0)
620         {
621                 v0 = 1;
622                 pc0 = ra;
623                 return;
624         }
625 #ifdef PSXBIOS_LOG
626         PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
627 #endif
628
629         while (--n >= 0 && *p1 == *p2++) {
630                 if (*p1++ == '\0') {
631                         v0 = 0;
632                         pc0 = ra;
633                         v1 = a2 - ((a2-n) - 1);
634                         a0 += (a2-n) - 1;
635                         a1 += (a2-n) - 1;
636                         a2 = n;
637                         return;
638                 }
639         }
640
641         v0 = (n < 0 ? 0 : *p1 - *--p2);
642         pc0 = ra;
643         v1 = a2 - ((a2-n) - 1);
644         a0 += (a2-n) - 1;
645         a1 += (a2-n) - 1;
646         a2 = n;
647 }
648
649 void psxBios_strcpy() { // 0x19
650         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
651         if (a0 == 0 || a1 == 0)
652         {
653                 v0 = 0;
654                 pc0 = ra;
655                 return;
656         }
657         while ((*p1++ = *p2++) != '\0');
658
659         v0 = a0; pc0 = ra;
660 }
661
662 void psxBios_strncpy() { // 0x1a
663         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
664         s32 n = a2, i;
665         if (a0 == 0 || a1 == 0)
666         {
667                 v0 = 0;
668                 pc0 = ra;
669                 return;
670         }
671         for (i = 0; i < n; i++) {
672                 if ((*p1++ = *p2++) == '\0') {
673                         while (++i < n) {
674                                 *p1++ = '\0';
675                         }
676                         v0 = a0; pc0 = ra;
677                         return;
678                 }
679         }
680
681         v0 = a0; pc0 = ra;
682 }
683
684 void psxBios_strlen() { // 0x1b
685         char *p = (char *)Ra0;
686         v0 = 0;
687         if (a0 == 0)
688         {
689                 pc0 = ra;
690                 return;
691         }
692         while (*p++) v0++;
693         pc0 = ra;
694 }
695
696 void psxBios_index() { // 0x1c
697         char *p = (char *)Ra0;
698         if (a0 == 0)
699         {
700                 v0 = 0;
701                 pc0 = ra;
702                 return;
703         }
704
705         do {
706                 if (*p == a1) {
707                         v0 = a0 + (p - (char *)Ra0);
708                         pc0 = ra;
709                         return;
710                 }
711         } while (*p++ != '\0');
712
713         v0 = 0; pc0 = ra;
714 }
715
716 void psxBios_rindex() { // 0x1d
717         char *p = (char *)Ra0;
718
719         v0 = 0;
720         if (a0 == 0)
721         {
722                 pc0 = ra;
723                 return;
724         }
725         do {
726                 if (*p == a1)
727                         v0 = a0 + (p - (char *)Ra0);
728         } while (*p++ != '\0');
729
730         pc0 = ra;
731 }
732
733 void psxBios_strchr() { // 0x1e
734         psxBios_index();
735 }
736
737 void psxBios_strrchr() { // 0x1f
738         psxBios_rindex();
739 }
740
741 void psxBios_strpbrk() { // 0x20
742         char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
743
744         while ((c = *p1++) != '\0') {
745                 for (scanp = p2; (sc = *scanp++) != '\0';) {
746                         if (sc == c) {
747                                 v0 = a0 + (p1 - 1 - (char *)Ra0);
748                                 pc0 = ra;
749                                 return;
750                         }
751                 }
752         }
753
754         // BUG: return a0 instead of NULL if not found
755         v0 = a0; pc0 = ra;
756 }
757
758 void psxBios_strspn() { // 0x21
759         char *p1, *p2;
760
761         for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
762                 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
763                 if (*p2 == '\0') break;
764         }
765
766         v0 = p1 - (char *)Ra0; pc0 = ra;
767 }
768
769 void psxBios_strcspn() { // 0x22
770         char *p1, *p2;
771
772         for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
773                 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
774                 if (*p2 != '\0') break;
775         }
776
777         v0 = p1 - (char *)Ra0; pc0 = ra;
778 }
779
780 void psxBios_strtok() { // 0x23
781         char *pcA0 = (char *)Ra0;
782         char *pcRet = strtok(pcA0, (char *)Ra1);
783         if (pcRet)
784                 v0 = a0 + pcRet - pcA0;
785         else
786                 v0 = 0;
787         pc0 = ra;
788 }
789
790 void psxBios_strstr() { // 0x24
791         char *p = (char *)Ra0, *p1, *p2;
792
793         while (*p != '\0') {
794                 p1 = p;
795                 p2 = (char *)Ra1;
796
797                 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
798                         p1++; p2++;
799                 }
800
801                 if (*p2 == '\0') {
802                         v0 = a0 + (p - (char *)Ra0);
803                         pc0 = ra;
804                         return;
805                 }
806
807                 p++;
808         }
809
810         v0 = 0; pc0 = ra;
811 }
812
813 void psxBios_toupper() { // 0x25
814         v0 = (s8)(a0 & 0xff);
815         if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
816         pc0 = ra;
817 }
818
819 void psxBios_tolower() { // 0x26
820         v0 = (s8)(a0 & 0xff);
821         if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
822         pc0 = ra;
823 }
824
825 void psxBios_bcopy() { // 0x27
826         char *p1 = (char *)Ra1, *p2 = (char *)Ra0;
827         v0 = a0;
828         if (a0 == 0 || a2 > 0x7FFFFFFF)
829         {
830                 pc0 = ra;
831                 return;
832         }
833         while ((s32)a2-- > 0) *p1++ = *p2++;
834         a2 = 0;
835         pc0 = ra;
836 }
837
838 void psxBios_bzero() { // 0x28
839         char *p = (char *)Ra0;
840         v0 = a0;
841         /* Same as memset here (See memset below) */
842         if (a1 > 0x7FFFFFFF || a1 == 0)
843         {
844                 v0 = 0;
845                 pc0 = ra;
846                 return;
847         }
848         else if (a0 == 0)
849         {
850                 pc0 = ra;
851                 return;
852         }
853         while ((s32)a1-- > 0) *p++ = '\0';
854         a1 = 0;
855         pc0 = ra;
856 }
857
858 void psxBios_bcmp() { // 0x29
859         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
860
861         if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
862
863         while ((s32)a2-- > 0) {
864                 if (*p1++ != *p2++) {
865                         v0 = *p1 - *p2; // BUG: compare the NEXT byte
866                         pc0 = ra;
867                         return;
868                 }
869         }
870
871         v0 = 0; pc0 = ra;
872 }
873
874 void psxBios_memcpy() { // 0x2a
875         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
876         v0 = a0;
877         if (a0 == 0 || a2 > 0x7FFFFFFF)
878         {
879                 pc0 = ra;
880                 return;
881         }
882         while ((s32)a2-- > 0) {
883                 *p1++ = *p2++;
884         }
885         a2 = 0;
886         pc0 = ra;
887 }
888
889 void psxBios_memset() { // 0x2b
890         char *p = (char *)Ra0;
891         v0 = a0;
892         if (a2 > 0x7FFFFFFF || a2 == 0)
893         {
894                 v0 = 0;
895                 pc0 = ra;
896                 return;
897         }
898         if (a0 == 0)
899         {
900                 pc0 = ra;
901                 return;
902         }
903         while ((s32)a2-- > 0) *p++ = (char)a1;
904         a2 = 0;
905         v0 = a0; pc0 = ra;
906 }
907
908 void psxBios_memmove() { // 0x2c
909         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
910         v0 = a0;
911         if (a0 == 0 || a2 > 0x7FFFFFFF)
912         {
913                 pc0 = ra;
914                 return;
915         }
916         if (p2 <= p1 && p2 + a2 > p1) {
917                 a2++; // BUG: copy one more byte here
918                 p1 += a2;
919                 p2 += a2;
920                 while ((s32)a2-- > 0) *--p1 = *--p2;
921         } else {
922                 while ((s32)a2-- > 0) *p1++ = *p2++;
923         }
924         pc0 = ra;
925 }
926
927 void psxBios_memcmp() { // 0x2d
928         psxBios_bcmp();
929 }
930
931 void psxBios_memchr() { // 0x2e
932         char *p = (char *)Ra0;
933
934         if (a0 == 0 || a2 > 0x7FFFFFFF)
935         {
936                 pc0 = ra;
937                 return;
938         }
939
940         while ((s32)a2-- > 0) {
941                 if (*p++ != (s8)a1) continue;
942                 v0 = a0 + (p - (char *)Ra0 - 1);
943                 pc0 = ra;
944                 return;
945         }
946
947         v0 = 0; pc0 = ra;
948 }
949
950 void psxBios_rand() { // 0x2f
951         u32 s = psxMu32(0x9010) * 1103515245 + 12345;
952         v0 = (s >> 16) & 0x7fff;
953         psxMu32ref(0x9010) = SWAPu32(s);
954         pc0 = ra;
955 }
956
957 void psxBios_srand() { // 0x30
958         psxMu32ref(0x9010) = SWAPu32(a0);
959         pc0 = ra;
960 }
961
962 static u32 qscmpfunc, qswidth;
963
964 static inline int qscmp(char *a, char *b) {
965         u32 sa0 = a0;
966
967         a0 = sa0 + (a - (char *)PSXM(sa0));
968         a1 = sa0 + (b - (char *)PSXM(sa0));
969
970         softCall2(qscmpfunc);
971
972         a0 = sa0;
973         return (s32)v0;
974 }
975
976 static inline void qexchange(char *i, char *j) {
977         char t;
978         int n = qswidth;
979
980         do {
981                 t = *i;
982                 *i++ = *j;
983                 *j++ = t;
984         } while (--n);
985 }
986
987 static inline void q3exchange(char *i, char *j, char *k) {
988         char t;
989         int n = qswidth;
990
991         do {
992                 t = *i;
993                 *i++ = *k;
994                 *k++ = *j;
995                 *j++ = t;
996         } while (--n);
997 }
998
999 static void qsort_main(char *a, char *l) {
1000         char *i, *j, *lp, *hp;
1001         int c;
1002         unsigned int n;
1003
1004 start:
1005         if ((n = l - a) <= qswidth)
1006                 return;
1007         n = qswidth * (n / (2 * qswidth));
1008         hp = lp = a + n;
1009         i = a;
1010         j = l - qswidth;
1011         while (TRUE) {
1012                 if (i < lp) {
1013                         if ((c = qscmp(i, lp)) == 0) {
1014                                 qexchange(i, lp -= qswidth);
1015                                 continue;
1016                         }
1017                         if (c < 0) {
1018                                 i += qswidth;
1019                                 continue;
1020                         }
1021                 }
1022
1023 loop:
1024                 if (j > hp) {
1025                         if ((c = qscmp(hp, j)) == 0) {
1026                                 qexchange(hp += qswidth, j);
1027                                 goto loop;
1028                         }
1029                         if (c > 0) {
1030                                 if (i == lp) {
1031                                         q3exchange(i, hp += qswidth, j);
1032                                         i = lp += qswidth;
1033                                         goto loop;
1034                                 }
1035                                 qexchange(i, j);
1036                                 j -= qswidth;
1037                                 i += qswidth;
1038                                 continue;
1039                         }
1040                         j -= qswidth;
1041                         goto loop;
1042                 }
1043
1044                 if (i == lp) {
1045                         if (lp - a >= l - hp) {
1046                                 qsort_main(hp + qswidth, l);
1047                                 l = lp;
1048                         } else {
1049                                 qsort_main(a, lp);
1050                                 a = hp + qswidth;
1051                         }
1052                         goto start;
1053                 }
1054
1055                 q3exchange(j, lp -= qswidth, i);
1056                 j = hp -= qswidth;
1057         }
1058 }
1059
1060 void psxBios_qsort() { // 0x31
1061         qswidth = a2;
1062         qscmpfunc = a3;
1063         qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1064
1065         pc0 = ra;
1066 }
1067
1068 void psxBios_malloc() { // 0x33
1069         u32 *chunk, *newchunk = NULL;
1070         unsigned int dsize = 0, csize, cstat;
1071         int colflag;
1072 #ifdef PSXBIOS_LOG
1073         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]);
1074 #endif
1075         if (!a0 || (!heap_size || !heap_addr)) {
1076                 v0 = 0;
1077                 pc0 = ra;
1078                 return;
1079         }
1080
1081         // scan through heap and combine free chunks of space
1082         chunk = heap_addr;
1083         colflag = 0;
1084         while(chunk < heap_end) {
1085                 // get size and status of actual chunk
1086                 csize = ((u32)*chunk) & 0xfffffffc;
1087                 cstat = ((u32)*chunk) & 1;
1088
1089                 // most probably broken heap descriptor
1090                 // this fixes Burning Road
1091                 if (*chunk == 0) {
1092                         newchunk = chunk;
1093                         dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1094                         colflag = 1;
1095                         break;
1096                 }
1097
1098                 // it's a free chunk
1099                 if(cstat == 1) {
1100                         if(colflag == 0) {
1101                                 newchunk = chunk;
1102                                 dsize = csize;
1103                                 colflag = 1;                    // let's begin a new collection of free memory
1104                         }
1105                         else dsize += (csize+4);        // add the new size including header
1106                 }
1107                 // not a free chunk: did we start a collection ?
1108                 else {
1109                         if(colflag == 1) {                      // collection is over
1110                                 colflag = 0;
1111                                 *newchunk = SWAP32(dsize | 1);
1112                         }
1113                 }
1114
1115                 // next chunk
1116                 chunk = (u32*)((uptr)chunk + csize + 4);
1117         }
1118         // if neccessary free memory on end of heap
1119         if (colflag == 1)
1120                 *newchunk = SWAP32(dsize | 1);
1121
1122         chunk = heap_addr;
1123         csize = ((u32)*chunk) & 0xfffffffc;
1124         cstat = ((u32)*chunk) & 1;
1125         dsize = (a0 + 3) & 0xfffffffc;
1126
1127         // exit on uninitialized heap
1128         if (chunk == NULL) {
1129                 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1130                 v0 = 0;
1131                 pc0 = ra;
1132                 return;
1133         }
1134
1135         // search an unused chunk that is big enough until the end of the heap
1136         while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1137                 chunk = (u32*)((uptr)chunk + csize + 4);
1138
1139                         // catch out of memory
1140                         if(chunk >= heap_end) {
1141                                 printf("malloc %x,%x: Out of memory error!\n",
1142                                         v0, a0);
1143                                 v0 = 0; pc0 = ra;
1144                                 return;
1145                         }
1146
1147                 csize = ((u32)*chunk) & 0xfffffffc;
1148                 cstat = ((u32)*chunk) & 1;
1149         }
1150
1151         // allocate memory
1152         if(dsize == csize) {
1153                 // chunk has same size
1154                 *chunk &= 0xfffffffc;
1155         } else if (dsize > csize) {
1156                 v0 = 0; pc0 = ra;
1157                 return;
1158         } else {
1159                 // split free chunk
1160                 *chunk = SWAP32(dsize);
1161                 newchunk = (u32*)((uptr)chunk + dsize + 4);
1162                 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1163         }
1164
1165         // return pointer to allocated memory
1166         v0 = ((uptr)chunk - (uptr)psxM) + 4;
1167         v0|= 0x80000000;
1168         //printf ("malloc %x,%x\n", v0, a0);
1169         pc0 = ra;
1170 }
1171
1172 void psxBios_free() { // 0x34
1173
1174 #ifdef PSXBIOS_LOG
1175         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x34]);
1176 #endif
1177
1178         SysPrintf("free %x: %x bytes\n", a0, *(u32*)(Ra0-4));
1179
1180         if (a0)
1181                 *(u32*)(Ra0-4) |= 1;    // set chunk to free
1182         pc0 = ra;
1183 }
1184
1185 void psxBios_calloc() { // 0x37
1186         void *pv0;
1187 #ifdef PSXBIOS_LOG
1188         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]);
1189 #endif
1190
1191         a0 = a0 * a1;
1192         psxBios_malloc();
1193         pv0 = Rv0;
1194         if (pv0)
1195                 memset(pv0, 0, a0);
1196 }
1197
1198 void psxBios_realloc() { // 0x38
1199         u32 block = a0;
1200         u32 size = a1;
1201 #ifdef PSXBIOS_LOG
1202         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1203 #endif
1204
1205         a0 = block;
1206         /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1207         if (block == 0)
1208         {
1209                 psxBios_malloc();
1210         }
1211         /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1212         else if (size == 0)
1213         {
1214                 psxBios_free();
1215         }
1216         /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1217         /* Note that it is not quite implemented this way here. */
1218         else
1219         {
1220                 psxBios_free();
1221                 a0 = size;
1222                 psxBios_malloc();
1223         }
1224 }
1225
1226
1227 /* InitHeap(void *block , int n) */
1228 void psxBios_InitHeap() { // 0x39
1229         unsigned int size;
1230
1231 #ifdef PSXBIOS_LOG
1232         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x39]);
1233 #endif
1234
1235         if (((a0 & 0x1fffff) + a1)>= 0x200000) size = 0x1ffffc - (a0 & 0x1fffff);
1236         else size = a1;
1237
1238         size &= 0xfffffffc;
1239
1240         heap_addr = (u32 *)Ra0;
1241         heap_size = size;
1242         heap_end = (u32 *)((u8 *)heap_addr + heap_size);
1243         /* HACKFIX: Commenting out this line fixes GTA2 crash */
1244         //*heap_addr = SWAP32(size | 1);
1245
1246         SysPrintf("InitHeap %x,%x : %x %x\n",a0,a1, (int)((uptr)heap_addr-(uptr)psxM), size);
1247
1248         pc0 = ra;
1249 }
1250
1251 void psxBios_getchar() { //0x3b
1252         v0 = getchar(); pc0 = ra;
1253 }
1254
1255 void psxBios_printf() { // 0x3f
1256         char tmp[1024];
1257         char tmp2[1024];
1258         u32 save[4];
1259         char *ptmp = tmp;
1260         int n=1, i=0, j;
1261         void *psp;
1262
1263         psp = PSXM(sp);
1264         if (psp != INVALID_PTR) {
1265                 memcpy(save, psp, 4 * 4);
1266                 psxMu32ref(sp) = SWAP32((u32)a0);
1267                 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1268                 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1269                 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1270         }
1271
1272         while (Ra0[i]) {
1273                 switch (Ra0[i]) {
1274                         case '%':
1275                                 j = 0;
1276                                 tmp2[j++] = '%';
1277 _start:
1278                                 switch (Ra0[++i]) {
1279                                         case '.':
1280                                         case 'l':
1281                                                 tmp2[j++] = Ra0[i]; goto _start;
1282                                         default:
1283                                                 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1284                                                         tmp2[j++] = Ra0[i];
1285                                                         goto _start;
1286                                                 }
1287                                                 break;
1288                                 }
1289                                 tmp2[j++] = Ra0[i];
1290                                 tmp2[j] = 0;
1291
1292                                 switch (Ra0[i]) {
1293                                         case 'f': case 'F':
1294                                                 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1295                                         case 'a': case 'A':
1296                                         case 'e': case 'E':
1297                                         case 'g': case 'G':
1298                                                 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1299                                         case 'p':
1300                                         case 'i': case 'u':
1301                                         case 'd': case 'D':
1302                                         case 'o': case 'O':
1303                                         case 'x': case 'X':
1304                                                 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1305                                         case 'c':
1306                                                 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1307                                         case 's':
1308                                                 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1309                                         case '%':
1310                                                 *ptmp++ = Ra0[i]; break;
1311                                 }
1312                                 i++;
1313                                 break;
1314                         default:
1315                                 *ptmp++ = Ra0[i++];
1316                 }
1317         }
1318         *ptmp = 0;
1319
1320         if (psp)
1321                 memcpy(psp, save, 4 * 4);
1322
1323         SysPrintf("%s", tmp);
1324
1325         pc0 = ra;
1326 }
1327
1328 void psxBios_format() { // 0x41
1329         if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1330         {
1331                 CreateMcd(Config.Mcd1);
1332                 LoadMcd(1, Config.Mcd1);
1333                 v0 = 1;
1334         }
1335         else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1336         {
1337                 CreateMcd(Config.Mcd2);
1338                 LoadMcd(2, Config.Mcd2);
1339                 v0 = 1;
1340         }
1341         else
1342         {
1343                 v0 = 0;
1344         }
1345         pc0 = ra;
1346 }
1347
1348 /*
1349  *      long Load(char *name, struct EXEC *header);
1350  */
1351
1352 void psxBios_Load() { // 0x42
1353         EXE_HEADER eheader;
1354         void *pa1;
1355
1356 #ifdef PSXBIOS_LOG
1357         PSXBIOS_LOG("psxBios_%s: %s, %x\n", biosA0n[0x42], Ra0, a1);
1358 #endif
1359
1360         pa1 = Ra1;
1361         if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
1362                 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1363                 v0 = 1;
1364         } else v0 = 0;
1365
1366         pc0 = ra;
1367 }
1368
1369 /*
1370  *      int Exec(struct EXEC *header , int argc , char **argv);
1371  */
1372
1373 void psxBios_Exec() { // 43
1374         EXEC *header = (EXEC*)Ra0;
1375         u32 tmp;
1376
1377 #ifdef PSXBIOS_LOG
1378         PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1379 #endif
1380
1381         header->_sp = sp;
1382         header->_fp = fp;
1383         header->_sp = sp;
1384         header->_gp = gp;
1385         header->ret = ra;
1386         header->base = s0;
1387
1388         if (header->S_addr != 0) {
1389                 tmp = header->S_addr + header->s_size;
1390                 sp = tmp;
1391                 fp = sp;
1392         }
1393
1394         gp = header->gp0;
1395
1396         s0 = a0;
1397
1398         a0 = a1;
1399         a1 = a2;
1400
1401         ra = 0x8000;
1402         pc0 = header->_pc0;
1403 }
1404
1405 void psxBios_FlushCache() { // 44
1406 #ifdef PSXBIOS_LOG
1407         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1408 #endif
1409         psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1410         psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1411         pc0 = ra;
1412 }
1413
1414 void psxBios_GPU_dw() { // 0x46
1415         int size;
1416         u32 *ptr;
1417
1418 #ifdef PSXBIOS_LOG
1419         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1420 #endif
1421
1422         GPU_writeData(0xa0000000);
1423         GPU_writeData((a1<<0x10)|(a0&0xffff));
1424         GPU_writeData((a3<<0x10)|(a2&0xffff));
1425         size = (a2*a3)/2;
1426         ptr = (u32*)PSXM(Rsp[4]);  //that is correct?
1427         while(size--)
1428         {
1429                 GPU_writeData(SWAPu32(*ptr++));
1430         } 
1431
1432         pc0 = ra;
1433 }
1434
1435 void psxBios_mem2vram() { // 0x47
1436         int size;
1437         gpuSyncPluginSR();
1438         GPU_writeData(0xa0000000);
1439         GPU_writeData((a1<<0x10)|(a0&0xffff));
1440         GPU_writeData((a3<<0x10)|(a2&0xffff));
1441         size = ((((a2 * a3) / 2) >> 4) << 16);
1442         GPU_writeStatus(0x04000002);
1443         psxHwWrite32(0x1f8010f4,0);
1444         psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1445         psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1446         psxHwWrite32(0x1f8010a4, size | 0x10);
1447         psxHwWrite32(0x1f8010a8,0x01000201);
1448
1449         pc0 = ra;
1450 }
1451
1452 void psxBios_SendGPU() { // 0x48
1453         GPU_writeStatus(a0);
1454         gpuSyncPluginSR();
1455         pc0 = ra;
1456 }
1457
1458 void psxBios_GPU_cw() { // 0x49
1459         gpuSyncPluginSR();
1460         GPU_writeData(a0);
1461         v0 = HW_GPU_STATUS;
1462         pc0 = ra;
1463 }
1464
1465 void psxBios_GPU_cwb() { // 0x4a
1466         u32 *ptr = (u32*)Ra0;
1467         int size = a1;
1468         gpuSyncPluginSR();
1469         while(size--)
1470         {
1471                 GPU_writeData(SWAPu32(*ptr++));
1472         }
1473
1474         pc0 = ra;
1475 }
1476    
1477 void psxBios_GPU_SendPackets() { //4b:  
1478         gpuSyncPluginSR();
1479         GPU_writeStatus(0x04000002);
1480         psxHwWrite32(0x1f8010f4,0);
1481         psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1482         psxHwWrite32(0x1f8010a0,a0);
1483         psxHwWrite32(0x1f8010a4,0);
1484         psxHwWrite32(0x1f8010a8,0x010000401);
1485         pc0 = ra;
1486 }
1487
1488 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1489         psxHwWrite32(0x1f8010a8,0x00000401);
1490         GPU_writeData(0x0400000);
1491         GPU_writeData(0x0200000);
1492         GPU_writeData(0x0100000);
1493         v0 = 0x1f801814;
1494         pc0 = ra;
1495 }
1496
1497 void psxBios_GPU_GetGPUStatus() { // 0x4d
1498         v0 = GPU_readStatus();
1499         pc0 = ra;
1500 }
1501
1502 #undef s_addr
1503
1504 void psxBios_LoadExec() { // 51
1505         EXEC *header = (EXEC*)PSXM(0xf000);
1506         u32 s_addr, s_size;
1507
1508 #ifdef PSXBIOS_LOG
1509         PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1510 #endif
1511         s_addr = a1; s_size = a2;
1512
1513         a1 = 0xf000;
1514         psxBios_Load();
1515
1516         header->S_addr = s_addr;
1517         header->s_size = s_size;
1518
1519         a0 = 0xf000; a1 = 0; a2 = 0;
1520         psxBios_Exec();
1521 }
1522
1523 void psxBios__bu_init() { // 70
1524 #ifdef PSXBIOS_LOG
1525         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1526 #endif
1527
1528         DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1529         DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1530
1531         pc0 = ra;
1532 }
1533
1534 void psxBios__96_init() { // 71
1535 #ifdef PSXBIOS_LOG
1536         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1537 #endif
1538
1539         pc0 = ra;
1540 }
1541
1542 void psxBios__96_remove() { // 72
1543 #ifdef PSXBIOS_LOG
1544         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1545 #endif
1546
1547         pc0 = ra;
1548 }
1549
1550 void psxBios_SetMem() { // 9f
1551         u32 new = psxHu32(0x1060);
1552
1553 #ifdef PSXBIOS_LOG
1554         PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1555 #endif
1556
1557         switch(a0) {
1558                 case 2:
1559                         psxHu32ref(0x1060) = SWAP32(new);
1560                         psxMu32ref(0x060) = a0;
1561                         SysPrintf("Change effective memory : %d MBytes\n",a0);
1562                         break;
1563
1564                 case 8:
1565                         psxHu32ref(0x1060) = SWAP32(new | 0x300);
1566                         psxMu32ref(0x060) = a0;
1567                         SysPrintf("Change effective memory : %d MBytes\n",a0);
1568
1569                 default:
1570                         SysPrintf("Effective memory must be 2/8 MBytes\n");
1571                 break;
1572         }
1573
1574         pc0 = ra;
1575 }
1576
1577 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1578 void psxBios_get_cd_status(void) //a6
1579 {
1580         v0 = 1;
1581         pc0 = ra;
1582 }
1583
1584 void psxBios__card_info() { // ab
1585 #ifdef PSXBIOS_LOG
1586         PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1587 #endif
1588         u32 ret, port;
1589         card_active_chan = a0;
1590         port = card_active_chan >> 4;
1591
1592         switch (port) {
1593         case 0x0:
1594         case 0x1:
1595                 ret = 0x2;
1596                 if (McdDisable[port & 1])
1597                         ret = 0x8;
1598                 break;
1599         default:
1600 #ifdef PSXBIOS_LOG
1601                 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
1602 #endif
1603                 ret = 0x11;
1604                 break;
1605         }
1606
1607         if (McdDisable[0] && McdDisable[1])
1608                 ret = 0x8;
1609
1610         DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1611 //      DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1612         DeliverEvent(0x81, ret); // 0xf4000001, 0x0004
1613         v0 = 1; pc0 = ra;
1614 }
1615
1616 void psxBios__card_load() { // ac
1617 #ifdef PSXBIOS_LOG
1618         PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1619 #endif
1620
1621         card_active_chan = a0;
1622
1623 //      DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1624         DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1625
1626         v0 = 1; pc0 = ra;
1627 }
1628
1629 /* System calls B0 */
1630
1631 void psxBios_SetRCnt() { // 02
1632 #ifdef PSXBIOS_LOG
1633         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1634 #endif
1635
1636         a0&= 0x3;
1637         if (a0 != 3) {
1638                 u32 mode=0;
1639
1640                 psxRcntWtarget(a0, a1);
1641                 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1642                 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1643                 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1644                 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1645                 else         { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1646
1647                 psxRcntWmode(a0, mode);
1648         }
1649         pc0 = ra;
1650 }
1651
1652 void psxBios_GetRCnt() { // 03
1653 #ifdef PSXBIOS_LOG
1654         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1655 #endif
1656
1657         a0&= 0x3;
1658         if (a0 != 3) v0 = psxRcntRcount(a0);
1659         else v0 = 0;
1660         pc0 = ra;
1661 }
1662
1663 void psxBios_StartRCnt() { // 04
1664 #ifdef PSXBIOS_LOG
1665         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1666 #endif
1667
1668         a0&= 0x3;
1669         if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1670         else psxHu32ref(0x1074)|= SWAPu32(0x1);
1671         v0 = 1; pc0 = ra;
1672 }
1673
1674 void psxBios_StopRCnt() { // 05
1675 #ifdef PSXBIOS_LOG
1676         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1677 #endif
1678
1679         a0&= 0x3;
1680         if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1681         else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1682         pc0 = ra;
1683 }
1684
1685 void psxBios_ResetRCnt() { // 06
1686 #ifdef PSXBIOS_LOG
1687         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1688 #endif
1689
1690         a0&= 0x3;
1691         if (a0 != 3) {
1692                 psxRcntWmode(a0, 0);
1693                 psxRcntWtarget(a0, 0);
1694                 psxRcntWcount(a0, 0);
1695         }
1696         pc0 = ra;
1697 }
1698
1699
1700 /* gets ev for use with EventCB */
1701 #define GetEv() \
1702         ev = (a0 >> 24) & 0xf; \
1703         if (ev == 0xf) ev = 0x5; \
1704         ev*= 32; \
1705         ev+= a0&0x1f;
1706
1707 /* gets spec for use with EventCB */
1708 #define GetSpec() \
1709         spec = 0; \
1710         switch (a1) { \
1711                 case 0x0301: spec = 16; break; \
1712                 case 0x0302: spec = 17; break; \
1713                 default: \
1714                         for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \
1715                         break; \
1716         }
1717
1718 void psxBios_DeliverEvent() { // 07
1719         int ev, spec;
1720         int i;
1721
1722         GetEv();
1723         GetSpec();
1724
1725 #ifdef PSXBIOS_LOG
1726         PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x07], ev, spec);
1727 #endif
1728
1729         DeliverEvent(ev, spec);
1730
1731         pc0 = ra;
1732 }
1733
1734 void psxBios_OpenEvent() { // 08
1735         int ev, spec;
1736         int i;
1737
1738         GetEv();
1739         GetSpec();
1740
1741 #ifdef PSXBIOS_LOG
1742         PSXBIOS_LOG("psxBios_%s %x,%x (class:%x, spec:%x, mode:%x, func:%x)\n", biosB0n[0x08], ev, spec, a0, a1, a2, a3);
1743 #endif
1744
1745         EventCB[ev][spec].status = EvStWAIT;
1746         EventCB[ev][spec].mode = a2;
1747         EventCB[ev][spec].fhandler = a3;
1748
1749         v0 = ev | (spec << 8);
1750         pc0 = ra;
1751 }
1752
1753 void psxBios_CloseEvent() { // 09
1754         int ev, spec;
1755
1756         ev   = a0 & 0xff;
1757         spec = (a0 >> 8) & 0xff;
1758
1759 #ifdef PSXBIOS_LOG
1760         PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x09], ev, spec);
1761 #endif
1762
1763         EventCB[ev][spec].status = EvStUNUSED;
1764
1765         v0 = 1; pc0 = ra;
1766 }
1767
1768 void psxBios_WaitEvent() { // 0a
1769         int ev, spec;
1770
1771         ev   = a0 & 0xff;
1772         spec = (a0 >> 8) & 0xff;
1773 #ifdef PSXBIOS_LOG
1774         PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0a], ev, spec);
1775 #endif
1776         if (EventCB[ev][spec].status == EvStUNUSED)
1777         {
1778                 v0 = 0;
1779                 pc0 = ra;
1780                 return;
1781         }
1782
1783         if (EventCB[ev][spec].status == EvStALREADY)
1784         {
1785                 /* Callback events (mode=EvMdINTR) do never set the ready flag (and thus WaitEvent would hang forever). */
1786                 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
1787                 v0 = 1;
1788                 pc0 = ra;
1789                 return;
1790         }
1791
1792         v0 = 0;
1793         pc0 = ra;
1794 }
1795
1796 void psxBios_TestEvent() { // 0b
1797         int ev, spec;
1798
1799         ev   = a0 & 0xff;
1800         spec = (a0 >> 8) & 0xff;
1801
1802         if (EventCB[ev][spec].status == EvStALREADY)
1803         {
1804                 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
1805                 v0 = 1;
1806         }
1807         else
1808         {
1809                 v0 = 0;
1810         }
1811
1812 #ifdef PSXBIOS_LOG
1813         PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0);
1814 #endif
1815
1816         pc0 = ra;
1817 }
1818
1819 void psxBios_EnableEvent() { // 0c
1820         int ev, spec;
1821
1822         ev   = a0 & 0xff;
1823         spec = (a0 >> 8) & 0xff;
1824
1825 #ifdef PSXBIOS_LOG
1826         PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0c], ev, spec);
1827 #endif
1828
1829         EventCB[ev][spec].status = EvStACTIVE;
1830
1831         v0 = 1; pc0 = ra;
1832 }
1833
1834 void psxBios_DisableEvent() { // 0d
1835         int ev, spec;
1836
1837         ev   = a0 & 0xff;
1838         spec = (a0 >> 8) & 0xff;
1839
1840 #ifdef PSXBIOS_LOG
1841         PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0d], ev, spec);
1842 #endif
1843
1844         EventCB[ev][spec].status = EvStWAIT;
1845
1846         v0 = 1; pc0 = ra;
1847 }
1848
1849 /*
1850  *      long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
1851  */
1852
1853 void psxBios_OpenTh() { // 0e
1854         int th;
1855
1856         for (th=1; th<8; th++)
1857         {
1858                 if (ThreadCB[th].status == 0) break;
1859
1860         }
1861         if (th == 8) {
1862                 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
1863                 // When no free TCB is found, return 0xffffffff according to Nocash doc.
1864 #ifdef PSXBIOS_LOG
1865                 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
1866 #endif
1867                 v0 = 0xffffffff;
1868                 pc0 = ra;
1869                 return;
1870         }
1871 #ifdef PSXBIOS_LOG
1872         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
1873 #endif
1874
1875         ThreadCB[th].status = 1;
1876         ThreadCB[th].func    = a0;
1877         ThreadCB[th].reg[29] = a1;
1878         ThreadCB[th].reg[28] = a2;
1879
1880         v0 = th; pc0 = ra;
1881 }
1882
1883 /*
1884  *      int CloseTh(long thread);
1885  */
1886
1887 void psxBios_CloseTh() { // 0f
1888         int th = a0 & 0xff;
1889
1890 #ifdef PSXBIOS_LOG
1891         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
1892 #endif
1893         /* The return value is always 1 (even if the handle was already closed). */
1894         v0 = 1;
1895         if (ThreadCB[th].status != 0) {
1896                 ThreadCB[th].status = 0;
1897         }
1898
1899         pc0 = ra;
1900 }
1901
1902 /*
1903  *      int ChangeTh(long thread);
1904  */
1905
1906 void psxBios_ChangeTh() { // 10
1907         int th = a0 & 0xff;
1908
1909 #ifdef PSXBIOS_LOG
1910 //      PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
1911 #endif
1912         /* The return value is always 1. */
1913         v0 = 1;
1914         if (ThreadCB[th].status == 0 || CurThread == th) {
1915                 pc0 = ra;
1916         } else {
1917                 if (ThreadCB[CurThread].status == 2) {
1918                         ThreadCB[CurThread].status = 1;
1919                         ThreadCB[CurThread].func = ra;
1920                         memcpy(ThreadCB[CurThread].reg, psxRegs.GPR.r, 32*4);
1921                 }
1922
1923                 memcpy(psxRegs.GPR.r, ThreadCB[th].reg, 32*4);
1924                 pc0 = ThreadCB[th].func;
1925                 ThreadCB[th].status = 2;
1926                 CurThread = th;
1927         }
1928 }
1929
1930 void psxBios_InitPAD() { // 0x12
1931 #ifdef PSXBIOS_LOG
1932         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x12]);
1933 #endif
1934
1935         pad_buf1 = (char*)Ra0;
1936         pad_buf1len = a1;
1937         pad_buf2 = (char*)Ra2;
1938         pad_buf2len = a3;
1939
1940         v0 = 1; pc0 = ra;
1941 }
1942
1943 void psxBios_StartPAD() { // 13
1944 #ifdef PSXBIOS_LOG
1945         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
1946 #endif
1947         pad_stopped = 0;
1948         psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1));
1949         psxRegs.CP0.n.Status |= 0x401;
1950         pc0 = ra;
1951 }
1952
1953 void psxBios_StopPAD() { // 14
1954 #ifdef PSXBIOS_LOG
1955         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
1956 #endif
1957         pad_stopped = 1;
1958         pad_buf1 = NULL;
1959         pad_buf2 = NULL;
1960         pc0 = ra;
1961 }
1962
1963 void psxBios_PAD_init() { // 15
1964 #ifdef PSXBIOS_LOG
1965         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
1966 #endif
1967         if (!(a0 == 0x20000000 || a0 == 0x20000001))
1968         {
1969                 v0 = 0;
1970                 pc0 = ra;
1971                 return;
1972         }
1973         psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
1974         pad_buf = (int *)Ra1;
1975         *pad_buf = -1;
1976         psxRegs.CP0.n.Status |= 0x401;
1977         v0 = 2;
1978         pc0 = ra;
1979 }
1980
1981 void psxBios_PAD_dr() { // 16
1982 #ifdef PSXBIOS_LOG
1983         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
1984 #endif
1985
1986         v0 = -1; pc0 = ra;
1987 }
1988
1989 void psxBios_ReturnFromException() { // 17
1990         LoadRegs();
1991
1992         pc0 = psxRegs.CP0.n.EPC;
1993         k0 = interrupt_r26;
1994         if (psxRegs.CP0.n.Cause & 0x80000000) pc0 += 4;
1995
1996         psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
1997                                                   ((psxRegs.CP0.n.Status & 0x3c) >> 2);
1998 }
1999
2000 void psxBios_ResetEntryInt() { // 18
2001 #ifdef PSXBIOS_LOG
2002         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2003 #endif
2004
2005         jmp_int = NULL;
2006         pc0 = ra;
2007 }
2008
2009 void psxBios_HookEntryInt() { // 19
2010 #ifdef PSXBIOS_LOG
2011         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x19]);
2012 #endif
2013
2014         jmp_int = (u32*)Ra0;
2015         pc0 = ra;
2016 }
2017
2018 void psxBios_UnDeliverEvent() { // 0x20
2019         int ev, spec;
2020         int i;
2021
2022         GetEv();
2023         GetSpec();
2024
2025 #ifdef PSXBIOS_LOG
2026         PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec);
2027 #endif
2028
2029         if (EventCB[ev][spec].status == EvStALREADY &&
2030                 EventCB[ev][spec].mode == EvMdNOINTR)
2031                 EventCB[ev][spec].status = EvStACTIVE;
2032
2033         pc0 = ra;
2034 }
2035
2036 char ffile[64], *pfile;
2037 int nfile;
2038
2039 static void buopen(int mcd, char *ptr, char *cfg)
2040 {
2041         int i;
2042         char *mcd_data = ptr;
2043
2044         strcpy(FDesc[1 + mcd].name, Ra0+5);
2045         FDesc[1 + mcd].offset = 0;
2046         FDesc[1 + mcd].mode   = a1;
2047
2048         for (i=1; i<16; i++) {
2049                 const char *fptr = mcd_data + 128 * i;
2050                 if ((*fptr & 0xF0) != 0x50) continue;
2051                 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2052                 FDesc[1 + mcd].mcfile = i;
2053                 SysPrintf("open %s\n", fptr+0xa);
2054                 v0 = 1 + mcd;
2055                 break;
2056         }
2057         if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2058                 for (i=1; i<16; i++) {
2059                         int j, xor, nblk = a1 >> 16;
2060                         char *pptr, *fptr2;
2061                         char *fptr = mcd_data + 128 * i;
2062
2063                         if ((*fptr & 0xF0) != 0xa0) continue;
2064
2065                         FDesc[1 + mcd].mcfile = i;
2066                         fptr[0] = 0x51;
2067                         fptr[4] = 0x00;
2068                         fptr[5] = 0x20 * nblk;
2069                         fptr[6] = 0x00;
2070                         fptr[7] = 0x00;
2071                         strcpy(fptr+0xa, FDesc[1 + mcd].name);
2072                         pptr = fptr2 = fptr;
2073                         for(j=2; j<=nblk; j++) {
2074                                 int k;
2075                                 for(i++; i<16; i++) {
2076                                         fptr2 += 128;
2077
2078                                         memset(fptr2, 0, 128);
2079                                         fptr2[0] = j < nblk ? 0x52 : 0x53;
2080                                         pptr[8] = i - 1;
2081                                         pptr[9] = 0;
2082                                         for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2083                                         pptr[127] = xor;
2084                                         pptr = fptr2;
2085                                         break;
2086                                 }
2087                                 /* shouldn't this return ENOSPC if i == 16? */
2088                         }
2089                         pptr[8] = pptr[9] = 0xff;
2090                         for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2091                         pptr[127] = xor;
2092                         SysPrintf("openC %s %d\n", ptr, nblk);
2093                         v0 = 1 + mcd;
2094                         /* just go ahead and resave them all */
2095                         SaveMcd(cfg, ptr, 128, 128 * 15);
2096                         break;
2097                 }
2098                 /* shouldn't this return ENOSPC if i == 16? */
2099         }
2100 }
2101
2102 /*
2103  *      int open(char *name , int mode);
2104  */
2105
2106 void psxBios_open() { // 0x32
2107         void *pa0 = Ra0;
2108
2109 #ifdef PSXBIOS_LOG
2110         PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2111 #endif
2112
2113         v0 = -1;
2114
2115         if (pa0 != INVALID_PTR) {
2116                 if (!strncmp(pa0, "bu00", 4)) {
2117                         buopen(1, Mcd1Data, Config.Mcd1);
2118                 }
2119
2120                 if (!strncmp(pa0, "bu10", 4)) {
2121                         buopen(2, Mcd2Data, Config.Mcd2);
2122                 }
2123         }
2124
2125         pc0 = ra;
2126 }
2127
2128 /*
2129  *      int lseek(int fd , int offset , int whence);
2130  */
2131
2132 void psxBios_lseek() { // 0x33
2133 #ifdef PSXBIOS_LOG
2134         PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2135 #endif
2136
2137         switch (a2) {
2138                 case 0: // SEEK_SET
2139                         FDesc[a0].offset = a1;
2140                         v0 = a1;
2141 //                      DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2142 //                      DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2143                         break;
2144
2145                 case 1: // SEEK_CUR
2146                         FDesc[a0].offset+= a1;
2147                         v0 = FDesc[a0].offset;
2148                         break;
2149         }
2150
2151         pc0 = ra;
2152 }
2153
2154
2155 /*
2156  *      int read(int fd , void *buf , int nbytes);
2157  */
2158
2159 void psxBios_read() { // 0x34
2160         char *ptr;
2161         void *pa1 = Ra1;
2162
2163 #ifdef PSXBIOS_LOG
2164         PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2165 #endif
2166
2167         v0 = -1;
2168
2169         if (pa1 != INVALID_PTR) {
2170                 switch (a0) {
2171                         case 2: buread(pa1, 1, a2); break;
2172                         case 3: buread(pa1, 2, a2); break;
2173                 }
2174         }
2175
2176         pc0 = ra;
2177 }
2178
2179 /*
2180  *      int write(int fd , void *buf , int nbytes);
2181  */
2182
2183 void psxBios_write() { // 0x35/0x03
2184         char *ptr;
2185         void *pa1 = Ra1;
2186
2187 #ifdef PSXBIOS_LOG
2188         PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2189 #endif
2190
2191         v0 = -1;
2192         if (pa1 == INVALID_PTR) {
2193                 pc0 = ra;
2194                 return;
2195         }
2196
2197         if (a0 == 1) { // stdout
2198                 char *ptr = pa1;
2199
2200                 v0 = a2;
2201                 while (a2 > 0) {
2202                         SysPrintf("%c", *ptr++); a2--;
2203                 }
2204                 pc0 = ra; return;
2205         }
2206
2207         switch (a0) {
2208                 case 2: buwrite(pa1, 1, a2); break;
2209                 case 3: buwrite(pa1, 2, a2); break;
2210         }
2211
2212         pc0 = ra;
2213 }
2214
2215 /*
2216  *      int close(int fd);
2217  */
2218
2219 void psxBios_close() { // 0x36
2220 #ifdef PSXBIOS_LOG
2221         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2222 #endif
2223
2224         v0 = a0;
2225         pc0 = ra;
2226 }
2227
2228 void psxBios_putchar() { // 3d
2229         SysPrintf("%c", (char)a0);
2230         pc0 = ra;
2231 }
2232
2233 void psxBios_puts() { // 3e/3f
2234         SysPrintf("%s", Ra0);
2235         pc0 = ra;
2236 }
2237
2238
2239 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2240  * We want to mimic the PSX's behaviour in this case for bufile. */
2241 static size_t strlen_internal(char* p)
2242 {
2243         size_t size_of_array = 0;
2244         while (*p++) size_of_array++;
2245         return size_of_array;
2246 }
2247
2248 #define bufile(mcd) { \
2249         size_t size_of_name = strlen_internal(dir->name); \
2250         while (nfile < 16) { \
2251                 int match=1; \
2252  \
2253                 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2254                 nfile++; \
2255                 if ((*ptr & 0xF0) != 0x50) continue; \
2256                 /* Bug link files show up as free block. */ \
2257                 if (!ptr[0xa]) continue; \
2258                 ptr+= 0xa; \
2259                 if (pfile[0] == 0) { \
2260                         strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2261                         if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2262                 } else for (i=0; i<20; i++) { \
2263                         if (pfile[i] == ptr[i]) { \
2264                                                                 dir->name[i] = ptr[i]; continue; } \
2265                         if (pfile[i] == '?') { \
2266                                 dir->name[i] = ptr[i]; continue; } \
2267                         if (pfile[i] == '*') { \
2268                                 strcpy(dir->name+i, ptr+i); break; } \
2269                         match = 0; break; \
2270                 } \
2271                 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2272                 if (match == 0) { continue; } \
2273                 dir->size = 8192; \
2274                 v0 = _dir; \
2275                 break; \
2276         } \
2277 }
2278
2279 /*
2280  *      struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2281  */
2282
2283 void psxBios_firstfile() { // 42
2284         struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2285         void *pa0 = Ra0;
2286         u32 _dir = a1;
2287         char *ptr;
2288         int i;
2289
2290 #ifdef PSXBIOS_LOG
2291         PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2292 #endif
2293
2294         v0 = 0;
2295
2296         if (pa0 != INVALID_PTR) {
2297                 strcpy(ffile, pa0);
2298                 pfile = ffile+5;
2299                 nfile = 0;
2300                 if (!strncmp(pa0, "bu00", 4)) {
2301                         // firstfile() calls _card_read() internally, so deliver it's event
2302                         DeliverEvent(0x11, 0x2);
2303                         bufile(1);
2304                 } else if (!strncmp(pa0, "bu10", 4)) {
2305                         // firstfile() calls _card_read() internally, so deliver it's event
2306                         DeliverEvent(0x11, 0x2);
2307                         bufile(2);
2308                 }
2309         }
2310
2311         pc0 = ra;
2312 }
2313
2314 /*
2315  *      struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2316  */
2317
2318 void psxBios_nextfile() { // 43
2319         struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2320         u32 _dir = a0;
2321         char *ptr;
2322         int i;
2323
2324 #ifdef PSXBIOS_LOG
2325         PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2326 #endif
2327
2328         v0 = 0;
2329
2330         if (!strncmp(ffile, "bu00", 4)) {
2331                 bufile(1);
2332         }
2333
2334         if (!strncmp(ffile, "bu10", 4)) {
2335                 bufile(2);
2336         }
2337
2338         pc0 = ra;
2339 }
2340
2341 #define burename(mcd) { \
2342         for (i=1; i<16; i++) { \
2343                 int namelen, j, xor = 0; \
2344                 ptr = Mcd##mcd##Data + 128 * i; \
2345                 if ((*ptr & 0xF0) != 0x50) continue; \
2346                 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2347                 namelen = strlen(Ra1+5); \
2348                 memcpy(ptr+0xa, Ra1+5, namelen); \
2349                 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2350                 for (j=0; j<127; j++) xor^= ptr[j]; \
2351                 ptr[127] = xor; \
2352                 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2353                 v0 = 1; \
2354                 break; \
2355         } \
2356 }
2357
2358 /*
2359  *      int rename(char *old, char *new);
2360  */
2361
2362 void psxBios_rename() { // 44
2363         void *pa0 = Ra0;
2364         void *pa1 = Ra1;
2365         char *ptr;
2366         int i;
2367
2368 #ifdef PSXBIOS_LOG
2369         PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2370 #endif
2371
2372         v0 = 0;
2373
2374         if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2375                 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2376                         burename(1);
2377                 }
2378
2379                 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2380                         burename(2);
2381                 }
2382         }
2383
2384         pc0 = ra;
2385 }
2386
2387
2388 #define budelete(mcd) { \
2389         for (i=1; i<16; i++) { \
2390                 ptr = Mcd##mcd##Data + 128 * i; \
2391                 if ((*ptr & 0xF0) != 0x50) continue; \
2392                 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2393                 *ptr = (*ptr & 0xf) | 0xA0; \
2394                 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2395                 SysPrintf("delete %s\n", ptr+0xa); \
2396                 v0 = 1; \
2397                 break; \
2398         } \
2399 }
2400
2401 /*
2402  *      int delete(char *name);
2403  */
2404
2405 void psxBios_delete() { // 45
2406         void *pa0 = Ra0;
2407         char *ptr;
2408         int i;
2409
2410 #ifdef PSXBIOS_LOG
2411         PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2412 #endif
2413
2414         v0 = 0;
2415
2416         if (pa0 != INVALID_PTR) {
2417                 if (!strncmp(pa0, "bu00", 4)) {
2418                         budelete(1);
2419                 }
2420
2421                 if (!strncmp(pa0, "bu10", 4)) {
2422                         budelete(2);
2423                 }
2424         }
2425
2426         pc0 = ra;
2427 }
2428
2429 void psxBios_InitCARD() { // 4a
2430 #ifdef PSXBIOS_LOG
2431         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2432 #endif
2433
2434         CardState = 0;
2435
2436         pc0 = ra;
2437 }
2438
2439 void psxBios_StartCARD() { // 4b
2440 #ifdef PSXBIOS_LOG
2441         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2442 #endif
2443
2444         if (CardState == 0) CardState = 1;
2445
2446         pc0 = ra;
2447 }
2448
2449 void psxBios_StopCARD() { // 4c
2450 #ifdef PSXBIOS_LOG
2451         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2452 #endif
2453
2454         if (CardState == 1) CardState = 0;
2455
2456         pc0 = ra;
2457 }
2458
2459 void psxBios__card_write() { // 0x4e
2460         void *pa2 = Ra2;
2461         int port;
2462
2463 #ifdef PSXBIOS_LOG
2464         PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2465 #endif
2466         /*
2467         Function also accepts sector 400h (a bug).
2468         But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2469         */
2470         if (!(a1 <= 0x3FF))
2471         {
2472                 /* Invalid sectors */
2473                 v0 = 0; pc0 = ra;
2474                 return;
2475         }
2476         card_active_chan = a0;
2477         port = a0 >> 4;
2478
2479         if (pa2 != INVALID_PTR) {
2480                 if (port == 0) {
2481                         memcpy(Mcd1Data + a1 * 128, pa2, 128);
2482                         SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2483                 } else {
2484                         memcpy(Mcd2Data + a1 * 128, pa2, 128);
2485                         SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2486                 }
2487         }
2488
2489         DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2490 //      DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2491
2492         v0 = 1; pc0 = ra;
2493 }
2494
2495 void psxBios__card_read() { // 0x4f
2496         void *pa2 = Ra2;
2497         int port;
2498
2499 #ifdef PSXBIOS_LOG
2500         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2501 #endif
2502         /*
2503         Function also accepts sector 400h (a bug).
2504         But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2505         */
2506         if (!(a1 <= 0x3FF))
2507         {
2508                 /* Invalid sectors */
2509                 v0 = 0; pc0 = ra;
2510                 return;
2511         }
2512         card_active_chan = a0;
2513         port = a0 >> 4;
2514
2515         if (pa2 != INVALID_PTR) {
2516                 if (port == 0) {
2517                         memcpy(pa2, Mcd1Data + a1 * 128, 128);
2518                 } else {
2519                         memcpy(pa2, Mcd2Data + a1 * 128, 128);
2520                 }
2521         }
2522
2523         DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2524 //      DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2525
2526         v0 = 1; pc0 = ra;
2527 }
2528
2529 void psxBios__new_card() { // 0x50
2530 #ifdef PSXBIOS_LOG
2531         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2532 #endif
2533
2534         pc0 = ra;
2535 }
2536
2537 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2538 void psxBios__get_error(void) // 55
2539 {
2540         v0 = 0;
2541         pc0 = ra;
2542 }
2543
2544 void psxBios_Krom2RawAdd() { // 0x51
2545         int i = 0;
2546
2547         const u32 table_8140[][2] = {
2548                 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2549                 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2550                 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2551                 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2552                 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2553                 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2554                 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2555                 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2556                 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2557                 {0xffff, 0}
2558         };
2559
2560         const u32 table_889f[][2] = {
2561                 {0x889f, 0x3d68},  {0x8900, 0x40ec},  {0x897f, 0x4fb0},  {0x8a00, 0x56f4},
2562                 {0x8a7f, 0x65b8},  {0x8b00, 0x6cfc},  {0x8b7f, 0x7bc0},  {0x8c00, 0x8304},
2563                 {0x8c7f, 0x91c8},  {0x8d00, 0x990c},  {0x8d7f, 0xa7d0},  {0x8e00, 0xaf14},
2564                 {0x8e7f, 0xbdd8},  {0x8f00, 0xc51c},  {0x8f7f, 0xd3e0},  {0x9000, 0xdb24},
2565                 {0x907f, 0xe9e8},  {0x9100, 0xf12c},  {0x917f, 0xfff0},  {0x9200, 0x10734},
2566                 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2567                 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2568                 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2569                 {0xffff, 0}
2570         };
2571
2572         if (a0 >= 0x8140 && a0 <= 0x84be) {
2573                 while (table_8140[i][0] <= a0) i++;
2574                 a0 -= table_8140[i - 1][0];
2575                 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2576         } else if (a0 >= 0x889f && a0 <= 0x9872) {
2577                 while (table_889f[i][0] <= a0) i++;
2578                 a0 -= table_889f[i - 1][0];
2579                 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2580         } else {
2581                 v0 = 0xffffffff;
2582         }
2583
2584         pc0 = ra;
2585 }
2586
2587 void psxBios_GetC0Table() { // 56
2588 #ifdef PSXBIOS_LOG
2589         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2590 #endif
2591
2592         v0 = 0x674; pc0 = ra;
2593 }
2594
2595 void psxBios_GetB0Table() { // 57
2596 #ifdef PSXBIOS_LOG
2597         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2598 #endif
2599
2600         v0 = 0x874; pc0 = ra;
2601 }
2602
2603 void psxBios__card_chan() { // 0x58
2604 #ifdef PSXBIOS_LOG
2605         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2606 #endif
2607
2608         v0 = card_active_chan;
2609         pc0 = ra;
2610 }
2611
2612 void psxBios_ChangeClearPad() { // 5b
2613 #ifdef PSXBIOS_LOG
2614         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2615 #endif
2616
2617         pc0 = ra;
2618 }
2619
2620 void psxBios__card_status() { // 5c
2621 #ifdef PSXBIOS_LOG
2622         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2623 #endif
2624
2625         v0 = card_active_chan;
2626         pc0 = ra;
2627 }
2628
2629 void psxBios__card_wait() { // 5d
2630 #ifdef PSXBIOS_LOG
2631         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2632 #endif
2633
2634         v0 = 1;
2635         pc0 = ra;
2636 }
2637
2638 /* System calls C0 */
2639
2640 /*
2641  * int SysEnqIntRP(int index , long *queue);
2642  */
2643
2644 void psxBios_SysEnqIntRP() { // 02
2645 #ifdef PSXBIOS_LOG
2646         PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x02] ,a0);
2647 #endif
2648
2649         SysIntRP[a0] = a1;
2650
2651         v0 = 0; pc0 = ra;
2652 }
2653
2654 /*
2655  * int SysDeqIntRP(int index , long *queue);
2656  */
2657
2658 void psxBios_SysDeqIntRP() { // 03
2659 #ifdef PSXBIOS_LOG
2660         PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x03], a0);
2661 #endif
2662
2663         SysIntRP[a0] = 0;
2664
2665         v0 = 0; pc0 = ra;
2666 }
2667
2668 void psxBios_ChangeClearRCnt() { // 0a
2669         u32 *ptr;
2670
2671 #ifdef PSXBIOS_LOG
2672         PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2673 #endif
2674
2675         ptr = (u32*)PSXM((a0 << 2) + 0x8600);
2676         v0 = *ptr;
2677         *ptr = a1;
2678
2679 //      psxRegs.CP0.n.Status|= 0x404;
2680         pc0 = ra;
2681 }
2682
2683 void psxBios_dummy() {
2684 #ifdef PSXBIOS_LOG
2685         PSXBIOS_LOG("unk %x call: %x\n", pc0 & 0x1fffff, t1);
2686 #endif
2687         pc0 = ra;
2688 }
2689
2690 void (*biosA0[256])();
2691 void (*biosB0[256])();
2692 void (*biosC0[256])();
2693
2694 #include "sjisfont.h"
2695
2696 void psxBiosInit() {
2697         u32 base, size;
2698         u32 *ptr;
2699         int i;
2700         uLongf len;
2701
2702         for(i = 0; i < 256; i++) {
2703                 biosA0[i] = NULL;
2704                 biosB0[i] = NULL;
2705                 biosC0[i] = NULL;
2706         }
2707         biosA0[0x3e] = psxBios_puts;
2708         biosA0[0x3f] = psxBios_printf;
2709
2710         biosB0[0x3d] = psxBios_putchar;
2711         biosB0[0x3f] = psxBios_puts;
2712
2713         if (!Config.HLE) return;
2714
2715         for(i = 0; i < 256; i++) {
2716                 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
2717                 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
2718                 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
2719         }
2720
2721         biosA0[0x00] = psxBios_open;
2722         biosA0[0x01] = psxBios_lseek;
2723         biosA0[0x02] = psxBios_read;
2724         biosA0[0x03] = psxBios_write;
2725         biosA0[0x04] = psxBios_close;
2726         //biosA0[0x05] = psxBios_ioctl;
2727         //biosA0[0x06] = psxBios_exit;
2728         //biosA0[0x07] = psxBios_sys_a0_07;
2729         biosA0[0x08] = psxBios_getc;
2730         biosA0[0x09] = psxBios_putc;
2731         biosA0[0x0a] = psxBios_todigit;
2732         //biosA0[0x0b] = psxBios_atof;
2733         //biosA0[0x0c] = psxBios_strtoul;
2734         //biosA0[0x0d] = psxBios_strtol;
2735         biosA0[0x0e] = psxBios_abs;
2736         biosA0[0x0f] = psxBios_labs;
2737         biosA0[0x10] = psxBios_atoi;
2738         biosA0[0x11] = psxBios_atol;
2739         //biosA0[0x12] = psxBios_atob;
2740         biosA0[0x13] = psxBios_setjmp;
2741         biosA0[0x14] = psxBios_longjmp;
2742         biosA0[0x15] = psxBios_strcat;
2743         biosA0[0x16] = psxBios_strncat;
2744         biosA0[0x17] = psxBios_strcmp;
2745         biosA0[0x18] = psxBios_strncmp;
2746         biosA0[0x19] = psxBios_strcpy;
2747         biosA0[0x1a] = psxBios_strncpy;
2748         biosA0[0x1b] = psxBios_strlen;
2749         biosA0[0x1c] = psxBios_index;
2750         biosA0[0x1d] = psxBios_rindex;
2751         biosA0[0x1e] = psxBios_strchr;
2752         biosA0[0x1f] = psxBios_strrchr;
2753         biosA0[0x20] = psxBios_strpbrk;
2754         biosA0[0x21] = psxBios_strspn;
2755         biosA0[0x22] = psxBios_strcspn;
2756         biosA0[0x23] = psxBios_strtok;
2757         biosA0[0x24] = psxBios_strstr;
2758         biosA0[0x25] = psxBios_toupper;
2759         biosA0[0x26] = psxBios_tolower;
2760         biosA0[0x27] = psxBios_bcopy;
2761         biosA0[0x28] = psxBios_bzero;
2762         biosA0[0x29] = psxBios_bcmp;
2763         biosA0[0x2a] = psxBios_memcpy;
2764         biosA0[0x2b] = psxBios_memset;
2765         biosA0[0x2c] = psxBios_memmove;
2766         biosA0[0x2d] = psxBios_memcmp;
2767         biosA0[0x2e] = psxBios_memchr;
2768         biosA0[0x2f] = psxBios_rand;
2769         biosA0[0x30] = psxBios_srand;
2770         biosA0[0x31] = psxBios_qsort;
2771         //biosA0[0x32] = psxBios_strtod;
2772         biosA0[0x33] = psxBios_malloc;
2773         biosA0[0x34] = psxBios_free;
2774         //biosA0[0x35] = psxBios_lsearch;
2775         //biosA0[0x36] = psxBios_bsearch;
2776         biosA0[0x37] = psxBios_calloc;
2777         biosA0[0x38] = psxBios_realloc;
2778         biosA0[0x39] = psxBios_InitHeap;
2779         //biosA0[0x3a] = psxBios__exit;
2780         biosA0[0x3b] = psxBios_getchar;
2781         biosA0[0x3c] = psxBios_putchar;
2782         //biosA0[0x3d] = psxBios_gets;
2783         //biosA0[0x40] = psxBios_sys_a0_40;
2784         //biosA0[0x41] = psxBios_LoadTest;
2785         biosA0[0x42] = psxBios_Load;
2786         biosA0[0x43] = psxBios_Exec;
2787         biosA0[0x44] = psxBios_FlushCache;
2788         //biosA0[0x45] = psxBios_InstallInterruptHandler;
2789         biosA0[0x46] = psxBios_GPU_dw;
2790         biosA0[0x47] = psxBios_mem2vram;
2791         biosA0[0x48] = psxBios_SendGPU;
2792         biosA0[0x49] = psxBios_GPU_cw;
2793         biosA0[0x4a] = psxBios_GPU_cwb;
2794         biosA0[0x4b] = psxBios_GPU_SendPackets;
2795         biosA0[0x4c] = psxBios_sys_a0_4c;
2796         biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
2797         //biosA0[0x4e] = psxBios_GPU_sync;
2798         //biosA0[0x4f] = psxBios_sys_a0_4f;
2799         //biosA0[0x50] = psxBios_sys_a0_50;
2800         biosA0[0x51] = psxBios_LoadExec;
2801         //biosA0[0x52] = psxBios_GetSysSp;
2802         //biosA0[0x53] = psxBios_sys_a0_53;
2803         //biosA0[0x54] = psxBios__96_init_a54;
2804         //biosA0[0x55] = psxBios__bu_init_a55;
2805         //biosA0[0x56] = psxBios__96_remove_a56;
2806         //biosA0[0x57] = psxBios_sys_a0_57;
2807         //biosA0[0x58] = psxBios_sys_a0_58;
2808         //biosA0[0x59] = psxBios_sys_a0_59;
2809         //biosA0[0x5a] = psxBios_sys_a0_5a;
2810         //biosA0[0x5b] = psxBios_dev_tty_init;
2811         //biosA0[0x5c] = psxBios_dev_tty_open;
2812         //biosA0[0x5d] = psxBios_sys_a0_5d;
2813         //biosA0[0x5e] = psxBios_dev_tty_ioctl;
2814         //biosA0[0x5f] = psxBios_dev_cd_open;
2815         //biosA0[0x60] = psxBios_dev_cd_read;
2816         //biosA0[0x61] = psxBios_dev_cd_close;
2817         //biosA0[0x62] = psxBios_dev_cd_firstfile;
2818         //biosA0[0x63] = psxBios_dev_cd_nextfile;
2819         //biosA0[0x64] = psxBios_dev_cd_chdir;
2820         //biosA0[0x65] = psxBios_dev_card_open;
2821         //biosA0[0x66] = psxBios_dev_card_read;
2822         //biosA0[0x67] = psxBios_dev_card_write;
2823         //biosA0[0x68] = psxBios_dev_card_close;
2824         //biosA0[0x69] = psxBios_dev_card_firstfile;
2825         //biosA0[0x6a] = psxBios_dev_card_nextfile;
2826         //biosA0[0x6b] = psxBios_dev_card_erase;
2827         //biosA0[0x6c] = psxBios_dev_card_undelete;
2828         //biosA0[0x6d] = psxBios_dev_card_format;
2829         //biosA0[0x6e] = psxBios_dev_card_rename;
2830         //biosA0[0x6f] = psxBios_dev_card_6f;
2831         biosA0[0x70] = psxBios__bu_init;
2832         biosA0[0x71] = psxBios__96_init;
2833         biosA0[0x72] = psxBios__96_remove;
2834         //biosA0[0x73] = psxBios_sys_a0_73;
2835         //biosA0[0x74] = psxBios_sys_a0_74;
2836         //biosA0[0x75] = psxBios_sys_a0_75;
2837         //biosA0[0x76] = psxBios_sys_a0_76;
2838         //biosA0[0x77] = psxBios_sys_a0_77;
2839         //biosA0[0x78] = psxBios__96_CdSeekL;
2840         //biosA0[0x79] = psxBios_sys_a0_79;
2841         //biosA0[0x7a] = psxBios_sys_a0_7a;
2842         //biosA0[0x7b] = psxBios_sys_a0_7b;
2843         //biosA0[0x7c] = psxBios__96_CdGetStatus;
2844         //biosA0[0x7d] = psxBios_sys_a0_7d;
2845         //biosA0[0x7e] = psxBios__96_CdRead;
2846         //biosA0[0x7f] = psxBios_sys_a0_7f;
2847         //biosA0[0x80] = psxBios_sys_a0_80;
2848         //biosA0[0x81] = psxBios_sys_a0_81;
2849         //biosA0[0x82] = psxBios_sys_a0_82;
2850         //biosA0[0x83] = psxBios_sys_a0_83;
2851         //biosA0[0x84] = psxBios_sys_a0_84;
2852         //biosA0[0x85] = psxBios__96_CdStop;
2853         //biosA0[0x86] = psxBios_sys_a0_86;
2854         //biosA0[0x87] = psxBios_sys_a0_87;
2855         //biosA0[0x88] = psxBios_sys_a0_88;
2856         //biosA0[0x89] = psxBios_sys_a0_89;
2857         //biosA0[0x8a] = psxBios_sys_a0_8a;
2858         //biosA0[0x8b] = psxBios_sys_a0_8b;
2859         //biosA0[0x8c] = psxBios_sys_a0_8c;
2860         //biosA0[0x8d] = psxBios_sys_a0_8d;
2861         //biosA0[0x8e] = psxBios_sys_a0_8e;
2862         //biosA0[0x8f] = psxBios_sys_a0_8f;
2863         //biosA0[0x90] = psxBios_sys_a0_90;
2864         //biosA0[0x91] = psxBios_sys_a0_91;
2865         //biosA0[0x92] = psxBios_sys_a0_92;
2866         //biosA0[0x93] = psxBios_sys_a0_93;
2867         //biosA0[0x94] = psxBios_sys_a0_94;
2868         //biosA0[0x95] = psxBios_sys_a0_95;
2869         //biosA0[0x96] = psxBios_AddCDROMDevice;
2870         //biosA0[0x97] = psxBios_AddMemCardDevide;
2871         //biosA0[0x98] = psxBios_DisableKernelIORedirection;
2872         //biosA0[0x99] = psxBios_EnableKernelIORedirection;
2873         //biosA0[0x9a] = psxBios_sys_a0_9a;
2874         //biosA0[0x9b] = psxBios_sys_a0_9b;
2875         //biosA0[0x9c] = psxBios_SetConf;
2876         //biosA0[0x9d] = psxBios_GetConf;
2877         //biosA0[0x9e] = psxBios_sys_a0_9e;
2878         biosA0[0x9f] = psxBios_SetMem;
2879         //biosA0[0xa0] = psxBios__boot;
2880         //biosA0[0xa1] = psxBios_SystemError;
2881         //biosA0[0xa2] = psxBios_EnqueueCdIntr;
2882         //biosA0[0xa3] = psxBios_DequeueCdIntr;
2883         //biosA0[0xa4] = psxBios_sys_a0_a4;
2884         //biosA0[0xa5] = psxBios_ReadSector;
2885         biosA0[0xa6] = psxBios_get_cd_status;
2886         //biosA0[0xa7] = psxBios_bufs_cb_0;
2887         //biosA0[0xa8] = psxBios_bufs_cb_1;
2888         //biosA0[0xa9] = psxBios_bufs_cb_2;
2889         //biosA0[0xaa] = psxBios_bufs_cb_3;
2890         biosA0[0xab] = psxBios__card_info;
2891         biosA0[0xac] = psxBios__card_load;
2892         //biosA0[0axd] = psxBios__card_auto;
2893         //biosA0[0xae] = psxBios_bufs_cd_4;
2894         //biosA0[0xaf] = psxBios_sys_a0_af;
2895         //biosA0[0xb0] = psxBios_sys_a0_b0;
2896         //biosA0[0xb1] = psxBios_sys_a0_b1;
2897         //biosA0[0xb2] = psxBios_do_a_long_jmp
2898         //biosA0[0xb3] = psxBios_sys_a0_b3;
2899         //biosA0[0xb4] = psxBios_sub_function;
2900 //*******************B0 CALLS****************************
2901         //biosB0[0x00] = psxBios_SysMalloc;
2902         //biosB0[0x01] = psxBios_sys_b0_01;
2903         biosB0[0x02] = psxBios_SetRCnt;
2904         biosB0[0x03] = psxBios_GetRCnt;
2905         biosB0[0x04] = psxBios_StartRCnt;
2906         biosB0[0x05] = psxBios_StopRCnt;
2907         biosB0[0x06] = psxBios_ResetRCnt;
2908         biosB0[0x07] = psxBios_DeliverEvent;
2909         biosB0[0x08] = psxBios_OpenEvent;
2910         biosB0[0x09] = psxBios_CloseEvent;
2911         biosB0[0x0a] = psxBios_WaitEvent;
2912         biosB0[0x0b] = psxBios_TestEvent;
2913         biosB0[0x0c] = psxBios_EnableEvent;
2914         biosB0[0x0d] = psxBios_DisableEvent;
2915         biosB0[0x0e] = psxBios_OpenTh;
2916         biosB0[0x0f] = psxBios_CloseTh;
2917         biosB0[0x10] = psxBios_ChangeTh;
2918         //biosB0[0x11] = psxBios_psxBios_b0_11;
2919         biosB0[0x12] = psxBios_InitPAD;
2920         biosB0[0x13] = psxBios_StartPAD;
2921         biosB0[0x14] = psxBios_StopPAD;
2922         biosB0[0x15] = psxBios_PAD_init;
2923         biosB0[0x16] = psxBios_PAD_dr;
2924         biosB0[0x17] = psxBios_ReturnFromException;
2925         biosB0[0x18] = psxBios_ResetEntryInt;
2926         biosB0[0x19] = psxBios_HookEntryInt;
2927         //biosB0[0x1a] = psxBios_sys_b0_1a;
2928         //biosB0[0x1b] = psxBios_sys_b0_1b;
2929         //biosB0[0x1c] = psxBios_sys_b0_1c;
2930         //biosB0[0x1d] = psxBios_sys_b0_1d;
2931         //biosB0[0x1e] = psxBios_sys_b0_1e;
2932         //biosB0[0x1f] = psxBios_sys_b0_1f;
2933         biosB0[0x20] = psxBios_UnDeliverEvent;
2934         //biosB0[0x21] = psxBios_sys_b0_21;
2935         //biosB0[0x22] = psxBios_sys_b0_22;
2936         //biosB0[0x23] = psxBios_sys_b0_23;
2937         //biosB0[0x24] = psxBios_sys_b0_24;
2938         //biosB0[0x25] = psxBios_sys_b0_25;
2939         //biosB0[0x26] = psxBios_sys_b0_26;
2940         //biosB0[0x27] = psxBios_sys_b0_27;
2941         //biosB0[0x28] = psxBios_sys_b0_28;
2942         //biosB0[0x29] = psxBios_sys_b0_29;
2943         //biosB0[0x2a] = psxBios_sys_b0_2a;
2944         //biosB0[0x2b] = psxBios_sys_b0_2b;
2945         //biosB0[0x2c] = psxBios_sys_b0_2c;
2946         //biosB0[0x2d] = psxBios_sys_b0_2d;
2947         //biosB0[0x2e] = psxBios_sys_b0_2e;
2948         //biosB0[0x2f] = psxBios_sys_b0_2f;
2949         //biosB0[0x30] = psxBios_sys_b0_30;
2950         //biosB0[0x31] = psxBios_sys_b0_31;
2951         biosB0[0x32] = psxBios_open;
2952         biosB0[0x33] = psxBios_lseek;
2953         biosB0[0x34] = psxBios_read;
2954         biosB0[0x35] = psxBios_write;
2955         biosB0[0x36] = psxBios_close;
2956         //biosB0[0x37] = psxBios_ioctl;
2957         //biosB0[0x38] = psxBios_exit;
2958         //biosB0[0x39] = psxBios_sys_b0_39;
2959         //biosB0[0x3a] = psxBios_getc;
2960         //biosB0[0x3b] = psxBios_putc;
2961         biosB0[0x3c] = psxBios_getchar;
2962         //biosB0[0x3e] = psxBios_gets;
2963         //biosB0[0x40] = psxBios_cd;
2964         biosB0[0x41] = psxBios_format;
2965         biosB0[0x42] = psxBios_firstfile;
2966         biosB0[0x43] = psxBios_nextfile;
2967         biosB0[0x44] = psxBios_rename;
2968         biosB0[0x45] = psxBios_delete;
2969         //biosB0[0x46] = psxBios_undelete;
2970         //biosB0[0x47] = psxBios_AddDevice;
2971         //biosB0[0x48] = psxBios_RemoteDevice;
2972         //biosB0[0x49] = psxBios_PrintInstalledDevices;
2973         biosB0[0x4a] = psxBios_InitCARD;
2974         biosB0[0x4b] = psxBios_StartCARD;
2975         biosB0[0x4c] = psxBios_StopCARD;
2976         //biosB0[0x4d] = psxBios_sys_b0_4d;
2977         biosB0[0x4e] = psxBios__card_write;
2978         biosB0[0x4f] = psxBios__card_read;
2979         biosB0[0x50] = psxBios__new_card;
2980         biosB0[0x51] = psxBios_Krom2RawAdd;
2981         //biosB0[0x52] = psxBios_sys_b0_52;
2982         //biosB0[0x53] = psxBios_sys_b0_53;
2983         //biosB0[0x54] = psxBios__get_errno;
2984         biosB0[0x55] = psxBios__get_error;
2985         biosB0[0x56] = psxBios_GetC0Table;
2986         biosB0[0x57] = psxBios_GetB0Table;
2987         biosB0[0x58] = psxBios__card_chan;
2988         //biosB0[0x59] = psxBios_sys_b0_59;
2989         //biosB0[0x5a] = psxBios_sys_b0_5a;
2990         biosB0[0x5b] = psxBios_ChangeClearPad;
2991         biosB0[0x5c] = psxBios__card_status;
2992         biosB0[0x5d] = psxBios__card_wait;
2993 //*******************C0 CALLS****************************
2994         //biosC0[0x00] = psxBios_InitRCnt;
2995         //biosC0[0x01] = psxBios_InitException;
2996         biosC0[0x02] = psxBios_SysEnqIntRP;
2997         biosC0[0x03] = psxBios_SysDeqIntRP;
2998         //biosC0[0x04] = psxBios_get_free_EvCB_slot;
2999         //biosC0[0x05] = psxBios_get_free_TCB_slot;
3000         //biosC0[0x06] = psxBios_ExceptionHandler;
3001         //biosC0[0x07] = psxBios_InstallExeptionHandler;
3002         //biosC0[0x08] = psxBios_SysInitMemory;
3003         //biosC0[0x09] = psxBios_SysInitKMem;
3004         biosC0[0x0a] = psxBios_ChangeClearRCnt;
3005         //biosC0[0x0b] = psxBios_SystemError;
3006         //biosC0[0x0c] = psxBios_InitDefInt;
3007         //biosC0[0x0d] = psxBios_sys_c0_0d;
3008         //biosC0[0x0e] = psxBios_sys_c0_0e;
3009         //biosC0[0x0f] = psxBios_sys_c0_0f;
3010         //biosC0[0x10] = psxBios_sys_c0_10;
3011         //biosC0[0x11] = psxBios_sys_c0_11;
3012         //biosC0[0x12] = psxBios_InstallDevices;
3013         //biosC0[0x13] = psxBios_FlushStfInOutPut;
3014         //biosC0[0x14] = psxBios_sys_c0_14;
3015         //biosC0[0x15] = psxBios__cdevinput;
3016         //biosC0[0x16] = psxBios__cdevscan;
3017         //biosC0[0x17] = psxBios__circgetc;
3018         //biosC0[0x18] = psxBios__circputc;
3019         //biosC0[0x19] = psxBios_ioabort;
3020         //biosC0[0x1a] = psxBios_sys_c0_1a
3021         //biosC0[0x1b] = psxBios_KernelRedirect;
3022         //biosC0[0x1c] = psxBios_PatchAOTable;
3023 //************** THE END ***************************************
3024 /**/
3025         base = 0x1000;
3026         size = sizeof(EvCB) * 32;
3027         EventCB = (void *)&psxR[base]; base += size * 6;
3028         memset(EventCB, 0, size * 6);
3029         HwEV = EventCB;
3030         EvEV = EventCB + 32;
3031         RcEV = EventCB + 32 * 2;
3032         UeEV = EventCB + 32 * 3;
3033         SwEV = EventCB + 32 * 4;
3034         ThEV = EventCB + 32 * 5;
3035
3036         ptr = (u32 *)&psxM[0x0874]; // b0 table
3037         ptr[0] = SWAPu32(0x4c54 - 0x884);
3038
3039         ptr = (u32 *)&psxM[0x0674]; // c0 table
3040         ptr[6] = SWAPu32(0xc80);
3041
3042         memset(SysIntRP, 0, sizeof(SysIntRP));
3043         memset(ThreadCB, 0, sizeof(ThreadCB));
3044         ThreadCB[0].status = 2; // main thread
3045
3046         pad_stopped = 1;
3047         jmp_int = NULL;
3048         pad_buf = NULL;
3049         pad_buf1 = NULL;
3050         pad_buf2 = NULL;
3051         pad_buf1len = pad_buf2len = 0;
3052         heap_addr = NULL;
3053         heap_end = NULL;
3054         heap_size = 0;
3055         CardState = -1;
3056         CurThread = 0;
3057         memset(FDesc, 0, sizeof(FDesc));
3058         card_active_chan = 0;
3059
3060         psxMu32ref(0x0150) = SWAPu32(0x160);
3061         psxMu32ref(0x0154) = SWAPu32(0x320);
3062         psxMu32ref(0x0160) = SWAPu32(0x248);
3063         strcpy((char *)&psxM[0x248], "bu");
3064 /*      psxMu32ref(0x0ca8) = SWAPu32(0x1f410004);
3065         psxMu32ref(0x0cf0) = SWAPu32(0x3c020000);
3066         psxMu32ref(0x0cf4) = SWAPu32(0x2442641c);
3067         psxMu32ref(0x09e0) = SWAPu32(0x43d0);
3068         psxMu32ref(0x4d98) = SWAPu32(0x946f000a);
3069 */
3070         // opcode HLE
3071         psxRu32ref(0x0000) = SWAPu32((0x3b << 26) | 4);
3072         /* Whatever this does, it actually breaks CTR, even without the uninitiliazed memory patch.
3073         Normally games shouldn't read from address 0 yet they do. See explanation below in details. */
3074         //psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0);
3075         psxMu32ref(0x00a0) = SWAPu32((0x3b << 26) | 1);
3076         psxMu32ref(0x00b0) = SWAPu32((0x3b << 26) | 2);
3077         psxMu32ref(0x00c0) = SWAPu32((0x3b << 26) | 3);
3078         psxMu32ref(0x4c54) = SWAPu32((0x3b << 26) | 0);
3079         psxMu32ref(0x8000) = SWAPu32((0x3b << 26) | 5);
3080         psxMu32ref(0x07a0) = SWAPu32((0x3b << 26) | 0);
3081         psxMu32ref(0x0884) = SWAPu32((0x3b << 26) | 0);
3082         psxMu32ref(0x0894) = SWAPu32((0x3b << 26) | 0);
3083
3084         // initial stack pointer for BIOS interrupt
3085         psxMu32ref(0x6c80) = SWAPu32(0x000085c8);
3086
3087         // initial RNG seed
3088         psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3089
3090         // fonts
3091         len = 0x80000 - 0x66000;
3092         uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3093         len = 0x80000 - 0x69d68;
3094         uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3095
3096         // memory size 2 MB
3097         psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3098
3099         hleSoftCall = FALSE;
3100
3101         /*      Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3102                 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3103                 Here are some examples of games not working with this fix in place :
3104                 R-type won't get past the Irem logo if not implemented.
3105                 Crash Team Racing will softlock after the Sony logo.
3106         */
3107
3108         psxMu32ref(0x0000) = SWAPu32(0x00000003);
3109         /*
3110         But overwritten by 00000003h after soon.
3111         psxMu32ref(0x0000) = SWAPu32(0x00001A3C);
3112         */
3113         psxMu32ref(0x0004) = SWAPu32(0x800C5A27);
3114         psxMu32ref(0x0008) = SWAPu32(0x08000403);
3115         psxMu32ref(0x000C) = SWAPu32(0x00000000);
3116 }
3117
3118 void psxBiosShutdown() {
3119 }
3120
3121 #define psxBios_PADpoll(pad) { \
3122         PAD##pad##_startPoll(pad); \
3123         pad_buf##pad[0] = 0; \
3124         pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3125         if (!(pad_buf##pad[1] & 0x0f)) { \
3126                 bufcount = 32; \
3127         } else { \
3128                 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3129         } \
3130         PAD##pad##_poll(0); \
3131         i = 2; \
3132         while (bufcount--) { \
3133                 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3134         } \
3135 }
3136
3137 void biosInterrupt() {
3138         int i, bufcount;
3139
3140 //      if (psxHu32(0x1070) & 0x1) { // Vsync
3141                 if (pad_buf != NULL) {
3142                         u32 *buf = (u32*)pad_buf;
3143
3144                         if (!Config.UseNet) {
3145                                 PAD1_startPoll(1);
3146                                 if (PAD1_poll(0x42) == 0x23) {
3147                                         PAD1_poll(0);
3148                                         *buf = PAD1_poll(0) << 8;
3149                                         *buf |= PAD1_poll(0);
3150                                         PAD1_poll(0);
3151                                         *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3152                                         *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3153                                 } else {
3154                                         PAD1_poll(0);
3155                                         *buf = PAD1_poll(0) << 8;
3156                                         *buf|= PAD1_poll(0);
3157                                 }
3158
3159                                 PAD2_startPoll(2);
3160                                 if (PAD2_poll(0x42) == 0x23) {
3161                                         PAD2_poll(0);
3162                                         *buf |= PAD2_poll(0) << 24;
3163                                         *buf |= PAD2_poll(0) << 16;
3164                                         PAD2_poll(0);
3165                                         *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3166                                         *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3167                                 } else {
3168                                         PAD2_poll(0);
3169                                         *buf |= PAD2_poll(0) << 24;
3170                                         *buf |= PAD2_poll(0) << 16;
3171                                 }
3172                         } else {
3173                                 u16 data;
3174
3175                                 PAD1_startPoll(1);
3176                                 PAD1_poll(0x42);
3177                                 PAD1_poll(0);
3178                                 data = PAD1_poll(0) << 8;
3179                                 data |= PAD1_poll(0);
3180
3181                                 if (NET_sendPadData(&data, 2) == -1)
3182                                         netError();
3183
3184                                 if (NET_recvPadData(&((u16*)buf)[0], 1) == -1)
3185                                         netError();
3186                                 if (NET_recvPadData(&((u16*)buf)[1], 2) == -1)
3187                                         netError();
3188                         }
3189                 }
3190                 if (Config.UseNet && pad_buf1 != NULL && pad_buf2 != NULL) {
3191                         psxBios_PADpoll(1);
3192
3193                         if (NET_sendPadData(pad_buf1, i) == -1)
3194                                 netError();
3195
3196                         if (NET_recvPadData(pad_buf1, 1) == -1)
3197                                 netError();
3198                         if (NET_recvPadData(pad_buf2, 2) == -1)
3199                                 netError();
3200                 } else {
3201                         if (!pad_stopped)  {
3202                                 if (pad_buf1) {
3203                                         psxBios_PADpoll(1);
3204                                 }
3205
3206                                 if (pad_buf2) {
3207                                         psxBios_PADpoll(2);
3208                                 }
3209                         }
3210                 }
3211
3212         if (psxHu32(0x1070) & 0x1) { // Vsync
3213                 if (RcEV[3][1].status == EvStACTIVE) {
3214                         softCall(RcEV[3][1].fhandler);
3215 //                      hwWrite32(0x1f801070, ~(1));
3216                 }
3217         }
3218
3219         if (psxHu32(0x1070) & 0x70) { // Rcnt 0,1,2
3220                 int i;
3221
3222                 for (i = 0; i < 3; i++) {
3223                         if (psxHu32(0x1070) & (1 << (i + 4))) {
3224                                 if (RcEV[i][1].status == EvStACTIVE) {
3225                                         softCall(RcEV[i][1].fhandler);
3226                                 }
3227                                 psxHwWrite32(0x1f801070, ~(1 << (i + 4)));
3228                         }
3229                 }
3230         }
3231 }
3232
3233 void psxBiosException() {
3234         int i;
3235
3236         switch (psxRegs.CP0.n.Cause & 0x3c) {
3237                 case 0x00: // Interrupt
3238                         interrupt_r26=psxRegs.CP0.n.EPC;
3239 #ifdef PSXCPU_LOG
3240 //                      PSXCPU_LOG("interrupt\n");
3241 #endif
3242                         SaveRegs();
3243
3244                         sp = psxMu32(0x6c80); // create new stack for interrupt handlers
3245
3246                         biosInterrupt();
3247
3248                         for (i = 0; i < 8; i++) {
3249                                 if (SysIntRP[i]) {
3250                                         u32 *queue = (u32 *)PSXM(SysIntRP[i]);
3251
3252                                         s0 = queue[2];
3253                                         softCall(queue[1]);
3254                                 }
3255                         }
3256
3257                         if (jmp_int != NULL) {
3258                                 int i;
3259
3260                                 psxHwWrite32(0x1f801070, 0xffffffff);
3261
3262                                 ra = jmp_int[0];
3263                                 sp = jmp_int[1];
3264                                 fp = jmp_int[2];
3265                                 for (i = 0; i < 8; i++) // s0-s7
3266                                          psxRegs.GPR.r[16 + i] = jmp_int[3 + i];
3267                                 gp = jmp_int[11];
3268
3269                                 v0 = 1;
3270                                 pc0 = ra;
3271                                 return;
3272                         }
3273                         psxHwWrite16(0x1f801070, 0);
3274                         break;
3275
3276                 case 0x20: // Syscall
3277 #ifdef PSXCPU_LOG
3278                         PSXCPU_LOG("syscall exp %x\n", a0);
3279 #endif
3280                         switch (a0) {
3281                                 case 1: // EnterCritical - disable irq's
3282                                         /* Fixes Medievil 2 not loading up new game, Digimon World not booting up and possibly others */
3283                                         v0 = (psxRegs.CP0.n.Status & 0x404) == 0x404;
3284                                         psxRegs.CP0.n.Status &= ~0x404;
3285                                         break;
3286
3287                                 case 2: // ExitCritical - enable irq's
3288                                         psxRegs.CP0.n.Status |= 0x404;
3289                                         break;
3290                                 /* Normally this should cover SYS(00h, SYS(04h but they don't do anything relevant so... */
3291                                 default:
3292                                         break;
3293                         }
3294                         pc0 = psxRegs.CP0.n.EPC + 4;
3295
3296                         psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3297                                                                   ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3298                         return;
3299
3300                 default:
3301 #ifdef PSXCPU_LOG
3302                         PSXCPU_LOG("unknown bios exception!\n");
3303 #endif
3304                         break;
3305         }
3306
3307         pc0 = psxRegs.CP0.n.EPC;
3308         if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;
3309
3310         psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3311                                                   ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3312 }
3313
3314 #define bfreeze(ptr, size) { \
3315         if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3316         if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3317         base += size; \
3318 }
3319
3320 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3321 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3322
3323 #define bfreezepsxMptr(ptr, type) { \
3324         if (Mode == 1) { \
3325                 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3326                 else psxRu32ref(base) = 0; \
3327         } else { \
3328                 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3329                 else (ptr) = NULL; \
3330         } \
3331         base += sizeof(u32); \
3332 }
3333
3334 void psxBiosFreeze(int Mode) {
3335         u32 base = 0x40000;
3336
3337         bfreezepsxMptr(jmp_int, u32);
3338         bfreezepsxMptr(pad_buf, int);
3339         bfreezepsxMptr(pad_buf1, char);
3340         bfreezepsxMptr(pad_buf2, char);
3341         bfreezepsxMptr(heap_addr, u32);
3342         bfreezel(&pad_buf1len);
3343         bfreezel(&pad_buf2len);
3344         bfreezes(regs);
3345         bfreezes(SysIntRP);
3346         bfreezel(&CardState);
3347         bfreezes(ThreadCB);
3348         bfreezel(&CurThread);
3349         bfreezes(FDesc);
3350         bfreezel(&card_active_chan);
3351         bfreezel(&pad_stopped);
3352         bfreezel(&heap_size);
3353 }