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