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