psxinterpreter: yet more exceptions, new config option
[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(EXEC_CALLER_HLE);
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(EXEC_CALLER_HLE);
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 static void psxBios_printf_psxout() { // 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 != INVALID_PTR)
1321                 memcpy(psp, save, 4 * 4);
1322
1323         SysPrintf("%s", tmp);
1324 }
1325
1326 void psxBios_printf() { // 0x3f
1327         psxBios_printf_psxout();
1328         pc0 = ra;
1329 }
1330
1331 void psxBios_format() { // 0x41
1332         if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1333         {
1334                 CreateMcd(Config.Mcd1);
1335                 LoadMcd(1, Config.Mcd1);
1336                 v0 = 1;
1337         }
1338         else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1339         {
1340                 CreateMcd(Config.Mcd2);
1341                 LoadMcd(2, Config.Mcd2);
1342                 v0 = 1;
1343         }
1344         else
1345         {
1346                 v0 = 0;
1347         }
1348         pc0 = ra;
1349 }
1350
1351 /*
1352  *      long Load(char *name, struct EXEC *header);
1353  */
1354
1355 void psxBios_Load() { // 0x42
1356         EXE_HEADER eheader;
1357         void *pa1;
1358
1359 #ifdef PSXBIOS_LOG
1360         PSXBIOS_LOG("psxBios_%s: %s, %x\n", biosA0n[0x42], Ra0, a1);
1361 #endif
1362
1363         pa1 = Ra1;
1364         if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
1365                 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1366                 v0 = 1;
1367         } else v0 = 0;
1368
1369         pc0 = ra;
1370 }
1371
1372 /*
1373  *      int Exec(struct EXEC *header , int argc , char **argv);
1374  */
1375
1376 void psxBios_Exec() { // 43
1377         EXEC *header = (EXEC*)Ra0;
1378         u32 tmp;
1379
1380 #ifdef PSXBIOS_LOG
1381         PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1382 #endif
1383
1384         header->_sp = sp;
1385         header->_fp = fp;
1386         header->_sp = sp;
1387         header->_gp = gp;
1388         header->ret = ra;
1389         header->base = s0;
1390
1391         if (header->S_addr != 0) {
1392                 tmp = header->S_addr + header->s_size;
1393                 sp = tmp;
1394                 fp = sp;
1395         }
1396
1397         gp = header->gp0;
1398
1399         s0 = a0;
1400
1401         a0 = a1;
1402         a1 = a2;
1403
1404         ra = 0x8000;
1405         pc0 = header->_pc0;
1406 }
1407
1408 void psxBios_FlushCache() { // 44
1409 #ifdef PSXBIOS_LOG
1410         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1411 #endif
1412         psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1413         psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1414         pc0 = ra;
1415 }
1416
1417 void psxBios_GPU_dw() { // 0x46
1418         int size;
1419         u32 *ptr;
1420
1421 #ifdef PSXBIOS_LOG
1422         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1423 #endif
1424
1425         GPU_writeData(0xa0000000);
1426         GPU_writeData((a1<<0x10)|(a0&0xffff));
1427         GPU_writeData((a3<<0x10)|(a2&0xffff));
1428         size = (a2*a3)/2;
1429         ptr = (u32*)PSXM(Rsp[4]);  //that is correct?
1430         while(size--)
1431         {
1432                 GPU_writeData(SWAPu32(*ptr++));
1433         } 
1434
1435         pc0 = ra;
1436 }
1437
1438 void psxBios_mem2vram() { // 0x47
1439         int size;
1440         gpuSyncPluginSR();
1441         GPU_writeData(0xa0000000);
1442         GPU_writeData((a1<<0x10)|(a0&0xffff));
1443         GPU_writeData((a3<<0x10)|(a2&0xffff));
1444         size = ((((a2 * a3) / 2) >> 4) << 16);
1445         GPU_writeStatus(0x04000002);
1446         psxHwWrite32(0x1f8010f4,0);
1447         psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1448         psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1449         psxHwWrite32(0x1f8010a4, size | 0x10);
1450         psxHwWrite32(0x1f8010a8,0x01000201);
1451
1452         pc0 = ra;
1453 }
1454
1455 void psxBios_SendGPU() { // 0x48
1456         GPU_writeStatus(a0);
1457         gpuSyncPluginSR();
1458         pc0 = ra;
1459 }
1460
1461 void psxBios_GPU_cw() { // 0x49
1462         gpuSyncPluginSR();
1463         GPU_writeData(a0);
1464         v0 = HW_GPU_STATUS;
1465         pc0 = ra;
1466 }
1467
1468 void psxBios_GPU_cwb() { // 0x4a
1469         u32 *ptr = (u32*)Ra0;
1470         int size = a1;
1471         gpuSyncPluginSR();
1472         while(size--)
1473         {
1474                 GPU_writeData(SWAPu32(*ptr++));
1475         }
1476
1477         pc0 = ra;
1478 }
1479    
1480 void psxBios_GPU_SendPackets() { //4b:  
1481         gpuSyncPluginSR();
1482         GPU_writeStatus(0x04000002);
1483         psxHwWrite32(0x1f8010f4,0);
1484         psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1485         psxHwWrite32(0x1f8010a0,a0);
1486         psxHwWrite32(0x1f8010a4,0);
1487         psxHwWrite32(0x1f8010a8,0x010000401);
1488         pc0 = ra;
1489 }
1490
1491 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1492         psxHwWrite32(0x1f8010a8,0x00000401);
1493         GPU_writeData(0x0400000);
1494         GPU_writeData(0x0200000);
1495         GPU_writeData(0x0100000);
1496         v0 = 0x1f801814;
1497         pc0 = ra;
1498 }
1499
1500 void psxBios_GPU_GetGPUStatus() { // 0x4d
1501         v0 = GPU_readStatus();
1502         pc0 = ra;
1503 }
1504
1505 #undef s_addr
1506
1507 void psxBios_LoadExec() { // 51
1508         EXEC *header = (EXEC*)PSXM(0xf000);
1509         u32 s_addr, s_size;
1510
1511 #ifdef PSXBIOS_LOG
1512         PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1513 #endif
1514         s_addr = a1; s_size = a2;
1515
1516         a1 = 0xf000;
1517         psxBios_Load();
1518
1519         header->S_addr = s_addr;
1520         header->s_size = s_size;
1521
1522         a0 = 0xf000; a1 = 0; a2 = 0;
1523         psxBios_Exec();
1524 }
1525
1526 void psxBios__bu_init() { // 70
1527 #ifdef PSXBIOS_LOG
1528         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1529 #endif
1530
1531         DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1532         DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1533
1534         pc0 = ra;
1535 }
1536
1537 void psxBios__96_init() { // 71
1538 #ifdef PSXBIOS_LOG
1539         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1540 #endif
1541
1542         pc0 = ra;
1543 }
1544
1545 void psxBios__96_remove() { // 72
1546 #ifdef PSXBIOS_LOG
1547         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1548 #endif
1549
1550         pc0 = ra;
1551 }
1552
1553 void psxBios_SetMem() { // 9f
1554         u32 new = psxHu32(0x1060);
1555
1556 #ifdef PSXBIOS_LOG
1557         PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1558 #endif
1559
1560         switch(a0) {
1561                 case 2:
1562                         psxHu32ref(0x1060) = SWAP32(new);
1563                         psxMu32ref(0x060) = a0;
1564                         SysPrintf("Change effective memory : %d MBytes\n",a0);
1565                         break;
1566
1567                 case 8:
1568                         psxHu32ref(0x1060) = SWAP32(new | 0x300);
1569                         psxMu32ref(0x060) = a0;
1570                         SysPrintf("Change effective memory : %d MBytes\n",a0);
1571
1572                 default:
1573                         SysPrintf("Effective memory must be 2/8 MBytes\n");
1574                 break;
1575         }
1576
1577         pc0 = ra;
1578 }
1579
1580 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1581 void psxBios_get_cd_status(void) //a6
1582 {
1583         v0 = 1;
1584         pc0 = ra;
1585 }
1586
1587 void psxBios__card_info() { // ab
1588 #ifdef PSXBIOS_LOG
1589         PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1590 #endif
1591         u32 ret, port;
1592         card_active_chan = a0;
1593         port = card_active_chan >> 4;
1594
1595         switch (port) {
1596         case 0x0:
1597         case 0x1:
1598                 ret = 0x2;
1599                 if (McdDisable[port & 1])
1600                         ret = 0x8;
1601                 break;
1602         default:
1603 #ifdef PSXBIOS_LOG
1604                 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
1605 #endif
1606                 ret = 0x11;
1607                 break;
1608         }
1609
1610         if (McdDisable[0] && McdDisable[1])
1611                 ret = 0x8;
1612
1613         DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1614 //      DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1615         DeliverEvent(0x81, ret); // 0xf4000001, 0x0004
1616         v0 = 1; pc0 = ra;
1617 }
1618
1619 void psxBios__card_load() { // ac
1620 #ifdef PSXBIOS_LOG
1621         PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1622 #endif
1623
1624         card_active_chan = a0;
1625
1626 //      DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1627         DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1628
1629         v0 = 1; pc0 = ra;
1630 }
1631
1632 /* System calls B0 */
1633
1634 void psxBios_SetRCnt() { // 02
1635 #ifdef PSXBIOS_LOG
1636         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1637 #endif
1638
1639         a0&= 0x3;
1640         if (a0 != 3) {
1641                 u32 mode=0;
1642
1643                 psxRcntWtarget(a0, a1);
1644                 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1645                 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1646                 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1647                 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1648                 else         { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1649
1650                 psxRcntWmode(a0, mode);
1651         }
1652         pc0 = ra;
1653 }
1654
1655 void psxBios_GetRCnt() { // 03
1656 #ifdef PSXBIOS_LOG
1657         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1658 #endif
1659
1660         a0&= 0x3;
1661         if (a0 != 3) v0 = psxRcntRcount(a0);
1662         else v0 = 0;
1663         pc0 = ra;
1664 }
1665
1666 void psxBios_StartRCnt() { // 04
1667 #ifdef PSXBIOS_LOG
1668         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1669 #endif
1670
1671         a0&= 0x3;
1672         if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1673         else psxHu32ref(0x1074)|= SWAPu32(0x1);
1674         v0 = 1; pc0 = ra;
1675 }
1676
1677 void psxBios_StopRCnt() { // 05
1678 #ifdef PSXBIOS_LOG
1679         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1680 #endif
1681
1682         a0&= 0x3;
1683         if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1684         else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1685         pc0 = ra;
1686 }
1687
1688 void psxBios_ResetRCnt() { // 06
1689 #ifdef PSXBIOS_LOG
1690         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1691 #endif
1692
1693         a0&= 0x3;
1694         if (a0 != 3) {
1695                 psxRcntWmode(a0, 0);
1696                 psxRcntWtarget(a0, 0);
1697                 psxRcntWcount(a0, 0);
1698         }
1699         pc0 = ra;
1700 }
1701
1702
1703 /* gets ev for use with EventCB */
1704 #define GetEv() \
1705         ev = (a0 >> 24) & 0xf; \
1706         if (ev == 0xf) ev = 0x5; \
1707         ev*= 32; \
1708         ev+= a0&0x1f;
1709
1710 /* gets spec for use with EventCB */
1711 #define GetSpec() \
1712         spec = 0; \
1713         switch (a1) { \
1714                 case 0x0301: spec = 16; break; \
1715                 case 0x0302: spec = 17; break; \
1716                 default: \
1717                         for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \
1718                         break; \
1719         }
1720
1721 void psxBios_DeliverEvent() { // 07
1722         int ev, spec;
1723         int i;
1724
1725         GetEv();
1726         GetSpec();
1727
1728 #ifdef PSXBIOS_LOG
1729         PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x07], ev, spec);
1730 #endif
1731
1732         DeliverEvent(ev, spec);
1733
1734         pc0 = ra;
1735 }
1736
1737 void psxBios_OpenEvent() { // 08
1738         int ev, spec;
1739         int i;
1740
1741         GetEv();
1742         GetSpec();
1743
1744 #ifdef PSXBIOS_LOG
1745         PSXBIOS_LOG("psxBios_%s %x,%x (class:%x, spec:%x, mode:%x, func:%x)\n", biosB0n[0x08], ev, spec, a0, a1, a2, a3);
1746 #endif
1747
1748         EventCB[ev][spec].status = EvStWAIT;
1749         EventCB[ev][spec].mode = a2;
1750         EventCB[ev][spec].fhandler = a3;
1751
1752         v0 = ev | (spec << 8);
1753         pc0 = ra;
1754 }
1755
1756 void psxBios_CloseEvent() { // 09
1757         int ev, spec;
1758
1759         ev   = a0 & 0xff;
1760         spec = (a0 >> 8) & 0xff;
1761
1762 #ifdef PSXBIOS_LOG
1763         PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x09], ev, spec);
1764 #endif
1765
1766         EventCB[ev][spec].status = EvStUNUSED;
1767
1768         v0 = 1; pc0 = ra;
1769 }
1770
1771 void psxBios_WaitEvent() { // 0a
1772         int ev, spec;
1773
1774         ev   = a0 & 0xff;
1775         spec = (a0 >> 8) & 0xff;
1776 #ifdef PSXBIOS_LOG
1777         PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0a], ev, spec);
1778 #endif
1779         if (EventCB[ev][spec].status == EvStUNUSED)
1780         {
1781                 v0 = 0;
1782                 pc0 = ra;
1783                 return;
1784         }
1785
1786         if (EventCB[ev][spec].status == EvStALREADY)
1787         {
1788                 /* Callback events (mode=EvMdINTR) do never set the ready flag (and thus WaitEvent would hang forever). */
1789                 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
1790                 v0 = 1;
1791                 pc0 = ra;
1792                 return;
1793         }
1794
1795         v0 = 0;
1796         pc0 = ra;
1797 }
1798
1799 void psxBios_TestEvent() { // 0b
1800         int ev, spec;
1801
1802         ev   = a0 & 0xff;
1803         spec = (a0 >> 8) & 0xff;
1804
1805         if (EventCB[ev][spec].status == EvStALREADY)
1806         {
1807                 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
1808                 v0 = 1;
1809         }
1810         else
1811         {
1812                 v0 = 0;
1813         }
1814
1815 #ifdef PSXBIOS_LOG
1816         PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0);
1817 #endif
1818
1819         pc0 = ra;
1820 }
1821
1822 void psxBios_EnableEvent() { // 0c
1823         int ev, spec;
1824
1825         ev   = a0 & 0xff;
1826         spec = (a0 >> 8) & 0xff;
1827
1828 #ifdef PSXBIOS_LOG
1829         PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0c], ev, spec);
1830 #endif
1831
1832         EventCB[ev][spec].status = EvStACTIVE;
1833
1834         v0 = 1; pc0 = ra;
1835 }
1836
1837 void psxBios_DisableEvent() { // 0d
1838         int ev, spec;
1839
1840         ev   = a0 & 0xff;
1841         spec = (a0 >> 8) & 0xff;
1842
1843 #ifdef PSXBIOS_LOG
1844         PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0d], ev, spec);
1845 #endif
1846
1847         EventCB[ev][spec].status = EvStWAIT;
1848
1849         v0 = 1; pc0 = ra;
1850 }
1851
1852 /*
1853  *      long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
1854  */
1855
1856 void psxBios_OpenTh() { // 0e
1857         int th;
1858
1859         for (th=1; th<8; th++)
1860         {
1861                 if (ThreadCB[th].status == 0) break;
1862
1863         }
1864         if (th == 8) {
1865                 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
1866                 // When no free TCB is found, return 0xffffffff according to Nocash doc.
1867 #ifdef PSXBIOS_LOG
1868                 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
1869 #endif
1870                 v0 = 0xffffffff;
1871                 pc0 = ra;
1872                 return;
1873         }
1874 #ifdef PSXBIOS_LOG
1875         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
1876 #endif
1877
1878         ThreadCB[th].status = 1;
1879         ThreadCB[th].func    = a0;
1880         ThreadCB[th].reg[29] = a1;
1881         ThreadCB[th].reg[28] = a2;
1882
1883         v0 = th; pc0 = ra;
1884 }
1885
1886 /*
1887  *      int CloseTh(long thread);
1888  */
1889
1890 void psxBios_CloseTh() { // 0f
1891         int th = a0 & 0xff;
1892
1893 #ifdef PSXBIOS_LOG
1894         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
1895 #endif
1896         /* The return value is always 1 (even if the handle was already closed). */
1897         v0 = 1;
1898         if (ThreadCB[th].status != 0) {
1899                 ThreadCB[th].status = 0;
1900         }
1901
1902         pc0 = ra;
1903 }
1904
1905 /*
1906  *      int ChangeTh(long thread);
1907  */
1908
1909 void psxBios_ChangeTh() { // 10
1910         int th = a0 & 0xff;
1911
1912 #ifdef PSXBIOS_LOG
1913 //      PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
1914 #endif
1915         /* The return value is always 1. */
1916         v0 = 1;
1917         if (ThreadCB[th].status == 0 || CurThread == th) {
1918                 pc0 = ra;
1919         } else {
1920                 if (ThreadCB[CurThread].status == 2) {
1921                         ThreadCB[CurThread].status = 1;
1922                         ThreadCB[CurThread].func = ra;
1923                         memcpy(ThreadCB[CurThread].reg, psxRegs.GPR.r, 32*4);
1924                 }
1925
1926                 memcpy(psxRegs.GPR.r, ThreadCB[th].reg, 32*4);
1927                 pc0 = ThreadCB[th].func;
1928                 ThreadCB[th].status = 2;
1929                 CurThread = th;
1930         }
1931 }
1932
1933 void psxBios_InitPAD() { // 0x12
1934 #ifdef PSXBIOS_LOG
1935         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x12]);
1936 #endif
1937
1938         pad_buf1 = (char*)Ra0;
1939         pad_buf1len = a1;
1940         pad_buf2 = (char*)Ra2;
1941         pad_buf2len = a3;
1942
1943         v0 = 1; pc0 = ra;
1944 }
1945
1946 void psxBios_StartPAD() { // 13
1947 #ifdef PSXBIOS_LOG
1948         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
1949 #endif
1950         pad_stopped = 0;
1951         psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1));
1952         psxRegs.CP0.n.SR |= 0x401;
1953         pc0 = ra;
1954 }
1955
1956 void psxBios_StopPAD() { // 14
1957 #ifdef PSXBIOS_LOG
1958         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
1959 #endif
1960         pad_stopped = 1;
1961         pad_buf1 = NULL;
1962         pad_buf2 = NULL;
1963         pc0 = ra;
1964 }
1965
1966 void psxBios_PAD_init() { // 15
1967 #ifdef PSXBIOS_LOG
1968         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
1969 #endif
1970         if (!(a0 == 0x20000000 || a0 == 0x20000001))
1971         {
1972                 v0 = 0;
1973                 pc0 = ra;
1974                 return;
1975         }
1976         psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
1977         pad_buf = (int *)Ra1;
1978         *pad_buf = -1;
1979         psxRegs.CP0.n.SR |= 0x401;
1980         v0 = 2;
1981         pc0 = ra;
1982 }
1983
1984 void psxBios_PAD_dr() { // 16
1985 #ifdef PSXBIOS_LOG
1986         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
1987 #endif
1988
1989         v0 = -1; pc0 = ra;
1990 }
1991
1992 void psxBios_ReturnFromException() { // 17
1993         LoadRegs();
1994
1995         pc0 = psxRegs.CP0.n.EPC;
1996         k0 = interrupt_r26;
1997         if (psxRegs.CP0.n.Cause & 0x80000000) pc0 += 4;
1998
1999         psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
2000 }
2001
2002 void psxBios_ResetEntryInt() { // 18
2003 #ifdef PSXBIOS_LOG
2004         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2005 #endif
2006
2007         jmp_int = NULL;
2008         pc0 = ra;
2009 }
2010
2011 void psxBios_HookEntryInt() { // 19
2012 #ifdef PSXBIOS_LOG
2013         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x19]);
2014 #endif
2015
2016         jmp_int = (u32*)Ra0;
2017         pc0 = ra;
2018 }
2019
2020 void psxBios_UnDeliverEvent() { // 0x20
2021         int ev, spec;
2022         int i;
2023
2024         GetEv();
2025         GetSpec();
2026
2027 #ifdef PSXBIOS_LOG
2028         PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec);
2029 #endif
2030
2031         if (EventCB[ev][spec].status == EvStALREADY &&
2032                 EventCB[ev][spec].mode == EvMdNOINTR)
2033                 EventCB[ev][spec].status = EvStACTIVE;
2034
2035         pc0 = ra;
2036 }
2037
2038 char ffile[64], *pfile;
2039 int nfile;
2040
2041 static void buopen(int mcd, char *ptr, char *cfg)
2042 {
2043         int i;
2044         char *mcd_data = ptr;
2045
2046         strcpy(FDesc[1 + mcd].name, Ra0+5);
2047         FDesc[1 + mcd].offset = 0;
2048         FDesc[1 + mcd].mode   = a1;
2049
2050         for (i=1; i<16; i++) {
2051                 const char *fptr = mcd_data + 128 * i;
2052                 if ((*fptr & 0xF0) != 0x50) continue;
2053                 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2054                 FDesc[1 + mcd].mcfile = i;
2055                 SysPrintf("open %s\n", fptr+0xa);
2056                 v0 = 1 + mcd;
2057                 break;
2058         }
2059         if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2060                 for (i=1; i<16; i++) {
2061                         int j, xor, nblk = a1 >> 16;
2062                         char *pptr, *fptr2;
2063                         char *fptr = mcd_data + 128 * i;
2064
2065                         if ((*fptr & 0xF0) != 0xa0) continue;
2066
2067                         FDesc[1 + mcd].mcfile = i;
2068                         fptr[0] = 0x51;
2069                         fptr[4] = 0x00;
2070                         fptr[5] = 0x20 * nblk;
2071                         fptr[6] = 0x00;
2072                         fptr[7] = 0x00;
2073                         strcpy(fptr+0xa, FDesc[1 + mcd].name);
2074                         pptr = fptr2 = fptr;
2075                         for(j=2; j<=nblk; j++) {
2076                                 int k;
2077                                 for(i++; i<16; i++) {
2078                                         fptr2 += 128;
2079
2080                                         memset(fptr2, 0, 128);
2081                                         fptr2[0] = j < nblk ? 0x52 : 0x53;
2082                                         pptr[8] = i - 1;
2083                                         pptr[9] = 0;
2084                                         for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2085                                         pptr[127] = xor;
2086                                         pptr = fptr2;
2087                                         break;
2088                                 }
2089                                 /* shouldn't this return ENOSPC if i == 16? */
2090                         }
2091                         pptr[8] = pptr[9] = 0xff;
2092                         for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2093                         pptr[127] = xor;
2094                         SysPrintf("openC %s %d\n", ptr, nblk);
2095                         v0 = 1 + mcd;
2096                         /* just go ahead and resave them all */
2097                         SaveMcd(cfg, ptr, 128, 128 * 15);
2098                         break;
2099                 }
2100                 /* shouldn't this return ENOSPC if i == 16? */
2101         }
2102 }
2103
2104 /*
2105  *      int open(char *name , int mode);
2106  */
2107
2108 void psxBios_open() { // 0x32
2109         void *pa0 = Ra0;
2110
2111 #ifdef PSXBIOS_LOG
2112         PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2113 #endif
2114
2115         v0 = -1;
2116
2117         if (pa0 != INVALID_PTR) {
2118                 if (!strncmp(pa0, "bu00", 4)) {
2119                         buopen(1, Mcd1Data, Config.Mcd1);
2120                 }
2121
2122                 if (!strncmp(pa0, "bu10", 4)) {
2123                         buopen(2, Mcd2Data, Config.Mcd2);
2124                 }
2125         }
2126
2127         pc0 = ra;
2128 }
2129
2130 /*
2131  *      int lseek(int fd , int offset , int whence);
2132  */
2133
2134 void psxBios_lseek() { // 0x33
2135 #ifdef PSXBIOS_LOG
2136         PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2137 #endif
2138
2139         switch (a2) {
2140                 case 0: // SEEK_SET
2141                         FDesc[a0].offset = a1;
2142                         v0 = a1;
2143 //                      DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2144 //                      DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2145                         break;
2146
2147                 case 1: // SEEK_CUR
2148                         FDesc[a0].offset+= a1;
2149                         v0 = FDesc[a0].offset;
2150                         break;
2151         }
2152
2153         pc0 = ra;
2154 }
2155
2156
2157 /*
2158  *      int read(int fd , void *buf , int nbytes);
2159  */
2160
2161 void psxBios_read() { // 0x34
2162         char *ptr;
2163         void *pa1 = Ra1;
2164
2165 #ifdef PSXBIOS_LOG
2166         PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2167 #endif
2168
2169         v0 = -1;
2170
2171         if (pa1 != INVALID_PTR) {
2172                 switch (a0) {
2173                         case 2: buread(pa1, 1, a2); break;
2174                         case 3: buread(pa1, 2, a2); break;
2175                 }
2176         }
2177
2178         pc0 = ra;
2179 }
2180
2181 /*
2182  *      int write(int fd , void *buf , int nbytes);
2183  */
2184
2185 void psxBios_write() { // 0x35/0x03
2186         char *ptr;
2187         void *pa1 = Ra1;
2188
2189 #ifdef PSXBIOS_LOG
2190         PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2191 #endif
2192
2193         v0 = -1;
2194         if (pa1 == INVALID_PTR) {
2195                 pc0 = ra;
2196                 return;
2197         }
2198
2199         if (a0 == 1) { // stdout
2200                 char *ptr = pa1;
2201
2202                 v0 = a2;
2203                 while (a2 > 0) {
2204                         SysPrintf("%c", *ptr++); a2--;
2205                 }
2206                 pc0 = ra; return;
2207         }
2208
2209         switch (a0) {
2210                 case 2: buwrite(pa1, 1, a2); break;
2211                 case 3: buwrite(pa1, 2, a2); break;
2212         }
2213
2214         pc0 = ra;
2215 }
2216
2217 static void psxBios_write_psxout() {
2218         if (a0 == 1) { // stdout
2219                 const char *ptr = Ra1;
2220                 int len = a2;
2221
2222                 if (ptr != INVALID_PTR)
2223                         while (len-- > 0)
2224                                 SysPrintf("%c", *ptr++);
2225         }
2226 }
2227
2228 static void psxBios_putchar_psxout() { // 3d
2229         SysPrintf("%c", (char)a0);
2230 }
2231
2232 static void psxBios_puts_psxout() { // 3e/3f
2233         SysPrintf("%s", Ra0);
2234 }
2235
2236 /*
2237  *      int close(int fd);
2238  */
2239
2240 void psxBios_close() { // 0x36
2241 #ifdef PSXBIOS_LOG
2242         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2243 #endif
2244
2245         v0 = a0;
2246         pc0 = ra;
2247 }
2248
2249 void psxBios_putchar() { // 3d
2250         SysPrintf("%c", (char)a0);
2251         pc0 = ra;
2252 }
2253
2254 void psxBios_puts() { // 3e/3f
2255         SysPrintf("%s", Ra0);
2256         pc0 = ra;
2257 }
2258
2259
2260 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2261  * We want to mimic the PSX's behaviour in this case for bufile. */
2262 static size_t strlen_internal(char* p)
2263 {
2264         size_t size_of_array = 0;
2265         while (*p++) size_of_array++;
2266         return size_of_array;
2267 }
2268
2269 #define bufile(mcd) { \
2270         size_t size_of_name = strlen_internal(dir->name); \
2271         while (nfile < 16) { \
2272                 int match=1; \
2273  \
2274                 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2275                 nfile++; \
2276                 if ((*ptr & 0xF0) != 0x50) continue; \
2277                 /* Bug link files show up as free block. */ \
2278                 if (!ptr[0xa]) continue; \
2279                 ptr+= 0xa; \
2280                 if (pfile[0] == 0) { \
2281                         strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2282                         if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2283                 } else for (i=0; i<20; i++) { \
2284                         if (pfile[i] == ptr[i]) { \
2285                                                                 dir->name[i] = ptr[i]; continue; } \
2286                         if (pfile[i] == '?') { \
2287                                 dir->name[i] = ptr[i]; continue; } \
2288                         if (pfile[i] == '*') { \
2289                                 strcpy(dir->name+i, ptr+i); break; } \
2290                         match = 0; break; \
2291                 } \
2292                 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2293                 if (match == 0) { continue; } \
2294                 dir->size = 8192; \
2295                 v0 = _dir; \
2296                 break; \
2297         } \
2298 }
2299
2300 /*
2301  *      struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2302  */
2303
2304 void psxBios_firstfile() { // 42
2305         struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2306         void *pa0 = Ra0;
2307         u32 _dir = a1;
2308         char *ptr;
2309         int i;
2310
2311 #ifdef PSXBIOS_LOG
2312         PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2313 #endif
2314
2315         v0 = 0;
2316
2317         if (pa0 != INVALID_PTR) {
2318                 strcpy(ffile, pa0);
2319                 pfile = ffile+5;
2320                 nfile = 0;
2321                 if (!strncmp(pa0, "bu00", 4)) {
2322                         // firstfile() calls _card_read() internally, so deliver it's event
2323                         DeliverEvent(0x11, 0x2);
2324                         bufile(1);
2325                 } else if (!strncmp(pa0, "bu10", 4)) {
2326                         // firstfile() calls _card_read() internally, so deliver it's event
2327                         DeliverEvent(0x11, 0x2);
2328                         bufile(2);
2329                 }
2330         }
2331
2332         pc0 = ra;
2333 }
2334
2335 /*
2336  *      struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2337  */
2338
2339 void psxBios_nextfile() { // 43
2340         struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2341         u32 _dir = a0;
2342         char *ptr;
2343         int i;
2344
2345 #ifdef PSXBIOS_LOG
2346         PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2347 #endif
2348
2349         v0 = 0;
2350
2351         if (!strncmp(ffile, "bu00", 4)) {
2352                 bufile(1);
2353         }
2354
2355         if (!strncmp(ffile, "bu10", 4)) {
2356                 bufile(2);
2357         }
2358
2359         pc0 = ra;
2360 }
2361
2362 #define burename(mcd) { \
2363         for (i=1; i<16; i++) { \
2364                 int namelen, j, xor = 0; \
2365                 ptr = Mcd##mcd##Data + 128 * i; \
2366                 if ((*ptr & 0xF0) != 0x50) continue; \
2367                 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2368                 namelen = strlen(Ra1+5); \
2369                 memcpy(ptr+0xa, Ra1+5, namelen); \
2370                 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2371                 for (j=0; j<127; j++) xor^= ptr[j]; \
2372                 ptr[127] = xor; \
2373                 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2374                 v0 = 1; \
2375                 break; \
2376         } \
2377 }
2378
2379 /*
2380  *      int rename(char *old, char *new);
2381  */
2382
2383 void psxBios_rename() { // 44
2384         void *pa0 = Ra0;
2385         void *pa1 = Ra1;
2386         char *ptr;
2387         int i;
2388
2389 #ifdef PSXBIOS_LOG
2390         PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2391 #endif
2392
2393         v0 = 0;
2394
2395         if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2396                 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2397                         burename(1);
2398                 }
2399
2400                 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2401                         burename(2);
2402                 }
2403         }
2404
2405         pc0 = ra;
2406 }
2407
2408
2409 #define budelete(mcd) { \
2410         for (i=1; i<16; i++) { \
2411                 ptr = Mcd##mcd##Data + 128 * i; \
2412                 if ((*ptr & 0xF0) != 0x50) continue; \
2413                 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2414                 *ptr = (*ptr & 0xf) | 0xA0; \
2415                 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2416                 SysPrintf("delete %s\n", ptr+0xa); \
2417                 v0 = 1; \
2418                 break; \
2419         } \
2420 }
2421
2422 /*
2423  *      int delete(char *name);
2424  */
2425
2426 void psxBios_delete() { // 45
2427         void *pa0 = Ra0;
2428         char *ptr;
2429         int i;
2430
2431 #ifdef PSXBIOS_LOG
2432         PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2433 #endif
2434
2435         v0 = 0;
2436
2437         if (pa0 != INVALID_PTR) {
2438                 if (!strncmp(pa0, "bu00", 4)) {
2439                         budelete(1);
2440                 }
2441
2442                 if (!strncmp(pa0, "bu10", 4)) {
2443                         budelete(2);
2444                 }
2445         }
2446
2447         pc0 = ra;
2448 }
2449
2450 void psxBios_InitCARD() { // 4a
2451 #ifdef PSXBIOS_LOG
2452         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2453 #endif
2454
2455         CardState = 0;
2456
2457         pc0 = ra;
2458 }
2459
2460 void psxBios_StartCARD() { // 4b
2461 #ifdef PSXBIOS_LOG
2462         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2463 #endif
2464
2465         if (CardState == 0) CardState = 1;
2466
2467         pc0 = ra;
2468 }
2469
2470 void psxBios_StopCARD() { // 4c
2471 #ifdef PSXBIOS_LOG
2472         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2473 #endif
2474
2475         if (CardState == 1) CardState = 0;
2476
2477         pc0 = ra;
2478 }
2479
2480 void psxBios__card_write() { // 0x4e
2481         void *pa2 = Ra2;
2482         int port;
2483
2484 #ifdef PSXBIOS_LOG
2485         PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2486 #endif
2487         /*
2488         Function also accepts sector 400h (a bug).
2489         But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2490         */
2491         if (!(a1 <= 0x3FF))
2492         {
2493                 /* Invalid sectors */
2494                 v0 = 0; pc0 = ra;
2495                 return;
2496         }
2497         card_active_chan = a0;
2498         port = a0 >> 4;
2499
2500         if (pa2 != INVALID_PTR) {
2501                 if (port == 0) {
2502                         memcpy(Mcd1Data + a1 * 128, pa2, 128);
2503                         SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2504                 } else {
2505                         memcpy(Mcd2Data + a1 * 128, pa2, 128);
2506                         SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2507                 }
2508         }
2509
2510         DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2511 //      DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2512
2513         v0 = 1; pc0 = ra;
2514 }
2515
2516 void psxBios__card_read() { // 0x4f
2517         void *pa2 = Ra2;
2518         int port;
2519
2520 #ifdef PSXBIOS_LOG
2521         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2522 #endif
2523         /*
2524         Function also accepts sector 400h (a bug).
2525         But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2526         */
2527         if (!(a1 <= 0x3FF))
2528         {
2529                 /* Invalid sectors */
2530                 v0 = 0; pc0 = ra;
2531                 return;
2532         }
2533         card_active_chan = a0;
2534         port = a0 >> 4;
2535
2536         if (pa2 != INVALID_PTR) {
2537                 if (port == 0) {
2538                         memcpy(pa2, Mcd1Data + a1 * 128, 128);
2539                 } else {
2540                         memcpy(pa2, Mcd2Data + a1 * 128, 128);
2541                 }
2542         }
2543
2544         DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2545 //      DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2546
2547         v0 = 1; pc0 = ra;
2548 }
2549
2550 void psxBios__new_card() { // 0x50
2551 #ifdef PSXBIOS_LOG
2552         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2553 #endif
2554
2555         pc0 = ra;
2556 }
2557
2558 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2559 void psxBios__get_error(void) // 55
2560 {
2561         v0 = 0;
2562         pc0 = ra;
2563 }
2564
2565 void psxBios_Krom2RawAdd() { // 0x51
2566         int i = 0;
2567
2568         const u32 table_8140[][2] = {
2569                 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2570                 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2571                 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2572                 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2573                 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2574                 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2575                 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2576                 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2577                 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2578                 {0xffff, 0}
2579         };
2580
2581         const u32 table_889f[][2] = {
2582                 {0x889f, 0x3d68},  {0x8900, 0x40ec},  {0x897f, 0x4fb0},  {0x8a00, 0x56f4},
2583                 {0x8a7f, 0x65b8},  {0x8b00, 0x6cfc},  {0x8b7f, 0x7bc0},  {0x8c00, 0x8304},
2584                 {0x8c7f, 0x91c8},  {0x8d00, 0x990c},  {0x8d7f, 0xa7d0},  {0x8e00, 0xaf14},
2585                 {0x8e7f, 0xbdd8},  {0x8f00, 0xc51c},  {0x8f7f, 0xd3e0},  {0x9000, 0xdb24},
2586                 {0x907f, 0xe9e8},  {0x9100, 0xf12c},  {0x917f, 0xfff0},  {0x9200, 0x10734},
2587                 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2588                 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2589                 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2590                 {0xffff, 0}
2591         };
2592
2593         if (a0 >= 0x8140 && a0 <= 0x84be) {
2594                 while (table_8140[i][0] <= a0) i++;
2595                 a0 -= table_8140[i - 1][0];
2596                 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2597         } else if (a0 >= 0x889f && a0 <= 0x9872) {
2598                 while (table_889f[i][0] <= a0) i++;
2599                 a0 -= table_889f[i - 1][0];
2600                 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2601         } else {
2602                 v0 = 0xffffffff;
2603         }
2604
2605         pc0 = ra;
2606 }
2607
2608 void psxBios_GetC0Table() { // 56
2609 #ifdef PSXBIOS_LOG
2610         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2611 #endif
2612
2613         v0 = 0x674; pc0 = ra;
2614 }
2615
2616 void psxBios_GetB0Table() { // 57
2617 #ifdef PSXBIOS_LOG
2618         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2619 #endif
2620
2621         v0 = 0x874; pc0 = ra;
2622 }
2623
2624 void psxBios__card_chan() { // 0x58
2625 #ifdef PSXBIOS_LOG
2626         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2627 #endif
2628
2629         v0 = card_active_chan;
2630         pc0 = ra;
2631 }
2632
2633 void psxBios_ChangeClearPad() { // 5b
2634 #ifdef PSXBIOS_LOG
2635         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2636 #endif
2637
2638         pc0 = ra;
2639 }
2640
2641 void psxBios__card_status() { // 5c
2642 #ifdef PSXBIOS_LOG
2643         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2644 #endif
2645
2646         v0 = card_active_chan;
2647         pc0 = ra;
2648 }
2649
2650 void psxBios__card_wait() { // 5d
2651 #ifdef PSXBIOS_LOG
2652         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2653 #endif
2654
2655         v0 = 1;
2656         pc0 = ra;
2657 }
2658
2659 /* System calls C0 */
2660
2661 /*
2662  * int SysEnqIntRP(int index , long *queue);
2663  */
2664
2665 void psxBios_SysEnqIntRP() { // 02
2666 #ifdef PSXBIOS_LOG
2667         PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x02] ,a0);
2668 #endif
2669
2670         SysIntRP[a0] = a1;
2671
2672         v0 = 0; pc0 = ra;
2673 }
2674
2675 /*
2676  * int SysDeqIntRP(int index , long *queue);
2677  */
2678
2679 void psxBios_SysDeqIntRP() { // 03
2680 #ifdef PSXBIOS_LOG
2681         PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x03], a0);
2682 #endif
2683
2684         SysIntRP[a0] = 0;
2685
2686         v0 = 0; pc0 = ra;
2687 }
2688
2689 void psxBios_ChangeClearRCnt() { // 0a
2690         u32 *ptr;
2691
2692 #ifdef PSXBIOS_LOG
2693         PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2694 #endif
2695
2696         ptr = (u32*)PSXM((a0 << 2) + 0x8600);
2697         v0 = *ptr;
2698         *ptr = a1;
2699
2700 //      psxRegs.CP0.n.SR|= 0x404;
2701         pc0 = ra;
2702 }
2703
2704 void psxBios_dummy() {
2705 #ifdef PSXBIOS_LOG
2706         PSXBIOS_LOG("unk %x call: %x\n", pc0 & 0x1fffff, t1);
2707 #endif
2708         pc0 = ra;
2709 }
2710
2711 void (*biosA0[256])();
2712 void (*biosB0[256])();
2713 void (*biosC0[256])();
2714
2715 #include "sjisfont.h"
2716
2717 void psxBiosInit() {
2718         u32 base, size;
2719         u32 *ptr;
2720         int i;
2721         uLongf len;
2722
2723         for(i = 0; i < 256; i++) {
2724                 biosA0[i] = NULL;
2725                 biosB0[i] = NULL;
2726                 biosC0[i] = NULL;
2727         }
2728         biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
2729         biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
2730         biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
2731         biosA0[0x3f] = psxBios_printf_psxout;
2732
2733         if (!Config.HLE) return;
2734
2735         for(i = 0; i < 256; i++) {
2736                 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
2737                 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
2738                 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
2739         }
2740
2741         biosA0[0x00] = psxBios_open;
2742         biosA0[0x01] = psxBios_lseek;
2743         biosA0[0x02] = psxBios_read;
2744         biosA0[0x03] = psxBios_write;
2745         biosA0[0x04] = psxBios_close;
2746         //biosA0[0x05] = psxBios_ioctl;
2747         //biosA0[0x06] = psxBios_exit;
2748         //biosA0[0x07] = psxBios_sys_a0_07;
2749         biosA0[0x08] = psxBios_getc;
2750         biosA0[0x09] = psxBios_putc;
2751         biosA0[0x0a] = psxBios_todigit;
2752         //biosA0[0x0b] = psxBios_atof;
2753         //biosA0[0x0c] = psxBios_strtoul;
2754         //biosA0[0x0d] = psxBios_strtol;
2755         biosA0[0x0e] = psxBios_abs;
2756         biosA0[0x0f] = psxBios_labs;
2757         biosA0[0x10] = psxBios_atoi;
2758         biosA0[0x11] = psxBios_atol;
2759         //biosA0[0x12] = psxBios_atob;
2760         biosA0[0x13] = psxBios_setjmp;
2761         biosA0[0x14] = psxBios_longjmp;
2762         biosA0[0x15] = psxBios_strcat;
2763         biosA0[0x16] = psxBios_strncat;
2764         biosA0[0x17] = psxBios_strcmp;
2765         biosA0[0x18] = psxBios_strncmp;
2766         biosA0[0x19] = psxBios_strcpy;
2767         biosA0[0x1a] = psxBios_strncpy;
2768         biosA0[0x1b] = psxBios_strlen;
2769         biosA0[0x1c] = psxBios_index;
2770         biosA0[0x1d] = psxBios_rindex;
2771         biosA0[0x1e] = psxBios_strchr;
2772         biosA0[0x1f] = psxBios_strrchr;
2773         biosA0[0x20] = psxBios_strpbrk;
2774         biosA0[0x21] = psxBios_strspn;
2775         biosA0[0x22] = psxBios_strcspn;
2776         biosA0[0x23] = psxBios_strtok;
2777         biosA0[0x24] = psxBios_strstr;
2778         biosA0[0x25] = psxBios_toupper;
2779         biosA0[0x26] = psxBios_tolower;
2780         biosA0[0x27] = psxBios_bcopy;
2781         biosA0[0x28] = psxBios_bzero;
2782         biosA0[0x29] = psxBios_bcmp;
2783         biosA0[0x2a] = psxBios_memcpy;
2784         biosA0[0x2b] = psxBios_memset;
2785         biosA0[0x2c] = psxBios_memmove;
2786         biosA0[0x2d] = psxBios_memcmp;
2787         biosA0[0x2e] = psxBios_memchr;
2788         biosA0[0x2f] = psxBios_rand;
2789         biosA0[0x30] = psxBios_srand;
2790         biosA0[0x31] = psxBios_qsort;
2791         //biosA0[0x32] = psxBios_strtod;
2792         biosA0[0x33] = psxBios_malloc;
2793         biosA0[0x34] = psxBios_free;
2794         //biosA0[0x35] = psxBios_lsearch;
2795         //biosA0[0x36] = psxBios_bsearch;
2796         biosA0[0x37] = psxBios_calloc;
2797         biosA0[0x38] = psxBios_realloc;
2798         biosA0[0x39] = psxBios_InitHeap;
2799         //biosA0[0x3a] = psxBios__exit;
2800         biosA0[0x3b] = psxBios_getchar;
2801         biosA0[0x3c] = psxBios_putchar;
2802         //biosA0[0x3d] = psxBios_gets;
2803         //biosA0[0x40] = psxBios_sys_a0_40;
2804         //biosA0[0x41] = psxBios_LoadTest;
2805         biosA0[0x42] = psxBios_Load;
2806         biosA0[0x43] = psxBios_Exec;
2807         biosA0[0x44] = psxBios_FlushCache;
2808         //biosA0[0x45] = psxBios_InstallInterruptHandler;
2809         biosA0[0x46] = psxBios_GPU_dw;
2810         biosA0[0x47] = psxBios_mem2vram;
2811         biosA0[0x48] = psxBios_SendGPU;
2812         biosA0[0x49] = psxBios_GPU_cw;
2813         biosA0[0x4a] = psxBios_GPU_cwb;
2814         biosA0[0x4b] = psxBios_GPU_SendPackets;
2815         biosA0[0x4c] = psxBios_sys_a0_4c;
2816         biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
2817         //biosA0[0x4e] = psxBios_GPU_sync;
2818         //biosA0[0x4f] = psxBios_sys_a0_4f;
2819         //biosA0[0x50] = psxBios_sys_a0_50;
2820         biosA0[0x51] = psxBios_LoadExec;
2821         //biosA0[0x52] = psxBios_GetSysSp;
2822         //biosA0[0x53] = psxBios_sys_a0_53;
2823         //biosA0[0x54] = psxBios__96_init_a54;
2824         //biosA0[0x55] = psxBios__bu_init_a55;
2825         //biosA0[0x56] = psxBios__96_remove_a56;
2826         //biosA0[0x57] = psxBios_sys_a0_57;
2827         //biosA0[0x58] = psxBios_sys_a0_58;
2828         //biosA0[0x59] = psxBios_sys_a0_59;
2829         //biosA0[0x5a] = psxBios_sys_a0_5a;
2830         //biosA0[0x5b] = psxBios_dev_tty_init;
2831         //biosA0[0x5c] = psxBios_dev_tty_open;
2832         //biosA0[0x5d] = psxBios_sys_a0_5d;
2833         //biosA0[0x5e] = psxBios_dev_tty_ioctl;
2834         //biosA0[0x5f] = psxBios_dev_cd_open;
2835         //biosA0[0x60] = psxBios_dev_cd_read;
2836         //biosA0[0x61] = psxBios_dev_cd_close;
2837         //biosA0[0x62] = psxBios_dev_cd_firstfile;
2838         //biosA0[0x63] = psxBios_dev_cd_nextfile;
2839         //biosA0[0x64] = psxBios_dev_cd_chdir;
2840         //biosA0[0x65] = psxBios_dev_card_open;
2841         //biosA0[0x66] = psxBios_dev_card_read;
2842         //biosA0[0x67] = psxBios_dev_card_write;
2843         //biosA0[0x68] = psxBios_dev_card_close;
2844         //biosA0[0x69] = psxBios_dev_card_firstfile;
2845         //biosA0[0x6a] = psxBios_dev_card_nextfile;
2846         //biosA0[0x6b] = psxBios_dev_card_erase;
2847         //biosA0[0x6c] = psxBios_dev_card_undelete;
2848         //biosA0[0x6d] = psxBios_dev_card_format;
2849         //biosA0[0x6e] = psxBios_dev_card_rename;
2850         //biosA0[0x6f] = psxBios_dev_card_6f;
2851         biosA0[0x70] = psxBios__bu_init;
2852         biosA0[0x71] = psxBios__96_init;
2853         biosA0[0x72] = psxBios__96_remove;
2854         //biosA0[0x73] = psxBios_sys_a0_73;
2855         //biosA0[0x74] = psxBios_sys_a0_74;
2856         //biosA0[0x75] = psxBios_sys_a0_75;
2857         //biosA0[0x76] = psxBios_sys_a0_76;
2858         //biosA0[0x77] = psxBios_sys_a0_77;
2859         //biosA0[0x78] = psxBios__96_CdSeekL;
2860         //biosA0[0x79] = psxBios_sys_a0_79;
2861         //biosA0[0x7a] = psxBios_sys_a0_7a;
2862         //biosA0[0x7b] = psxBios_sys_a0_7b;
2863         //biosA0[0x7c] = psxBios__96_CdGetStatus;
2864         //biosA0[0x7d] = psxBios_sys_a0_7d;
2865         //biosA0[0x7e] = psxBios__96_CdRead;
2866         //biosA0[0x7f] = psxBios_sys_a0_7f;
2867         //biosA0[0x80] = psxBios_sys_a0_80;
2868         //biosA0[0x81] = psxBios_sys_a0_81;
2869         //biosA0[0x82] = psxBios_sys_a0_82;
2870         //biosA0[0x83] = psxBios_sys_a0_83;
2871         //biosA0[0x84] = psxBios_sys_a0_84;
2872         //biosA0[0x85] = psxBios__96_CdStop;
2873         //biosA0[0x86] = psxBios_sys_a0_86;
2874         //biosA0[0x87] = psxBios_sys_a0_87;
2875         //biosA0[0x88] = psxBios_sys_a0_88;
2876         //biosA0[0x89] = psxBios_sys_a0_89;
2877         //biosA0[0x8a] = psxBios_sys_a0_8a;
2878         //biosA0[0x8b] = psxBios_sys_a0_8b;
2879         //biosA0[0x8c] = psxBios_sys_a0_8c;
2880         //biosA0[0x8d] = psxBios_sys_a0_8d;
2881         //biosA0[0x8e] = psxBios_sys_a0_8e;
2882         //biosA0[0x8f] = psxBios_sys_a0_8f;
2883         //biosA0[0x90] = psxBios_sys_a0_90;
2884         //biosA0[0x91] = psxBios_sys_a0_91;
2885         //biosA0[0x92] = psxBios_sys_a0_92;
2886         //biosA0[0x93] = psxBios_sys_a0_93;
2887         //biosA0[0x94] = psxBios_sys_a0_94;
2888         //biosA0[0x95] = psxBios_sys_a0_95;
2889         //biosA0[0x96] = psxBios_AddCDROMDevice;
2890         //biosA0[0x97] = psxBios_AddMemCardDevide;
2891         //biosA0[0x98] = psxBios_DisableKernelIORedirection;
2892         //biosA0[0x99] = psxBios_EnableKernelIORedirection;
2893         //biosA0[0x9a] = psxBios_sys_a0_9a;
2894         //biosA0[0x9b] = psxBios_sys_a0_9b;
2895         //biosA0[0x9c] = psxBios_SetConf;
2896         //biosA0[0x9d] = psxBios_GetConf;
2897         //biosA0[0x9e] = psxBios_sys_a0_9e;
2898         biosA0[0x9f] = psxBios_SetMem;
2899         //biosA0[0xa0] = psxBios__boot;
2900         //biosA0[0xa1] = psxBios_SystemError;
2901         //biosA0[0xa2] = psxBios_EnqueueCdIntr;
2902         //biosA0[0xa3] = psxBios_DequeueCdIntr;
2903         //biosA0[0xa4] = psxBios_sys_a0_a4;
2904         //biosA0[0xa5] = psxBios_ReadSector;
2905         biosA0[0xa6] = psxBios_get_cd_status;
2906         //biosA0[0xa7] = psxBios_bufs_cb_0;
2907         //biosA0[0xa8] = psxBios_bufs_cb_1;
2908         //biosA0[0xa9] = psxBios_bufs_cb_2;
2909         //biosA0[0xaa] = psxBios_bufs_cb_3;
2910         biosA0[0xab] = psxBios__card_info;
2911         biosA0[0xac] = psxBios__card_load;
2912         //biosA0[0axd] = psxBios__card_auto;
2913         //biosA0[0xae] = psxBios_bufs_cd_4;
2914         //biosA0[0xaf] = psxBios_sys_a0_af;
2915         //biosA0[0xb0] = psxBios_sys_a0_b0;
2916         //biosA0[0xb1] = psxBios_sys_a0_b1;
2917         //biosA0[0xb2] = psxBios_do_a_long_jmp
2918         //biosA0[0xb3] = psxBios_sys_a0_b3;
2919         //biosA0[0xb4] = psxBios_sub_function;
2920 //*******************B0 CALLS****************************
2921         //biosB0[0x00] = psxBios_SysMalloc;
2922         //biosB0[0x01] = psxBios_sys_b0_01;
2923         biosB0[0x02] = psxBios_SetRCnt;
2924         biosB0[0x03] = psxBios_GetRCnt;
2925         biosB0[0x04] = psxBios_StartRCnt;
2926         biosB0[0x05] = psxBios_StopRCnt;
2927         biosB0[0x06] = psxBios_ResetRCnt;
2928         biosB0[0x07] = psxBios_DeliverEvent;
2929         biosB0[0x08] = psxBios_OpenEvent;
2930         biosB0[0x09] = psxBios_CloseEvent;
2931         biosB0[0x0a] = psxBios_WaitEvent;
2932         biosB0[0x0b] = psxBios_TestEvent;
2933         biosB0[0x0c] = psxBios_EnableEvent;
2934         biosB0[0x0d] = psxBios_DisableEvent;
2935         biosB0[0x0e] = psxBios_OpenTh;
2936         biosB0[0x0f] = psxBios_CloseTh;
2937         biosB0[0x10] = psxBios_ChangeTh;
2938         //biosB0[0x11] = psxBios_psxBios_b0_11;
2939         biosB0[0x12] = psxBios_InitPAD;
2940         biosB0[0x13] = psxBios_StartPAD;
2941         biosB0[0x14] = psxBios_StopPAD;
2942         biosB0[0x15] = psxBios_PAD_init;
2943         biosB0[0x16] = psxBios_PAD_dr;
2944         biosB0[0x17] = psxBios_ReturnFromException;
2945         biosB0[0x18] = psxBios_ResetEntryInt;
2946         biosB0[0x19] = psxBios_HookEntryInt;
2947         //biosB0[0x1a] = psxBios_sys_b0_1a;
2948         //biosB0[0x1b] = psxBios_sys_b0_1b;
2949         //biosB0[0x1c] = psxBios_sys_b0_1c;
2950         //biosB0[0x1d] = psxBios_sys_b0_1d;
2951         //biosB0[0x1e] = psxBios_sys_b0_1e;
2952         //biosB0[0x1f] = psxBios_sys_b0_1f;
2953         biosB0[0x20] = psxBios_UnDeliverEvent;
2954         //biosB0[0x21] = psxBios_sys_b0_21;
2955         //biosB0[0x22] = psxBios_sys_b0_22;
2956         //biosB0[0x23] = psxBios_sys_b0_23;
2957         //biosB0[0x24] = psxBios_sys_b0_24;
2958         //biosB0[0x25] = psxBios_sys_b0_25;
2959         //biosB0[0x26] = psxBios_sys_b0_26;
2960         //biosB0[0x27] = psxBios_sys_b0_27;
2961         //biosB0[0x28] = psxBios_sys_b0_28;
2962         //biosB0[0x29] = psxBios_sys_b0_29;
2963         //biosB0[0x2a] = psxBios_sys_b0_2a;
2964         //biosB0[0x2b] = psxBios_sys_b0_2b;
2965         //biosB0[0x2c] = psxBios_sys_b0_2c;
2966         //biosB0[0x2d] = psxBios_sys_b0_2d;
2967         //biosB0[0x2e] = psxBios_sys_b0_2e;
2968         //biosB0[0x2f] = psxBios_sys_b0_2f;
2969         //biosB0[0x30] = psxBios_sys_b0_30;
2970         //biosB0[0x31] = psxBios_sys_b0_31;
2971         biosB0[0x32] = psxBios_open;
2972         biosB0[0x33] = psxBios_lseek;
2973         biosB0[0x34] = psxBios_read;
2974         biosB0[0x35] = psxBios_write;
2975         biosB0[0x36] = psxBios_close;
2976         //biosB0[0x37] = psxBios_ioctl;
2977         //biosB0[0x38] = psxBios_exit;
2978         //biosB0[0x39] = psxBios_sys_b0_39;
2979         //biosB0[0x3a] = psxBios_getc;
2980         //biosB0[0x3b] = psxBios_putc;
2981         biosB0[0x3c] = psxBios_getchar;
2982         //biosB0[0x3e] = psxBios_gets;
2983         //biosB0[0x40] = psxBios_cd;
2984         biosB0[0x41] = psxBios_format;
2985         biosB0[0x42] = psxBios_firstfile;
2986         biosB0[0x43] = psxBios_nextfile;
2987         biosB0[0x44] = psxBios_rename;
2988         biosB0[0x45] = psxBios_delete;
2989         //biosB0[0x46] = psxBios_undelete;
2990         //biosB0[0x47] = psxBios_AddDevice;
2991         //biosB0[0x48] = psxBios_RemoteDevice;
2992         //biosB0[0x49] = psxBios_PrintInstalledDevices;
2993         biosB0[0x4a] = psxBios_InitCARD;
2994         biosB0[0x4b] = psxBios_StartCARD;
2995         biosB0[0x4c] = psxBios_StopCARD;
2996         //biosB0[0x4d] = psxBios_sys_b0_4d;
2997         biosB0[0x4e] = psxBios__card_write;
2998         biosB0[0x4f] = psxBios__card_read;
2999         biosB0[0x50] = psxBios__new_card;
3000         biosB0[0x51] = psxBios_Krom2RawAdd;
3001         //biosB0[0x52] = psxBios_sys_b0_52;
3002         //biosB0[0x53] = psxBios_sys_b0_53;
3003         //biosB0[0x54] = psxBios__get_errno;
3004         biosB0[0x55] = psxBios__get_error;
3005         biosB0[0x56] = psxBios_GetC0Table;
3006         biosB0[0x57] = psxBios_GetB0Table;
3007         biosB0[0x58] = psxBios__card_chan;
3008         //biosB0[0x59] = psxBios_sys_b0_59;
3009         //biosB0[0x5a] = psxBios_sys_b0_5a;
3010         biosB0[0x5b] = psxBios_ChangeClearPad;
3011         biosB0[0x5c] = psxBios__card_status;
3012         biosB0[0x5d] = psxBios__card_wait;
3013 //*******************C0 CALLS****************************
3014         //biosC0[0x00] = psxBios_InitRCnt;
3015         //biosC0[0x01] = psxBios_InitException;
3016         biosC0[0x02] = psxBios_SysEnqIntRP;
3017         biosC0[0x03] = psxBios_SysDeqIntRP;
3018         //biosC0[0x04] = psxBios_get_free_EvCB_slot;
3019         //biosC0[0x05] = psxBios_get_free_TCB_slot;
3020         //biosC0[0x06] = psxBios_ExceptionHandler;
3021         //biosC0[0x07] = psxBios_InstallExeptionHandler;
3022         //biosC0[0x08] = psxBios_SysInitMemory;
3023         //biosC0[0x09] = psxBios_SysInitKMem;
3024         biosC0[0x0a] = psxBios_ChangeClearRCnt;
3025         //biosC0[0x0b] = psxBios_SystemError;
3026         //biosC0[0x0c] = psxBios_InitDefInt;
3027         //biosC0[0x0d] = psxBios_sys_c0_0d;
3028         //biosC0[0x0e] = psxBios_sys_c0_0e;
3029         //biosC0[0x0f] = psxBios_sys_c0_0f;
3030         //biosC0[0x10] = psxBios_sys_c0_10;
3031         //biosC0[0x11] = psxBios_sys_c0_11;
3032         //biosC0[0x12] = psxBios_InstallDevices;
3033         //biosC0[0x13] = psxBios_FlushStfInOutPut;
3034         //biosC0[0x14] = psxBios_sys_c0_14;
3035         //biosC0[0x15] = psxBios__cdevinput;
3036         //biosC0[0x16] = psxBios__cdevscan;
3037         //biosC0[0x17] = psxBios__circgetc;
3038         //biosC0[0x18] = psxBios__circputc;
3039         //biosC0[0x19] = psxBios_ioabort;
3040         //biosC0[0x1a] = psxBios_sys_c0_1a
3041         //biosC0[0x1b] = psxBios_KernelRedirect;
3042         //biosC0[0x1c] = psxBios_PatchAOTable;
3043 //************** THE END ***************************************
3044 /**/
3045         base = 0x1000;
3046         size = sizeof(EvCB) * 32;
3047         EventCB = (void *)&psxR[base]; base += size * 6;
3048         memset(EventCB, 0, size * 6);
3049         HwEV = EventCB;
3050         EvEV = EventCB + 32;
3051         RcEV = EventCB + 32 * 2;
3052         UeEV = EventCB + 32 * 3;
3053         SwEV = EventCB + 32 * 4;
3054         ThEV = EventCB + 32 * 5;
3055
3056         ptr = (u32 *)&psxM[0x0874]; // b0 table
3057         ptr[0] = SWAPu32(0x4c54 - 0x884);
3058
3059         ptr = (u32 *)&psxM[0x0674]; // c0 table
3060         ptr[6] = SWAPu32(0xc80);
3061
3062         memset(SysIntRP, 0, sizeof(SysIntRP));
3063         memset(ThreadCB, 0, sizeof(ThreadCB));
3064         ThreadCB[0].status = 2; // main thread
3065
3066         pad_stopped = 1;
3067         jmp_int = NULL;
3068         pad_buf = NULL;
3069         pad_buf1 = NULL;
3070         pad_buf2 = NULL;
3071         pad_buf1len = pad_buf2len = 0;
3072         heap_addr = NULL;
3073         heap_end = NULL;
3074         heap_size = 0;
3075         CardState = -1;
3076         CurThread = 0;
3077         memset(FDesc, 0, sizeof(FDesc));
3078         card_active_chan = 0;
3079
3080         psxMu32ref(0x0150) = SWAPu32(0x160);
3081         psxMu32ref(0x0154) = SWAPu32(0x320);
3082         psxMu32ref(0x0160) = SWAPu32(0x248);
3083         strcpy((char *)&psxM[0x248], "bu");
3084 /*      psxMu32ref(0x0ca8) = SWAPu32(0x1f410004);
3085         psxMu32ref(0x0cf0) = SWAPu32(0x3c020000);
3086         psxMu32ref(0x0cf4) = SWAPu32(0x2442641c);
3087         psxMu32ref(0x09e0) = SWAPu32(0x43d0);
3088         psxMu32ref(0x4d98) = SWAPu32(0x946f000a);
3089 */
3090         // opcode HLE
3091         psxRu32ref(0x0000) = SWAPu32((0x3b << 26) | 4);
3092         /* Whatever this does, it actually breaks CTR, even without the uninitiliazed memory patch.
3093         Normally games shouldn't read from address 0 yet they do. See explanation below in details. */
3094         //psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0);
3095         psxMu32ref(0x00a0) = SWAPu32((0x3b << 26) | 1);
3096         psxMu32ref(0x00b0) = SWAPu32((0x3b << 26) | 2);
3097         psxMu32ref(0x00c0) = SWAPu32((0x3b << 26) | 3);
3098         psxMu32ref(0x4c54) = SWAPu32((0x3b << 26) | 0);
3099         psxMu32ref(0x8000) = SWAPu32((0x3b << 26) | 5);
3100         psxMu32ref(0x07a0) = SWAPu32((0x3b << 26) | 0);
3101         psxMu32ref(0x0884) = SWAPu32((0x3b << 26) | 0);
3102         psxMu32ref(0x0894) = SWAPu32((0x3b << 26) | 0);
3103
3104         // initial stack pointer for BIOS interrupt
3105         psxMu32ref(0x6c80) = SWAPu32(0x000085c8);
3106
3107         // initial RNG seed
3108         psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3109
3110         // fonts
3111         len = 0x80000 - 0x66000;
3112         uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3113         len = 0x80000 - 0x69d68;
3114         uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3115
3116         // memory size 2 MB
3117         psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3118
3119         hleSoftCall = FALSE;
3120
3121         /*      Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3122                 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3123                 Here are some examples of games not working with this fix in place :
3124                 R-type won't get past the Irem logo if not implemented.
3125                 Crash Team Racing will softlock after the Sony logo.
3126         */
3127
3128         psxMu32ref(0x0000) = SWAPu32(0x00000003);
3129         /*
3130         But overwritten by 00000003h after soon.
3131         psxMu32ref(0x0000) = SWAPu32(0x00001A3C);
3132         */
3133         psxMu32ref(0x0004) = SWAPu32(0x800C5A27);
3134         psxMu32ref(0x0008) = SWAPu32(0x08000403);
3135         psxMu32ref(0x000C) = SWAPu32(0x00000000);
3136 }
3137
3138 void psxBiosShutdown() {
3139 }
3140
3141 #define psxBios_PADpoll(pad) { \
3142         PAD##pad##_startPoll(pad); \
3143         pad_buf##pad[0] = 0; \
3144         pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3145         if (!(pad_buf##pad[1] & 0x0f)) { \
3146                 bufcount = 32; \
3147         } else { \
3148                 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3149         } \
3150         PAD##pad##_poll(0); \
3151         i = 2; \
3152         while (bufcount--) { \
3153                 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3154         } \
3155 }
3156
3157 void biosInterrupt() {
3158         int i, bufcount;
3159
3160 //      if (psxHu32(0x1070) & 0x1) { // Vsync
3161                 if (pad_buf != NULL) {
3162                         u32 *buf = (u32*)pad_buf;
3163
3164                         if (!Config.UseNet) {
3165                                 PAD1_startPoll(1);
3166                                 if (PAD1_poll(0x42) == 0x23) {
3167                                         PAD1_poll(0);
3168                                         *buf = PAD1_poll(0) << 8;
3169                                         *buf |= PAD1_poll(0);
3170                                         PAD1_poll(0);
3171                                         *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3172                                         *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3173                                 } else {
3174                                         PAD1_poll(0);
3175                                         *buf = PAD1_poll(0) << 8;
3176                                         *buf|= PAD1_poll(0);
3177                                 }
3178
3179                                 PAD2_startPoll(2);
3180                                 if (PAD2_poll(0x42) == 0x23) {
3181                                         PAD2_poll(0);
3182                                         *buf |= PAD2_poll(0) << 24;
3183                                         *buf |= PAD2_poll(0) << 16;
3184                                         PAD2_poll(0);
3185                                         *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3186                                         *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3187                                 } else {
3188                                         PAD2_poll(0);
3189                                         *buf |= PAD2_poll(0) << 24;
3190                                         *buf |= PAD2_poll(0) << 16;
3191                                 }
3192                         } else {
3193                                 u16 data;
3194
3195                                 PAD1_startPoll(1);
3196                                 PAD1_poll(0x42);
3197                                 PAD1_poll(0);
3198                                 data = PAD1_poll(0) << 8;
3199                                 data |= PAD1_poll(0);
3200
3201                                 if (NET_sendPadData(&data, 2) == -1)
3202                                         netError();
3203
3204                                 if (NET_recvPadData(&((u16*)buf)[0], 1) == -1)
3205                                         netError();
3206                                 if (NET_recvPadData(&((u16*)buf)[1], 2) == -1)
3207                                         netError();
3208                         }
3209                 }
3210                 if (Config.UseNet && pad_buf1 != NULL && pad_buf2 != NULL) {
3211                         psxBios_PADpoll(1);
3212
3213                         if (NET_sendPadData(pad_buf1, i) == -1)
3214                                 netError();
3215
3216                         if (NET_recvPadData(pad_buf1, 1) == -1)
3217                                 netError();
3218                         if (NET_recvPadData(pad_buf2, 2) == -1)
3219                                 netError();
3220                 } else {
3221                         if (!pad_stopped)  {
3222                                 if (pad_buf1) {
3223                                         psxBios_PADpoll(1);
3224                                 }
3225
3226                                 if (pad_buf2) {
3227                                         psxBios_PADpoll(2);
3228                                 }
3229                         }
3230                 }
3231
3232         if (psxHu32(0x1070) & 0x1) { // Vsync
3233                 if (RcEV[3][1].status == EvStACTIVE) {
3234                         softCall(RcEV[3][1].fhandler);
3235 //                      hwWrite32(0x1f801070, ~(1));
3236                 }
3237         }
3238
3239         if (psxHu32(0x1070) & 0x70) { // Rcnt 0,1,2
3240                 int i;
3241
3242                 for (i = 0; i < 3; i++) {
3243                         if (psxHu32(0x1070) & (1 << (i + 4))) {
3244                                 if (RcEV[i][1].status == EvStACTIVE) {
3245                                         softCall(RcEV[i][1].fhandler);
3246                                 }
3247                                 psxHwWrite32(0x1f801070, ~(1 << (i + 4)));
3248                         }
3249                 }
3250         }
3251 }
3252
3253 void psxBiosException() {
3254         int i;
3255
3256         switch (psxRegs.CP0.n.Cause & 0x3c) {
3257                 case 0x00: // Interrupt
3258                         interrupt_r26=psxRegs.CP0.n.EPC;
3259 #ifdef PSXCPU_LOG
3260 //                      PSXCPU_LOG("interrupt\n");
3261 #endif
3262                         SaveRegs();
3263
3264                         sp = psxMu32(0x6c80); // create new stack for interrupt handlers
3265
3266                         biosInterrupt();
3267
3268                         for (i = 0; i < 8; i++) {
3269                                 if (SysIntRP[i]) {
3270                                         u32 *queue = (u32 *)PSXM(SysIntRP[i]);
3271
3272                                         s0 = queue[2];
3273                                         softCall(queue[1]);
3274                                 }
3275                         }
3276
3277                         if (jmp_int != NULL) {
3278                                 int i;
3279
3280                                 psxHwWrite32(0x1f801070, 0xffffffff);
3281
3282                                 ra = jmp_int[0];
3283                                 sp = jmp_int[1];
3284                                 fp = jmp_int[2];
3285                                 for (i = 0; i < 8; i++) // s0-s7
3286                                          psxRegs.GPR.r[16 + i] = jmp_int[3 + i];
3287                                 gp = jmp_int[11];
3288
3289                                 v0 = 1;
3290                                 pc0 = ra;
3291                                 return;
3292                         }
3293                         psxHwWrite16(0x1f801070, 0);
3294                         break;
3295
3296                 case 0x20: // Syscall
3297 #ifdef PSXCPU_LOG
3298                         PSXCPU_LOG("syscall exp %x\n", a0);
3299 #endif
3300                         switch (a0) {
3301                                 case 1: // EnterCritical - disable irq's
3302                                         /* Fixes Medievil 2 not loading up new game, Digimon World not booting up and possibly others */
3303                                         v0 = (psxRegs.CP0.n.SR & 0x404) == 0x404;
3304                                         psxRegs.CP0.n.SR &= ~0x404;
3305                                         break;
3306
3307                                 case 2: // ExitCritical - enable irq's
3308                                         psxRegs.CP0.n.SR |= 0x404;
3309                                         break;
3310                                 /* Normally this should cover SYS(00h, SYS(04h but they don't do anything relevant so... */
3311                                 default:
3312                                         break;
3313                         }
3314                         pc0 = psxRegs.CP0.n.EPC + 4;
3315
3316                         psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
3317                         return;
3318
3319                 default:
3320 #ifdef PSXCPU_LOG
3321                         PSXCPU_LOG("unknown bios exception!\n");
3322 #endif
3323                         break;
3324         }
3325
3326         pc0 = psxRegs.CP0.n.EPC;
3327         if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;
3328
3329         psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
3330 }
3331
3332 #define bfreeze(ptr, size) { \
3333         if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3334         if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3335         base += size; \
3336 }
3337
3338 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3339 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3340
3341 #define bfreezepsxMptr(ptr, type) { \
3342         if (Mode == 1) { \
3343                 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3344                 else psxRu32ref(base) = 0; \
3345         } else { \
3346                 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3347                 else (ptr) = NULL; \
3348         } \
3349         base += sizeof(u32); \
3350 }
3351
3352 void psxBiosFreeze(int Mode) {
3353         u32 base = 0x40000;
3354
3355         bfreezepsxMptr(jmp_int, u32);
3356         bfreezepsxMptr(pad_buf, int);
3357         bfreezepsxMptr(pad_buf1, char);
3358         bfreezepsxMptr(pad_buf2, char);
3359         bfreezepsxMptr(heap_addr, u32);
3360         bfreezel(&pad_buf1len);
3361         bfreezel(&pad_buf2len);
3362         bfreezes(regs);
3363         bfreezes(SysIntRP);
3364         bfreezel(&CardState);
3365         bfreezes(ThreadCB);
3366         bfreezel(&CurThread);
3367         bfreezes(FDesc);
3368         bfreezel(&card_active_chan);
3369         bfreezel(&pad_stopped);
3370         bfreezel(&heap_size);
3371 }