8c8093b120c74d74917ec22ffd21b0897c51aa78
[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         /* Function also accepts sector 400h (a bug) */
2454         if (!(a1 <= 0x400))
2455         {
2456                 /* Invalid sectors */
2457                 v0 = 0; pc0 = ra;
2458                 return;
2459         }
2460         card_active_chan = a0;
2461         port = a0 >> 4;
2462
2463         if (pa2) {
2464                 if (port == 0) {
2465                         memcpy(Mcd1Data + a1 * 128, pa2, 128);
2466                         SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2467                 } else {
2468                         memcpy(Mcd2Data + a1 * 128, pa2, 128);
2469                         SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2470                 }
2471         }
2472
2473         DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2474 //      DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2475
2476         v0 = 1; pc0 = ra;
2477 }
2478
2479 void psxBios__card_read() { // 0x4f
2480         void *pa2 = Ra2;
2481         int port;
2482
2483 #ifdef PSXBIOS_LOG
2484         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2485 #endif
2486         /* Function also accepts sector 400h (a bug) */
2487         if (!(a1 <= 0x400))
2488         {
2489                 /* Invalid sectors */
2490                 v0 = 0; pc0 = ra;
2491                 return;
2492         }
2493         card_active_chan = a0;
2494         port = a0 >> 4;
2495
2496         if (pa2) {
2497                 if (port == 0) {
2498                         memcpy(pa2, Mcd1Data + a1 * 128, 128);
2499                 } else {
2500                         memcpy(pa2, Mcd2Data + a1 * 128, 128);
2501                 }
2502         }
2503
2504         DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2505 //      DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2506
2507         v0 = 1; pc0 = ra;
2508 }
2509
2510 void psxBios__new_card() { // 0x50
2511 #ifdef PSXBIOS_LOG
2512         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2513 #endif
2514
2515         pc0 = ra;
2516 }
2517
2518 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2519 void psxBios__get_error(void) // 55
2520
2521         v0 = 0;
2522         pc0 = ra;
2523 }
2524
2525 void psxBios_Krom2RawAdd() { // 0x51
2526         int i = 0;
2527
2528         const u32 table_8140[][2] = {
2529                 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2530                 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2531                 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2532                 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2533                 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2534                 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2535                 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2536                 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2537                 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2538                 {0xffff, 0}
2539         };
2540
2541         const u32 table_889f[][2] = {
2542                 {0x889f, 0x3d68},  {0x8900, 0x40ec},  {0x897f, 0x4fb0},  {0x8a00, 0x56f4},
2543                 {0x8a7f, 0x65b8},  {0x8b00, 0x6cfc},  {0x8b7f, 0x7bc0},  {0x8c00, 0x8304},
2544                 {0x8c7f, 0x91c8},  {0x8d00, 0x990c},  {0x8d7f, 0xa7d0},  {0x8e00, 0xaf14},
2545                 {0x8e7f, 0xbdd8},  {0x8f00, 0xc51c},  {0x8f7f, 0xd3e0},  {0x9000, 0xdb24},
2546                 {0x907f, 0xe9e8},  {0x9100, 0xf12c},  {0x917f, 0xfff0},  {0x9200, 0x10734},
2547                 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2548                 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2549                 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2550                 {0xffff, 0}
2551         };
2552
2553         if (a0 >= 0x8140 && a0 <= 0x84be) {
2554                 while (table_8140[i][0] <= a0) i++;
2555                 a0 -= table_8140[i - 1][0];
2556                 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2557         } else if (a0 >= 0x889f && a0 <= 0x9872) {
2558                 while (table_889f[i][0] <= a0) i++;
2559                 a0 -= table_889f[i - 1][0];
2560                 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2561         } else {
2562                 v0 = 0xffffffff;
2563         }
2564
2565         pc0 = ra;
2566 }
2567
2568 void psxBios_GetC0Table() { // 56
2569 #ifdef PSXBIOS_LOG
2570         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2571 #endif
2572
2573         v0 = 0x674; pc0 = ra;
2574 }
2575
2576 void psxBios_GetB0Table() { // 57
2577 #ifdef PSXBIOS_LOG
2578         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2579 #endif
2580
2581         v0 = 0x874; pc0 = ra;
2582 }
2583
2584 void psxBios__card_chan() { // 0x58
2585 #ifdef PSXBIOS_LOG
2586         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2587 #endif
2588
2589         v0 = card_active_chan;
2590         pc0 = ra;
2591 }
2592
2593 void psxBios_ChangeClearPad() { // 5b
2594 #ifdef PSXBIOS_LOG
2595         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2596 #endif  
2597
2598         pc0 = ra;
2599 }
2600
2601 void psxBios__card_status() { // 5c
2602 #ifdef PSXBIOS_LOG
2603         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2604 #endif
2605
2606         v0 = card_active_chan;
2607         pc0 = ra;
2608 }
2609
2610 void psxBios__card_wait() { // 5d
2611 #ifdef PSXBIOS_LOG
2612         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2613 #endif
2614
2615         v0 = 1;
2616         pc0 = ra;
2617 }
2618
2619 /* System calls C0 */
2620
2621 /*
2622  * int SysEnqIntRP(int index , long *queue);
2623  */
2624
2625 void psxBios_SysEnqIntRP() { // 02
2626 #ifdef PSXBIOS_LOG
2627         PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x02] ,a0);
2628 #endif
2629
2630         SysIntRP[a0] = a1;
2631
2632         v0 = 0; pc0 = ra;
2633 }
2634
2635 /*
2636  * int SysDeqIntRP(int index , long *queue);
2637  */
2638
2639 void psxBios_SysDeqIntRP() { // 03
2640 #ifdef PSXBIOS_LOG
2641         PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x03], a0);
2642 #endif
2643
2644         SysIntRP[a0] = 0;
2645
2646         v0 = 0; pc0 = ra;
2647 }
2648
2649 void psxBios_ChangeClearRCnt() { // 0a
2650         u32 *ptr;
2651
2652 #ifdef PSXBIOS_LOG
2653         PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2654 #endif
2655
2656         ptr = (u32*)PSXM((a0 << 2) + 0x8600);
2657         v0 = *ptr;
2658         *ptr = a1;
2659
2660 //      psxRegs.CP0.n.Status|= 0x404;
2661         pc0 = ra;
2662 }
2663
2664 void psxBios_dummy() { 
2665 #ifdef PSXBIOS_LOG
2666         PSXBIOS_LOG("unk %x call: %x\n", pc0 & 0x1fffff, t1);
2667 #endif
2668         pc0 = ra; 
2669 }
2670
2671 void (*biosA0[256])();
2672 void (*biosB0[256])();
2673 void (*biosC0[256])();
2674
2675 #include "sjisfont.h"
2676
2677 void psxBiosInit() {
2678         u32 base, size;
2679         u32 *ptr; 
2680         int i;
2681         uLongf len;
2682
2683         for(i = 0; i < 256; i++) {
2684                 biosA0[i] = NULL;
2685                 biosB0[i] = NULL;
2686                 biosC0[i] = NULL;
2687         }
2688         biosA0[0x3e] = psxBios_puts;
2689         biosA0[0x3f] = psxBios_printf;
2690
2691         biosB0[0x3d] = psxBios_putchar;
2692         biosB0[0x3f] = psxBios_puts;
2693
2694         if (!Config.HLE) return;
2695
2696         for(i = 0; i < 256; i++) {
2697                 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
2698                 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
2699                 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
2700         }
2701
2702         biosA0[0x00] = psxBios_open;
2703         biosA0[0x01] = psxBios_lseek;
2704         biosA0[0x02] = psxBios_read;
2705         biosA0[0x03] = psxBios_write;
2706         biosA0[0x04] = psxBios_close;
2707         //biosA0[0x05] = psxBios_ioctl;
2708         //biosA0[0x06] = psxBios_exit;
2709         //biosA0[0x07] = psxBios_sys_a0_07;
2710         biosA0[0x08] = psxBios_getc;
2711         biosA0[0x09] = psxBios_putc;
2712         biosA0[0x0a] = psxBios_todigit;
2713         //biosA0[0x0b] = psxBios_atof;
2714         //biosA0[0x0c] = psxBios_strtoul;
2715         //biosA0[0x0d] = psxBios_strtol;
2716         biosA0[0x0e] = psxBios_abs;
2717         biosA0[0x0f] = psxBios_labs;
2718         biosA0[0x10] = psxBios_atoi;
2719         biosA0[0x11] = psxBios_atol;
2720         //biosA0[0x12] = psxBios_atob;
2721         biosA0[0x13] = psxBios_setjmp;
2722         biosA0[0x14] = psxBios_longjmp;
2723         biosA0[0x15] = psxBios_strcat;
2724         biosA0[0x16] = psxBios_strncat;
2725         biosA0[0x17] = psxBios_strcmp;
2726         biosA0[0x18] = psxBios_strncmp;
2727         biosA0[0x19] = psxBios_strcpy;
2728         biosA0[0x1a] = psxBios_strncpy;
2729         biosA0[0x1b] = psxBios_strlen;
2730         biosA0[0x1c] = psxBios_index;
2731         biosA0[0x1d] = psxBios_rindex;
2732         biosA0[0x1e] = psxBios_strchr;
2733         biosA0[0x1f] = psxBios_strrchr;
2734         biosA0[0x20] = psxBios_strpbrk;
2735         biosA0[0x21] = psxBios_strspn;
2736         biosA0[0x22] = psxBios_strcspn;
2737         biosA0[0x23] = psxBios_strtok;
2738         biosA0[0x24] = psxBios_strstr;
2739         biosA0[0x25] = psxBios_toupper;
2740         biosA0[0x26] = psxBios_tolower;
2741         biosA0[0x27] = psxBios_bcopy;
2742         biosA0[0x28] = psxBios_bzero;
2743         biosA0[0x29] = psxBios_bcmp;
2744         biosA0[0x2a] = psxBios_memcpy;
2745         biosA0[0x2b] = psxBios_memset;
2746         biosA0[0x2c] = psxBios_memmove;
2747         biosA0[0x2d] = psxBios_memcmp;
2748         biosA0[0x2e] = psxBios_memchr;
2749         biosA0[0x2f] = psxBios_rand;
2750         biosA0[0x30] = psxBios_srand;
2751         biosA0[0x31] = psxBios_qsort;
2752         //biosA0[0x32] = psxBios_strtod;
2753         biosA0[0x33] = psxBios_malloc;
2754         biosA0[0x34] = psxBios_free;
2755         //biosA0[0x35] = psxBios_lsearch;
2756         //biosA0[0x36] = psxBios_bsearch;
2757         biosA0[0x37] = psxBios_calloc;
2758         biosA0[0x38] = psxBios_realloc;
2759         biosA0[0x39] = psxBios_InitHeap;
2760         //biosA0[0x3a] = psxBios__exit;
2761         biosA0[0x3b] = psxBios_getchar;
2762         biosA0[0x3c] = psxBios_putchar; 
2763         //biosA0[0x3d] = psxBios_gets;
2764         //biosA0[0x40] = psxBios_sys_a0_40;
2765         //biosA0[0x41] = psxBios_LoadTest;
2766         biosA0[0x42] = psxBios_Load;
2767         biosA0[0x43] = psxBios_Exec;
2768         biosA0[0x44] = psxBios_FlushCache;
2769         //biosA0[0x45] = psxBios_InstallInterruptHandler;
2770         biosA0[0x46] = psxBios_GPU_dw;
2771         biosA0[0x47] = psxBios_mem2vram;
2772         biosA0[0x48] = psxBios_SendGPU;
2773         biosA0[0x49] = psxBios_GPU_cw;
2774         biosA0[0x4a] = psxBios_GPU_cwb;
2775         biosA0[0x4b] = psxBios_GPU_SendPackets;
2776         biosA0[0x4c] = psxBios_sys_a0_4c;
2777         biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
2778         //biosA0[0x4e] = psxBios_GPU_sync;      
2779         //biosA0[0x4f] = psxBios_sys_a0_4f;
2780         //biosA0[0x50] = psxBios_sys_a0_50;
2781         biosA0[0x51] = psxBios_LoadExec;
2782         //biosA0[0x52] = psxBios_GetSysSp;
2783         //biosA0[0x53] = psxBios_sys_a0_53;
2784         //biosA0[0x54] = psxBios__96_init_a54;
2785         //biosA0[0x55] = psxBios__bu_init_a55;
2786         //biosA0[0x56] = psxBios__96_remove_a56;
2787         //biosA0[0x57] = psxBios_sys_a0_57;
2788         //biosA0[0x58] = psxBios_sys_a0_58;
2789         //biosA0[0x59] = psxBios_sys_a0_59;
2790         //biosA0[0x5a] = psxBios_sys_a0_5a;
2791         //biosA0[0x5b] = psxBios_dev_tty_init;
2792         //biosA0[0x5c] = psxBios_dev_tty_open;
2793         //biosA0[0x5d] = psxBios_sys_a0_5d;
2794         //biosA0[0x5e] = psxBios_dev_tty_ioctl;
2795         //biosA0[0x5f] = psxBios_dev_cd_open;
2796         //biosA0[0x60] = psxBios_dev_cd_read;
2797         //biosA0[0x61] = psxBios_dev_cd_close;
2798         //biosA0[0x62] = psxBios_dev_cd_firstfile;
2799         //biosA0[0x63] = psxBios_dev_cd_nextfile;
2800         //biosA0[0x64] = psxBios_dev_cd_chdir;
2801         //biosA0[0x65] = psxBios_dev_card_open;
2802         //biosA0[0x66] = psxBios_dev_card_read;
2803         //biosA0[0x67] = psxBios_dev_card_write;
2804         //biosA0[0x68] = psxBios_dev_card_close;
2805         //biosA0[0x69] = psxBios_dev_card_firstfile;
2806         //biosA0[0x6a] = psxBios_dev_card_nextfile;
2807         //biosA0[0x6b] = psxBios_dev_card_erase;
2808         //biosA0[0x6c] = psxBios_dev_card_undelete;
2809         //biosA0[0x6d] = psxBios_dev_card_format;
2810         //biosA0[0x6e] = psxBios_dev_card_rename;
2811         //biosA0[0x6f] = psxBios_dev_card_6f;
2812         biosA0[0x70] = psxBios__bu_init;
2813         biosA0[0x71] = psxBios__96_init;
2814         biosA0[0x72] = psxBios__96_remove;
2815         //biosA0[0x73] = psxBios_sys_a0_73;
2816         //biosA0[0x74] = psxBios_sys_a0_74;
2817         //biosA0[0x75] = psxBios_sys_a0_75;
2818         //biosA0[0x76] = psxBios_sys_a0_76;
2819         //biosA0[0x77] = psxBios_sys_a0_77;
2820         //biosA0[0x78] = psxBios__96_CdSeekL;
2821         //biosA0[0x79] = psxBios_sys_a0_79;
2822         //biosA0[0x7a] = psxBios_sys_a0_7a;
2823         //biosA0[0x7b] = psxBios_sys_a0_7b;
2824         //biosA0[0x7c] = psxBios__96_CdGetStatus;
2825         //biosA0[0x7d] = psxBios_sys_a0_7d;
2826         //biosA0[0x7e] = psxBios__96_CdRead;
2827         //biosA0[0x7f] = psxBios_sys_a0_7f;
2828         //biosA0[0x80] = psxBios_sys_a0_80;
2829         //biosA0[0x81] = psxBios_sys_a0_81;
2830         //biosA0[0x82] = psxBios_sys_a0_82;             
2831         //biosA0[0x83] = psxBios_sys_a0_83;
2832         //biosA0[0x84] = psxBios_sys_a0_84;
2833         //biosA0[0x85] = psxBios__96_CdStop;    
2834         //biosA0[0x86] = psxBios_sys_a0_86;
2835         //biosA0[0x87] = psxBios_sys_a0_87;
2836         //biosA0[0x88] = psxBios_sys_a0_88;
2837         //biosA0[0x89] = psxBios_sys_a0_89;
2838         //biosA0[0x8a] = psxBios_sys_a0_8a;
2839         //biosA0[0x8b] = psxBios_sys_a0_8b;
2840         //biosA0[0x8c] = psxBios_sys_a0_8c;
2841         //biosA0[0x8d] = psxBios_sys_a0_8d;
2842         //biosA0[0x8e] = psxBios_sys_a0_8e;
2843         //biosA0[0x8f] = psxBios_sys_a0_8f;
2844         //biosA0[0x90] = psxBios_sys_a0_90;
2845         //biosA0[0x91] = psxBios_sys_a0_91;
2846         //biosA0[0x92] = psxBios_sys_a0_92;
2847         //biosA0[0x93] = psxBios_sys_a0_93;
2848         //biosA0[0x94] = psxBios_sys_a0_94;
2849         //biosA0[0x95] = psxBios_sys_a0_95;
2850         //biosA0[0x96] = psxBios_AddCDROMDevice;
2851         //biosA0[0x97] = psxBios_AddMemCardDevide;
2852         //biosA0[0x98] = psxBios_DisableKernelIORedirection;
2853         //biosA0[0x99] = psxBios_EnableKernelIORedirection;
2854         //biosA0[0x9a] = psxBios_sys_a0_9a;
2855         //biosA0[0x9b] = psxBios_sys_a0_9b;
2856         //biosA0[0x9c] = psxBios_SetConf;
2857         //biosA0[0x9d] = psxBios_GetConf;
2858         //biosA0[0x9e] = psxBios_sys_a0_9e;
2859         biosA0[0x9f] = psxBios_SetMem;
2860         //biosA0[0xa0] = psxBios__boot;
2861         //biosA0[0xa1] = psxBios_SystemError;
2862         //biosA0[0xa2] = psxBios_EnqueueCdIntr;
2863         //biosA0[0xa3] = psxBios_DequeueCdIntr;
2864         //biosA0[0xa4] = psxBios_sys_a0_a4;
2865         //biosA0[0xa5] = psxBios_ReadSector;
2866         biosA0[0xa6] = psxBios_get_cd_status;
2867         //biosA0[0xa7] = psxBios_bufs_cb_0;
2868         //biosA0[0xa8] = psxBios_bufs_cb_1;
2869         //biosA0[0xa9] = psxBios_bufs_cb_2;
2870         //biosA0[0xaa] = psxBios_bufs_cb_3;
2871         biosA0[0xab] = psxBios__card_info;
2872         biosA0[0xac] = psxBios__card_load;
2873         //biosA0[0axd] = psxBios__card_auto;
2874         //biosA0[0xae] = psxBios_bufs_cd_4;
2875         //biosA0[0xaf] = psxBios_sys_a0_af;
2876         //biosA0[0xb0] = psxBios_sys_a0_b0;
2877         //biosA0[0xb1] = psxBios_sys_a0_b1;
2878         //biosA0[0xb2] = psxBios_do_a_long_jmp
2879         //biosA0[0xb3] = psxBios_sys_a0_b3;
2880         //biosA0[0xb4] = psxBios_sub_function;
2881 //*******************B0 CALLS****************************
2882         //biosB0[0x00] = psxBios_SysMalloc;
2883         //biosB0[0x01] = psxBios_sys_b0_01;
2884         biosB0[0x02] = psxBios_SetRCnt;
2885         biosB0[0x03] = psxBios_GetRCnt;
2886         biosB0[0x04] = psxBios_StartRCnt;
2887         biosB0[0x05] = psxBios_StopRCnt;
2888         biosB0[0x06] = psxBios_ResetRCnt;
2889         biosB0[0x07] = psxBios_DeliverEvent;
2890         biosB0[0x08] = psxBios_OpenEvent;
2891         biosB0[0x09] = psxBios_CloseEvent;
2892         biosB0[0x0a] = psxBios_WaitEvent;
2893         biosB0[0x0b] = psxBios_TestEvent;
2894         biosB0[0x0c] = psxBios_EnableEvent;
2895         biosB0[0x0d] = psxBios_DisableEvent;
2896         biosB0[0x0e] = psxBios_OpenTh;
2897         biosB0[0x0f] = psxBios_CloseTh;
2898         biosB0[0x10] = psxBios_ChangeTh;
2899         //biosB0[0x11] = psxBios_psxBios_b0_11;
2900         biosB0[0x12] = psxBios_InitPAD;
2901         biosB0[0x13] = psxBios_StartPAD;
2902         biosB0[0x14] = psxBios_StopPAD;
2903         biosB0[0x15] = psxBios_PAD_init;
2904         biosB0[0x16] = psxBios_PAD_dr;
2905         biosB0[0x17] = psxBios_ReturnFromException;
2906         biosB0[0x18] = psxBios_ResetEntryInt;
2907         biosB0[0x19] = psxBios_HookEntryInt;
2908         //biosB0[0x1a] = psxBios_sys_b0_1a;
2909         //biosB0[0x1b] = psxBios_sys_b0_1b;
2910         //biosB0[0x1c] = psxBios_sys_b0_1c;
2911         //biosB0[0x1d] = psxBios_sys_b0_1d;
2912         //biosB0[0x1e] = psxBios_sys_b0_1e;
2913         //biosB0[0x1f] = psxBios_sys_b0_1f;
2914         biosB0[0x20] = psxBios_UnDeliverEvent;
2915         //biosB0[0x21] = psxBios_sys_b0_21;
2916         //biosB0[0x22] = psxBios_sys_b0_22;
2917         //biosB0[0x23] = psxBios_sys_b0_23;
2918         //biosB0[0x24] = psxBios_sys_b0_24;
2919         //biosB0[0x25] = psxBios_sys_b0_25;
2920         //biosB0[0x26] = psxBios_sys_b0_26;
2921         //biosB0[0x27] = psxBios_sys_b0_27;
2922         //biosB0[0x28] = psxBios_sys_b0_28;
2923         //biosB0[0x29] = psxBios_sys_b0_29;
2924         //biosB0[0x2a] = psxBios_sys_b0_2a;
2925         //biosB0[0x2b] = psxBios_sys_b0_2b;
2926         //biosB0[0x2c] = psxBios_sys_b0_2c;
2927         //biosB0[0x2d] = psxBios_sys_b0_2d;
2928         //biosB0[0x2e] = psxBios_sys_b0_2e;
2929         //biosB0[0x2f] = psxBios_sys_b0_2f;
2930         //biosB0[0x30] = psxBios_sys_b0_30;
2931         //biosB0[0x31] = psxBios_sys_b0_31;
2932         biosB0[0x32] = psxBios_open;
2933         biosB0[0x33] = psxBios_lseek;
2934         biosB0[0x34] = psxBios_read;
2935         biosB0[0x35] = psxBios_write;
2936         biosB0[0x36] = psxBios_close;
2937         //biosB0[0x37] = psxBios_ioctl;
2938         //biosB0[0x38] = psxBios_exit;
2939         //biosB0[0x39] = psxBios_sys_b0_39;
2940         //biosB0[0x3a] = psxBios_getc;
2941         //biosB0[0x3b] = psxBios_putc;
2942         biosB0[0x3c] = psxBios_getchar;
2943         //biosB0[0x3e] = psxBios_gets;
2944         //biosB0[0x40] = psxBios_cd;
2945         biosB0[0x41] = psxBios_format;
2946         biosB0[0x42] = psxBios_firstfile;
2947         biosB0[0x43] = psxBios_nextfile;
2948         biosB0[0x44] = psxBios_rename;
2949         biosB0[0x45] = psxBios_delete;
2950         //biosB0[0x46] = psxBios_undelete;
2951         //biosB0[0x47] = psxBios_AddDevice;
2952         //biosB0[0x48] = psxBios_RemoteDevice;
2953         //biosB0[0x49] = psxBios_PrintInstalledDevices;
2954         biosB0[0x4a] = psxBios_InitCARD;
2955         biosB0[0x4b] = psxBios_StartCARD;
2956         biosB0[0x4c] = psxBios_StopCARD;
2957         //biosB0[0x4d] = psxBios_sys_b0_4d;
2958         biosB0[0x4e] = psxBios__card_write;
2959         biosB0[0x4f] = psxBios__card_read;
2960         biosB0[0x50] = psxBios__new_card;
2961         biosB0[0x51] = psxBios_Krom2RawAdd;
2962         //biosB0[0x52] = psxBios_sys_b0_52;
2963         //biosB0[0x53] = psxBios_sys_b0_53;
2964         //biosB0[0x54] = psxBios__get_errno;
2965         biosB0[0x55] = psxBios__get_error;
2966         biosB0[0x56] = psxBios_GetC0Table;
2967         biosB0[0x57] = psxBios_GetB0Table;
2968         biosB0[0x58] = psxBios__card_chan;
2969         //biosB0[0x59] = psxBios_sys_b0_59;
2970         //biosB0[0x5a] = psxBios_sys_b0_5a;
2971         biosB0[0x5b] = psxBios_ChangeClearPad;
2972         biosB0[0x5c] = psxBios__card_status;
2973         biosB0[0x5d] = psxBios__card_wait;
2974 //*******************C0 CALLS****************************
2975         //biosC0[0x00] = psxBios_InitRCnt;
2976         //biosC0[0x01] = psxBios_InitException;
2977         biosC0[0x02] = psxBios_SysEnqIntRP;
2978         biosC0[0x03] = psxBios_SysDeqIntRP;
2979         //biosC0[0x04] = psxBios_get_free_EvCB_slot;
2980         //biosC0[0x05] = psxBios_get_free_TCB_slot;
2981         //biosC0[0x06] = psxBios_ExceptionHandler;
2982         //biosC0[0x07] = psxBios_InstallExeptionHandler;
2983         //biosC0[0x08] = psxBios_SysInitMemory;
2984         //biosC0[0x09] = psxBios_SysInitKMem;
2985         biosC0[0x0a] = psxBios_ChangeClearRCnt; 
2986         //biosC0[0x0b] = psxBios_SystemError;
2987         //biosC0[0x0c] = psxBios_InitDefInt;
2988         //biosC0[0x0d] = psxBios_sys_c0_0d;
2989         //biosC0[0x0e] = psxBios_sys_c0_0e;
2990         //biosC0[0x0f] = psxBios_sys_c0_0f;
2991         //biosC0[0x10] = psxBios_sys_c0_10;
2992         //biosC0[0x11] = psxBios_sys_c0_11;
2993         //biosC0[0x12] = psxBios_InstallDevices;
2994         //biosC0[0x13] = psxBios_FlushStfInOutPut;
2995         //biosC0[0x14] = psxBios_sys_c0_14;
2996         //biosC0[0x15] = psxBios__cdevinput;
2997         //biosC0[0x16] = psxBios__cdevscan;
2998         //biosC0[0x17] = psxBios__circgetc;
2999         //biosC0[0x18] = psxBios__circputc;
3000         //biosC0[0x19] = psxBios_ioabort;
3001         //biosC0[0x1a] = psxBios_sys_c0_1a
3002         //biosC0[0x1b] = psxBios_KernelRedirect;
3003         //biosC0[0x1c] = psxBios_PatchAOTable;
3004 //************** THE END ***************************************
3005 /**/
3006         base = 0x1000;
3007         size = sizeof(EvCB) * 32;
3008         Event = (void *)&psxR[base]; base += size * 6;
3009         memset(Event, 0, size * 6);
3010         HwEV = Event;
3011         EvEV = Event + 32;
3012         RcEV = Event + 32 * 2;
3013         UeEV = Event + 32 * 3;
3014         SwEV = Event + 32 * 4;
3015         ThEV = Event + 32 * 5;
3016
3017         ptr = (u32 *)&psxM[0x0874]; // b0 table
3018         ptr[0] = SWAPu32(0x4c54 - 0x884);
3019
3020         ptr = (u32 *)&psxM[0x0674]; // c0 table
3021         ptr[6] = SWAPu32(0xc80);
3022
3023         memset(SysIntRP, 0, sizeof(SysIntRP));
3024         memset(Thread, 0, sizeof(Thread));
3025         Thread[0].status = 2; // main thread
3026
3027         pad_stopped = 1;
3028         jmp_int = NULL;
3029         pad_buf = NULL;
3030         pad_buf1 = NULL;
3031         pad_buf2 = NULL;
3032         pad_buf1len = pad_buf2len = 0;
3033         heap_addr = NULL;
3034         heap_end = NULL;
3035         heap_size = 0;
3036         CardState = -1;
3037         CurThread = 0;
3038         memset(FDesc, 0, sizeof(FDesc));
3039         card_active_chan = 0;
3040
3041         psxMu32ref(0x0150) = SWAPu32(0x160);
3042         psxMu32ref(0x0154) = SWAPu32(0x320);
3043         psxMu32ref(0x0160) = SWAPu32(0x248);
3044         strcpy((char *)&psxM[0x248], "bu");
3045 /*      psxMu32ref(0x0ca8) = SWAPu32(0x1f410004);
3046         psxMu32ref(0x0cf0) = SWAPu32(0x3c020000);
3047         psxMu32ref(0x0cf4) = SWAPu32(0x2442641c);
3048         psxMu32ref(0x09e0) = SWAPu32(0x43d0);
3049         psxMu32ref(0x4d98) = SWAPu32(0x946f000a);
3050 */
3051         // opcode HLE
3052         psxRu32ref(0x0000) = SWAPu32((0x3b << 26) | 4);
3053         /* Whatever this does, it actually breaks CTR, even without the uninitiliazed memory patch. 
3054         Normally games shouldn't read from address 0 yet they do. See explanation below in details. */
3055         //psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0);
3056         psxMu32ref(0x00a0) = SWAPu32((0x3b << 26) | 1);
3057         psxMu32ref(0x00b0) = SWAPu32((0x3b << 26) | 2);
3058         psxMu32ref(0x00c0) = SWAPu32((0x3b << 26) | 3);
3059         psxMu32ref(0x4c54) = SWAPu32((0x3b << 26) | 0);
3060         psxMu32ref(0x8000) = SWAPu32((0x3b << 26) | 5);
3061         psxMu32ref(0x07a0) = SWAPu32((0x3b << 26) | 0);
3062         psxMu32ref(0x0884) = SWAPu32((0x3b << 26) | 0);
3063         psxMu32ref(0x0894) = SWAPu32((0x3b << 26) | 0);
3064
3065         // initial stack pointer for BIOS interrupt
3066         psxMu32ref(0x6c80) = SWAPu32(0x000085c8);
3067
3068         // initial RNG seed
3069         psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3070
3071         // fonts
3072         len = 0x80000 - 0x66000;
3073         uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3074         len = 0x80000 - 0x69d68;
3075         uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3076
3077         // memory size 2 MB
3078         psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3079
3080         hleSoftCall = FALSE;
3081         
3082         /*      Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3083                 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3084                 Here are some examples of games not working with this fix in place :
3085                 R-type won't get past the Irem logo if not implemented.
3086                 Crash Team Racing will softlock after the Sony logo.
3087         */
3088         
3089         psxMu32ref(0x0000) = SWAPu32(0x00000003);
3090         /*
3091         But overwritten by 00000003h after soon.
3092         psxMu32ref(0x0000) = SWAPu32(0x00001A3C);
3093         */
3094         psxMu32ref(0x0004) = SWAPu32(0x800C5A27);
3095         psxMu32ref(0x0008) = SWAPu32(0x08000403);
3096         psxMu32ref(0x000C) = SWAPu32(0x00000000);
3097 }
3098
3099 void psxBiosShutdown() {
3100 }
3101
3102 #define psxBios_PADpoll(pad) { \
3103         PAD##pad##_startPoll(pad); \
3104         pad_buf##pad[0] = 0; \
3105         pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3106         if (!(pad_buf##pad[1] & 0x0f)) { \
3107                 bufcount = 32; \
3108         } else { \
3109                 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3110         } \
3111         PAD##pad##_poll(0); \
3112         i = 2; \
3113         while (bufcount--) { \
3114                 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3115         } \
3116 }
3117
3118 void biosInterrupt() {
3119         int i, bufcount;
3120
3121 //      if (psxHu32(0x1070) & 0x1) { // Vsync
3122                 if (pad_buf != NULL) {
3123                         u32 *buf = (u32*)pad_buf;
3124
3125                         if (!Config.UseNet) {
3126                                 PAD1_startPoll(1);
3127                                 if (PAD1_poll(0x42) == 0x23) {
3128                                         PAD1_poll(0);
3129                                         *buf = PAD1_poll(0) << 8;
3130                                         *buf |= PAD1_poll(0);
3131                                         PAD1_poll(0);
3132                                         *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3133                                         *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3134                                 } else {
3135                                         PAD1_poll(0);
3136                                         *buf = PAD1_poll(0) << 8;
3137                                         *buf|= PAD1_poll(0);
3138                                 }
3139
3140                                 PAD2_startPoll(2);
3141                                 if (PAD2_poll(0x42) == 0x23) {
3142                                         PAD2_poll(0);
3143                                         *buf |= PAD2_poll(0) << 24;
3144                                         *buf |= PAD2_poll(0) << 16;
3145                                         PAD2_poll(0);
3146                                         *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3147                                         *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3148                                 } else {
3149                                         PAD2_poll(0);
3150                                         *buf |= PAD2_poll(0) << 24;
3151                                         *buf |= PAD2_poll(0) << 16;
3152                                 }
3153                         } else {
3154                                 u16 data;
3155
3156                                 PAD1_startPoll(1);
3157                                 PAD1_poll(0x42);
3158                                 PAD1_poll(0);
3159                                 data = PAD1_poll(0) << 8;
3160                                 data |= PAD1_poll(0);
3161
3162                                 if (NET_sendPadData(&data, 2) == -1)
3163                                         netError();
3164
3165                                 if (NET_recvPadData(&((u16*)buf)[0], 1) == -1)
3166                                         netError();
3167                                 if (NET_recvPadData(&((u16*)buf)[1], 2) == -1)
3168                                         netError();
3169                         }
3170                 }
3171                 if (Config.UseNet && pad_buf1 != NULL && pad_buf2 != NULL) {
3172                         psxBios_PADpoll(1);
3173
3174                         if (NET_sendPadData(pad_buf1, i) == -1)
3175                                 netError();
3176
3177                         if (NET_recvPadData(pad_buf1, 1) == -1)
3178                                 netError();
3179                         if (NET_recvPadData(pad_buf2, 2) == -1)
3180                                 netError();
3181                 } else {
3182                         if (!pad_stopped)  {
3183                                 if (pad_buf1) {
3184                                         psxBios_PADpoll(1);
3185                                 }
3186
3187                                 if (pad_buf2) {
3188                                         psxBios_PADpoll(2);
3189                                 }
3190                         }
3191                 }
3192
3193         if (psxHu32(0x1070) & 0x1) { // Vsync
3194                 if (RcEV[3][1].status == EvStACTIVE) {
3195                         softCall(RcEV[3][1].fhandler);
3196 //                      hwWrite32(0x1f801070, ~(1));
3197                 }
3198         }
3199
3200         if (psxHu32(0x1070) & 0x70) { // Rcnt 0,1,2
3201                 int i;
3202
3203                 for (i = 0; i < 3; i++) {
3204                         if (psxHu32(0x1070) & (1 << (i + 4))) {
3205                                 if (RcEV[i][1].status == EvStACTIVE) {
3206                                         softCall(RcEV[i][1].fhandler);
3207                                 }
3208                                 psxHwWrite32(0x1f801070, ~(1 << (i + 4)));
3209                         }
3210                 }
3211         }
3212 }
3213
3214 void psxBiosException() {
3215         int i;
3216
3217         switch (psxRegs.CP0.n.Cause & 0x3c) {
3218                 case 0x00: // Interrupt
3219                         interrupt_r26=psxRegs.CP0.n.EPC;
3220 #ifdef PSXCPU_LOG
3221 //                      PSXCPU_LOG("interrupt\n");
3222 #endif
3223                         SaveRegs();
3224
3225                         sp = psxMu32(0x6c80); // create new stack for interrupt handlers
3226
3227                         biosInterrupt();
3228
3229                         for (i = 0; i < 8; i++) {
3230                                 if (SysIntRP[i]) {
3231                                         u32 *queue = (u32 *)PSXM(SysIntRP[i]);
3232
3233                                         s0 = queue[2];
3234                                         softCall(queue[1]);
3235                                 }
3236                         }
3237
3238                         if (jmp_int != NULL) {
3239                                 int i;
3240
3241                                 psxHwWrite32(0x1f801070, 0xffffffff);
3242
3243                                 ra = jmp_int[0];
3244                                 sp = jmp_int[1];
3245                                 fp = jmp_int[2];
3246                                 for (i = 0; i < 8; i++) // s0-s7
3247                                          psxRegs.GPR.r[16 + i] = jmp_int[3 + i];
3248                                 gp = jmp_int[11];
3249
3250                                 v0 = 1;
3251                                 pc0 = ra;
3252                                 return;
3253                         }
3254                         psxHwWrite16(0x1f801070, 0);
3255                         break;
3256
3257                 case 0x20: // Syscall
3258 #ifdef PSXCPU_LOG
3259                         PSXCPU_LOG("syscall exp %x\n", a0);
3260 #endif
3261                         switch (a0) {
3262                                 case 1: // EnterCritical - disable irq's
3263                                         /* Fixes Medievil 2 not loading up new game, Digimon World not booting up and possibly others */
3264                                         v0 = (psxRegs.CP0.n.Status & 0x404) == 0x404;
3265                                         psxRegs.CP0.n.Status &= ~0x404;
3266                                         break;
3267
3268                                 case 2: // ExitCritical - enable irq's
3269                                         psxRegs.CP0.n.Status |= 0x404; 
3270                                         break;
3271                                 /* Normally this should cover SYS(00h, SYS(04h but they don't do anything relevant so... */
3272                                 default:
3273                                         break;
3274                         }
3275                         pc0 = psxRegs.CP0.n.EPC + 4;
3276
3277                         psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3278                                                                   ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3279                         return;
3280
3281                 default:
3282 #ifdef PSXCPU_LOG
3283                         PSXCPU_LOG("unknown bios exception!\n");
3284 #endif
3285                         break;
3286         }
3287
3288         pc0 = psxRegs.CP0.n.EPC;
3289         if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;
3290
3291         psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3292                                                   ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3293 }
3294
3295 #define bfreeze(ptr, size) { \
3296         if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3297         if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3298         base += size; \
3299 }
3300
3301 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3302 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3303
3304 #define bfreezepsxMptr(ptr, type) { \
3305         if (Mode == 1) { \
3306                 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3307                 else psxRu32ref(base) = 0; \
3308         } else { \
3309                 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3310                 else (ptr) = NULL; \
3311         } \
3312         base += sizeof(u32); \
3313 }
3314
3315 void psxBiosFreeze(int Mode) {
3316         u32 base = 0x40000;
3317
3318         bfreezepsxMptr(jmp_int, u32);
3319         bfreezepsxMptr(pad_buf, int);
3320         bfreezepsxMptr(pad_buf1, char);
3321         bfreezepsxMptr(pad_buf2, char);
3322         bfreezepsxMptr(heap_addr, u32);
3323         bfreezel(&pad_buf1len);
3324         bfreezel(&pad_buf2len);
3325         bfreezes(regs);
3326         bfreezes(SysIntRP);
3327         bfreezel(&CardState);
3328         bfreezes(Thread);
3329         bfreezel(&CurThread);
3330         bfreezes(FDesc);
3331         bfreezel(&card_active_chan);
3332         bfreezel(&pad_stopped);
3333         bfreezel(&heap_size);
3334 }