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