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