deal with some more annoying warnings
[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
1409         pc0 = ra;
1410 }
1411
1412 void psxBios_GPU_dw() { // 0x46
1413         int size;
1414         s32 *ptr;
1415
1416 #ifdef PSXBIOS_LOG
1417         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1418 #endif
1419
1420         GPU_writeData(0xa0000000);
1421         GPU_writeData((a1<<16)|(a0&0xffff));
1422         GPU_writeData((a3<<16)|(a2&0xffff));
1423         size = (a2*a3+1)/2;
1424         ptr = (s32*)PSXM(Rsp[4]);  //that is correct?
1425         do {
1426                 GPU_writeData(SWAP32(*ptr));
1427                 ptr++;
1428         } while(--size);
1429
1430         pc0 = ra;
1431 }  
1432
1433 void psxBios_mem2vram() { // 0x47
1434         int size;
1435
1436         GPU_writeData(0xa0000000);
1437         GPU_writeData((a1<<16)|(a0&0xffff));
1438         GPU_writeData((a3<<16)|(a2&0xffff));
1439         size = (a2*a3+1)/2;
1440         GPU_writeStatus(0x04000002);
1441         psxHwWrite32(0x1f8010f4,0);
1442         psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1443         psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1444         psxHwWrite32(0x1f8010a4,((size/16)<<16)|16);
1445         psxHwWrite32(0x1f8010a8,0x01000201);
1446
1447         pc0 = ra;
1448 }
1449
1450 void psxBios_SendGPU() { // 0x48
1451         GPU_writeStatus(a0);
1452         gpuSyncPluginSR();
1453         pc0 = ra;
1454 }
1455
1456 void psxBios_GPU_cw() { // 0x49
1457         GPU_writeData(a0);
1458         pc0 = ra;
1459 }
1460
1461 void psxBios_GPU_cwb() { // 0x4a
1462         s32 *ptr = (s32*)Ra0;
1463         int size = a1;
1464         while(size--) {
1465                 GPU_writeData(SWAP32(*ptr));
1466                 ptr++;
1467         }
1468
1469         pc0 = ra;
1470 }
1471    
1472 void psxBios_GPU_SendPackets() { //4b:  
1473         GPU_writeStatus(0x04000002);
1474         psxHwWrite32(0x1f8010f4,0);
1475         psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1476         psxHwWrite32(0x1f8010a0,a0);
1477         psxHwWrite32(0x1f8010a4,0);
1478         psxHwWrite32(0x1f8010a8,0x010000401);
1479         pc0 = ra;
1480 }
1481
1482 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1483         psxHwWrite32(0x1f8010a8,0x00000401);
1484         GPU_writeData(0x0400000);
1485         GPU_writeData(0x0200000);
1486         GPU_writeData(0x0100000);
1487         v0 = 0x1f801814;
1488         pc0 = ra;
1489 }
1490
1491 void psxBios_GPU_GetGPUStatus() { // 0x4d
1492         v0 = GPU_readStatus();
1493         pc0 = ra;
1494 }
1495
1496 #undef s_addr
1497
1498 void psxBios_LoadExec() { // 51
1499         EXEC *header = (EXEC*)PSXM(0xf000);
1500         u32 s_addr, s_size;
1501
1502 #ifdef PSXBIOS_LOG
1503         PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1504 #endif
1505         s_addr = a1; s_size = a2;
1506
1507         a1 = 0xf000;    
1508         psxBios_Load();
1509
1510         header->S_addr = s_addr;
1511         header->s_size = s_size;
1512
1513         a0 = 0xf000; a1 = 0; a2 = 0;
1514         psxBios_Exec();
1515 }
1516
1517 void psxBios__bu_init() { // 70
1518 #ifdef PSXBIOS_LOG
1519         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1520 #endif
1521
1522         DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1523         DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1524
1525         pc0 = ra;
1526 }
1527
1528 void psxBios__96_init() { // 71
1529 #ifdef PSXBIOS_LOG
1530         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1531 #endif
1532
1533         pc0 = ra;
1534 }
1535
1536 void psxBios__96_remove() { // 72
1537 #ifdef PSXBIOS_LOG
1538         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1539 #endif
1540
1541         pc0 = ra;
1542 }
1543
1544 void psxBios_SetMem() { // 9f
1545         u32 new = psxHu32(0x1060);
1546
1547 #ifdef PSXBIOS_LOG
1548         PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1549 #endif
1550
1551         switch(a0) {
1552                 case 2:
1553                         psxHu32ref(0x1060) = SWAP32(new);
1554                         psxMu32ref(0x060) = a0;
1555                         SysPrintf("Change effective memory : %d MBytes\n",a0);
1556                         break;
1557
1558                 case 8:
1559                         psxHu32ref(0x1060) = SWAP32(new | 0x300);
1560                         psxMu32ref(0x060) = a0;
1561                         SysPrintf("Change effective memory : %d MBytes\n",a0);
1562         
1563                 default:
1564                         SysPrintf("Effective memory must be 2/8 MBytes\n");
1565                 break;
1566         }
1567
1568         pc0 = ra;
1569 }
1570
1571 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1572 void psxBios_get_cd_status(void) //a6
1573 {
1574         v0 = 1;
1575         pc0 = ra;
1576 }
1577
1578 void psxBios__card_info() { // ab
1579 #ifdef PSXBIOS_LOG
1580         PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1581 #endif
1582         u32 ret;
1583         card_active_chan = a0;
1584
1585         switch (card_active_chan) 
1586         {
1587         case 0x00: case 0x01: case 0x02: case 0x03:
1588                 ret = Config.Mcd1[0] ? 0x2 : 0x8;
1589                 break;
1590         case 0x10: case 0x11: case 0x12: case 0x13:
1591                 ret = Config.Mcd2[0] ? 0x2 : 0x8;
1592                 break;
1593         default:
1594 #ifdef PSXBIOS_LOG
1595                 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
1596 #endif
1597                 ret = 0x11;
1598                 break;
1599         }
1600         
1601         DeliverEvent(0x11, 0x2); // 0xf4000001, 0x0004
1602         DeliverEvent(0x81, ret); // 0xf4000001, 0x0004
1603         v0 = 1; pc0 = ra;
1604 }
1605
1606 void psxBios__card_load() { // ac
1607 #ifdef PSXBIOS_LOG
1608         PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1609 #endif
1610
1611         card_active_chan = a0;
1612
1613 //      DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1614         DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1615
1616         v0 = 1; pc0 = ra;
1617 }
1618
1619 /* System calls B0 */
1620
1621 void psxBios_SetRCnt() { // 02
1622 #ifdef PSXBIOS_LOG
1623         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1624 #endif
1625
1626         a0&= 0x3;
1627         if (a0 != 3) {
1628                 u32 mode=0;
1629
1630                 psxRcntWtarget(a0, a1);
1631                 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1632                 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1633                 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1634                 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1635                 else         { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1636
1637                 psxRcntWmode(a0, mode);
1638         }
1639         pc0 = ra;
1640 }
1641
1642 void psxBios_GetRCnt() { // 03
1643 #ifdef PSXBIOS_LOG
1644         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1645 #endif
1646
1647         a0&= 0x3;
1648         if (a0 != 3) v0 = psxRcntRcount(a0);
1649         else v0 = 0;
1650         pc0 = ra;
1651 }
1652
1653 void psxBios_StartRCnt() { // 04
1654 #ifdef PSXBIOS_LOG
1655         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1656 #endif
1657
1658         a0&= 0x3;
1659         if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1660         else psxHu32ref(0x1074)|= SWAPu32(0x1);
1661         v0 = 1; pc0 = ra;
1662 }
1663
1664 void psxBios_StopRCnt() { // 05
1665 #ifdef PSXBIOS_LOG
1666         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1667 #endif
1668
1669         a0&= 0x3;
1670         if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1671         else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1672         pc0 = ra;
1673 }
1674
1675 void psxBios_ResetRCnt() { // 06
1676 #ifdef PSXBIOS_LOG
1677         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1678 #endif
1679
1680         a0&= 0x3;
1681         if (a0 != 3) {
1682                 psxRcntWmode(a0, 0);
1683                 psxRcntWtarget(a0, 0);
1684                 psxRcntWcount(a0, 0);
1685         }
1686         pc0 = ra;
1687 }
1688
1689
1690 /* gets ev for use with Event */
1691 #define GetEv() \
1692         ev = (a0 >> 24) & 0xf; \
1693         if (ev == 0xf) ev = 0x5; \
1694         ev*= 32; \
1695         ev+= a0&0x1f;
1696
1697 /* gets spec for use with Event */
1698 #define GetSpec() \
1699         spec = 0; \
1700         switch (a1) { \
1701                 case 0x0301: spec = 16; break; \
1702                 case 0x0302: spec = 17; break; \
1703                 default: \
1704                         for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \
1705                         break; \
1706         }
1707
1708 void psxBios_DeliverEvent() { // 07
1709         int ev, spec;
1710         int i;
1711
1712         GetEv();
1713         GetSpec();
1714
1715 #ifdef PSXBIOS_LOG
1716         PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x07], ev, spec);
1717 #endif
1718
1719         DeliverEvent(ev, spec);
1720
1721         pc0 = ra;
1722 }
1723
1724 void psxBios_OpenEvent() { // 08
1725         int ev, spec;
1726         int i;
1727
1728         GetEv();
1729         GetSpec();
1730
1731 #ifdef PSXBIOS_LOG
1732         PSXBIOS_LOG("psxBios_%s %x,%x (class:%x, spec:%x, mode:%x, func:%x)\n", biosB0n[0x08], ev, spec, a0, a1, a2, a3);
1733 #endif
1734
1735         Event[ev][spec].status = EvStWAIT;
1736         Event[ev][spec].mode = a2;
1737         Event[ev][spec].fhandler = a3;
1738
1739         v0 = ev | (spec << 8);
1740         pc0 = ra;
1741 }
1742
1743 void psxBios_CloseEvent() { // 09
1744         int ev, spec;
1745
1746         ev   = a0 & 0xff;
1747         spec = (a0 >> 8) & 0xff;
1748
1749 #ifdef PSXBIOS_LOG
1750         PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x09], ev, spec);
1751 #endif
1752
1753         Event[ev][spec].status = EvStUNUSED;
1754
1755         v0 = 1; pc0 = ra;
1756 }
1757
1758 void psxBios_WaitEvent() { // 0a
1759         int ev, spec;
1760
1761         ev   = a0 & 0xff;
1762         spec = (a0 >> 8) & 0xff;
1763 #ifdef PSXBIOS_LOG
1764         PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0a], ev, spec);
1765 #endif
1766         if (Event[ev][spec].status == EvStUNUSED)
1767         {
1768                 v0 = 0;
1769                 pc0 = ra;       
1770                 return;
1771         }
1772
1773         if (Event[ev][spec].status == EvStALREADY) 
1774         {
1775                 /* Callback events (mode=EvMdINTR) do never set the ready flag (and thus WaitEvent would hang forever). */
1776                 if (!(Event[ev][spec].mode == EvMdINTR)) Event[ev][spec].status = EvStACTIVE;
1777                 v0 = 1;
1778                 pc0 = ra;
1779                 return;
1780         }
1781
1782         v0 = 0;
1783         pc0 = ra;
1784 }
1785
1786 void psxBios_TestEvent() { // 0b
1787         int ev, spec;
1788
1789         ev   = a0 & 0xff;
1790         spec = (a0 >> 8) & 0xff;
1791
1792         if (Event[ev][spec].status == EvStALREADY) 
1793         {
1794                 if (!(Event[ev][spec].mode == EvMdINTR)) Event[ev][spec].status = EvStACTIVE;
1795                 v0 = 1;
1796         } 
1797         else 
1798         {
1799                 v0 = 0;
1800         }
1801
1802 #ifdef PSXBIOS_LOG
1803         PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0);
1804 #endif
1805
1806         pc0 = ra;
1807 }
1808
1809 void psxBios_EnableEvent() { // 0c
1810         int ev, spec;
1811
1812         ev   = a0 & 0xff;
1813         spec = (a0 >> 8) & 0xff;
1814
1815 #ifdef PSXBIOS_LOG
1816         PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0c], ev, spec);
1817 #endif
1818
1819         Event[ev][spec].status = EvStACTIVE;
1820
1821         v0 = 1; pc0 = ra;
1822 }
1823
1824 void psxBios_DisableEvent() { // 0d
1825         int ev, spec;
1826
1827         ev   = a0 & 0xff;
1828         spec = (a0 >> 8) & 0xff;
1829
1830 #ifdef PSXBIOS_LOG
1831         PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0d], ev, spec);
1832 #endif
1833
1834         Event[ev][spec].status = EvStWAIT;
1835
1836         v0 = 1; pc0 = ra;
1837 }
1838
1839 /*
1840  *      long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
1841  */
1842
1843 void psxBios_OpenTh() { // 0e
1844         int th;
1845
1846         for (th=1; th<8; th++)
1847         {
1848                 if (Thread[th].status == 0) break;
1849
1850         }
1851         if (th == 8) {
1852                 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
1853                 // When no free TCB is found, return 0xffffffff according to Nocash doc.
1854 #ifdef PSXBIOS_LOG
1855                 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
1856 #endif
1857                 v0 = 0xffffffff;
1858                 pc0 = ra;
1859                 return;
1860         }
1861 #ifdef PSXBIOS_LOG
1862         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
1863 #endif
1864
1865         Thread[th].status = 1;
1866         Thread[th].func    = a0;
1867         Thread[th].reg[29] = a1;
1868         Thread[th].reg[28] = a2;
1869
1870         v0 = th; pc0 = ra;
1871 }
1872
1873 /*
1874  *      int CloseTh(long thread);
1875  */
1876
1877 void psxBios_CloseTh() { // 0f
1878         int th = a0 & 0xff;
1879
1880 #ifdef PSXBIOS_LOG
1881         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
1882 #endif
1883         /* The return value is always 1 (even if the handle was already closed). */
1884         v0 = 1;
1885         if (Thread[th].status != 0) {
1886                 Thread[th].status = 0;
1887         }
1888
1889         pc0 = ra;
1890 }
1891
1892 /*
1893  *      int ChangeTh(long thread);
1894  */
1895
1896 void psxBios_ChangeTh() { // 10
1897         int th = a0 & 0xff;
1898
1899 #ifdef PSXBIOS_LOG
1900 //      PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
1901 #endif
1902         /* The return value is always 1. */
1903         v0 = 1;
1904         if (Thread[th].status == 0 || CurThread == th) {
1905                 pc0 = ra;
1906         } else {
1907                 if (Thread[CurThread].status == 2) {
1908                         Thread[CurThread].status = 1;
1909                         Thread[CurThread].func = ra;
1910                         memcpy(Thread[CurThread].reg, psxRegs.GPR.r, 32*4);
1911                 }
1912
1913                 memcpy(psxRegs.GPR.r, Thread[th].reg, 32*4);
1914                 pc0 = Thread[th].func;
1915                 Thread[th].status = 2;
1916                 CurThread = th;
1917         }
1918 }
1919
1920 void psxBios_InitPAD() { // 0x12
1921 #ifdef PSXBIOS_LOG
1922         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x12]);
1923 #endif
1924
1925         pad_buf1 = (char*)Ra0;
1926         pad_buf1len = a1;
1927         pad_buf2 = (char*)Ra2;
1928         pad_buf2len = a3;
1929
1930         v0 = 1; pc0 = ra;
1931 }
1932
1933 void psxBios_StartPAD() { // 13
1934 #ifdef PSXBIOS_LOG
1935         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
1936 #endif
1937         pad_stopped = 0;
1938         psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1));
1939         psxRegs.CP0.n.Status |= 0x401;
1940         pc0 = ra;
1941 }
1942
1943 void psxBios_StopPAD() { // 14
1944 #ifdef PSXBIOS_LOG
1945         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
1946 #endif
1947         pad_stopped = 1;
1948         pad_buf1 = NULL;
1949         pad_buf2 = NULL;
1950         pc0 = ra;
1951 }
1952
1953 void psxBios_PAD_init() { // 15
1954 #ifdef PSXBIOS_LOG
1955         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
1956 #endif
1957         if (!(a0 == 0x20000000 || a0 == 0x20000001))
1958         {
1959                 v0 = 0;
1960                 pc0 = ra;
1961                 return;
1962         }
1963         psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
1964         pad_buf = (int *)Ra1;
1965         *pad_buf = -1;
1966         psxRegs.CP0.n.Status |= 0x401;
1967         v0 = 2;
1968         pc0 = ra;
1969 }
1970
1971 void psxBios_PAD_dr() { // 16
1972 #ifdef PSXBIOS_LOG
1973         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
1974 #endif
1975
1976         v0 = -1; pc0 = ra;
1977 }
1978
1979 void psxBios_ReturnFromException() { // 17
1980         LoadRegs();
1981
1982         pc0 = psxRegs.CP0.n.EPC;
1983         k0 = interrupt_r26;
1984         if (psxRegs.CP0.n.Cause & 0x80000000) pc0 += 4;
1985
1986         psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
1987                                                   ((psxRegs.CP0.n.Status & 0x3c) >> 2);
1988 }
1989
1990 void psxBios_ResetEntryInt() { // 18
1991 #ifdef PSXBIOS_LOG
1992         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
1993 #endif
1994
1995         jmp_int = NULL;
1996         pc0 = ra;
1997 }
1998
1999 void psxBios_HookEntryInt() { // 19
2000 #ifdef PSXBIOS_LOG
2001         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x19]);
2002 #endif
2003
2004         jmp_int = (u32*)Ra0;
2005         pc0 = ra;
2006 }
2007
2008 void psxBios_UnDeliverEvent() { // 0x20
2009         int ev, spec;
2010         int i;
2011
2012         GetEv();
2013         GetSpec();
2014
2015 #ifdef PSXBIOS_LOG
2016         PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec);
2017 #endif
2018
2019         if (Event[ev][spec].status == EvStALREADY &&
2020                 Event[ev][spec].mode == EvMdNOINTR)
2021                 Event[ev][spec].status = EvStACTIVE;
2022
2023         pc0 = ra;
2024 }
2025
2026 char ffile[64], *pfile;
2027 int nfile;
2028 static void buopen(int mcd, u8 *ptr, u8 *cfg)
2029 {
2030         int i;
2031         u8 *fptr = ptr;
2032
2033         strcpy(FDesc[1 + mcd].name, Ra0+5);
2034         FDesc[1 + mcd].offset = 0;
2035         FDesc[1 + mcd].mode   = a1;
2036
2037         for (i=1; i<16; i++) {
2038                 fptr += 128;
2039                 if ((*fptr & 0xF0) != 0x50) continue;
2040                 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2041                 FDesc[1 + mcd].mcfile = i;
2042                 SysPrintf("open %s\n", fptr+0xa);
2043                 v0 = 1 + mcd;
2044                 break;
2045         }
2046         if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2047                 fptr = ptr;
2048                 for (i=1; i<16; i++) {
2049                         int j, xor, nblk = a1 >> 16;
2050                         u8 *pptr, *fptr2;
2051
2052                         fptr += 128;
2053                         if ((*fptr & 0xF0) != 0xa0) continue;
2054
2055                         FDesc[1 + mcd].mcfile = i;
2056                         fptr[0] = 0x51;
2057                         fptr[4] = 0x00;
2058                         fptr[5] = 0x20 * nblk;
2059                         fptr[6] = 0x00;
2060                         fptr[7] = 0x00;
2061                         strcpy(fptr+0xa, FDesc[1 + mcd].name);
2062                         pptr = fptr2 = fptr;
2063                         for(j=2; j<=nblk; j++) {
2064                                 int k;
2065                                 for(i++; i<16; i++) {
2066                                         fptr2 += 128;
2067                                         
2068                                         memset(fptr2, 0, 128);
2069                                         fptr2[0] = j < nblk ? 0x52 : 0x53;
2070                                         pptr[8] = i - 1;
2071                                         pptr[9] = 0;
2072                                         for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2073                                         pptr[127] = xor;
2074                                         pptr = fptr2;
2075                                         break;
2076                                 }
2077                                 /* shouldn't this return ENOSPC if i == 16? */
2078                         }
2079                         pptr[8] = pptr[9] = 0xff;
2080                         for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2081                         pptr[127] = xor;
2082                         SysPrintf("openC %s %d\n", ptr, nblk);
2083                         v0 = 1 + mcd;
2084                         /* just go ahead and resave them all */
2085                         SaveMcd(cfg, ptr, 128, 128 * 15);
2086                         break;
2087                 }
2088                 /* shouldn't this return ENOSPC if i == 16? */
2089         }
2090 }
2091
2092 /*
2093  *      int open(char *name , int mode);
2094  */
2095
2096 void psxBios_open() { // 0x32
2097         void *pa0 = Ra0;
2098
2099 #ifdef PSXBIOS_LOG
2100         PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2101 #endif
2102
2103         v0 = -1;
2104
2105         if (pa0) {
2106                 if (!strncmp(pa0, "bu00", 4)) {
2107                         buopen(1, Mcd1Data, Config.Mcd1);
2108                 }
2109
2110                 if (!strncmp(pa0, "bu10", 4)) {
2111                         buopen(2, Mcd2Data, Config.Mcd2);
2112                 }
2113         }
2114
2115         pc0 = ra;
2116 }
2117
2118 /*
2119  *      int lseek(int fd , int offset , int whence);
2120  */
2121
2122 void psxBios_lseek() { // 0x33
2123 #ifdef PSXBIOS_LOG
2124         PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2125 #endif
2126
2127         switch (a2) {
2128                 case 0: // SEEK_SET
2129                         FDesc[a0].offset = a1;
2130                         v0 = a1;
2131 //                      DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2132 //                      DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2133                         break;
2134
2135                 case 1: // SEEK_CUR
2136                         FDesc[a0].offset+= a1;
2137                         v0 = FDesc[a0].offset;
2138                         break;
2139         }
2140
2141         pc0 = ra;
2142 }
2143
2144
2145 /*
2146  *      int read(int fd , void *buf , int nbytes);
2147  */
2148
2149 void psxBios_read() { // 0x34
2150         char *ptr;
2151         void *pa1 = Ra1;
2152
2153 #ifdef PSXBIOS_LOG
2154         PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2155 #endif
2156
2157         v0 = -1;
2158
2159         if (pa1) {
2160                 switch (a0) {
2161                         case 2: buread(pa1, 1, a2); break;
2162                         case 3: buread(pa1, 2, a2); break;
2163                 }
2164         }
2165                 
2166         pc0 = ra;
2167 }
2168
2169 /*
2170  *      int write(int fd , void *buf , int nbytes);
2171  */
2172
2173 void psxBios_write() { // 0x35/0x03
2174         char *ptr;
2175         void *pa1 = Ra1;
2176
2177 #ifdef PSXBIOS_LOG
2178         PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2179 #endif
2180
2181         v0 = -1;
2182         if (!pa1) {
2183                 pc0 = ra;
2184                 return;
2185         }
2186
2187         if (a0 == 1) { // stdout
2188                 char *ptr = pa1;
2189
2190                 v0 = a2;
2191                 while (a2 > 0) {
2192                         SysPrintf("%c", *ptr++); a2--;
2193                 }
2194                 pc0 = ra; return;
2195         }
2196
2197         switch (a0) {
2198                 case 2: buwrite(pa1, 1, a2); break;
2199                 case 3: buwrite(pa1, 2, a2); break;
2200         }
2201
2202         pc0 = ra;
2203 }
2204
2205 /*
2206  *      int close(int fd);
2207  */
2208
2209 void psxBios_close() { // 0x36
2210 #ifdef PSXBIOS_LOG
2211         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2212 #endif
2213
2214         v0 = a0;
2215         pc0 = ra;
2216 }
2217
2218 void psxBios_putchar() { // 3d
2219         SysPrintf("%c", (char)a0);
2220         pc0 = ra;
2221 }
2222
2223 void psxBios_puts() { // 3e/3f
2224         SysPrintf("%s", Ra0);
2225         pc0 = ra;
2226 }
2227
2228
2229 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2230  * We want to mimic the PSX's behaviour in this case for bufile. */
2231 static size_t strlen_internal(char* p) 
2232 {
2233         size_t size_of_array = 0;
2234         while (*p++) size_of_array++;
2235         return size_of_array;
2236 }
2237
2238 #define bufile(mcd) { \
2239         size_t size_of_name = strlen_internal(dir->name); \
2240         while (nfile < 16) { \
2241                 int match=1; \
2242  \
2243                 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2244                 nfile++; \
2245                 if ((*ptr & 0xF0) != 0x50) continue; \
2246                 /* Bug link files show up as free block. */ \
2247                 if (!ptr[0xa]) continue; \
2248                 ptr+= 0xa; \
2249                 if (pfile[0] == 0) { \
2250                         strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2251                         if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2252                 } else for (i=0; i<20; i++) { \
2253                         if (pfile[i] == ptr[i]) { \
2254                                                                 dir->name[i] = ptr[i]; continue; } \
2255                         if (pfile[i] == '?') { \
2256                                 dir->name[i] = ptr[i]; continue; } \
2257                         if (pfile[i] == '*') { \
2258                                 strcpy(dir->name+i, ptr+i); break; } \
2259                         match = 0; break; \
2260                 } \
2261                 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2262                 if (match == 0) { continue; } \
2263                 dir->size = 8192; \
2264                 v0 = _dir; \
2265                 break; \
2266         } \
2267 }
2268
2269 /*
2270  *      struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2271  */
2272  
2273 void psxBios_firstfile() { // 42
2274         struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2275         void *pa0 = Ra0;
2276         u32 _dir = a1;
2277         char *ptr;
2278         int i;
2279
2280 #ifdef PSXBIOS_LOG
2281         PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2282 #endif
2283
2284         v0 = 0;
2285
2286         if (pa0) {
2287                 strcpy(ffile, pa0);
2288                 pfile = ffile+5;
2289                 nfile = 0;
2290                 if (!strncmp(pa0, "bu00", 4)) {
2291                         // firstfile() calls _card_read() internally, so deliver it's event
2292                         DeliverEvent(0x11, 0x2);
2293                         bufile(1);
2294                 } else if (!strncmp(pa0, "bu10", 4)) {
2295                         // firstfile() calls _card_read() internally, so deliver it's event
2296                         DeliverEvent(0x11, 0x2);
2297                         bufile(2);
2298                 }
2299         }
2300
2301         pc0 = ra;
2302 }
2303
2304 /*
2305  *      struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2306  */
2307
2308 void psxBios_nextfile() { // 43
2309         struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2310         u32 _dir = a0;
2311         char *ptr;
2312         int i;
2313
2314 #ifdef PSXBIOS_LOG
2315         PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2316 #endif
2317
2318         v0 = 0;
2319
2320         if (!strncmp(ffile, "bu00", 4)) {
2321                 bufile(1);
2322         }
2323
2324         if (!strncmp(ffile, "bu10", 4)) {
2325                 bufile(2);
2326         }
2327
2328         pc0 = ra;
2329 }
2330
2331 #define burename(mcd) { \
2332         for (i=1; i<16; i++) { \
2333                 int namelen, j, xor = 0; \
2334                 ptr = Mcd##mcd##Data + 128 * i; \
2335                 if ((*ptr & 0xF0) != 0x50) continue; \
2336                 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2337                 namelen = strlen(Ra1+5); \
2338                 memcpy(ptr+0xa, Ra1+5, namelen); \
2339                 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2340                 for (j=0; j<127; j++) xor^= ptr[j]; \
2341                 ptr[127] = xor; \
2342                 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2343                 v0 = 1; \
2344                 break; \
2345         } \
2346 }
2347
2348 /*
2349  *      int rename(char *old, char *new);
2350  */
2351
2352 void psxBios_rename() { // 44
2353         void *pa0 = Ra0;
2354         void *pa1 = Ra1;
2355         char *ptr;
2356         int i;
2357
2358 #ifdef PSXBIOS_LOG
2359         PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2360 #endif
2361
2362         v0 = 0;
2363
2364         if (pa0 && pa1) {
2365                 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2366                         burename(1);
2367                 }
2368
2369                 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2370                         burename(2);
2371                 }
2372         }
2373
2374         pc0 = ra;
2375 }
2376
2377
2378 #define budelete(mcd) { \
2379         for (i=1; i<16; i++) { \
2380                 ptr = Mcd##mcd##Data + 128 * i; \
2381                 if ((*ptr & 0xF0) != 0x50) continue; \
2382                 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2383                 *ptr = (*ptr & 0xf) | 0xA0; \
2384                 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2385                 SysPrintf("delete %s\n", ptr+0xa); \
2386                 v0 = 1; \
2387                 break; \
2388         } \
2389 }
2390
2391 /*
2392  *      int delete(char *name);
2393  */
2394
2395 void psxBios_delete() { // 45
2396         void *pa0 = Ra0;
2397         char *ptr;
2398         int i;
2399
2400 #ifdef PSXBIOS_LOG
2401         PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2402 #endif
2403
2404         v0 = 0;
2405
2406         if (pa0) {
2407                 if (!strncmp(pa0, "bu00", 4)) {
2408                         budelete(1);
2409                 }
2410
2411                 if (!strncmp(pa0, "bu10", 4)) {
2412                         budelete(2);
2413                 }
2414         }
2415
2416         pc0 = ra;
2417 }
2418
2419 void psxBios_InitCARD() { // 4a
2420 #ifdef PSXBIOS_LOG
2421         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2422 #endif
2423
2424         CardState = 0;
2425
2426         pc0 = ra;
2427 }
2428
2429 void psxBios_StartCARD() { // 4b
2430 #ifdef PSXBIOS_LOG
2431         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2432 #endif
2433
2434         if (CardState == 0) CardState = 1;
2435
2436         pc0 = ra;
2437 }
2438
2439 void psxBios_StopCARD() { // 4c
2440 #ifdef PSXBIOS_LOG
2441         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2442 #endif
2443
2444         if (CardState == 1) CardState = 0;
2445
2446         pc0 = ra;
2447 }
2448
2449 void psxBios__card_write() { // 0x4e
2450         void *pa2 = Ra2;
2451         int port;
2452
2453 #ifdef PSXBIOS_LOG
2454         PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2455 #endif
2456         /*
2457         Function also accepts sector 400h (a bug).
2458         But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2459         */
2460         if (!(a1 <= 0x3FF))
2461         {
2462                 /* Invalid sectors */
2463                 v0 = 0; pc0 = ra;
2464                 return;
2465         }
2466         card_active_chan = a0;
2467         port = a0 >> 4;
2468
2469         if (pa2) {
2470                 if (port == 0) {
2471                         memcpy(Mcd1Data + a1 * 128, pa2, 128);
2472                         SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2473                 } else {
2474                         memcpy(Mcd2Data + a1 * 128, pa2, 128);
2475                         SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2476                 }
2477         }
2478
2479         DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2480 //      DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2481
2482         v0 = 1; pc0 = ra;
2483 }
2484
2485 void psxBios__card_read() { // 0x4f
2486         void *pa2 = Ra2;
2487         int port;
2488
2489 #ifdef PSXBIOS_LOG
2490         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2491 #endif
2492         /*
2493         Function also accepts sector 400h (a bug).
2494         But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2495         */
2496         if (!(a1 <= 0x3FF))
2497         {
2498                 /* Invalid sectors */
2499                 v0 = 0; pc0 = ra;
2500                 return;
2501         }
2502         card_active_chan = a0;
2503         port = a0 >> 4;
2504
2505         if (pa2) {
2506                 if (port == 0) {
2507                         memcpy(pa2, Mcd1Data + a1 * 128, 128);
2508                 } else {
2509                         memcpy(pa2, Mcd2Data + a1 * 128, 128);
2510                 }
2511         }
2512
2513         DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2514 //      DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2515
2516         v0 = 1; pc0 = ra;
2517 }
2518
2519 void psxBios__new_card() { // 0x50
2520 #ifdef PSXBIOS_LOG
2521         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2522 #endif
2523
2524         pc0 = ra;
2525 }
2526
2527 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2528 void psxBios__get_error(void) // 55
2529
2530         v0 = 0;
2531         pc0 = ra;
2532 }
2533
2534 void psxBios_Krom2RawAdd() { // 0x51
2535         int i = 0;
2536
2537         const u32 table_8140[][2] = {
2538                 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2539                 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2540                 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2541                 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2542                 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2543                 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2544                 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2545                 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2546                 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2547                 {0xffff, 0}
2548         };
2549
2550         const u32 table_889f[][2] = {
2551                 {0x889f, 0x3d68},  {0x8900, 0x40ec},  {0x897f, 0x4fb0},  {0x8a00, 0x56f4},
2552                 {0x8a7f, 0x65b8},  {0x8b00, 0x6cfc},  {0x8b7f, 0x7bc0},  {0x8c00, 0x8304},
2553                 {0x8c7f, 0x91c8},  {0x8d00, 0x990c},  {0x8d7f, 0xa7d0},  {0x8e00, 0xaf14},
2554                 {0x8e7f, 0xbdd8},  {0x8f00, 0xc51c},  {0x8f7f, 0xd3e0},  {0x9000, 0xdb24},
2555                 {0x907f, 0xe9e8},  {0x9100, 0xf12c},  {0x917f, 0xfff0},  {0x9200, 0x10734},
2556                 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2557                 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2558                 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2559                 {0xffff, 0}
2560         };
2561
2562         if (a0 >= 0x8140 && a0 <= 0x84be) {
2563                 while (table_8140[i][0] <= a0) i++;
2564                 a0 -= table_8140[i - 1][0];
2565                 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2566         } else if (a0 >= 0x889f && a0 <= 0x9872) {
2567                 while (table_889f[i][0] <= a0) i++;
2568                 a0 -= table_889f[i - 1][0];
2569                 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2570         } else {
2571                 v0 = 0xffffffff;
2572         }
2573
2574         pc0 = ra;
2575 }
2576
2577 void psxBios_GetC0Table() { // 56
2578 #ifdef PSXBIOS_LOG
2579         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2580 #endif
2581
2582         v0 = 0x674; pc0 = ra;
2583 }
2584
2585 void psxBios_GetB0Table() { // 57
2586 #ifdef PSXBIOS_LOG
2587         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2588 #endif
2589
2590         v0 = 0x874; pc0 = ra;
2591 }
2592
2593 void psxBios__card_chan() { // 0x58
2594 #ifdef PSXBIOS_LOG
2595         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2596 #endif
2597
2598         v0 = card_active_chan;
2599         pc0 = ra;
2600 }
2601
2602 void psxBios_ChangeClearPad() { // 5b
2603 #ifdef PSXBIOS_LOG
2604         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2605 #endif  
2606
2607         pc0 = ra;
2608 }
2609
2610 void psxBios__card_status() { // 5c
2611 #ifdef PSXBIOS_LOG
2612         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2613 #endif
2614
2615         v0 = card_active_chan;
2616         pc0 = ra;
2617 }
2618
2619 void psxBios__card_wait() { // 5d
2620 #ifdef PSXBIOS_LOG
2621         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2622 #endif
2623
2624         v0 = 1;
2625         pc0 = ra;
2626 }
2627
2628 /* System calls C0 */
2629
2630 /*
2631  * int SysEnqIntRP(int index , long *queue);
2632  */
2633
2634 void psxBios_SysEnqIntRP() { // 02
2635 #ifdef PSXBIOS_LOG
2636         PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x02] ,a0);
2637 #endif
2638
2639         SysIntRP[a0] = a1;
2640
2641         v0 = 0; pc0 = ra;
2642 }
2643
2644 /*
2645  * int SysDeqIntRP(int index , long *queue);
2646  */
2647
2648 void psxBios_SysDeqIntRP() { // 03
2649 #ifdef PSXBIOS_LOG
2650         PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x03], a0);
2651 #endif
2652
2653         SysIntRP[a0] = 0;
2654
2655         v0 = 0; pc0 = ra;
2656 }
2657
2658 void psxBios_ChangeClearRCnt() { // 0a
2659         u32 *ptr;
2660
2661 #ifdef PSXBIOS_LOG
2662         PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2663 #endif
2664
2665         ptr = (u32*)PSXM((a0 << 2) + 0x8600);
2666         v0 = *ptr;
2667         *ptr = a1;
2668
2669 //      psxRegs.CP0.n.Status|= 0x404;
2670         pc0 = ra;
2671 }
2672
2673 void psxBios_dummy() { 
2674 #ifdef PSXBIOS_LOG
2675         PSXBIOS_LOG("unk %x call: %x\n", pc0 & 0x1fffff, t1);
2676 #endif
2677         pc0 = ra; 
2678 }
2679
2680 void (*biosA0[256])();
2681 void (*biosB0[256])();
2682 void (*biosC0[256])();
2683
2684 #include "sjisfont.h"
2685
2686 void psxBiosInit() {
2687         u32 base, size;
2688         u32 *ptr; 
2689         int i;
2690         uLongf len;
2691
2692         for(i = 0; i < 256; i++) {
2693                 biosA0[i] = NULL;
2694                 biosB0[i] = NULL;
2695                 biosC0[i] = NULL;
2696         }
2697         biosA0[0x3e] = psxBios_puts;
2698         biosA0[0x3f] = psxBios_printf;
2699
2700         biosB0[0x3d] = psxBios_putchar;
2701         biosB0[0x3f] = psxBios_puts;
2702
2703         if (!Config.HLE) return;
2704
2705         for(i = 0; i < 256; i++) {
2706                 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
2707                 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
2708                 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
2709         }
2710
2711         biosA0[0x00] = psxBios_open;
2712         biosA0[0x01] = psxBios_lseek;
2713         biosA0[0x02] = psxBios_read;
2714         biosA0[0x03] = psxBios_write;
2715         biosA0[0x04] = psxBios_close;
2716         //biosA0[0x05] = psxBios_ioctl;
2717         //biosA0[0x06] = psxBios_exit;
2718         //biosA0[0x07] = psxBios_sys_a0_07;
2719         biosA0[0x08] = psxBios_getc;
2720         biosA0[0x09] = psxBios_putc;
2721         biosA0[0x0a] = psxBios_todigit;
2722         //biosA0[0x0b] = psxBios_atof;
2723         //biosA0[0x0c] = psxBios_strtoul;
2724         //biosA0[0x0d] = psxBios_strtol;
2725         biosA0[0x0e] = psxBios_abs;
2726         biosA0[0x0f] = psxBios_labs;
2727         biosA0[0x10] = psxBios_atoi;
2728         biosA0[0x11] = psxBios_atol;
2729         //biosA0[0x12] = psxBios_atob;
2730         biosA0[0x13] = psxBios_setjmp;
2731         biosA0[0x14] = psxBios_longjmp;
2732         biosA0[0x15] = psxBios_strcat;
2733         biosA0[0x16] = psxBios_strncat;
2734         biosA0[0x17] = psxBios_strcmp;
2735         biosA0[0x18] = psxBios_strncmp;
2736         biosA0[0x19] = psxBios_strcpy;
2737         biosA0[0x1a] = psxBios_strncpy;
2738         biosA0[0x1b] = psxBios_strlen;
2739         biosA0[0x1c] = psxBios_index;
2740         biosA0[0x1d] = psxBios_rindex;
2741         biosA0[0x1e] = psxBios_strchr;
2742         biosA0[0x1f] = psxBios_strrchr;
2743         biosA0[0x20] = psxBios_strpbrk;
2744         biosA0[0x21] = psxBios_strspn;
2745         biosA0[0x22] = psxBios_strcspn;
2746         biosA0[0x23] = psxBios_strtok;
2747         biosA0[0x24] = psxBios_strstr;
2748         biosA0[0x25] = psxBios_toupper;
2749         biosA0[0x26] = psxBios_tolower;
2750         biosA0[0x27] = psxBios_bcopy;
2751         biosA0[0x28] = psxBios_bzero;
2752         biosA0[0x29] = psxBios_bcmp;
2753         biosA0[0x2a] = psxBios_memcpy;
2754         biosA0[0x2b] = psxBios_memset;
2755         biosA0[0x2c] = psxBios_memmove;
2756         biosA0[0x2d] = psxBios_memcmp;
2757         biosA0[0x2e] = psxBios_memchr;
2758         biosA0[0x2f] = psxBios_rand;
2759         biosA0[0x30] = psxBios_srand;
2760         biosA0[0x31] = psxBios_qsort;
2761         //biosA0[0x32] = psxBios_strtod;
2762         biosA0[0x33] = psxBios_malloc;
2763         biosA0[0x34] = psxBios_free;
2764         //biosA0[0x35] = psxBios_lsearch;
2765         //biosA0[0x36] = psxBios_bsearch;
2766         biosA0[0x37] = psxBios_calloc;
2767         biosA0[0x38] = psxBios_realloc;
2768         biosA0[0x39] = psxBios_InitHeap;
2769         //biosA0[0x3a] = psxBios__exit;
2770         biosA0[0x3b] = psxBios_getchar;
2771         biosA0[0x3c] = psxBios_putchar; 
2772         //biosA0[0x3d] = psxBios_gets;
2773         //biosA0[0x40] = psxBios_sys_a0_40;
2774         //biosA0[0x41] = psxBios_LoadTest;
2775         biosA0[0x42] = psxBios_Load;
2776         biosA0[0x43] = psxBios_Exec;
2777         biosA0[0x44] = psxBios_FlushCache;
2778         //biosA0[0x45] = psxBios_InstallInterruptHandler;
2779         biosA0[0x46] = psxBios_GPU_dw;
2780         biosA0[0x47] = psxBios_mem2vram;
2781         biosA0[0x48] = psxBios_SendGPU;
2782         biosA0[0x49] = psxBios_GPU_cw;
2783         biosA0[0x4a] = psxBios_GPU_cwb;
2784         biosA0[0x4b] = psxBios_GPU_SendPackets;
2785         biosA0[0x4c] = psxBios_sys_a0_4c;
2786         biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
2787         //biosA0[0x4e] = psxBios_GPU_sync;      
2788         //biosA0[0x4f] = psxBios_sys_a0_4f;
2789         //biosA0[0x50] = psxBios_sys_a0_50;
2790         biosA0[0x51] = psxBios_LoadExec;
2791         //biosA0[0x52] = psxBios_GetSysSp;
2792         //biosA0[0x53] = psxBios_sys_a0_53;
2793         //biosA0[0x54] = psxBios__96_init_a54;
2794         //biosA0[0x55] = psxBios__bu_init_a55;
2795         //biosA0[0x56] = psxBios__96_remove_a56;
2796         //biosA0[0x57] = psxBios_sys_a0_57;
2797         //biosA0[0x58] = psxBios_sys_a0_58;
2798         //biosA0[0x59] = psxBios_sys_a0_59;
2799         //biosA0[0x5a] = psxBios_sys_a0_5a;
2800         //biosA0[0x5b] = psxBios_dev_tty_init;
2801         //biosA0[0x5c] = psxBios_dev_tty_open;
2802         //biosA0[0x5d] = psxBios_sys_a0_5d;
2803         //biosA0[0x5e] = psxBios_dev_tty_ioctl;
2804         //biosA0[0x5f] = psxBios_dev_cd_open;
2805         //biosA0[0x60] = psxBios_dev_cd_read;
2806         //biosA0[0x61] = psxBios_dev_cd_close;
2807         //biosA0[0x62] = psxBios_dev_cd_firstfile;
2808         //biosA0[0x63] = psxBios_dev_cd_nextfile;
2809         //biosA0[0x64] = psxBios_dev_cd_chdir;
2810         //biosA0[0x65] = psxBios_dev_card_open;
2811         //biosA0[0x66] = psxBios_dev_card_read;
2812         //biosA0[0x67] = psxBios_dev_card_write;
2813         //biosA0[0x68] = psxBios_dev_card_close;
2814         //biosA0[0x69] = psxBios_dev_card_firstfile;
2815         //biosA0[0x6a] = psxBios_dev_card_nextfile;
2816         //biosA0[0x6b] = psxBios_dev_card_erase;
2817         //biosA0[0x6c] = psxBios_dev_card_undelete;
2818         //biosA0[0x6d] = psxBios_dev_card_format;
2819         //biosA0[0x6e] = psxBios_dev_card_rename;
2820         //biosA0[0x6f] = psxBios_dev_card_6f;
2821         biosA0[0x70] = psxBios__bu_init;
2822         biosA0[0x71] = psxBios__96_init;
2823         biosA0[0x72] = psxBios__96_remove;
2824         //biosA0[0x73] = psxBios_sys_a0_73;
2825         //biosA0[0x74] = psxBios_sys_a0_74;
2826         //biosA0[0x75] = psxBios_sys_a0_75;
2827         //biosA0[0x76] = psxBios_sys_a0_76;
2828         //biosA0[0x77] = psxBios_sys_a0_77;
2829         //biosA0[0x78] = psxBios__96_CdSeekL;
2830         //biosA0[0x79] = psxBios_sys_a0_79;
2831         //biosA0[0x7a] = psxBios_sys_a0_7a;
2832         //biosA0[0x7b] = psxBios_sys_a0_7b;
2833         //biosA0[0x7c] = psxBios__96_CdGetStatus;
2834         //biosA0[0x7d] = psxBios_sys_a0_7d;
2835         //biosA0[0x7e] = psxBios__96_CdRead;
2836         //biosA0[0x7f] = psxBios_sys_a0_7f;
2837         //biosA0[0x80] = psxBios_sys_a0_80;
2838         //biosA0[0x81] = psxBios_sys_a0_81;
2839         //biosA0[0x82] = psxBios_sys_a0_82;             
2840         //biosA0[0x83] = psxBios_sys_a0_83;
2841         //biosA0[0x84] = psxBios_sys_a0_84;
2842         //biosA0[0x85] = psxBios__96_CdStop;    
2843         //biosA0[0x86] = psxBios_sys_a0_86;
2844         //biosA0[0x87] = psxBios_sys_a0_87;
2845         //biosA0[0x88] = psxBios_sys_a0_88;
2846         //biosA0[0x89] = psxBios_sys_a0_89;
2847         //biosA0[0x8a] = psxBios_sys_a0_8a;
2848         //biosA0[0x8b] = psxBios_sys_a0_8b;
2849         //biosA0[0x8c] = psxBios_sys_a0_8c;
2850         //biosA0[0x8d] = psxBios_sys_a0_8d;
2851         //biosA0[0x8e] = psxBios_sys_a0_8e;
2852         //biosA0[0x8f] = psxBios_sys_a0_8f;
2853         //biosA0[0x90] = psxBios_sys_a0_90;
2854         //biosA0[0x91] = psxBios_sys_a0_91;
2855         //biosA0[0x92] = psxBios_sys_a0_92;
2856         //biosA0[0x93] = psxBios_sys_a0_93;
2857         //biosA0[0x94] = psxBios_sys_a0_94;
2858         //biosA0[0x95] = psxBios_sys_a0_95;
2859         //biosA0[0x96] = psxBios_AddCDROMDevice;
2860         //biosA0[0x97] = psxBios_AddMemCardDevide;
2861         //biosA0[0x98] = psxBios_DisableKernelIORedirection;
2862         //biosA0[0x99] = psxBios_EnableKernelIORedirection;
2863         //biosA0[0x9a] = psxBios_sys_a0_9a;
2864         //biosA0[0x9b] = psxBios_sys_a0_9b;
2865         //biosA0[0x9c] = psxBios_SetConf;
2866         //biosA0[0x9d] = psxBios_GetConf;
2867         //biosA0[0x9e] = psxBios_sys_a0_9e;
2868         biosA0[0x9f] = psxBios_SetMem;
2869         //biosA0[0xa0] = psxBios__boot;
2870         //biosA0[0xa1] = psxBios_SystemError;
2871         //biosA0[0xa2] = psxBios_EnqueueCdIntr;
2872         //biosA0[0xa3] = psxBios_DequeueCdIntr;
2873         //biosA0[0xa4] = psxBios_sys_a0_a4;
2874         //biosA0[0xa5] = psxBios_ReadSector;
2875         biosA0[0xa6] = psxBios_get_cd_status;
2876         //biosA0[0xa7] = psxBios_bufs_cb_0;
2877         //biosA0[0xa8] = psxBios_bufs_cb_1;
2878         //biosA0[0xa9] = psxBios_bufs_cb_2;
2879         //biosA0[0xaa] = psxBios_bufs_cb_3;
2880         biosA0[0xab] = psxBios__card_info;
2881         biosA0[0xac] = psxBios__card_load;
2882         //biosA0[0axd] = psxBios__card_auto;
2883         //biosA0[0xae] = psxBios_bufs_cd_4;
2884         //biosA0[0xaf] = psxBios_sys_a0_af;
2885         //biosA0[0xb0] = psxBios_sys_a0_b0;
2886         //biosA0[0xb1] = psxBios_sys_a0_b1;
2887         //biosA0[0xb2] = psxBios_do_a_long_jmp
2888         //biosA0[0xb3] = psxBios_sys_a0_b3;
2889         //biosA0[0xb4] = psxBios_sub_function;
2890 //*******************B0 CALLS****************************
2891         //biosB0[0x00] = psxBios_SysMalloc;
2892         //biosB0[0x01] = psxBios_sys_b0_01;
2893         biosB0[0x02] = psxBios_SetRCnt;
2894         biosB0[0x03] = psxBios_GetRCnt;
2895         biosB0[0x04] = psxBios_StartRCnt;
2896         biosB0[0x05] = psxBios_StopRCnt;
2897         biosB0[0x06] = psxBios_ResetRCnt;
2898         biosB0[0x07] = psxBios_DeliverEvent;
2899         biosB0[0x08] = psxBios_OpenEvent;
2900         biosB0[0x09] = psxBios_CloseEvent;
2901         biosB0[0x0a] = psxBios_WaitEvent;
2902         biosB0[0x0b] = psxBios_TestEvent;
2903         biosB0[0x0c] = psxBios_EnableEvent;
2904         biosB0[0x0d] = psxBios_DisableEvent;
2905         biosB0[0x0e] = psxBios_OpenTh;
2906         biosB0[0x0f] = psxBios_CloseTh;
2907         biosB0[0x10] = psxBios_ChangeTh;
2908         //biosB0[0x11] = psxBios_psxBios_b0_11;
2909         biosB0[0x12] = psxBios_InitPAD;
2910         biosB0[0x13] = psxBios_StartPAD;
2911         biosB0[0x14] = psxBios_StopPAD;
2912         biosB0[0x15] = psxBios_PAD_init;
2913         biosB0[0x16] = psxBios_PAD_dr;
2914         biosB0[0x17] = psxBios_ReturnFromException;
2915         biosB0[0x18] = psxBios_ResetEntryInt;
2916         biosB0[0x19] = psxBios_HookEntryInt;
2917         //biosB0[0x1a] = psxBios_sys_b0_1a;
2918         //biosB0[0x1b] = psxBios_sys_b0_1b;
2919         //biosB0[0x1c] = psxBios_sys_b0_1c;
2920         //biosB0[0x1d] = psxBios_sys_b0_1d;
2921         //biosB0[0x1e] = psxBios_sys_b0_1e;
2922         //biosB0[0x1f] = psxBios_sys_b0_1f;
2923         biosB0[0x20] = psxBios_UnDeliverEvent;
2924         //biosB0[0x21] = psxBios_sys_b0_21;
2925         //biosB0[0x22] = psxBios_sys_b0_22;
2926         //biosB0[0x23] = psxBios_sys_b0_23;
2927         //biosB0[0x24] = psxBios_sys_b0_24;
2928         //biosB0[0x25] = psxBios_sys_b0_25;
2929         //biosB0[0x26] = psxBios_sys_b0_26;
2930         //biosB0[0x27] = psxBios_sys_b0_27;
2931         //biosB0[0x28] = psxBios_sys_b0_28;
2932         //biosB0[0x29] = psxBios_sys_b0_29;
2933         //biosB0[0x2a] = psxBios_sys_b0_2a;
2934         //biosB0[0x2b] = psxBios_sys_b0_2b;
2935         //biosB0[0x2c] = psxBios_sys_b0_2c;
2936         //biosB0[0x2d] = psxBios_sys_b0_2d;
2937         //biosB0[0x2e] = psxBios_sys_b0_2e;
2938         //biosB0[0x2f] = psxBios_sys_b0_2f;
2939         //biosB0[0x30] = psxBios_sys_b0_30;
2940         //biosB0[0x31] = psxBios_sys_b0_31;
2941         biosB0[0x32] = psxBios_open;
2942         biosB0[0x33] = psxBios_lseek;
2943         biosB0[0x34] = psxBios_read;
2944         biosB0[0x35] = psxBios_write;
2945         biosB0[0x36] = psxBios_close;
2946         //biosB0[0x37] = psxBios_ioctl;
2947         //biosB0[0x38] = psxBios_exit;
2948         //biosB0[0x39] = psxBios_sys_b0_39;
2949         //biosB0[0x3a] = psxBios_getc;
2950         //biosB0[0x3b] = psxBios_putc;
2951         biosB0[0x3c] = psxBios_getchar;
2952         //biosB0[0x3e] = psxBios_gets;
2953         //biosB0[0x40] = psxBios_cd;
2954         biosB0[0x41] = psxBios_format;
2955         biosB0[0x42] = psxBios_firstfile;
2956         biosB0[0x43] = psxBios_nextfile;
2957         biosB0[0x44] = psxBios_rename;
2958         biosB0[0x45] = psxBios_delete;
2959         //biosB0[0x46] = psxBios_undelete;
2960         //biosB0[0x47] = psxBios_AddDevice;
2961         //biosB0[0x48] = psxBios_RemoteDevice;
2962         //biosB0[0x49] = psxBios_PrintInstalledDevices;
2963         biosB0[0x4a] = psxBios_InitCARD;
2964         biosB0[0x4b] = psxBios_StartCARD;
2965         biosB0[0x4c] = psxBios_StopCARD;
2966         //biosB0[0x4d] = psxBios_sys_b0_4d;
2967         biosB0[0x4e] = psxBios__card_write;
2968         biosB0[0x4f] = psxBios__card_read;
2969         biosB0[0x50] = psxBios__new_card;
2970         biosB0[0x51] = psxBios_Krom2RawAdd;
2971         //biosB0[0x52] = psxBios_sys_b0_52;
2972         //biosB0[0x53] = psxBios_sys_b0_53;
2973         //biosB0[0x54] = psxBios__get_errno;
2974         biosB0[0x55] = psxBios__get_error;
2975         biosB0[0x56] = psxBios_GetC0Table;
2976         biosB0[0x57] = psxBios_GetB0Table;
2977         biosB0[0x58] = psxBios__card_chan;
2978         //biosB0[0x59] = psxBios_sys_b0_59;
2979         //biosB0[0x5a] = psxBios_sys_b0_5a;
2980         biosB0[0x5b] = psxBios_ChangeClearPad;
2981         biosB0[0x5c] = psxBios__card_status;
2982         biosB0[0x5d] = psxBios__card_wait;
2983 //*******************C0 CALLS****************************
2984         //biosC0[0x00] = psxBios_InitRCnt;
2985         //biosC0[0x01] = psxBios_InitException;
2986         biosC0[0x02] = psxBios_SysEnqIntRP;
2987         biosC0[0x03] = psxBios_SysDeqIntRP;
2988         //biosC0[0x04] = psxBios_get_free_EvCB_slot;
2989         //biosC0[0x05] = psxBios_get_free_TCB_slot;
2990         //biosC0[0x06] = psxBios_ExceptionHandler;
2991         //biosC0[0x07] = psxBios_InstallExeptionHandler;
2992         //biosC0[0x08] = psxBios_SysInitMemory;
2993         //biosC0[0x09] = psxBios_SysInitKMem;
2994         biosC0[0x0a] = psxBios_ChangeClearRCnt; 
2995         //biosC0[0x0b] = psxBios_SystemError;
2996         //biosC0[0x0c] = psxBios_InitDefInt;
2997         //biosC0[0x0d] = psxBios_sys_c0_0d;
2998         //biosC0[0x0e] = psxBios_sys_c0_0e;
2999         //biosC0[0x0f] = psxBios_sys_c0_0f;
3000         //biosC0[0x10] = psxBios_sys_c0_10;
3001         //biosC0[0x11] = psxBios_sys_c0_11;
3002         //biosC0[0x12] = psxBios_InstallDevices;
3003         //biosC0[0x13] = psxBios_FlushStfInOutPut;
3004         //biosC0[0x14] = psxBios_sys_c0_14;
3005         //biosC0[0x15] = psxBios__cdevinput;
3006         //biosC0[0x16] = psxBios__cdevscan;
3007         //biosC0[0x17] = psxBios__circgetc;
3008         //biosC0[0x18] = psxBios__circputc;
3009         //biosC0[0x19] = psxBios_ioabort;
3010         //biosC0[0x1a] = psxBios_sys_c0_1a
3011         //biosC0[0x1b] = psxBios_KernelRedirect;
3012         //biosC0[0x1c] = psxBios_PatchAOTable;
3013 //************** THE END ***************************************
3014 /**/
3015         base = 0x1000;
3016         size = sizeof(EvCB) * 32;
3017         Event = (void *)&psxR[base]; base += size * 6;
3018         memset(Event, 0, size * 6);
3019         HwEV = Event;
3020         EvEV = Event + 32;
3021         RcEV = Event + 32 * 2;
3022         UeEV = Event + 32 * 3;
3023         SwEV = Event + 32 * 4;
3024         ThEV = Event + 32 * 5;
3025
3026         ptr = (u32 *)&psxM[0x0874]; // b0 table
3027         ptr[0] = SWAPu32(0x4c54 - 0x884);
3028
3029         ptr = (u32 *)&psxM[0x0674]; // c0 table
3030         ptr[6] = SWAPu32(0xc80);
3031
3032         memset(SysIntRP, 0, sizeof(SysIntRP));
3033         memset(Thread, 0, sizeof(Thread));
3034         Thread[0].status = 2; // main thread
3035
3036         pad_stopped = 1;
3037         jmp_int = NULL;
3038         pad_buf = NULL;
3039         pad_buf1 = NULL;
3040         pad_buf2 = NULL;
3041         pad_buf1len = pad_buf2len = 0;
3042         heap_addr = NULL;
3043         heap_end = NULL;
3044         heap_size = 0;
3045         CardState = -1;
3046         CurThread = 0;
3047         memset(FDesc, 0, sizeof(FDesc));
3048         card_active_chan = 0;
3049
3050         psxMu32ref(0x0150) = SWAPu32(0x160);
3051         psxMu32ref(0x0154) = SWAPu32(0x320);
3052         psxMu32ref(0x0160) = SWAPu32(0x248);
3053         strcpy((char *)&psxM[0x248], "bu");
3054 /*      psxMu32ref(0x0ca8) = SWAPu32(0x1f410004);
3055         psxMu32ref(0x0cf0) = SWAPu32(0x3c020000);
3056         psxMu32ref(0x0cf4) = SWAPu32(0x2442641c);
3057         psxMu32ref(0x09e0) = SWAPu32(0x43d0);
3058         psxMu32ref(0x4d98) = SWAPu32(0x946f000a);
3059 */
3060         // opcode HLE
3061         psxRu32ref(0x0000) = SWAPu32((0x3b << 26) | 4);
3062         /* Whatever this does, it actually breaks CTR, even without the uninitiliazed memory patch. 
3063         Normally games shouldn't read from address 0 yet they do. See explanation below in details. */
3064         //psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0);
3065         psxMu32ref(0x00a0) = SWAPu32((0x3b << 26) | 1);
3066         psxMu32ref(0x00b0) = SWAPu32((0x3b << 26) | 2);
3067         psxMu32ref(0x00c0) = SWAPu32((0x3b << 26) | 3);
3068         psxMu32ref(0x4c54) = SWAPu32((0x3b << 26) | 0);
3069         psxMu32ref(0x8000) = SWAPu32((0x3b << 26) | 5);
3070         psxMu32ref(0x07a0) = SWAPu32((0x3b << 26) | 0);
3071         psxMu32ref(0x0884) = SWAPu32((0x3b << 26) | 0);
3072         psxMu32ref(0x0894) = SWAPu32((0x3b << 26) | 0);
3073
3074         // initial stack pointer for BIOS interrupt
3075         psxMu32ref(0x6c80) = SWAPu32(0x000085c8);
3076
3077         // initial RNG seed
3078         psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3079
3080         // fonts
3081         len = 0x80000 - 0x66000;
3082         uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3083         len = 0x80000 - 0x69d68;
3084         uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3085
3086         // memory size 2 MB
3087         psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3088
3089         hleSoftCall = FALSE;
3090         
3091         /*      Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3092                 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3093                 Here are some examples of games not working with this fix in place :
3094                 R-type won't get past the Irem logo if not implemented.
3095                 Crash Team Racing will softlock after the Sony logo.
3096         */
3097         
3098         psxMu32ref(0x0000) = SWAPu32(0x00000003);
3099         /*
3100         But overwritten by 00000003h after soon.
3101         psxMu32ref(0x0000) = SWAPu32(0x00001A3C);
3102         */
3103         psxMu32ref(0x0004) = SWAPu32(0x800C5A27);
3104         psxMu32ref(0x0008) = SWAPu32(0x08000403);
3105         psxMu32ref(0x000C) = SWAPu32(0x00000000);
3106 }
3107
3108 void psxBiosShutdown() {
3109 }
3110
3111 #define psxBios_PADpoll(pad) { \
3112         PAD##pad##_startPoll(pad); \
3113         pad_buf##pad[0] = 0; \
3114         pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3115         if (!(pad_buf##pad[1] & 0x0f)) { \
3116                 bufcount = 32; \
3117         } else { \
3118                 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3119         } \
3120         PAD##pad##_poll(0); \
3121         i = 2; \
3122         while (bufcount--) { \
3123                 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3124         } \
3125 }
3126
3127 void biosInterrupt() {
3128         int i, bufcount;
3129
3130 //      if (psxHu32(0x1070) & 0x1) { // Vsync
3131                 if (pad_buf != NULL) {
3132                         u32 *buf = (u32*)pad_buf;
3133
3134                         if (!Config.UseNet) {
3135                                 PAD1_startPoll(1);
3136                                 if (PAD1_poll(0x42) == 0x23) {
3137                                         PAD1_poll(0);
3138                                         *buf = PAD1_poll(0) << 8;
3139                                         *buf |= PAD1_poll(0);
3140                                         PAD1_poll(0);
3141                                         *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3142                                         *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3143                                 } else {
3144                                         PAD1_poll(0);
3145                                         *buf = PAD1_poll(0) << 8;
3146                                         *buf|= PAD1_poll(0);
3147                                 }
3148
3149                                 PAD2_startPoll(2);
3150                                 if (PAD2_poll(0x42) == 0x23) {
3151                                         PAD2_poll(0);
3152                                         *buf |= PAD2_poll(0) << 24;
3153                                         *buf |= PAD2_poll(0) << 16;
3154                                         PAD2_poll(0);
3155                                         *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3156                                         *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3157                                 } else {
3158                                         PAD2_poll(0);
3159                                         *buf |= PAD2_poll(0) << 24;
3160                                         *buf |= PAD2_poll(0) << 16;
3161                                 }
3162                         } else {
3163                                 u16 data;
3164
3165                                 PAD1_startPoll(1);
3166                                 PAD1_poll(0x42);
3167                                 PAD1_poll(0);
3168                                 data = PAD1_poll(0) << 8;
3169                                 data |= PAD1_poll(0);
3170
3171                                 if (NET_sendPadData(&data, 2) == -1)
3172                                         netError();
3173
3174                                 if (NET_recvPadData(&((u16*)buf)[0], 1) == -1)
3175                                         netError();
3176                                 if (NET_recvPadData(&((u16*)buf)[1], 2) == -1)
3177                                         netError();
3178                         }
3179                 }
3180                 if (Config.UseNet && pad_buf1 != NULL && pad_buf2 != NULL) {
3181                         psxBios_PADpoll(1);
3182
3183                         if (NET_sendPadData(pad_buf1, i) == -1)
3184                                 netError();
3185
3186                         if (NET_recvPadData(pad_buf1, 1) == -1)
3187                                 netError();
3188                         if (NET_recvPadData(pad_buf2, 2) == -1)
3189                                 netError();
3190                 } else {
3191                         if (!pad_stopped)  {
3192                                 if (pad_buf1) {
3193                                         psxBios_PADpoll(1);
3194                                 }
3195
3196                                 if (pad_buf2) {
3197                                         psxBios_PADpoll(2);
3198                                 }
3199                         }
3200                 }
3201
3202         if (psxHu32(0x1070) & 0x1) { // Vsync
3203                 if (RcEV[3][1].status == EvStACTIVE) {
3204                         softCall(RcEV[3][1].fhandler);
3205 //                      hwWrite32(0x1f801070, ~(1));
3206                 }
3207         }
3208
3209         if (psxHu32(0x1070) & 0x70) { // Rcnt 0,1,2
3210                 int i;
3211
3212                 for (i = 0; i < 3; i++) {
3213                         if (psxHu32(0x1070) & (1 << (i + 4))) {
3214                                 if (RcEV[i][1].status == EvStACTIVE) {
3215                                         softCall(RcEV[i][1].fhandler);
3216                                 }
3217                                 psxHwWrite32(0x1f801070, ~(1 << (i + 4)));
3218                         }
3219                 }
3220         }
3221 }
3222
3223 void psxBiosException() {
3224         int i;
3225
3226         switch (psxRegs.CP0.n.Cause & 0x3c) {
3227                 case 0x00: // Interrupt
3228                         interrupt_r26=psxRegs.CP0.n.EPC;
3229 #ifdef PSXCPU_LOG
3230 //                      PSXCPU_LOG("interrupt\n");
3231 #endif
3232                         SaveRegs();
3233
3234                         sp = psxMu32(0x6c80); // create new stack for interrupt handlers
3235
3236                         biosInterrupt();
3237
3238                         for (i = 0; i < 8; i++) {
3239                                 if (SysIntRP[i]) {
3240                                         u32 *queue = (u32 *)PSXM(SysIntRP[i]);
3241
3242                                         s0 = queue[2];
3243                                         softCall(queue[1]);
3244                                 }
3245                         }
3246
3247                         if (jmp_int != NULL) {
3248                                 int i;
3249
3250                                 psxHwWrite32(0x1f801070, 0xffffffff);
3251
3252                                 ra = jmp_int[0];
3253                                 sp = jmp_int[1];
3254                                 fp = jmp_int[2];
3255                                 for (i = 0; i < 8; i++) // s0-s7
3256                                          psxRegs.GPR.r[16 + i] = jmp_int[3 + i];
3257                                 gp = jmp_int[11];
3258
3259                                 v0 = 1;
3260                                 pc0 = ra;
3261                                 return;
3262                         }
3263                         psxHwWrite16(0x1f801070, 0);
3264                         break;
3265
3266                 case 0x20: // Syscall
3267 #ifdef PSXCPU_LOG
3268                         PSXCPU_LOG("syscall exp %x\n", a0);
3269 #endif
3270                         switch (a0) {
3271                                 case 1: // EnterCritical - disable irq's
3272                                         /* Fixes Medievil 2 not loading up new game, Digimon World not booting up and possibly others */
3273                                         v0 = (psxRegs.CP0.n.Status & 0x404) == 0x404;
3274                                         psxRegs.CP0.n.Status &= ~0x404;
3275                                         break;
3276
3277                                 case 2: // ExitCritical - enable irq's
3278                                         psxRegs.CP0.n.Status |= 0x404; 
3279                                         break;
3280                                 /* Normally this should cover SYS(00h, SYS(04h but they don't do anything relevant so... */
3281                                 default:
3282                                         break;
3283                         }
3284                         pc0 = psxRegs.CP0.n.EPC + 4;
3285
3286                         psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3287                                                                   ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3288                         return;
3289
3290                 default:
3291 #ifdef PSXCPU_LOG
3292                         PSXCPU_LOG("unknown bios exception!\n");
3293 #endif
3294                         break;
3295         }
3296
3297         pc0 = psxRegs.CP0.n.EPC;
3298         if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;
3299
3300         psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3301                                                   ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3302 }
3303
3304 #define bfreeze(ptr, size) { \
3305         if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3306         if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3307         base += size; \
3308 }
3309
3310 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3311 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3312
3313 #define bfreezepsxMptr(ptr, type) { \
3314         if (Mode == 1) { \
3315                 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3316                 else psxRu32ref(base) = 0; \
3317         } else { \
3318                 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3319                 else (ptr) = NULL; \
3320         } \
3321         base += sizeof(u32); \
3322 }
3323
3324 void psxBiosFreeze(int Mode) {
3325         u32 base = 0x40000;
3326
3327         bfreezepsxMptr(jmp_int, u32);
3328         bfreezepsxMptr(pad_buf, int);
3329         bfreezepsxMptr(pad_buf1, char);
3330         bfreezepsxMptr(pad_buf2, char);
3331         bfreezepsxMptr(heap_addr, u32);
3332         bfreezel(&pad_buf1len);
3333         bfreezel(&pad_buf2len);
3334         bfreezes(regs);
3335         bfreezes(SysIntRP);
3336         bfreezel(&CardState);
3337         bfreezes(Thread);
3338         bfreezel(&CurThread);
3339         bfreezes(FDesc);
3340         bfreezel(&card_active_chan);
3341         bfreezel(&pad_stopped);
3342         bfreezel(&heap_size);
3343 }