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