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