adjust bios handling again
[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.Status |= 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.Status |= 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.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
2000                                                   ((psxRegs.CP0.n.Status & 0x3c) >> 2);
2001 }
2002
2003 void psxBios_ResetEntryInt() { // 18
2004 #ifdef PSXBIOS_LOG
2005         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2006 #endif
2007
2008         jmp_int = NULL;
2009         pc0 = ra;
2010 }
2011
2012 void psxBios_HookEntryInt() { // 19
2013 #ifdef PSXBIOS_LOG
2014         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x19]);
2015 #endif
2016
2017         jmp_int = (u32*)Ra0;
2018         pc0 = ra;
2019 }
2020
2021 void psxBios_UnDeliverEvent() { // 0x20
2022         int ev, spec;
2023         int i;
2024
2025         GetEv();
2026         GetSpec();
2027
2028 #ifdef PSXBIOS_LOG
2029         PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec);
2030 #endif
2031
2032         if (EventCB[ev][spec].status == EvStALREADY &&
2033                 EventCB[ev][spec].mode == EvMdNOINTR)
2034                 EventCB[ev][spec].status = EvStACTIVE;
2035
2036         pc0 = ra;
2037 }
2038
2039 char ffile[64], *pfile;
2040 int nfile;
2041
2042 static void buopen(int mcd, char *ptr, char *cfg)
2043 {
2044         int i;
2045         char *mcd_data = ptr;
2046
2047         strcpy(FDesc[1 + mcd].name, Ra0+5);
2048         FDesc[1 + mcd].offset = 0;
2049         FDesc[1 + mcd].mode   = a1;
2050
2051         for (i=1; i<16; i++) {
2052                 const char *fptr = mcd_data + 128 * i;
2053                 if ((*fptr & 0xF0) != 0x50) continue;
2054                 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2055                 FDesc[1 + mcd].mcfile = i;
2056                 SysPrintf("open %s\n", fptr+0xa);
2057                 v0 = 1 + mcd;
2058                 break;
2059         }
2060         if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2061                 for (i=1; i<16; i++) {
2062                         int j, xor, nblk = a1 >> 16;
2063                         char *pptr, *fptr2;
2064                         char *fptr = mcd_data + 128 * i;
2065
2066                         if ((*fptr & 0xF0) != 0xa0) continue;
2067
2068                         FDesc[1 + mcd].mcfile = i;
2069                         fptr[0] = 0x51;
2070                         fptr[4] = 0x00;
2071                         fptr[5] = 0x20 * nblk;
2072                         fptr[6] = 0x00;
2073                         fptr[7] = 0x00;
2074                         strcpy(fptr+0xa, FDesc[1 + mcd].name);
2075                         pptr = fptr2 = fptr;
2076                         for(j=2; j<=nblk; j++) {
2077                                 int k;
2078                                 for(i++; i<16; i++) {
2079                                         fptr2 += 128;
2080
2081                                         memset(fptr2, 0, 128);
2082                                         fptr2[0] = j < nblk ? 0x52 : 0x53;
2083                                         pptr[8] = i - 1;
2084                                         pptr[9] = 0;
2085                                         for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2086                                         pptr[127] = xor;
2087                                         pptr = fptr2;
2088                                         break;
2089                                 }
2090                                 /* shouldn't this return ENOSPC if i == 16? */
2091                         }
2092                         pptr[8] = pptr[9] = 0xff;
2093                         for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2094                         pptr[127] = xor;
2095                         SysPrintf("openC %s %d\n", ptr, nblk);
2096                         v0 = 1 + mcd;
2097                         /* just go ahead and resave them all */
2098                         SaveMcd(cfg, ptr, 128, 128 * 15);
2099                         break;
2100                 }
2101                 /* shouldn't this return ENOSPC if i == 16? */
2102         }
2103 }
2104
2105 /*
2106  *      int open(char *name , int mode);
2107  */
2108
2109 void psxBios_open() { // 0x32
2110         void *pa0 = Ra0;
2111
2112 #ifdef PSXBIOS_LOG
2113         PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2114 #endif
2115
2116         v0 = -1;
2117
2118         if (pa0 != INVALID_PTR) {
2119                 if (!strncmp(pa0, "bu00", 4)) {
2120                         buopen(1, Mcd1Data, Config.Mcd1);
2121                 }
2122
2123                 if (!strncmp(pa0, "bu10", 4)) {
2124                         buopen(2, Mcd2Data, Config.Mcd2);
2125                 }
2126         }
2127
2128         pc0 = ra;
2129 }
2130
2131 /*
2132  *      int lseek(int fd , int offset , int whence);
2133  */
2134
2135 void psxBios_lseek() { // 0x33
2136 #ifdef PSXBIOS_LOG
2137         PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2138 #endif
2139
2140         switch (a2) {
2141                 case 0: // SEEK_SET
2142                         FDesc[a0].offset = a1;
2143                         v0 = a1;
2144 //                      DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2145 //                      DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2146                         break;
2147
2148                 case 1: // SEEK_CUR
2149                         FDesc[a0].offset+= a1;
2150                         v0 = FDesc[a0].offset;
2151                         break;
2152         }
2153
2154         pc0 = ra;
2155 }
2156
2157
2158 /*
2159  *      int read(int fd , void *buf , int nbytes);
2160  */
2161
2162 void psxBios_read() { // 0x34
2163         char *ptr;
2164         void *pa1 = Ra1;
2165
2166 #ifdef PSXBIOS_LOG
2167         PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2168 #endif
2169
2170         v0 = -1;
2171
2172         if (pa1 != INVALID_PTR) {
2173                 switch (a0) {
2174                         case 2: buread(pa1, 1, a2); break;
2175                         case 3: buread(pa1, 2, a2); break;
2176                 }
2177         }
2178
2179         pc0 = ra;
2180 }
2181
2182 /*
2183  *      int write(int fd , void *buf , int nbytes);
2184  */
2185
2186 void psxBios_write() { // 0x35/0x03
2187         char *ptr;
2188         void *pa1 = Ra1;
2189
2190 #ifdef PSXBIOS_LOG
2191         PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2192 #endif
2193
2194         v0 = -1;
2195         if (pa1 == INVALID_PTR) {
2196                 pc0 = ra;
2197                 return;
2198         }
2199
2200         if (a0 == 1) { // stdout
2201                 char *ptr = pa1;
2202
2203                 v0 = a2;
2204                 while (a2 > 0) {
2205                         SysPrintf("%c", *ptr++); a2--;
2206                 }
2207                 pc0 = ra; return;
2208         }
2209
2210         switch (a0) {
2211                 case 2: buwrite(pa1, 1, a2); break;
2212                 case 3: buwrite(pa1, 2, a2); break;
2213         }
2214
2215         pc0 = ra;
2216 }
2217
2218 static void psxBios_write_psxout() {
2219         if (a0 == 1) { // stdout
2220                 const char *ptr = Ra1;
2221                 int len = a2;
2222
2223                 if (ptr != INVALID_PTR)
2224                         while (len-- > 0)
2225                                 SysPrintf("%c", *ptr++);
2226         }
2227 }
2228
2229 static void psxBios_putchar_psxout() { // 3d
2230         SysPrintf("%c", (char)a0);
2231 }
2232
2233 static void psxBios_puts_psxout() { // 3e/3f
2234         SysPrintf("%s", Ra0);
2235 }
2236
2237 /*
2238  *      int close(int fd);
2239  */
2240
2241 void psxBios_close() { // 0x36
2242 #ifdef PSXBIOS_LOG
2243         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2244 #endif
2245
2246         v0 = a0;
2247         pc0 = ra;
2248 }
2249
2250 void psxBios_putchar() { // 3d
2251         SysPrintf("%c", (char)a0);
2252         pc0 = ra;
2253 }
2254
2255 void psxBios_puts() { // 3e/3f
2256         SysPrintf("%s", Ra0);
2257         pc0 = ra;
2258 }
2259
2260
2261 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2262  * We want to mimic the PSX's behaviour in this case for bufile. */
2263 static size_t strlen_internal(char* p)
2264 {
2265         size_t size_of_array = 0;
2266         while (*p++) size_of_array++;
2267         return size_of_array;
2268 }
2269
2270 #define bufile(mcd) { \
2271         size_t size_of_name = strlen_internal(dir->name); \
2272         while (nfile < 16) { \
2273                 int match=1; \
2274  \
2275                 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2276                 nfile++; \
2277                 if ((*ptr & 0xF0) != 0x50) continue; \
2278                 /* Bug link files show up as free block. */ \
2279                 if (!ptr[0xa]) continue; \
2280                 ptr+= 0xa; \
2281                 if (pfile[0] == 0) { \
2282                         strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2283                         if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2284                 } else for (i=0; i<20; i++) { \
2285                         if (pfile[i] == ptr[i]) { \
2286                                                                 dir->name[i] = ptr[i]; continue; } \
2287                         if (pfile[i] == '?') { \
2288                                 dir->name[i] = ptr[i]; continue; } \
2289                         if (pfile[i] == '*') { \
2290                                 strcpy(dir->name+i, ptr+i); break; } \
2291                         match = 0; break; \
2292                 } \
2293                 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2294                 if (match == 0) { continue; } \
2295                 dir->size = 8192; \
2296                 v0 = _dir; \
2297                 break; \
2298         } \
2299 }
2300
2301 /*
2302  *      struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2303  */
2304
2305 void psxBios_firstfile() { // 42
2306         struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2307         void *pa0 = Ra0;
2308         u32 _dir = a1;
2309         char *ptr;
2310         int i;
2311
2312 #ifdef PSXBIOS_LOG
2313         PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2314 #endif
2315
2316         v0 = 0;
2317
2318         if (pa0 != INVALID_PTR) {
2319                 strcpy(ffile, pa0);
2320                 pfile = ffile+5;
2321                 nfile = 0;
2322                 if (!strncmp(pa0, "bu00", 4)) {
2323                         // firstfile() calls _card_read() internally, so deliver it's event
2324                         DeliverEvent(0x11, 0x2);
2325                         bufile(1);
2326                 } else if (!strncmp(pa0, "bu10", 4)) {
2327                         // firstfile() calls _card_read() internally, so deliver it's event
2328                         DeliverEvent(0x11, 0x2);
2329                         bufile(2);
2330                 }
2331         }
2332
2333         pc0 = ra;
2334 }
2335
2336 /*
2337  *      struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2338  */
2339
2340 void psxBios_nextfile() { // 43
2341         struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2342         u32 _dir = a0;
2343         char *ptr;
2344         int i;
2345
2346 #ifdef PSXBIOS_LOG
2347         PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2348 #endif
2349
2350         v0 = 0;
2351
2352         if (!strncmp(ffile, "bu00", 4)) {
2353                 bufile(1);
2354         }
2355
2356         if (!strncmp(ffile, "bu10", 4)) {
2357                 bufile(2);
2358         }
2359
2360         pc0 = ra;
2361 }
2362
2363 #define burename(mcd) { \
2364         for (i=1; i<16; i++) { \
2365                 int namelen, j, xor = 0; \
2366                 ptr = Mcd##mcd##Data + 128 * i; \
2367                 if ((*ptr & 0xF0) != 0x50) continue; \
2368                 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2369                 namelen = strlen(Ra1+5); \
2370                 memcpy(ptr+0xa, Ra1+5, namelen); \
2371                 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2372                 for (j=0; j<127; j++) xor^= ptr[j]; \
2373                 ptr[127] = xor; \
2374                 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2375                 v0 = 1; \
2376                 break; \
2377         } \
2378 }
2379
2380 /*
2381  *      int rename(char *old, char *new);
2382  */
2383
2384 void psxBios_rename() { // 44
2385         void *pa0 = Ra0;
2386         void *pa1 = Ra1;
2387         char *ptr;
2388         int i;
2389
2390 #ifdef PSXBIOS_LOG
2391         PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2392 #endif
2393
2394         v0 = 0;
2395
2396         if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2397                 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2398                         burename(1);
2399                 }
2400
2401                 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2402                         burename(2);
2403                 }
2404         }
2405
2406         pc0 = ra;
2407 }
2408
2409
2410 #define budelete(mcd) { \
2411         for (i=1; i<16; i++) { \
2412                 ptr = Mcd##mcd##Data + 128 * i; \
2413                 if ((*ptr & 0xF0) != 0x50) continue; \
2414                 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2415                 *ptr = (*ptr & 0xf) | 0xA0; \
2416                 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2417                 SysPrintf("delete %s\n", ptr+0xa); \
2418                 v0 = 1; \
2419                 break; \
2420         } \
2421 }
2422
2423 /*
2424  *      int delete(char *name);
2425  */
2426
2427 void psxBios_delete() { // 45
2428         void *pa0 = Ra0;
2429         char *ptr;
2430         int i;
2431
2432 #ifdef PSXBIOS_LOG
2433         PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2434 #endif
2435
2436         v0 = 0;
2437
2438         if (pa0 != INVALID_PTR) {
2439                 if (!strncmp(pa0, "bu00", 4)) {
2440                         budelete(1);
2441                 }
2442
2443                 if (!strncmp(pa0, "bu10", 4)) {
2444                         budelete(2);
2445                 }
2446         }
2447
2448         pc0 = ra;
2449 }
2450
2451 void psxBios_InitCARD() { // 4a
2452 #ifdef PSXBIOS_LOG
2453         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2454 #endif
2455
2456         CardState = 0;
2457
2458         pc0 = ra;
2459 }
2460
2461 void psxBios_StartCARD() { // 4b
2462 #ifdef PSXBIOS_LOG
2463         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2464 #endif
2465
2466         if (CardState == 0) CardState = 1;
2467
2468         pc0 = ra;
2469 }
2470
2471 void psxBios_StopCARD() { // 4c
2472 #ifdef PSXBIOS_LOG
2473         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2474 #endif
2475
2476         if (CardState == 1) CardState = 0;
2477
2478         pc0 = ra;
2479 }
2480
2481 void psxBios__card_write() { // 0x4e
2482         void *pa2 = Ra2;
2483         int port;
2484
2485 #ifdef PSXBIOS_LOG
2486         PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2487 #endif
2488         /*
2489         Function also accepts sector 400h (a bug).
2490         But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2491         */
2492         if (!(a1 <= 0x3FF))
2493         {
2494                 /* Invalid sectors */
2495                 v0 = 0; pc0 = ra;
2496                 return;
2497         }
2498         card_active_chan = a0;
2499         port = a0 >> 4;
2500
2501         if (pa2 != INVALID_PTR) {
2502                 if (port == 0) {
2503                         memcpy(Mcd1Data + a1 * 128, pa2, 128);
2504                         SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2505                 } else {
2506                         memcpy(Mcd2Data + a1 * 128, pa2, 128);
2507                         SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2508                 }
2509         }
2510
2511         DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2512 //      DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2513
2514         v0 = 1; pc0 = ra;
2515 }
2516
2517 void psxBios__card_read() { // 0x4f
2518         void *pa2 = Ra2;
2519         int port;
2520
2521 #ifdef PSXBIOS_LOG
2522         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2523 #endif
2524         /*
2525         Function also accepts sector 400h (a bug).
2526         But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2527         */
2528         if (!(a1 <= 0x3FF))
2529         {
2530                 /* Invalid sectors */
2531                 v0 = 0; pc0 = ra;
2532                 return;
2533         }
2534         card_active_chan = a0;
2535         port = a0 >> 4;
2536
2537         if (pa2 != INVALID_PTR) {
2538                 if (port == 0) {
2539                         memcpy(pa2, Mcd1Data + a1 * 128, 128);
2540                 } else {
2541                         memcpy(pa2, Mcd2Data + a1 * 128, 128);
2542                 }
2543         }
2544
2545         DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2546 //      DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2547
2548         v0 = 1; pc0 = ra;
2549 }
2550
2551 void psxBios__new_card() { // 0x50
2552 #ifdef PSXBIOS_LOG
2553         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2554 #endif
2555
2556         pc0 = ra;
2557 }
2558
2559 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2560 void psxBios__get_error(void) // 55
2561 {
2562         v0 = 0;
2563         pc0 = ra;
2564 }
2565
2566 void psxBios_Krom2RawAdd() { // 0x51
2567         int i = 0;
2568
2569         const u32 table_8140[][2] = {
2570                 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2571                 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2572                 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2573                 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2574                 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2575                 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2576                 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2577                 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2578                 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2579                 {0xffff, 0}
2580         };
2581
2582         const u32 table_889f[][2] = {
2583                 {0x889f, 0x3d68},  {0x8900, 0x40ec},  {0x897f, 0x4fb0},  {0x8a00, 0x56f4},
2584                 {0x8a7f, 0x65b8},  {0x8b00, 0x6cfc},  {0x8b7f, 0x7bc0},  {0x8c00, 0x8304},
2585                 {0x8c7f, 0x91c8},  {0x8d00, 0x990c},  {0x8d7f, 0xa7d0},  {0x8e00, 0xaf14},
2586                 {0x8e7f, 0xbdd8},  {0x8f00, 0xc51c},  {0x8f7f, 0xd3e0},  {0x9000, 0xdb24},
2587                 {0x907f, 0xe9e8},  {0x9100, 0xf12c},  {0x917f, 0xfff0},  {0x9200, 0x10734},
2588                 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2589                 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2590                 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2591                 {0xffff, 0}
2592         };
2593
2594         if (a0 >= 0x8140 && a0 <= 0x84be) {
2595                 while (table_8140[i][0] <= a0) i++;
2596                 a0 -= table_8140[i - 1][0];
2597                 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2598         } else if (a0 >= 0x889f && a0 <= 0x9872) {
2599                 while (table_889f[i][0] <= a0) i++;
2600                 a0 -= table_889f[i - 1][0];
2601                 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2602         } else {
2603                 v0 = 0xffffffff;
2604         }
2605
2606         pc0 = ra;
2607 }
2608
2609 void psxBios_GetC0Table() { // 56
2610 #ifdef PSXBIOS_LOG
2611         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2612 #endif
2613
2614         v0 = 0x674; pc0 = ra;
2615 }
2616
2617 void psxBios_GetB0Table() { // 57
2618 #ifdef PSXBIOS_LOG
2619         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2620 #endif
2621
2622         v0 = 0x874; pc0 = ra;
2623 }
2624
2625 void psxBios__card_chan() { // 0x58
2626 #ifdef PSXBIOS_LOG
2627         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2628 #endif
2629
2630         v0 = card_active_chan;
2631         pc0 = ra;
2632 }
2633
2634 void psxBios_ChangeClearPad() { // 5b
2635 #ifdef PSXBIOS_LOG
2636         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2637 #endif
2638
2639         pc0 = ra;
2640 }
2641
2642 void psxBios__card_status() { // 5c
2643 #ifdef PSXBIOS_LOG
2644         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2645 #endif
2646
2647         v0 = card_active_chan;
2648         pc0 = ra;
2649 }
2650
2651 void psxBios__card_wait() { // 5d
2652 #ifdef PSXBIOS_LOG
2653         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2654 #endif
2655
2656         v0 = 1;
2657         pc0 = ra;
2658 }
2659
2660 /* System calls C0 */
2661
2662 /*
2663  * int SysEnqIntRP(int index , long *queue);
2664  */
2665
2666 void psxBios_SysEnqIntRP() { // 02
2667 #ifdef PSXBIOS_LOG
2668         PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x02] ,a0);
2669 #endif
2670
2671         SysIntRP[a0] = a1;
2672
2673         v0 = 0; pc0 = ra;
2674 }
2675
2676 /*
2677  * int SysDeqIntRP(int index , long *queue);
2678  */
2679
2680 void psxBios_SysDeqIntRP() { // 03
2681 #ifdef PSXBIOS_LOG
2682         PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x03], a0);
2683 #endif
2684
2685         SysIntRP[a0] = 0;
2686
2687         v0 = 0; pc0 = ra;
2688 }
2689
2690 void psxBios_ChangeClearRCnt() { // 0a
2691         u32 *ptr;
2692
2693 #ifdef PSXBIOS_LOG
2694         PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2695 #endif
2696
2697         ptr = (u32*)PSXM((a0 << 2) + 0x8600);
2698         v0 = *ptr;
2699         *ptr = a1;
2700
2701 //      psxRegs.CP0.n.Status|= 0x404;
2702         pc0 = ra;
2703 }
2704
2705 void psxBios_dummy() {
2706 #ifdef PSXBIOS_LOG
2707         PSXBIOS_LOG("unk %x call: %x\n", pc0 & 0x1fffff, t1);
2708 #endif
2709         pc0 = ra;
2710 }
2711
2712 void (*biosA0[256])();
2713 void (*biosB0[256])();
2714 void (*biosC0[256])();
2715
2716 #include "sjisfont.h"
2717
2718 void psxBiosInit() {
2719         u32 base, size;
2720         u32 *ptr;
2721         int i;
2722         uLongf len;
2723
2724         for(i = 0; i < 256; i++) {
2725                 biosA0[i] = NULL;
2726                 biosB0[i] = NULL;
2727                 biosC0[i] = NULL;
2728         }
2729         biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
2730         biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
2731         biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
2732         biosA0[0x3f] = psxBios_printf_psxout;
2733
2734         if (!Config.HLE) return;
2735
2736         for(i = 0; i < 256; i++) {
2737                 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
2738                 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
2739                 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
2740         }
2741
2742         biosA0[0x00] = psxBios_open;
2743         biosA0[0x01] = psxBios_lseek;
2744         biosA0[0x02] = psxBios_read;
2745         biosA0[0x03] = psxBios_write;
2746         biosA0[0x04] = psxBios_close;
2747         //biosA0[0x05] = psxBios_ioctl;
2748         //biosA0[0x06] = psxBios_exit;
2749         //biosA0[0x07] = psxBios_sys_a0_07;
2750         biosA0[0x08] = psxBios_getc;
2751         biosA0[0x09] = psxBios_putc;
2752         biosA0[0x0a] = psxBios_todigit;
2753         //biosA0[0x0b] = psxBios_atof;
2754         //biosA0[0x0c] = psxBios_strtoul;
2755         //biosA0[0x0d] = psxBios_strtol;
2756         biosA0[0x0e] = psxBios_abs;
2757         biosA0[0x0f] = psxBios_labs;
2758         biosA0[0x10] = psxBios_atoi;
2759         biosA0[0x11] = psxBios_atol;
2760         //biosA0[0x12] = psxBios_atob;
2761         biosA0[0x13] = psxBios_setjmp;
2762         biosA0[0x14] = psxBios_longjmp;
2763         biosA0[0x15] = psxBios_strcat;
2764         biosA0[0x16] = psxBios_strncat;
2765         biosA0[0x17] = psxBios_strcmp;
2766         biosA0[0x18] = psxBios_strncmp;
2767         biosA0[0x19] = psxBios_strcpy;
2768         biosA0[0x1a] = psxBios_strncpy;
2769         biosA0[0x1b] = psxBios_strlen;
2770         biosA0[0x1c] = psxBios_index;
2771         biosA0[0x1d] = psxBios_rindex;
2772         biosA0[0x1e] = psxBios_strchr;
2773         biosA0[0x1f] = psxBios_strrchr;
2774         biosA0[0x20] = psxBios_strpbrk;
2775         biosA0[0x21] = psxBios_strspn;
2776         biosA0[0x22] = psxBios_strcspn;
2777         biosA0[0x23] = psxBios_strtok;
2778         biosA0[0x24] = psxBios_strstr;
2779         biosA0[0x25] = psxBios_toupper;
2780         biosA0[0x26] = psxBios_tolower;
2781         biosA0[0x27] = psxBios_bcopy;
2782         biosA0[0x28] = psxBios_bzero;
2783         biosA0[0x29] = psxBios_bcmp;
2784         biosA0[0x2a] = psxBios_memcpy;
2785         biosA0[0x2b] = psxBios_memset;
2786         biosA0[0x2c] = psxBios_memmove;
2787         biosA0[0x2d] = psxBios_memcmp;
2788         biosA0[0x2e] = psxBios_memchr;
2789         biosA0[0x2f] = psxBios_rand;
2790         biosA0[0x30] = psxBios_srand;
2791         biosA0[0x31] = psxBios_qsort;
2792         //biosA0[0x32] = psxBios_strtod;
2793         biosA0[0x33] = psxBios_malloc;
2794         biosA0[0x34] = psxBios_free;
2795         //biosA0[0x35] = psxBios_lsearch;
2796         //biosA0[0x36] = psxBios_bsearch;
2797         biosA0[0x37] = psxBios_calloc;
2798         biosA0[0x38] = psxBios_realloc;
2799         biosA0[0x39] = psxBios_InitHeap;
2800         //biosA0[0x3a] = psxBios__exit;
2801         biosA0[0x3b] = psxBios_getchar;
2802         biosA0[0x3c] = psxBios_putchar;
2803         //biosA0[0x3d] = psxBios_gets;
2804         //biosA0[0x40] = psxBios_sys_a0_40;
2805         //biosA0[0x41] = psxBios_LoadTest;
2806         biosA0[0x42] = psxBios_Load;
2807         biosA0[0x43] = psxBios_Exec;
2808         biosA0[0x44] = psxBios_FlushCache;
2809         //biosA0[0x45] = psxBios_InstallInterruptHandler;
2810         biosA0[0x46] = psxBios_GPU_dw;
2811         biosA0[0x47] = psxBios_mem2vram;
2812         biosA0[0x48] = psxBios_SendGPU;
2813         biosA0[0x49] = psxBios_GPU_cw;
2814         biosA0[0x4a] = psxBios_GPU_cwb;
2815         biosA0[0x4b] = psxBios_GPU_SendPackets;
2816         biosA0[0x4c] = psxBios_sys_a0_4c;
2817         biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
2818         //biosA0[0x4e] = psxBios_GPU_sync;
2819         //biosA0[0x4f] = psxBios_sys_a0_4f;
2820         //biosA0[0x50] = psxBios_sys_a0_50;
2821         biosA0[0x51] = psxBios_LoadExec;
2822         //biosA0[0x52] = psxBios_GetSysSp;
2823         //biosA0[0x53] = psxBios_sys_a0_53;
2824         //biosA0[0x54] = psxBios__96_init_a54;
2825         //biosA0[0x55] = psxBios__bu_init_a55;
2826         //biosA0[0x56] = psxBios__96_remove_a56;
2827         //biosA0[0x57] = psxBios_sys_a0_57;
2828         //biosA0[0x58] = psxBios_sys_a0_58;
2829         //biosA0[0x59] = psxBios_sys_a0_59;
2830         //biosA0[0x5a] = psxBios_sys_a0_5a;
2831         //biosA0[0x5b] = psxBios_dev_tty_init;
2832         //biosA0[0x5c] = psxBios_dev_tty_open;
2833         //biosA0[0x5d] = psxBios_sys_a0_5d;
2834         //biosA0[0x5e] = psxBios_dev_tty_ioctl;
2835         //biosA0[0x5f] = psxBios_dev_cd_open;
2836         //biosA0[0x60] = psxBios_dev_cd_read;
2837         //biosA0[0x61] = psxBios_dev_cd_close;
2838         //biosA0[0x62] = psxBios_dev_cd_firstfile;
2839         //biosA0[0x63] = psxBios_dev_cd_nextfile;
2840         //biosA0[0x64] = psxBios_dev_cd_chdir;
2841         //biosA0[0x65] = psxBios_dev_card_open;
2842         //biosA0[0x66] = psxBios_dev_card_read;
2843         //biosA0[0x67] = psxBios_dev_card_write;
2844         //biosA0[0x68] = psxBios_dev_card_close;
2845         //biosA0[0x69] = psxBios_dev_card_firstfile;
2846         //biosA0[0x6a] = psxBios_dev_card_nextfile;
2847         //biosA0[0x6b] = psxBios_dev_card_erase;
2848         //biosA0[0x6c] = psxBios_dev_card_undelete;
2849         //biosA0[0x6d] = psxBios_dev_card_format;
2850         //biosA0[0x6e] = psxBios_dev_card_rename;
2851         //biosA0[0x6f] = psxBios_dev_card_6f;
2852         biosA0[0x70] = psxBios__bu_init;
2853         biosA0[0x71] = psxBios__96_init;
2854         biosA0[0x72] = psxBios__96_remove;
2855         //biosA0[0x73] = psxBios_sys_a0_73;
2856         //biosA0[0x74] = psxBios_sys_a0_74;
2857         //biosA0[0x75] = psxBios_sys_a0_75;
2858         //biosA0[0x76] = psxBios_sys_a0_76;
2859         //biosA0[0x77] = psxBios_sys_a0_77;
2860         //biosA0[0x78] = psxBios__96_CdSeekL;
2861         //biosA0[0x79] = psxBios_sys_a0_79;
2862         //biosA0[0x7a] = psxBios_sys_a0_7a;
2863         //biosA0[0x7b] = psxBios_sys_a0_7b;
2864         //biosA0[0x7c] = psxBios__96_CdGetStatus;
2865         //biosA0[0x7d] = psxBios_sys_a0_7d;
2866         //biosA0[0x7e] = psxBios__96_CdRead;
2867         //biosA0[0x7f] = psxBios_sys_a0_7f;
2868         //biosA0[0x80] = psxBios_sys_a0_80;
2869         //biosA0[0x81] = psxBios_sys_a0_81;
2870         //biosA0[0x82] = psxBios_sys_a0_82;
2871         //biosA0[0x83] = psxBios_sys_a0_83;
2872         //biosA0[0x84] = psxBios_sys_a0_84;
2873         //biosA0[0x85] = psxBios__96_CdStop;
2874         //biosA0[0x86] = psxBios_sys_a0_86;
2875         //biosA0[0x87] = psxBios_sys_a0_87;
2876         //biosA0[0x88] = psxBios_sys_a0_88;
2877         //biosA0[0x89] = psxBios_sys_a0_89;
2878         //biosA0[0x8a] = psxBios_sys_a0_8a;
2879         //biosA0[0x8b] = psxBios_sys_a0_8b;
2880         //biosA0[0x8c] = psxBios_sys_a0_8c;
2881         //biosA0[0x8d] = psxBios_sys_a0_8d;
2882         //biosA0[0x8e] = psxBios_sys_a0_8e;
2883         //biosA0[0x8f] = psxBios_sys_a0_8f;
2884         //biosA0[0x90] = psxBios_sys_a0_90;
2885         //biosA0[0x91] = psxBios_sys_a0_91;
2886         //biosA0[0x92] = psxBios_sys_a0_92;
2887         //biosA0[0x93] = psxBios_sys_a0_93;
2888         //biosA0[0x94] = psxBios_sys_a0_94;
2889         //biosA0[0x95] = psxBios_sys_a0_95;
2890         //biosA0[0x96] = psxBios_AddCDROMDevice;
2891         //biosA0[0x97] = psxBios_AddMemCardDevide;
2892         //biosA0[0x98] = psxBios_DisableKernelIORedirection;
2893         //biosA0[0x99] = psxBios_EnableKernelIORedirection;
2894         //biosA0[0x9a] = psxBios_sys_a0_9a;
2895         //biosA0[0x9b] = psxBios_sys_a0_9b;
2896         //biosA0[0x9c] = psxBios_SetConf;
2897         //biosA0[0x9d] = psxBios_GetConf;
2898         //biosA0[0x9e] = psxBios_sys_a0_9e;
2899         biosA0[0x9f] = psxBios_SetMem;
2900         //biosA0[0xa0] = psxBios__boot;
2901         //biosA0[0xa1] = psxBios_SystemError;
2902         //biosA0[0xa2] = psxBios_EnqueueCdIntr;
2903         //biosA0[0xa3] = psxBios_DequeueCdIntr;
2904         //biosA0[0xa4] = psxBios_sys_a0_a4;
2905         //biosA0[0xa5] = psxBios_ReadSector;
2906         biosA0[0xa6] = psxBios_get_cd_status;
2907         //biosA0[0xa7] = psxBios_bufs_cb_0;
2908         //biosA0[0xa8] = psxBios_bufs_cb_1;
2909         //biosA0[0xa9] = psxBios_bufs_cb_2;
2910         //biosA0[0xaa] = psxBios_bufs_cb_3;
2911         biosA0[0xab] = psxBios__card_info;
2912         biosA0[0xac] = psxBios__card_load;
2913         //biosA0[0axd] = psxBios__card_auto;
2914         //biosA0[0xae] = psxBios_bufs_cd_4;
2915         //biosA0[0xaf] = psxBios_sys_a0_af;
2916         //biosA0[0xb0] = psxBios_sys_a0_b0;
2917         //biosA0[0xb1] = psxBios_sys_a0_b1;
2918         //biosA0[0xb2] = psxBios_do_a_long_jmp
2919         //biosA0[0xb3] = psxBios_sys_a0_b3;
2920         //biosA0[0xb4] = psxBios_sub_function;
2921 //*******************B0 CALLS****************************
2922         //biosB0[0x00] = psxBios_SysMalloc;
2923         //biosB0[0x01] = psxBios_sys_b0_01;
2924         biosB0[0x02] = psxBios_SetRCnt;
2925         biosB0[0x03] = psxBios_GetRCnt;
2926         biosB0[0x04] = psxBios_StartRCnt;
2927         biosB0[0x05] = psxBios_StopRCnt;
2928         biosB0[0x06] = psxBios_ResetRCnt;
2929         biosB0[0x07] = psxBios_DeliverEvent;
2930         biosB0[0x08] = psxBios_OpenEvent;
2931         biosB0[0x09] = psxBios_CloseEvent;
2932         biosB0[0x0a] = psxBios_WaitEvent;
2933         biosB0[0x0b] = psxBios_TestEvent;
2934         biosB0[0x0c] = psxBios_EnableEvent;
2935         biosB0[0x0d] = psxBios_DisableEvent;
2936         biosB0[0x0e] = psxBios_OpenTh;
2937         biosB0[0x0f] = psxBios_CloseTh;
2938         biosB0[0x10] = psxBios_ChangeTh;
2939         //biosB0[0x11] = psxBios_psxBios_b0_11;
2940         biosB0[0x12] = psxBios_InitPAD;
2941         biosB0[0x13] = psxBios_StartPAD;
2942         biosB0[0x14] = psxBios_StopPAD;
2943         biosB0[0x15] = psxBios_PAD_init;
2944         biosB0[0x16] = psxBios_PAD_dr;
2945         biosB0[0x17] = psxBios_ReturnFromException;
2946         biosB0[0x18] = psxBios_ResetEntryInt;
2947         biosB0[0x19] = psxBios_HookEntryInt;
2948         //biosB0[0x1a] = psxBios_sys_b0_1a;
2949         //biosB0[0x1b] = psxBios_sys_b0_1b;
2950         //biosB0[0x1c] = psxBios_sys_b0_1c;
2951         //biosB0[0x1d] = psxBios_sys_b0_1d;
2952         //biosB0[0x1e] = psxBios_sys_b0_1e;
2953         //biosB0[0x1f] = psxBios_sys_b0_1f;
2954         biosB0[0x20] = psxBios_UnDeliverEvent;
2955         //biosB0[0x21] = psxBios_sys_b0_21;
2956         //biosB0[0x22] = psxBios_sys_b0_22;
2957         //biosB0[0x23] = psxBios_sys_b0_23;
2958         //biosB0[0x24] = psxBios_sys_b0_24;
2959         //biosB0[0x25] = psxBios_sys_b0_25;
2960         //biosB0[0x26] = psxBios_sys_b0_26;
2961         //biosB0[0x27] = psxBios_sys_b0_27;
2962         //biosB0[0x28] = psxBios_sys_b0_28;
2963         //biosB0[0x29] = psxBios_sys_b0_29;
2964         //biosB0[0x2a] = psxBios_sys_b0_2a;
2965         //biosB0[0x2b] = psxBios_sys_b0_2b;
2966         //biosB0[0x2c] = psxBios_sys_b0_2c;
2967         //biosB0[0x2d] = psxBios_sys_b0_2d;
2968         //biosB0[0x2e] = psxBios_sys_b0_2e;
2969         //biosB0[0x2f] = psxBios_sys_b0_2f;
2970         //biosB0[0x30] = psxBios_sys_b0_30;
2971         //biosB0[0x31] = psxBios_sys_b0_31;
2972         biosB0[0x32] = psxBios_open;
2973         biosB0[0x33] = psxBios_lseek;
2974         biosB0[0x34] = psxBios_read;
2975         biosB0[0x35] = psxBios_write;
2976         biosB0[0x36] = psxBios_close;
2977         //biosB0[0x37] = psxBios_ioctl;
2978         //biosB0[0x38] = psxBios_exit;
2979         //biosB0[0x39] = psxBios_sys_b0_39;
2980         //biosB0[0x3a] = psxBios_getc;
2981         //biosB0[0x3b] = psxBios_putc;
2982         biosB0[0x3c] = psxBios_getchar;
2983         //biosB0[0x3e] = psxBios_gets;
2984         //biosB0[0x40] = psxBios_cd;
2985         biosB0[0x41] = psxBios_format;
2986         biosB0[0x42] = psxBios_firstfile;
2987         biosB0[0x43] = psxBios_nextfile;
2988         biosB0[0x44] = psxBios_rename;
2989         biosB0[0x45] = psxBios_delete;
2990         //biosB0[0x46] = psxBios_undelete;
2991         //biosB0[0x47] = psxBios_AddDevice;
2992         //biosB0[0x48] = psxBios_RemoteDevice;
2993         //biosB0[0x49] = psxBios_PrintInstalledDevices;
2994         biosB0[0x4a] = psxBios_InitCARD;
2995         biosB0[0x4b] = psxBios_StartCARD;
2996         biosB0[0x4c] = psxBios_StopCARD;
2997         //biosB0[0x4d] = psxBios_sys_b0_4d;
2998         biosB0[0x4e] = psxBios__card_write;
2999         biosB0[0x4f] = psxBios__card_read;
3000         biosB0[0x50] = psxBios__new_card;
3001         biosB0[0x51] = psxBios_Krom2RawAdd;
3002         //biosB0[0x52] = psxBios_sys_b0_52;
3003         //biosB0[0x53] = psxBios_sys_b0_53;
3004         //biosB0[0x54] = psxBios__get_errno;
3005         biosB0[0x55] = psxBios__get_error;
3006         biosB0[0x56] = psxBios_GetC0Table;
3007         biosB0[0x57] = psxBios_GetB0Table;
3008         biosB0[0x58] = psxBios__card_chan;
3009         //biosB0[0x59] = psxBios_sys_b0_59;
3010         //biosB0[0x5a] = psxBios_sys_b0_5a;
3011         biosB0[0x5b] = psxBios_ChangeClearPad;
3012         biosB0[0x5c] = psxBios__card_status;
3013         biosB0[0x5d] = psxBios__card_wait;
3014 //*******************C0 CALLS****************************
3015         //biosC0[0x00] = psxBios_InitRCnt;
3016         //biosC0[0x01] = psxBios_InitException;
3017         biosC0[0x02] = psxBios_SysEnqIntRP;
3018         biosC0[0x03] = psxBios_SysDeqIntRP;
3019         //biosC0[0x04] = psxBios_get_free_EvCB_slot;
3020         //biosC0[0x05] = psxBios_get_free_TCB_slot;
3021         //biosC0[0x06] = psxBios_ExceptionHandler;
3022         //biosC0[0x07] = psxBios_InstallExeptionHandler;
3023         //biosC0[0x08] = psxBios_SysInitMemory;
3024         //biosC0[0x09] = psxBios_SysInitKMem;
3025         biosC0[0x0a] = psxBios_ChangeClearRCnt;
3026         //biosC0[0x0b] = psxBios_SystemError;
3027         //biosC0[0x0c] = psxBios_InitDefInt;
3028         //biosC0[0x0d] = psxBios_sys_c0_0d;
3029         //biosC0[0x0e] = psxBios_sys_c0_0e;
3030         //biosC0[0x0f] = psxBios_sys_c0_0f;
3031         //biosC0[0x10] = psxBios_sys_c0_10;
3032         //biosC0[0x11] = psxBios_sys_c0_11;
3033         //biosC0[0x12] = psxBios_InstallDevices;
3034         //biosC0[0x13] = psxBios_FlushStfInOutPut;
3035         //biosC0[0x14] = psxBios_sys_c0_14;
3036         //biosC0[0x15] = psxBios__cdevinput;
3037         //biosC0[0x16] = psxBios__cdevscan;
3038         //biosC0[0x17] = psxBios__circgetc;
3039         //biosC0[0x18] = psxBios__circputc;
3040         //biosC0[0x19] = psxBios_ioabort;
3041         //biosC0[0x1a] = psxBios_sys_c0_1a
3042         //biosC0[0x1b] = psxBios_KernelRedirect;
3043         //biosC0[0x1c] = psxBios_PatchAOTable;
3044 //************** THE END ***************************************
3045 /**/
3046         base = 0x1000;
3047         size = sizeof(EvCB) * 32;
3048         EventCB = (void *)&psxR[base]; base += size * 6;
3049         memset(EventCB, 0, size * 6);
3050         HwEV = EventCB;
3051         EvEV = EventCB + 32;
3052         RcEV = EventCB + 32 * 2;
3053         UeEV = EventCB + 32 * 3;
3054         SwEV = EventCB + 32 * 4;
3055         ThEV = EventCB + 32 * 5;
3056
3057         ptr = (u32 *)&psxM[0x0874]; // b0 table
3058         ptr[0] = SWAPu32(0x4c54 - 0x884);
3059
3060         ptr = (u32 *)&psxM[0x0674]; // c0 table
3061         ptr[6] = SWAPu32(0xc80);
3062
3063         memset(SysIntRP, 0, sizeof(SysIntRP));
3064         memset(ThreadCB, 0, sizeof(ThreadCB));
3065         ThreadCB[0].status = 2; // main thread
3066
3067         pad_stopped = 1;
3068         jmp_int = NULL;
3069         pad_buf = NULL;
3070         pad_buf1 = NULL;
3071         pad_buf2 = NULL;
3072         pad_buf1len = pad_buf2len = 0;
3073         heap_addr = NULL;
3074         heap_end = NULL;
3075         heap_size = 0;
3076         CardState = -1;
3077         CurThread = 0;
3078         memset(FDesc, 0, sizeof(FDesc));
3079         card_active_chan = 0;
3080
3081         psxMu32ref(0x0150) = SWAPu32(0x160);
3082         psxMu32ref(0x0154) = SWAPu32(0x320);
3083         psxMu32ref(0x0160) = SWAPu32(0x248);
3084         strcpy((char *)&psxM[0x248], "bu");
3085 /*      psxMu32ref(0x0ca8) = SWAPu32(0x1f410004);
3086         psxMu32ref(0x0cf0) = SWAPu32(0x3c020000);
3087         psxMu32ref(0x0cf4) = SWAPu32(0x2442641c);
3088         psxMu32ref(0x09e0) = SWAPu32(0x43d0);
3089         psxMu32ref(0x4d98) = SWAPu32(0x946f000a);
3090 */
3091         // opcode HLE
3092         psxRu32ref(0x0000) = SWAPu32((0x3b << 26) | 4);
3093         /* Whatever this does, it actually breaks CTR, even without the uninitiliazed memory patch.
3094         Normally games shouldn't read from address 0 yet they do. See explanation below in details. */
3095         //psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0);
3096         psxMu32ref(0x00a0) = SWAPu32((0x3b << 26) | 1);
3097         psxMu32ref(0x00b0) = SWAPu32((0x3b << 26) | 2);
3098         psxMu32ref(0x00c0) = SWAPu32((0x3b << 26) | 3);
3099         psxMu32ref(0x4c54) = SWAPu32((0x3b << 26) | 0);
3100         psxMu32ref(0x8000) = SWAPu32((0x3b << 26) | 5);
3101         psxMu32ref(0x07a0) = SWAPu32((0x3b << 26) | 0);
3102         psxMu32ref(0x0884) = SWAPu32((0x3b << 26) | 0);
3103         psxMu32ref(0x0894) = SWAPu32((0x3b << 26) | 0);
3104
3105         // initial stack pointer for BIOS interrupt
3106         psxMu32ref(0x6c80) = SWAPu32(0x000085c8);
3107
3108         // initial RNG seed
3109         psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3110
3111         // fonts
3112         len = 0x80000 - 0x66000;
3113         uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3114         len = 0x80000 - 0x69d68;
3115         uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3116
3117         // memory size 2 MB
3118         psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3119
3120         hleSoftCall = FALSE;
3121
3122         /*      Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3123                 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3124                 Here are some examples of games not working with this fix in place :
3125                 R-type won't get past the Irem logo if not implemented.
3126                 Crash Team Racing will softlock after the Sony logo.
3127         */
3128
3129         psxMu32ref(0x0000) = SWAPu32(0x00000003);
3130         /*
3131         But overwritten by 00000003h after soon.
3132         psxMu32ref(0x0000) = SWAPu32(0x00001A3C);
3133         */
3134         psxMu32ref(0x0004) = SWAPu32(0x800C5A27);
3135         psxMu32ref(0x0008) = SWAPu32(0x08000403);
3136         psxMu32ref(0x000C) = SWAPu32(0x00000000);
3137 }
3138
3139 void psxBiosShutdown() {
3140 }
3141
3142 #define psxBios_PADpoll(pad) { \
3143         PAD##pad##_startPoll(pad); \
3144         pad_buf##pad[0] = 0; \
3145         pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3146         if (!(pad_buf##pad[1] & 0x0f)) { \
3147                 bufcount = 32; \
3148         } else { \
3149                 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3150         } \
3151         PAD##pad##_poll(0); \
3152         i = 2; \
3153         while (bufcount--) { \
3154                 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3155         } \
3156 }
3157
3158 void biosInterrupt() {
3159         int i, bufcount;
3160
3161 //      if (psxHu32(0x1070) & 0x1) { // Vsync
3162                 if (pad_buf != NULL) {
3163                         u32 *buf = (u32*)pad_buf;
3164
3165                         if (!Config.UseNet) {
3166                                 PAD1_startPoll(1);
3167                                 if (PAD1_poll(0x42) == 0x23) {
3168                                         PAD1_poll(0);
3169                                         *buf = PAD1_poll(0) << 8;
3170                                         *buf |= PAD1_poll(0);
3171                                         PAD1_poll(0);
3172                                         *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3173                                         *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3174                                 } else {
3175                                         PAD1_poll(0);
3176                                         *buf = PAD1_poll(0) << 8;
3177                                         *buf|= PAD1_poll(0);
3178                                 }
3179
3180                                 PAD2_startPoll(2);
3181                                 if (PAD2_poll(0x42) == 0x23) {
3182                                         PAD2_poll(0);
3183                                         *buf |= PAD2_poll(0) << 24;
3184                                         *buf |= PAD2_poll(0) << 16;
3185                                         PAD2_poll(0);
3186                                         *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3187                                         *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3188                                 } else {
3189                                         PAD2_poll(0);
3190                                         *buf |= PAD2_poll(0) << 24;
3191                                         *buf |= PAD2_poll(0) << 16;
3192                                 }
3193                         } else {
3194                                 u16 data;
3195
3196                                 PAD1_startPoll(1);
3197                                 PAD1_poll(0x42);
3198                                 PAD1_poll(0);
3199                                 data = PAD1_poll(0) << 8;
3200                                 data |= PAD1_poll(0);
3201
3202                                 if (NET_sendPadData(&data, 2) == -1)
3203                                         netError();
3204
3205                                 if (NET_recvPadData(&((u16*)buf)[0], 1) == -1)
3206                                         netError();
3207                                 if (NET_recvPadData(&((u16*)buf)[1], 2) == -1)
3208                                         netError();
3209                         }
3210                 }
3211                 if (Config.UseNet && pad_buf1 != NULL && pad_buf2 != NULL) {
3212                         psxBios_PADpoll(1);
3213
3214                         if (NET_sendPadData(pad_buf1, i) == -1)
3215                                 netError();
3216
3217                         if (NET_recvPadData(pad_buf1, 1) == -1)
3218                                 netError();
3219                         if (NET_recvPadData(pad_buf2, 2) == -1)
3220                                 netError();
3221                 } else {
3222                         if (!pad_stopped)  {
3223                                 if (pad_buf1) {
3224                                         psxBios_PADpoll(1);
3225                                 }
3226
3227                                 if (pad_buf2) {
3228                                         psxBios_PADpoll(2);
3229                                 }
3230                         }
3231                 }
3232
3233         if (psxHu32(0x1070) & 0x1) { // Vsync
3234                 if (RcEV[3][1].status == EvStACTIVE) {
3235                         softCall(RcEV[3][1].fhandler);
3236 //                      hwWrite32(0x1f801070, ~(1));
3237                 }
3238         }
3239
3240         if (psxHu32(0x1070) & 0x70) { // Rcnt 0,1,2
3241                 int i;
3242
3243                 for (i = 0; i < 3; i++) {
3244                         if (psxHu32(0x1070) & (1 << (i + 4))) {
3245                                 if (RcEV[i][1].status == EvStACTIVE) {
3246                                         softCall(RcEV[i][1].fhandler);
3247                                 }
3248                                 psxHwWrite32(0x1f801070, ~(1 << (i + 4)));
3249                         }
3250                 }
3251         }
3252 }
3253
3254 void psxBiosException() {
3255         int i;
3256
3257         switch (psxRegs.CP0.n.Cause & 0x3c) {
3258                 case 0x00: // Interrupt
3259                         interrupt_r26=psxRegs.CP0.n.EPC;
3260 #ifdef PSXCPU_LOG
3261 //                      PSXCPU_LOG("interrupt\n");
3262 #endif
3263                         SaveRegs();
3264
3265                         sp = psxMu32(0x6c80); // create new stack for interrupt handlers
3266
3267                         biosInterrupt();
3268
3269                         for (i = 0; i < 8; i++) {
3270                                 if (SysIntRP[i]) {
3271                                         u32 *queue = (u32 *)PSXM(SysIntRP[i]);
3272
3273                                         s0 = queue[2];
3274                                         softCall(queue[1]);
3275                                 }
3276                         }
3277
3278                         if (jmp_int != NULL) {
3279                                 int i;
3280
3281                                 psxHwWrite32(0x1f801070, 0xffffffff);
3282
3283                                 ra = jmp_int[0];
3284                                 sp = jmp_int[1];
3285                                 fp = jmp_int[2];
3286                                 for (i = 0; i < 8; i++) // s0-s7
3287                                          psxRegs.GPR.r[16 + i] = jmp_int[3 + i];
3288                                 gp = jmp_int[11];
3289
3290                                 v0 = 1;
3291                                 pc0 = ra;
3292                                 return;
3293                         }
3294                         psxHwWrite16(0x1f801070, 0);
3295                         break;
3296
3297                 case 0x20: // Syscall
3298 #ifdef PSXCPU_LOG
3299                         PSXCPU_LOG("syscall exp %x\n", a0);
3300 #endif
3301                         switch (a0) {
3302                                 case 1: // EnterCritical - disable irq's
3303                                         /* Fixes Medievil 2 not loading up new game, Digimon World not booting up and possibly others */
3304                                         v0 = (psxRegs.CP0.n.Status & 0x404) == 0x404;
3305                                         psxRegs.CP0.n.Status &= ~0x404;
3306                                         break;
3307
3308                                 case 2: // ExitCritical - enable irq's
3309                                         psxRegs.CP0.n.Status |= 0x404;
3310                                         break;
3311                                 /* Normally this should cover SYS(00h, SYS(04h but they don't do anything relevant so... */
3312                                 default:
3313                                         break;
3314                         }
3315                         pc0 = psxRegs.CP0.n.EPC + 4;
3316
3317                         psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3318                                                                   ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3319                         return;
3320
3321                 default:
3322 #ifdef PSXCPU_LOG
3323                         PSXCPU_LOG("unknown bios exception!\n");
3324 #endif
3325                         break;
3326         }
3327
3328         pc0 = psxRegs.CP0.n.EPC;
3329         if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;
3330
3331         psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3332                                                   ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3333 }
3334
3335 #define bfreeze(ptr, size) { \
3336         if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3337         if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3338         base += size; \
3339 }
3340
3341 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3342 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3343
3344 #define bfreezepsxMptr(ptr, type) { \
3345         if (Mode == 1) { \
3346                 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3347                 else psxRu32ref(base) = 0; \
3348         } else { \
3349                 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3350                 else (ptr) = NULL; \
3351         } \
3352         base += sizeof(u32); \
3353 }
3354
3355 void psxBiosFreeze(int Mode) {
3356         u32 base = 0x40000;
3357
3358         bfreezepsxMptr(jmp_int, u32);
3359         bfreezepsxMptr(pad_buf, int);
3360         bfreezepsxMptr(pad_buf1, char);
3361         bfreezepsxMptr(pad_buf2, char);
3362         bfreezepsxMptr(heap_addr, u32);
3363         bfreezel(&pad_buf1len);
3364         bfreezel(&pad_buf2len);
3365         bfreezes(regs);
3366         bfreezes(SysIntRP);
3367         bfreezel(&CardState);
3368         bfreezes(ThreadCB);
3369         bfreezel(&CurThread);
3370         bfreezes(FDesc);
3371         bfreezel(&card_active_chan);
3372         bfreezel(&pad_stopped);
3373         bfreezel(&heap_size);
3374 }