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