psxbios: unbreak bcopy
[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 "sio.h"
37 #include "psxhle.h"
38 #include "psxinterpreter.h"
39 #include <zlib.h>
40
41 #if (defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)
42 #pragma GCC diagnostic ignored "-Wpointer-sign"
43 #endif
44
45 #ifndef PSXBIOS_LOG
46 //#define PSXBIOS_LOG printf
47 #define PSXBIOS_LOG(...)
48 #endif
49
50 char *biosA0n[256] = {
51 // 0x00
52         "open",         "lseek",        "read",         "write",
53         "close",        "ioctl",        "exit",         "sys_a0_07",
54         "getc",         "putc",         "todigit",      "atof",
55         "strtoul",      "strtol",       "abs",          "labs",
56 // 0x10
57         "atoi",         "atol",         "atob",         "setjmp",
58         "longjmp",      "strcat",       "strncat",      "strcmp",
59         "strncmp",      "strcpy",       "strncpy",      "strlen",
60         "index",        "rindex",       "strchr",       "strrchr",
61 // 0x20
62         "strpbrk",      "strspn",       "strcspn",      "strtok",
63         "strstr",       "toupper",      "tolower",      "bcopy",
64         "bzero",        "bcmp",         "memcpy",       "memset",
65         "memmove",      "memcmp",       "memchr",       "rand",
66 // 0x30
67         "srand",        "qsort",        "strtod",       "malloc",
68         "free",         "lsearch",      "bsearch",      "calloc",
69         "realloc",      "InitHeap",     "_exit",        "getchar",
70         "putchar",      "gets",         "puts",         "printf",
71 // 0x40
72         "SystemErrorUnresolvedException", "LoadTest",           "Load",         "Exec",
73         "FlushCache",           "InstallInterruptHandler",      "GPU_dw",       "mem2vram",
74         "SendGPUStatus",        "GPU_cw",                       "GPU_cwb",      "SendPackets",
75         "sys_a0_4c",            "GetGPUStatus",                         "GPU_sync",     "sys_a0_4f",
76 // 0x50
77         "sys_a0_50",            "LoadExec",                             "GetSysSp",             "sys_a0_53",
78         "_96_init()",           "_bu_init()",                   "_96_remove()", "sys_a0_57",
79         "sys_a0_58",            "sys_a0_59",                    "sys_a0_5a",    "dev_tty_init",
80         "dev_tty_open",         "sys_a0_5d",                    "dev_tty_ioctl","dev_cd_open",
81 // 0x60
82         "dev_cd_read",          "dev_cd_close",                 "dev_cd_firstfile",     "dev_cd_nextfile",
83         "dev_cd_chdir",         "dev_card_open",                "dev_card_read",        "dev_card_write",
84         "dev_card_close",       "dev_card_firstfile",   "dev_card_nextfile","dev_card_erase",
85         "dev_card_undelete","dev_card_format",          "dev_card_rename",      "dev_card_6f",
86 // 0x70
87         "_bu_init",                     "_96_init",             "CdRemove",             "sys_a0_73",
88         "sys_a0_74",            "sys_a0_75",    "sys_a0_76",            "sys_a0_77",
89         "_96_CdSeekL",          "sys_a0_79",    "sys_a0_7a",            "sys_a0_7b",
90         "_96_CdGetStatus",      "sys_a0_7d",    "_96_CdRead",           "sys_a0_7f",
91 // 0x80
92         "sys_a0_80",            "sys_a0_81",    "sys_a0_82",            "sys_a0_83",
93         "sys_a0_84",            "_96_CdStop",   "sys_a0_86",            "sys_a0_87",
94         "sys_a0_88",            "sys_a0_89",    "sys_a0_8a",            "sys_a0_8b",
95         "sys_a0_8c",            "sys_a0_8d",    "sys_a0_8e",            "sys_a0_8f",
96 // 0x90
97         "sys_a0_90",            "sys_a0_91",    "sys_a0_92",            "sys_a0_93",
98         "sys_a0_94",            "sys_a0_95",    "AddCDROMDevice",       "AddMemCardDevide",
99         "DisableKernelIORedirection",           "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
100         "SetConf",                      "GetConf",              "sys_a0_9e",            "SetMem",
101 // 0xa0
102         "_boot",                        "SystemError",  "EnqueueCdIntr",        "DequeueCdIntr",
103         "sys_a0_a4",            "ReadSector",   "get_cd_status",        "bufs_cb_0",
104         "bufs_cb_1",            "bufs_cb_2",    "bufs_cb_3",            "_card_info",
105         "_card_load",           "_card_auto",   "bufs_cd_4",            "sys_a0_af",
106 // 0xb0
107         "sys_a0_b0",            "sys_a0_b1",    "do_a_long_jmp",        "sys_a0_b3",
108         "GetSystemInfo",
109 };
110
111 char *biosB0n[256] = {
112 // 0x00
113         "SysMalloc",            "sys_b0_01",    "sys_b0_02",    "sys_b0_03",
114         "sys_b0_04",            "sys_b0_05",    "sys_b0_06",    "DeliverEvent",
115         "OpenEvent",            "CloseEvent",   "WaitEvent",    "TestEvent",
116         "EnableEvent",          "DisableEvent", "OpenTh",               "CloseTh",
117 // 0x10
118         "ChangeTh",                     "sys_b0_11",    "InitPAD",              "StartPAD",
119         "StopPAD",                      "PAD_init",             "PAD_dr",               "ReturnFromExecption",
120         "ResetEntryInt",        "HookEntryInt", "sys_b0_1a",    "sys_b0_1b",
121         "sys_b0_1c",            "sys_b0_1d",    "sys_b0_1e",    "sys_b0_1f",
122 // 0x20
123         "UnDeliverEvent",       "sys_b0_21",    "sys_b0_22",    "sys_b0_23",
124         "sys_b0_24",            "sys_b0_25",    "sys_b0_26",    "sys_b0_27",
125         "sys_b0_28",            "sys_b0_29",    "sys_b0_2a",    "sys_b0_2b",
126         "sys_b0_2c",            "sys_b0_2d",    "sys_b0_2e",    "sys_b0_2f",
127 // 0x30
128         "sys_b0_30",            "sys_b0_31",    "open",                 "lseek",
129         "read",                         "write",                "close",                "ioctl",
130         "exit",                         "sys_b0_39",    "getc",                 "putc",
131         "getchar",                      "putchar",              "gets",                 "puts",
132 // 0x40
133         "cd",                           "format",               "firstfile",    "nextfile",
134         "rename",                       "delete",               "undelete",             "AddDevice",
135         "RemoteDevice",         "PrintInstalledDevices", "InitCARD", "StartCARD",
136         "StopCARD",                     "sys_b0_4d",    "_card_write",  "_card_read",
137 // 0x50
138         "_new_card",            "Krom2RawAdd",  "sys_b0_52",    "sys_b0_53",
139         "_get_errno",           "_get_error",   "GetC0Table",   "GetB0Table",
140         "_card_chan",           "sys_b0_59",    "sys_b0_5a",    "ChangeClearPAD",
141         "_card_status",         "_card_wait",
142 };
143
144 char *biosC0n[256] = {
145 // 0x00
146         "InitRCnt",                       "InitException",              "SysEnqIntRP",          "SysDeqIntRP",
147         "get_free_EvCB_slot", "get_free_TCB_slot",      "ExceptionHandler",     "InstallExeptionHandler",
148         "SysInitMemory",          "SysInitKMem",                "ChangeClearRCnt",      "SystemError",
149         "InitDefInt",             "sys_c0_0d",                  "sys_c0_0e",            "sys_c0_0f",
150 // 0x10
151         "sys_c0_10",              "sys_c0_11",                  "InstallDevices",       "FlushStfInOutPut",
152         "sys_c0_14",              "_cdevinput",                 "_cdevscan",            "_circgetc",
153         "_circputc",              "ioabort",                    "sys_c0_1a",            "KernelRedirect",
154         "PatchAOTable",
155 };
156
157 //#define r0 (psxRegs.GPR.n.r0)
158 #define at (psxRegs.GPR.n.at)
159 #define v0 (psxRegs.GPR.n.v0)
160 #define v1 (psxRegs.GPR.n.v1)
161 #define a0 (psxRegs.GPR.n.a0)
162 #define a1 (psxRegs.GPR.n.a1)
163 #define a2 (psxRegs.GPR.n.a2)
164 #define a3 (psxRegs.GPR.n.a3)
165 #define t0 (psxRegs.GPR.n.t0)
166 #define t1 (psxRegs.GPR.n.t1)
167 #define t2 (psxRegs.GPR.n.t2)
168 #define t3 (psxRegs.GPR.n.t3)
169 #define t4 (psxRegs.GPR.n.t4)
170 #define t5 (psxRegs.GPR.n.t5)
171 #define t6 (psxRegs.GPR.n.t6)
172 #define t7 (psxRegs.GPR.n.t7)
173 #define t8 (psxRegs.GPR.n.t8)
174 #define t9 (psxRegs.GPR.n.t9)
175 #define s0 (psxRegs.GPR.n.s0)
176 #define s1 (psxRegs.GPR.n.s1)
177 #define s2 (psxRegs.GPR.n.s2)
178 #define s3 (psxRegs.GPR.n.s3)
179 #define s4 (psxRegs.GPR.n.s4)
180 #define s5 (psxRegs.GPR.n.s5)
181 #define s6 (psxRegs.GPR.n.s6)
182 #define s7 (psxRegs.GPR.n.s7)
183 #define k0 (psxRegs.GPR.n.k0)
184 #define k1 (psxRegs.GPR.n.k1)
185 #define gp (psxRegs.GPR.n.gp)
186 #define sp (psxRegs.GPR.n.sp)
187 #define fp (psxRegs.GPR.n.fp)
188 #define ra (psxRegs.GPR.n.ra)
189 #define pc0 (psxRegs.pc)
190
191 #define Ra0 ((char *)PSXM(a0))
192 #define Ra1 ((char *)PSXM(a1))
193 #define Ra2 ((char *)PSXM(a2))
194 #define Ra3 ((char *)PSXM(a3))
195 #define Rv0 ((char *)PSXM(v0))
196 #define Rsp ((char *)PSXM(sp))
197
198 typedef struct {
199         u32 class;
200         u32 status;
201         u32 spec;
202         u32 mode;
203         u32 fhandler;
204         u32 unused[2];
205 } EvCB;
206
207 #define EvStUNUSED      0x0000
208 #define EvStDISABLED    0x1000
209 #define EvStACTIVE      0x2000
210 #define EvStALREADY     0x4000
211
212 #define EvMdCALL        0x1000
213 #define EvMdMARK        0x2000
214
215 typedef struct {
216         u32 status;
217         u32 mode;
218         u32 reg[32];
219         u32 epc;
220         u32 hi, lo;
221         u32 sr, cause;
222         u32 unused[9];
223 } TCB;
224
225 typedef struct {
226         u32 _pc0;
227         u32 gp0;
228         u32 t_addr;
229         u32 t_size;
230         u32 d_addr; // 10
231         u32 d_size;
232         u32 b_addr;
233         u32 b_size; // 1c
234         u32 S_addr;
235         u32 s_size;
236         u32 _sp, _fp, _gp, ret, base;
237 } EXEC;
238
239 struct DIRENTRY {
240         char name[20];
241         s32 attr;
242         s32 size;
243         u32 next;
244         s32 head;
245         char system[4];
246 };
247
248 typedef struct {
249         char name[32];
250         u32  mode;
251         u32  offset;
252         u32  size;
253         u32  mcfile;
254 } FileDesc;
255
256 // todo: FileDesc layout is wrong
257 // todo: get rid of these globals
258 static FileDesc FDesc[32];
259 static char ffile[64], *pfile;
260 static int nfile;
261
262 // fixed RAM offsets, SCPH1001 compatible
263 #define A_TT_ExCB       0x0100
264 #define A_TT_PCB        0x0108
265 #define A_TT_TCB        0x0110
266 #define A_TT_EvCB       0x0120
267 #define A_A0_TABLE      0x0200
268 #define A_B0_TABLE      0x0874
269 #define A_C0_TABLE      0x0674
270 #define A_SYSCALL       0x0650
271 #define A_EXCEPTION     0x0c80
272 #define A_EXC_SP        0x6cf0
273 #define A_EEXIT_DEF     0x6cf4
274 #define A_KMALLOC_PTR   0x7460
275 #define A_KMALLOC_SIZE  0x7464
276 #define A_KMALLOC_END   0x7468
277 #define A_PADCRD_CHN_E  0x74a8  // pad/card irq chain entry, see hleExcPadCard1()
278 #define A_PAD_IRQR_ENA  0x74b8  // pad read on vint irq (nocash 'pad_enable_flag')
279 #define A_CARD_IRQR_ENA 0x74bc  // same for card
280 #define A_PAD_INBUF     0x74c8  // 2x buffers for rx pad data
281 #define A_PAD_OUTBUF    0x74d0  // 2x buffers for tx pad data
282 #define A_PAD_IN_LEN    0x74d8
283 #define A_PAD_OUT_LEN   0x74e0
284 #define A_PAD_DR_DST    0x74c4
285 #define A_CARD_CHAN1    0x7500
286 #define A_PAD_DR_BUF1   0x7570
287 #define A_PAD_DR_BUF2   0x7598
288 #define A_EEXIT_PTR     0x75d0
289 #define A_EXC_STACK     0x85d8  // exception stack top
290 #define A_RCNT_VBL_ACK  0x8600
291 #define A_PAD_ACK_VBL   0x8914  // enable vint ack by pad reading code
292 #define A_HEAP_BASE     0x9000
293 #define A_HEAP_SIZE     0x9004
294 #define A_HEAP_END      0x9008
295 #define A_HEAP_FLAG     0x900c
296 #define A_CD_EVENTS     0xb9b8
297 #define A_EXC_GP        0xf450
298
299 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
300
301 static u32 loadRam32(u32 addr)
302 {
303         assert(!(addr & 0x5f800000));
304         return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
305 }
306
307 static void *castRam8ptr(u32 addr)
308 {
309         assert(!(addr & 0x5f800000));
310         return psxM + (addr & 0x1fffff);
311 }
312
313 static void *castRam32ptr(u32 addr)
314 {
315         assert(!(addr & 0x5f800003));
316         return psxM + (addr & 0x1ffffc);
317 }
318
319 static void *loadRam8ptr(u32 addr)
320 {
321         return castRam8ptr(loadRam32(addr));
322 }
323
324 static void *loadRam32ptr(u32 addr)
325 {
326         return castRam32ptr(loadRam32(addr));
327 }
328
329 static void storeRam8(u32 addr, u8 d)
330 {
331         assert(!(addr & 0x5f800000));
332         *((u8 *)psxM + (addr & 0x1fffff)) = d;
333 }
334
335 static void storeRam32(u32 addr, u32 d)
336 {
337         assert(!(addr & 0x5f800000));
338         *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
339 }
340
341 static void mips_return(u32 val)
342 {
343         v0 = val;
344         pc0 = ra;
345 }
346
347 static void use_cycles(u32 cycle)
348 {
349         psxRegs.cycle += cycle * 2;
350 }
351
352 static void mips_return_c(u32 val, u32 cycle)
353 {
354         use_cycles(cycle);
355         mips_return(val);
356 }
357
358 static void mips_return_void_c(u32 cycle)
359 {
360         use_cycles(cycle);
361         pc0 = ra;
362 }
363
364 static int returned_from_exception(void)
365 {
366         // 0x80000080 means it took another exception just after return
367         return pc0 == k0 || pc0 == 0x80000080;
368 }
369
370 static inline void softCall(u32 pc) {
371         u32 sra = ra;
372         u32 ssr = psxRegs.CP0.n.SR;
373         u32 lim = 0;
374         pc0 = pc;
375         ra = 0x80001000;
376         psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
377
378         while (pc0 != 0x80001000 && ++lim < 1000000)
379                 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
380
381         if (lim == 1000000)
382                 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
383         ra = sra;
384         psxRegs.CP0.n.SR |= ssr & 0x404;
385 }
386
387 static inline void softCallInException(u32 pc) {
388         u32 sra = ra;
389         u32 lim = 0;
390         pc0 = pc;
391         ra = 0x80001000;
392
393         while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 1000000)
394                 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
395
396         if (lim == 1000000)
397                 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
398         if (pc0 == 0x80001000)
399                 ra = sra;
400 }
401
402 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
403 static u32 DeliverEvent(u32 class, u32 spec);
404 static u32 UnDeliverEvent(u32 class, u32 spec);
405 static void CloseEvent(u32 ev);
406
407 /*                                           *
408 //                                           *
409 //                                           *
410 //               System calls A0             */
411
412
413 #define buread(Ra1, mcd, length) { \
414         PSXBIOS_LOG("read %d: %x,%x (%s)\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2, Mcd##mcd##Data + 128 * FDesc[1 + mcd].mcfile + 0xa); \
415         ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
416         memcpy(Ra1, ptr, length); \
417         psxCpu->Clear(a1, (length + 3) / 4); \
418         if (FDesc[1 + mcd].mode & 0x8000) { \
419         DeliverEvent(0xf0000011, 0x0004); \
420         DeliverEvent(0xf4000001, 0x0004); \
421         v0 = 0; } \
422         else v0 = length; \
423         FDesc[1 + mcd].offset += v0; \
424 }
425
426 #define buwrite(Ra1, mcd, length) { \
427         u32 offset =  + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
428         PSXBIOS_LOG("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
429         ptr = Mcd##mcd##Data + offset; \
430         memcpy(ptr, Ra1, length); \
431         FDesc[1 + mcd].offset += length; \
432         SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
433         if (FDesc[1 + mcd].mode & 0x8000) { \
434         DeliverEvent(0xf0000011, 0x0004); \
435         DeliverEvent(0xf4000001, 0x0004); \
436         v0 = 0; } \
437         else v0 = length; \
438 }
439
440 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
441 /* For some strange reason, the returned character is sign-expanded; */
442 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
443 /* TODO FIX ME : Properly implement this behaviour */
444 void psxBios_getc(void) // 0x03, 0x35
445 {
446         char *ptr;
447         void *pa1 = Ra1;
448 #ifdef PSXBIOS_LOG
449         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
450 #endif
451         v0 = -1;
452
453         if (pa1 != INVALID_PTR) {
454                 switch (a0) {
455                         case 2: buread(pa1, 1, 1); break;
456                         case 3: buread(pa1, 2, 1); break;
457                 }
458         }
459
460         pc0 = ra;
461 }
462
463 /* Copy of psxBios_write, except size is 1. */
464 void psxBios_putc(void) // 0x09, 0x3B
465 {
466         char *ptr;
467         void *pa1 = Ra1;
468 #ifdef PSXBIOS_LOG
469         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
470 #endif
471         v0 = -1;
472         if (pa1 == INVALID_PTR) {
473                 pc0 = ra;
474                 return;
475         }
476
477         if (a0 == 1) { // stdout
478                 char *ptr = (char *)pa1;
479
480                 v0 = a2;
481                 while (a2 > 0) {
482                         printf("%c", *ptr++); a2--;
483                 }
484                 pc0 = ra; return;
485         }
486
487         switch (a0) {
488                 case 2: buwrite(pa1, 1, 1); break;
489                 case 3: buwrite(pa1, 2, 1); break;
490         }
491
492         pc0 = ra;
493 }
494
495 void psxBios_todigit(void) // 0x0a
496 {
497         int c = a0;
498 #ifdef PSXBIOS_LOG
499         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
500 #endif
501         c &= 0xFF;
502         if (c >= 0x30 && c < 0x3A) {
503                 c -= 0x30;
504         }
505         else if (c > 0x60 && c < 0x7B) {
506                 c -= 0x20;
507         }
508         else if (c > 0x40 && c < 0x5B) {
509                 c = c - 0x41 + 10;
510         }
511         else if (c >= 0x80) {
512                 c = -1;
513         }
514         else
515         {
516                 c = 0x0098967F;
517         }
518         v0 = c;
519         pc0 = ra;
520 }
521
522 void psxBios_abs() { // 0x0e
523         if ((s32)a0 < 0) v0 = -(s32)a0;
524         else v0 = a0;
525         pc0 = ra;
526 }
527
528 void psxBios_labs() { // 0x0f
529         psxBios_abs();
530 }
531
532 void psxBios_atoi() { // 0x10
533         s32 n = 0, f = 0;
534         char *p = (char *)Ra0;
535
536         for (;;p++) {
537                 switch (*p) {
538                         case ' ': case '\t': continue;
539                         case '-': f++;
540                         case '+': p++;
541                 }
542                 break;
543         }
544
545         while (*p >= '0' && *p <= '9') {
546                 n = n * 10 + *p++ - '0';
547         }
548
549         v0 = (f ? -n : n);
550         pc0 = ra;
551 }
552
553 void psxBios_atol() { // 0x11
554         psxBios_atoi();
555 }
556
557 struct jmp_buf_ {
558         u32 ra_, sp_, fp_;
559         u32 s[8];
560         u32 gp_;
561 };
562
563 static void psxBios_setjmp() { // 0x13
564         struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
565         int i;
566
567         PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
568
569         jmp_buf->ra_ = SWAP32(ra);
570         jmp_buf->sp_ = SWAP32(sp);
571         jmp_buf->fp_ = SWAP32(fp);
572         for (i = 0; i < 8; i++) // s0-s7
573                 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
574         jmp_buf->gp_ = SWAP32(gp);
575
576         mips_return_c(0, 15);
577 }
578
579 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
580 {
581         int i;
582
583         ra = SWAP32(jmp_buf->ra_);
584         sp = SWAP32(jmp_buf->sp_);
585         fp = SWAP32(jmp_buf->fp_);
586         for (i = 0; i < 8; i++) // s0-s7
587                 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
588         gp = SWAP32(jmp_buf->gp_);;
589 }
590
591 void psxBios_longjmp() { // 0x14
592         struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
593
594         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
595         longjmp_load(jmp_buf);
596         mips_return_c(a1, 15);
597 }
598
599 void psxBios_strcat() { // 0x15
600         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
601
602 #ifdef PSXBIOS_LOG
603         PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
604 #endif
605         if (a0 == 0 || a1 == 0)
606         {
607                 v0 = 0;
608                 pc0 = ra;
609                 return;
610         }
611         while (*p1++);
612         --p1;
613         while ((*p1++ = *p2++) != '\0');
614
615         v0 = a0; pc0 = ra;
616 }
617
618 void psxBios_strncat() { // 0x16
619         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
620         s32 n = a2;
621
622 #ifdef PSXBIOS_LOG
623         PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
624 #endif
625         if (a0 == 0 || a1 == 0)
626         {
627                 v0 = 0;
628                 pc0 = ra;
629                 return;
630         }
631         while (*p1++);
632         --p1;
633         while ((*p1++ = *p2++) != '\0') {
634                 if (--n < 0) {
635                         *--p1 = '\0';
636                         break;
637                 }
638         }
639
640         v0 = a0; pc0 = ra;
641 }
642
643 void psxBios_strcmp() { // 0x17
644         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
645         s32 n=0;
646         if (a0 == 0 && a1 == 0)
647         {
648                 v0 = 0;
649                 pc0 = ra;
650                 return;
651         }
652         else if (a0 == 0 && a1 != 0)
653         {
654                 v0 = -1;
655                 pc0 = ra;
656                 return;
657         }
658         else if (a0 != 0 && a1 == 0)
659         {
660                 v0 = 1;
661                 pc0 = ra;
662                 return;
663         }
664 #ifdef PSXBIOS_LOG
665         PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
666 #endif
667
668         while (*p1 == *p2++) {
669                 n++;
670                 if (*p1++ == '\0') {
671                         v1=n-1;
672                         a0+=n;
673                         a1+=n;
674                         v0 = 0;
675                         pc0 = ra;
676                         return;
677                 }
678         }
679
680         v0 = (*p1 - *--p2);
681         v1 = n;
682         a0+=n;
683         a1+=n;
684         pc0 = ra;
685 }
686
687 void psxBios_strncmp() { // 0x18
688         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
689         s32 n = a2;
690         if (a0 == 0 && a1 == 0)
691         {
692                 v0 = 0;
693                 pc0 = ra;
694                 return;
695         }
696         else if (a0 == 0 && a1 != 0)
697         {
698                 v0 = -1;
699                 pc0 = ra;
700                 return;
701         }
702         else if (a0 != 0 && a1 == 0)
703         {
704                 v0 = 1;
705                 pc0 = ra;
706                 return;
707         }
708 #ifdef PSXBIOS_LOG
709         PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
710 #endif
711
712         while (--n >= 0 && *p1 == *p2++) {
713                 if (*p1++ == '\0') {
714                         v0 = 0;
715                         pc0 = ra;
716                         v1 = a2 - ((a2-n) - 1);
717                         a0 += (a2-n) - 1;
718                         a1 += (a2-n) - 1;
719                         a2 = n;
720                         return;
721                 }
722         }
723
724         v0 = (n < 0 ? 0 : *p1 - *--p2);
725         pc0 = ra;
726         v1 = a2 - ((a2-n) - 1);
727         a0 += (a2-n) - 1;
728         a1 += (a2-n) - 1;
729         a2 = n;
730 }
731
732 void psxBios_strcpy() { // 0x19
733         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
734         if (a0 == 0 || a1 == 0)
735         {
736                 v0 = 0;
737                 pc0 = ra;
738                 return;
739         }
740         while ((*p1++ = *p2++) != '\0');
741
742         v0 = a0; pc0 = ra;
743 }
744
745 void psxBios_strncpy() { // 0x1a
746         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
747         s32 n = a2, i;
748         if (a0 == 0 || a1 == 0)
749         {
750                 v0 = 0;
751                 pc0 = ra;
752                 return;
753         }
754         for (i = 0; i < n; i++) {
755                 if ((*p1++ = *p2++) == '\0') {
756                         while (++i < n) {
757                                 *p1++ = '\0';
758                         }
759                         v0 = a0; pc0 = ra;
760                         return;
761                 }
762         }
763
764         v0 = a0; pc0 = ra;
765 }
766
767 void psxBios_strlen() { // 0x1b
768         char *p = (char *)Ra0;
769         v0 = 0;
770         if (a0 == 0)
771         {
772                 pc0 = ra;
773                 return;
774         }
775         while (*p++) v0++;
776         pc0 = ra;
777 }
778
779 void psxBios_index() { // 0x1c
780         char *p = (char *)Ra0;
781         if (a0 == 0)
782         {
783                 v0 = 0;
784                 pc0 = ra;
785                 return;
786         }
787
788         do {
789                 if (*p == a1) {
790                         v0 = a0 + (p - (char *)Ra0);
791                         pc0 = ra;
792                         return;
793                 }
794         } while (*p++ != '\0');
795
796         v0 = 0; pc0 = ra;
797 }
798
799 void psxBios_rindex() { // 0x1d
800         char *p = (char *)Ra0;
801
802         v0 = 0;
803         if (a0 == 0)
804         {
805                 pc0 = ra;
806                 return;
807         }
808         do {
809                 if (*p == a1)
810                         v0 = a0 + (p - (char *)Ra0);
811         } while (*p++ != '\0');
812
813         pc0 = ra;
814 }
815
816 void psxBios_strchr() { // 0x1e
817         psxBios_index();
818 }
819
820 void psxBios_strrchr() { // 0x1f
821         psxBios_rindex();
822 }
823
824 void psxBios_strpbrk() { // 0x20
825         char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
826
827         while ((c = *p1++) != '\0') {
828                 for (scanp = p2; (sc = *scanp++) != '\0';) {
829                         if (sc == c) {
830                                 v0 = a0 + (p1 - 1 - (char *)Ra0);
831                                 pc0 = ra;
832                                 return;
833                         }
834                 }
835         }
836
837         // BUG: return a0 instead of NULL if not found
838         v0 = a0; pc0 = ra;
839 }
840
841 void psxBios_strspn() { // 0x21
842         char *p1, *p2;
843
844         for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
845                 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
846                 if (*p2 == '\0') break;
847         }
848
849         v0 = p1 - (char *)Ra0; pc0 = ra;
850 }
851
852 void psxBios_strcspn() { // 0x22
853         char *p1, *p2;
854
855         for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
856                 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
857                 if (*p2 != '\0') break;
858         }
859
860         v0 = p1 - (char *)Ra0; pc0 = ra;
861 }
862
863 void psxBios_strtok() { // 0x23
864         char *pcA0 = (char *)Ra0;
865         char *pcRet = strtok(pcA0, (char *)Ra1);
866         if (pcRet)
867                 v0 = a0 + pcRet - pcA0;
868         else
869                 v0 = 0;
870         pc0 = ra;
871 }
872
873 void psxBios_strstr() { // 0x24
874         char *p = (char *)Ra0, *p1, *p2;
875
876         while (*p != '\0') {
877                 p1 = p;
878                 p2 = (char *)Ra1;
879
880                 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
881                         p1++; p2++;
882                 }
883
884                 if (*p2 == '\0') {
885                         v0 = a0 + (p - (char *)Ra0);
886                         pc0 = ra;
887                         return;
888                 }
889
890                 p++;
891         }
892
893         v0 = 0; pc0 = ra;
894 }
895
896 void psxBios_toupper() { // 0x25
897         v0 = (s8)(a0 & 0xff);
898         if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
899         pc0 = ra;
900 }
901
902 void psxBios_tolower() { // 0x26
903         v0 = (s8)(a0 & 0xff);
904         if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
905         pc0 = ra;
906 }
907
908 static void do_memset(u32 dst, u32 v, s32 len)
909 {
910         u32 d = dst;
911         s32 l = len;
912         while (l-- > 0) {
913                 u8 *db = PSXM(d);
914                 if (db != INVALID_PTR)
915                         *db = v;
916                 d++;
917         }
918         psxCpu->Clear(dst, (len + 3) / 4);
919 }
920
921 static void do_memcpy(u32 dst, u32 src, s32 len)
922 {
923         u32 d = dst, s = src;
924         s32 l = len;
925         while (l-- > 0) {
926                 const u8 *sb = PSXM(s);
927                 u8 *db = PSXM(d);
928                 if (db != INVALID_PTR && sb != INVALID_PTR)
929                         *db = *sb;
930                 d++;
931                 s++;
932         }
933         psxCpu->Clear(dst, (len + 3) / 4);
934 }
935
936 static void psxBios_memcpy();
937
938 static void psxBios_bcopy() { // 0x27 - memcpy with args swapped
939         //PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x27], a0, a1, a2);
940         u32 ret = a0, cycles = 0;
941         if (a0 == 0) // ...but it checks src this time
942         {
943                 mips_return_c(0, 4);
944                 return;
945         }
946         v1 = a0;
947         if ((s32)a2 > 0) {
948                 do_memcpy(a1, a0, a2);
949                 cycles = a2 * 6;
950                 a0 += a2;
951                 a1 += a2;
952                 a2 = 0;
953         }
954         mips_return_c(ret, cycles + 5);
955 }
956
957 static void psxBios_bzero() { // 0x28
958         /* Same as memset here (See memset below) */
959         u32 ret = a0, cycles;
960         if (a0 == 0 || (s32)a1 <= 0)
961         {
962                 mips_return_c(0, 6);
963                 return;
964         }
965         do_memset(a0, 0, a1);
966         cycles = a1 * 4;
967         a0 += a1;
968         a1 = 0;
969         // todo: many more cycles due to uncached bios mem
970         mips_return_c(ret, cycles + 5);
971 }
972
973 void psxBios_bcmp() { // 0x29
974         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
975
976         if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
977
978         while ((s32)a2-- > 0) {
979                 if (*p1++ != *p2++) {
980                         v0 = *p1 - *p2; // BUG: compare the NEXT byte
981                         pc0 = ra;
982                         return;
983                 }
984         }
985
986         v0 = 0; pc0 = ra;
987 }
988
989 static void psxBios_memcpy() { // 0x2a
990         u32 ret = a0, cycles = 0;
991         if (a0 == 0)
992         {
993                 mips_return_c(0, 4);
994                 return;
995         }
996         if ((s32)a2 > 0) {
997                 do_memcpy(a0, a1, a2);
998                 cycles = a2 * 6;
999                 v1 = a0;
1000                 a0 += a2;
1001                 a1 += a2;
1002                 a2 = 0;
1003         }
1004         mips_return_c(ret, cycles + 5);
1005 }
1006
1007 static void psxBios_memset() { // 0x2b
1008         u32 ret = a0, cycles;
1009         if (a0 == 0 || (s32)a2 <= 0)
1010         {
1011                 mips_return_c(0, 6);
1012                 return;
1013         }
1014         do_memset(a0, a1, a2);
1015         cycles = a2 * 4;
1016         a0 += a2;
1017         a2 = 0;
1018         // todo: many more cycles due to uncached bios mem
1019         mips_return_c(ret, cycles + 5);
1020 }
1021
1022 void psxBios_memmove() { // 0x2c
1023         u32 ret = a0, cycles = 0;
1024         if (a0 == 0)
1025         {
1026                 mips_return_c(0, 4);
1027                 return;
1028         }
1029         v1 = a0;
1030         if ((s32)a2 > 0 && a0 > a1 && a0 < a1 + a2) {
1031                 u32 dst = a0, len = a2 + 1;
1032                 a0 += a2;
1033                 a1 += a2;
1034                 while ((s32)a2 >= 0) { // BUG: copies one more byte here
1035                         const u8 *sb = PSXM(a1);
1036                         u8 *db = PSXM(a0);
1037                         if (db != INVALID_PTR && sb != INVALID_PTR)
1038                                 *db = *sb;
1039                         a0--;
1040                         a1--;
1041                         a2--;
1042                 }
1043                 psxCpu->Clear(dst, (len + 3) / 4);
1044                 cycles = 10 + len * 8;
1045         } else if ((s32)a2 > 0) {
1046                 do_memcpy(a0, a1, a2);
1047                 cycles = a2 * 6;
1048                 a0 += a2;
1049                 a1 += a2;
1050                 a2 = 0;
1051         }
1052         mips_return_c(ret, cycles + 5);
1053 }
1054
1055 void psxBios_memcmp() { // 0x2d
1056         psxBios_bcmp();
1057 }
1058
1059 void psxBios_memchr() { // 0x2e
1060         char *p = (char *)Ra0;
1061
1062         if (a0 == 0 || a2 > 0x7FFFFFFF)
1063         {
1064                 pc0 = ra;
1065                 return;
1066         }
1067
1068         while ((s32)a2-- > 0) {
1069                 if (*p++ != (s8)a1) continue;
1070                 v0 = a0 + (p - (char *)Ra0 - 1);
1071                 pc0 = ra;
1072                 return;
1073         }
1074
1075         v0 = 0; pc0 = ra;
1076 }
1077
1078 void psxBios_rand() { // 0x2f
1079         u32 s = psxMu32(0x9010) * 1103515245 + 12345;
1080         v0 = (s >> 16) & 0x7fff;
1081         psxMu32ref(0x9010) = SWAPu32(s);
1082         pc0 = ra;
1083 }
1084
1085 void psxBios_srand() { // 0x30
1086         psxMu32ref(0x9010) = SWAPu32(a0);
1087         pc0 = ra;
1088 }
1089
1090 static u32 qscmpfunc, qswidth;
1091
1092 static inline int qscmp(char *a, char *b) {
1093         u32 sa0 = a0;
1094
1095         a0 = sa0 + (a - (char *)PSXM(sa0));
1096         a1 = sa0 + (b - (char *)PSXM(sa0));
1097
1098         softCall(qscmpfunc);
1099
1100         a0 = sa0;
1101         return (s32)v0;
1102 }
1103
1104 static inline void qexchange(char *i, char *j) {
1105         char t;
1106         int n = qswidth;
1107
1108         do {
1109                 t = *i;
1110                 *i++ = *j;
1111                 *j++ = t;
1112         } while (--n);
1113 }
1114
1115 static inline void q3exchange(char *i, char *j, char *k) {
1116         char t;
1117         int n = qswidth;
1118
1119         do {
1120                 t = *i;
1121                 *i++ = *k;
1122                 *k++ = *j;
1123                 *j++ = t;
1124         } while (--n);
1125 }
1126
1127 static void qsort_main(char *a, char *l) {
1128         char *i, *j, *lp, *hp;
1129         int c;
1130         unsigned int n;
1131
1132 start:
1133         if ((n = l - a) <= qswidth)
1134                 return;
1135         n = qswidth * (n / (2 * qswidth));
1136         hp = lp = a + n;
1137         i = a;
1138         j = l - qswidth;
1139         while (TRUE) {
1140                 if (i < lp) {
1141                         if ((c = qscmp(i, lp)) == 0) {
1142                                 qexchange(i, lp -= qswidth);
1143                                 continue;
1144                         }
1145                         if (c < 0) {
1146                                 i += qswidth;
1147                                 continue;
1148                         }
1149                 }
1150
1151 loop:
1152                 if (j > hp) {
1153                         if ((c = qscmp(hp, j)) == 0) {
1154                                 qexchange(hp += qswidth, j);
1155                                 goto loop;
1156                         }
1157                         if (c > 0) {
1158                                 if (i == lp) {
1159                                         q3exchange(i, hp += qswidth, j);
1160                                         i = lp += qswidth;
1161                                         goto loop;
1162                                 }
1163                                 qexchange(i, j);
1164                                 j -= qswidth;
1165                                 i += qswidth;
1166                                 continue;
1167                         }
1168                         j -= qswidth;
1169                         goto loop;
1170                 }
1171
1172                 if (i == lp) {
1173                         if (lp - a >= l - hp) {
1174                                 qsort_main(hp + qswidth, l);
1175                                 l = lp;
1176                         } else {
1177                                 qsort_main(a, lp);
1178                                 a = hp + qswidth;
1179                         }
1180                         goto start;
1181                 }
1182
1183                 q3exchange(j, lp -= qswidth, i);
1184                 j = hp -= qswidth;
1185         }
1186 }
1187
1188 void psxBios_qsort() { // 0x31
1189         qswidth = a2;
1190         qscmpfunc = a3;
1191         qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1192
1193         pc0 = ra;
1194 }
1195
1196 // this isn't how the real bios works, but maybe good enough
1197 static void psxBios_malloc() { // 0x33
1198         u32 *heap_addr, *heap_end;
1199         u32 *chunk, *newchunk = NULL;
1200         unsigned int dsize = 0, csize, cstat;
1201         int colflag;
1202         PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x33], a0);
1203         heap_addr = loadRam32ptr(A_HEAP_BASE);
1204         heap_end = loadRam32ptr(A_HEAP_END);
1205         if (heap_addr >= heap_end) {
1206                 v0 = 0;
1207                 pc0 = ra;
1208                 return;
1209         }
1210
1211         // scan through heap and combine free chunks of space
1212         chunk = heap_addr;
1213         colflag = 0;
1214         while(chunk < heap_end) {
1215                 // get size and status of actual chunk
1216                 csize = ((u32)*chunk) & 0xfffffffc;
1217                 cstat = ((u32)*chunk) & 1;
1218
1219                 // most probably broken heap descriptor
1220                 // this fixes Burning Road
1221                 if (*chunk == 0) {
1222                         newchunk = chunk;
1223                         dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1224                         colflag = 1;
1225                         break;
1226                 }
1227
1228                 // it's a free chunk
1229                 if(cstat == 1) {
1230                         if(colflag == 0) {
1231                                 newchunk = chunk;
1232                                 dsize = csize;
1233                                 colflag = 1;                    // let's begin a new collection of free memory
1234                         }
1235                         else dsize += (csize+4);        // add the new size including header
1236                 }
1237                 // not a free chunk: did we start a collection ?
1238                 else {
1239                         if(colflag == 1) {                      // collection is over
1240                                 colflag = 0;
1241                                 *newchunk = SWAP32(dsize | 1);
1242                         }
1243                 }
1244
1245                 // next chunk
1246                 chunk = (u32*)((uptr)chunk + csize + 4);
1247         }
1248         // if neccessary free memory on end of heap
1249         if (colflag == 1)
1250                 *newchunk = SWAP32(dsize | 1);
1251
1252         chunk = heap_addr;
1253         csize = ((u32)*chunk) & 0xfffffffc;
1254         cstat = ((u32)*chunk) & 1;
1255         dsize = (a0 + 3) & 0xfffffffc;
1256
1257         // exit on uninitialized heap
1258         if (chunk == NULL) {
1259                 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1260                 v0 = 0;
1261                 pc0 = ra;
1262                 return;
1263         }
1264
1265         // search an unused chunk that is big enough until the end of the heap
1266         while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1267                 chunk = (u32*)((uptr)chunk + csize + 4);
1268
1269                         // catch out of memory
1270                         if(chunk >= heap_end) {
1271                                 printf("malloc %x,%x: Out of memory error!\n",
1272                                         v0, a0);
1273                                 v0 = 0; pc0 = ra;
1274                                 return;
1275                         }
1276
1277                 csize = ((u32)*chunk) & 0xfffffffc;
1278                 cstat = ((u32)*chunk) & 1;
1279         }
1280
1281         // allocate memory
1282         if(dsize == csize) {
1283                 // chunk has same size
1284                 *chunk &= 0xfffffffc;
1285         } else if (dsize > csize) {
1286                 v0 = 0; pc0 = ra;
1287                 return;
1288         } else {
1289                 // split free chunk
1290                 *chunk = SWAP32(dsize);
1291                 newchunk = (u32*)((uptr)chunk + dsize + 4);
1292                 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1293         }
1294
1295         // return pointer to allocated memory
1296         v0 = ((uptr)chunk - (uptr)psxM) + 4;
1297         v0|= 0x80000000;
1298         //printf ("malloc %x,%x\n", v0, a0);
1299         pc0 = ra;
1300 }
1301
1302 static void psxBios_free() { // 0x34
1303         PSXBIOS_LOG("psxBios_%s %x (%x bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1304         storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1305         mips_return_void_c(5);
1306 }
1307
1308 static void psxBios_calloc() { // 0x37
1309         u32 ret, size;
1310         PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
1311
1312         a0 = size = a0 * a1;
1313         psxBios_malloc();
1314         ret = v0;
1315         if (ret) {
1316                 a0 = ret; a1 = size;
1317                 psxBios_bzero();
1318         }
1319         mips_return_c(ret, 21);
1320 }
1321
1322 void psxBios_realloc() { // 0x38
1323         u32 block = a0;
1324         u32 size = a1;
1325 #ifdef PSXBIOS_LOG
1326         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1327 #endif
1328
1329         a0 = block;
1330         /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1331         if (block == 0)
1332         {
1333                 psxBios_malloc();
1334         }
1335         /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1336         else if (size == 0)
1337         {
1338                 psxBios_free();
1339         }
1340         /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1341         /* Note that it is not quite implemented this way here. */
1342         else
1343         {
1344                 psxBios_free();
1345                 a0 = size;
1346                 psxBios_malloc();
1347         }
1348 }
1349
1350
1351 /* InitHeap(void *block , int n) */
1352 static void psxBios_InitHeap() { // 0x39
1353         PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
1354
1355         storeRam32(A_HEAP_BASE, a0);
1356         storeRam32(A_HEAP_SIZE, a1);
1357         storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
1358         storeRam32(A_HEAP_FLAG, 0);
1359         storeRam32(a0, 0);
1360
1361         mips_return_void_c(14);
1362 }
1363
1364 void psxBios_getchar() { //0x3b
1365         v0 = getchar(); pc0 = ra;
1366 }
1367
1368 static void psxBios_printf_psxout() { // 0x3f
1369         char tmp[1024];
1370         char tmp2[1024];
1371         u32 save[4];
1372         char *ptmp = tmp;
1373         int n=1, i=0, j;
1374         void *psp;
1375
1376         psp = PSXM(sp);
1377         if (psp != INVALID_PTR) {
1378                 memcpy(save, psp, 4 * 4);
1379                 psxMu32ref(sp) = SWAP32((u32)a0);
1380                 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1381                 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1382                 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1383         }
1384
1385         while (Ra0[i]) {
1386                 switch (Ra0[i]) {
1387                         case '%':
1388                                 j = 0;
1389                                 tmp2[j++] = '%';
1390 _start:
1391                                 switch (Ra0[++i]) {
1392                                         case '.':
1393                                         case 'l':
1394                                                 tmp2[j++] = Ra0[i]; goto _start;
1395                                         default:
1396                                                 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1397                                                         tmp2[j++] = Ra0[i];
1398                                                         goto _start;
1399                                                 }
1400                                                 break;
1401                                 }
1402                                 tmp2[j++] = Ra0[i];
1403                                 tmp2[j] = 0;
1404
1405                                 switch (Ra0[i]) {
1406                                         case 'f': case 'F':
1407                                                 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1408                                         case 'a': case 'A':
1409                                         case 'e': case 'E':
1410                                         case 'g': case 'G':
1411                                                 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1412                                         case 'p':
1413                                         case 'i': case 'u':
1414                                         case 'd': case 'D':
1415                                         case 'o': case 'O':
1416                                         case 'x': case 'X':
1417                                                 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1418                                         case 'c':
1419                                                 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1420                                         case 's':
1421                                                 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1422                                         case '%':
1423                                                 *ptmp++ = Ra0[i]; break;
1424                                 }
1425                                 i++;
1426                                 break;
1427                         default:
1428                                 *ptmp++ = Ra0[i++];
1429                 }
1430         }
1431         *ptmp = 0;
1432
1433         if (psp != INVALID_PTR)
1434                 memcpy(psp, save, 4 * 4);
1435
1436         if (Config.PsxOut)
1437                 SysPrintf("%s", tmp);
1438 }
1439
1440 void psxBios_printf() { // 0x3f
1441         psxBios_printf_psxout();
1442         pc0 = ra;
1443 }
1444
1445 void psxBios_format() { // 0x41
1446         if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1447         {
1448                 CreateMcd(Config.Mcd1);
1449                 LoadMcd(1, Config.Mcd1);
1450                 v0 = 1;
1451         }
1452         else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1453         {
1454                 CreateMcd(Config.Mcd2);
1455                 LoadMcd(2, Config.Mcd2);
1456                 v0 = 1;
1457         }
1458         else
1459         {
1460                 v0 = 0;
1461         }
1462         pc0 = ra;
1463 }
1464
1465 static void psxBios_SystemErrorUnresolvedException() {
1466         if (loadRam32(0xfffc) != 0x12345678) { // prevent log flood
1467                 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1468                 storeRam32(0xfffc, 0x12345678);
1469         }
1470         mips_return_void_c(1000);
1471 }
1472
1473 /*
1474  *      long Load(char *name, struct EXEC *header);
1475  */
1476
1477 void psxBios_Load() { // 0x42
1478         EXE_HEADER eheader;
1479         void *pa1;
1480
1481         pa1 = Ra1;
1482         if (pa1 != INVALID_PTR && LoadCdromFile(Ra0, &eheader) == 0) {
1483                 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1484                 psxCpu->Clear(a1, sizeof(EXEC) / 4);
1485                 v0 = 1;
1486         } else v0 = 0;
1487         PSXBIOS_LOG("psxBios_%s: %s, %d -> %d\n", biosA0n[0x42], Ra0, a1, v0);
1488
1489         pc0 = ra;
1490 }
1491
1492 /*
1493  *      int Exec(struct EXEC *header , int argc , char **argv);
1494  */
1495
1496 void psxBios_Exec() { // 43
1497         EXEC *header = (EXEC *)castRam32ptr(a0);
1498         u32 ptr;
1499         s32 len;
1500
1501         PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1502
1503         header->_sp = SWAP32(sp);
1504         header->_fp = SWAP32(fp);
1505         header->_sp = SWAP32(sp);
1506         header->_gp = SWAP32(gp);
1507         header->ret = SWAP32(ra);
1508         header->base = SWAP32(s0);
1509
1510         ptr = SWAP32(header->b_addr);
1511         len = SWAP32(header->b_size);
1512         if (len != 0) do {
1513                 storeRam32(ptr, 0);
1514                 len -= 4; ptr += 4;
1515         } while (len > 0);
1516
1517         if (header->S_addr != 0)
1518                 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1519
1520         gp = SWAP32(header->gp0);
1521
1522         s0 = a0;
1523
1524         a0 = a1;
1525         a1 = a2;
1526
1527         ra = 0x8000;
1528         pc0 = SWAP32(header->_pc0);
1529 }
1530
1531 void psxBios_FlushCache() { // 44
1532 #ifdef PSXBIOS_LOG
1533         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1534 #endif
1535         psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1536         psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1537         pc0 = ra;
1538 }
1539
1540 void psxBios_GPU_dw() { // 0x46
1541         int size;
1542         u32 *ptr;
1543
1544 #ifdef PSXBIOS_LOG
1545         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1546 #endif
1547
1548         GPU_writeData(0xa0000000);
1549         GPU_writeData((a1<<0x10)|(a0&0xffff));
1550         GPU_writeData((a3<<0x10)|(a2&0xffff));
1551         size = (a2*a3)/2;
1552         ptr = (u32*)PSXM(Rsp[4]);  //that is correct?
1553         while(size--)
1554         {
1555                 GPU_writeData(SWAPu32(*ptr++));
1556         } 
1557
1558         pc0 = ra;
1559 }
1560
1561 void psxBios_mem2vram() { // 0x47
1562         int size;
1563         gpuSyncPluginSR();
1564         GPU_writeData(0xa0000000);
1565         GPU_writeData((a1<<0x10)|(a0&0xffff));
1566         GPU_writeData((a3<<0x10)|(a2&0xffff));
1567         size = ((((a2 * a3) / 2) >> 4) << 16);
1568         GPU_writeStatus(0x04000002);
1569         psxHwWrite32(0x1f8010f4,0);
1570         psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1571         psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1572         psxHwWrite32(0x1f8010a4, size | 0x10);
1573         psxHwWrite32(0x1f8010a8,0x01000201);
1574
1575         pc0 = ra;
1576 }
1577
1578 void psxBios_SendGPU() { // 0x48
1579         GPU_writeStatus(a0);
1580         gpuSyncPluginSR();
1581         pc0 = ra;
1582 }
1583
1584 void psxBios_GPU_cw() { // 0x49
1585         gpuSyncPluginSR();
1586         GPU_writeData(a0);
1587         v0 = HW_GPU_STATUS;
1588         pc0 = ra;
1589 }
1590
1591 void psxBios_GPU_cwb() { // 0x4a
1592         u32 *ptr = (u32*)Ra0;
1593         int size = a1;
1594         gpuSyncPluginSR();
1595         while(size--)
1596         {
1597                 GPU_writeData(SWAPu32(*ptr++));
1598         }
1599
1600         pc0 = ra;
1601 }
1602    
1603 void psxBios_GPU_SendPackets() { //4b:  
1604         gpuSyncPluginSR();
1605         GPU_writeStatus(0x04000002);
1606         psxHwWrite32(0x1f8010f4,0);
1607         psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1608         psxHwWrite32(0x1f8010a0,a0);
1609         psxHwWrite32(0x1f8010a4,0);
1610         psxHwWrite32(0x1f8010a8,0x010000401);
1611         pc0 = ra;
1612 }
1613
1614 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1615         psxHwWrite32(0x1f8010a8,0x00000401);
1616         GPU_writeData(0x0400000);
1617         GPU_writeData(0x0200000);
1618         GPU_writeData(0x0100000);
1619         v0 = 0x1f801814;
1620         pc0 = ra;
1621 }
1622
1623 void psxBios_GPU_GetGPUStatus() { // 0x4d
1624         v0 = GPU_readStatus();
1625         pc0 = ra;
1626 }
1627
1628 #undef s_addr
1629
1630 void psxBios_LoadExec() { // 51
1631         EXEC *header = (EXEC*)PSXM(0xf000);
1632         u32 s_addr, s_size;
1633
1634 #ifdef PSXBIOS_LOG
1635         PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1636 #endif
1637         s_addr = a1; s_size = a2;
1638
1639         a1 = 0xf000;
1640         psxBios_Load();
1641
1642         header->S_addr = s_addr;
1643         header->s_size = s_size;
1644
1645         a0 = 0xf000; a1 = 0; a2 = 0;
1646         psxBios_Exec();
1647 }
1648
1649 void psxBios__bu_init() { // 70
1650 #ifdef PSXBIOS_LOG
1651         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1652 #endif
1653
1654         DeliverEvent(0xf0000011, 0x0004);
1655         DeliverEvent(0xf4000001, 0x0004);
1656
1657         pc0 = ra;
1658 }
1659
1660 void psxBios__96_init() { // 71
1661 #ifdef PSXBIOS_LOG
1662         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1663 #endif
1664
1665         pc0 = ra;
1666 }
1667
1668 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1669 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1670 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1671
1672 static void psxBios_DequeueCdIntr_() {
1673         psxBios_SysDeqIntRP_(0, 0x91d0);
1674         psxBios_SysDeqIntRP_(0, 0x91e0);
1675         use_cycles(16);
1676 }
1677
1678 static void psxBios_DequeueCdIntr() { // a3
1679         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1680         psxBios_DequeueCdIntr_();
1681 }
1682
1683 static void psxBios_CdRemove() { // 56, 72
1684         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1685
1686         CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1687         CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1688         CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1689         CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1690         CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1691         psxBios_DequeueCdIntr_();
1692
1693         // EnterCriticalSection - should be done at the beginning,
1694         // but this way is much easier to implement
1695         a0 = 1;
1696         pc0 = A_SYSCALL;
1697         use_cycles(30);
1698 }
1699
1700 void psxBios_SetMem() { // 9f
1701         u32 new = psxHu32(0x1060);
1702
1703 #ifdef PSXBIOS_LOG
1704         PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1705 #endif
1706
1707         switch(a0) {
1708                 case 2:
1709                         psxHu32ref(0x1060) = SWAP32(new);
1710                         psxMu32ref(0x060) = a0;
1711                         PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1712                         break;
1713
1714                 case 8:
1715                         psxHu32ref(0x1060) = SWAP32(new | 0x300);
1716                         psxMu32ref(0x060) = a0;
1717                         PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1718
1719                 default:
1720                         PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
1721                 break;
1722         }
1723
1724         pc0 = ra;
1725 }
1726
1727 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1728 static void psxBios_get_cd_status() // a6
1729 {
1730         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
1731         v0 = 1;
1732         pc0 = ra;
1733 }
1734
1735 static void psxBios__card_info() { // ab
1736         PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1737         u32 ret, port;
1738         storeRam32(A_CARD_CHAN1, a0);
1739         port = a0 >> 4;
1740
1741         switch (port) {
1742         case 0x0:
1743         case 0x1:
1744                 ret = 0x0004;
1745                 if (McdDisable[port & 1])
1746                         ret = 0x0100;
1747                 break;
1748         default:
1749                 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
1750                 ret = 0x0302;
1751                 break;
1752         }
1753
1754         if (McdDisable[0] && McdDisable[1])
1755                 ret = 0x0100;
1756
1757         DeliverEvent(0xf0000011, 0x0004);
1758 //      DeliverEvent(0xf4000001, 0x0004);
1759         DeliverEvent(0xf4000001, ret);
1760         v0 = 1; pc0 = ra;
1761 }
1762
1763 void psxBios__card_load() { // ac
1764 #ifdef PSXBIOS_LOG
1765         PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1766 #endif
1767
1768         storeRam32(A_CARD_CHAN1, a0);
1769
1770 //      DeliverEvent(0xf0000011, 0x0004);
1771         DeliverEvent(0xf4000001, 0x0004);
1772
1773         v0 = 1; pc0 = ra;
1774 }
1775
1776 static void psxBios_GetSystemInfo() { // b4
1777         u32 ret = 0;
1778         //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
1779         SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
1780         switch (a0) {
1781         case 0:
1782         case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
1783         case 2: ret = 0xbfc0012c; break;
1784         case 5: ret = loadRam32(0x60) << 10; break;
1785         }
1786         mips_return_c(ret, 20);
1787 }
1788
1789 /* System calls B0 */
1790
1791 static u32 psxBios_SysMalloc_(u32 size);
1792
1793 static void psxBios_SysMalloc() { // B 00
1794         u32 ret = psxBios_SysMalloc_(a0);
1795
1796         PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1797         mips_return_c(ret, 33);
1798 }
1799
1800 void psxBios_SetRCnt() { // 02
1801 #ifdef PSXBIOS_LOG
1802         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1803 #endif
1804
1805         a0&= 0x3;
1806         if (a0 != 3) {
1807                 u32 mode=0;
1808
1809                 psxRcntWtarget(a0, a1);
1810                 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1811                 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1812                 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1813                 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1814                 else         { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1815
1816                 psxRcntWmode(a0, mode);
1817         }
1818         pc0 = ra;
1819 }
1820
1821 void psxBios_GetRCnt() { // 03
1822 #ifdef PSXBIOS_LOG
1823         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1824 #endif
1825
1826         a0&= 0x3;
1827         if (a0 != 3) v0 = psxRcntRcount(a0);
1828         else v0 = 0;
1829         pc0 = ra;
1830 }
1831
1832 void psxBios_StartRCnt() { // 04
1833 #ifdef PSXBIOS_LOG
1834         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1835 #endif
1836
1837         a0&= 0x3;
1838         if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1839         else psxHu32ref(0x1074)|= SWAPu32(0x1);
1840         v0 = 1; pc0 = ra;
1841 }
1842
1843 void psxBios_StopRCnt() { // 05
1844 #ifdef PSXBIOS_LOG
1845         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1846 #endif
1847
1848         a0&= 0x3;
1849         if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1850         else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1851         pc0 = ra;
1852 }
1853
1854 void psxBios_ResetRCnt() { // 06
1855 #ifdef PSXBIOS_LOG
1856         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1857 #endif
1858
1859         a0&= 0x3;
1860         if (a0 != 3) {
1861                 psxRcntWmode(a0, 0);
1862                 psxRcntWtarget(a0, 0);
1863                 psxRcntWcount(a0, 0);
1864         }
1865         pc0 = ra;
1866 }
1867
1868 static u32 DeliverEvent(u32 class, u32 spec) {
1869         EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1870         u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1871         u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1872         u32 i, lim = evcb_len / 0x1c;
1873
1874         for (i = 0; i < lim; i++, ev++) {
1875                 use_cycles(8);
1876                 if (SWAP32(ev->status) != EvStACTIVE)
1877                         continue;
1878                 use_cycles(4);
1879                 if (SWAP32(ev->class) != class)
1880                         continue;
1881                 use_cycles(4);
1882                 if (SWAP32(ev->spec) != spec)
1883                         continue;
1884                 use_cycles(6);
1885                 ret = SWAP32(ev->mode);
1886                 if (ret == EvMdMARK) {
1887                         ev->status = SWAP32(EvStALREADY);
1888                         continue;
1889                 }
1890                 use_cycles(8);
1891                 if (ret == EvMdCALL) {
1892                         ret = SWAP32(ev->fhandler);
1893                         if (ret) {
1894                                 v0 = ret;
1895                                 softCall(ret);
1896                                 ret = v0;
1897                         }
1898                 }
1899         }
1900         use_cycles(29);
1901         return ret;
1902 }
1903
1904 static u32 UnDeliverEvent(u32 class, u32 spec) {
1905         EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1906         u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1907         u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1908         u32 i, lim = evcb_len / 0x1c;
1909
1910         for (i = 0; i < lim; i++, ev++) {
1911                 use_cycles(8);
1912                 if (SWAP32(ev->status) != EvStALREADY)
1913                         continue;
1914                 use_cycles(4);
1915                 if (SWAP32(ev->class) != class)
1916                         continue;
1917                 use_cycles(4);
1918                 if (SWAP32(ev->spec) != spec)
1919                         continue;
1920                 use_cycles(6);
1921                 if (SWAP32(ev->mode) == EvMdMARK)
1922                         ev->status = SWAP32(EvStACTIVE);
1923         }
1924         use_cycles(28);
1925         return ret;
1926 }
1927
1928 static void psxBios_DeliverEvent() { // 07
1929         u32 ret;
1930         PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
1931
1932         ret = DeliverEvent(a0, a1);
1933         mips_return(ret);
1934 }
1935
1936 static s32 get_free_EvCB_slot() {
1937         EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1938         u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
1939
1940         use_cycles(19);
1941         for (i = 0; i < lim; i++, ev++) {
1942                 use_cycles(8);
1943                 if (ev->status == SWAP32(EvStUNUSED))
1944                         return i;
1945         }
1946         return -1;
1947 }
1948
1949 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
1950         u32 ret = get_free_EvCB_slot();
1951         if ((s32)ret >= 0) {
1952                 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
1953                 ev->class = SWAP32(class);
1954                 ev->status = SWAP32(EvStDISABLED);
1955                 ev->spec = SWAP32(spec);
1956                 ev->mode = SWAP32(mode);
1957                 ev->fhandler = SWAP32(func);
1958                 ret |= 0xf1000000u;
1959         }
1960         return ret;
1961 }
1962
1963 static void psxBios_OpenEvent() { // 08
1964         u32 ret = OpenEvent(a0, a1, a2, a3);
1965         PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
1966                 biosB0n[0x08], a0, a1, a2, a3, ret);
1967         mips_return_c(ret, 36);
1968 }
1969
1970 static void CloseEvent(u32 ev)
1971 {
1972         u32 base = loadRam32(A_TT_EvCB);
1973         storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
1974 }
1975
1976 static void psxBios_CloseEvent() { // 09
1977         PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
1978                 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
1979         CloseEvent(a0);
1980         mips_return_c(1, 10);
1981 }
1982
1983 static void psxBios_WaitEvent() { // 0a
1984         u32 base = loadRam32(A_TT_EvCB);
1985         u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1986         PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
1987
1988         use_cycles(15);
1989         if (status == EvStALREADY) {
1990                 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
1991                 mips_return(1);
1992                 return;
1993         }
1994         if (status != EvStACTIVE)
1995         {
1996                 mips_return_c(0, 2);
1997                 return;
1998         }
1999
2000         // retrigger this hlecall after the next emulation event
2001         pc0 -= 4;
2002         if ((s32)(next_interupt - psxRegs.cycle) > 0)
2003                 psxRegs.cycle = next_interupt;
2004         psxBranchTest();
2005 }
2006
2007 static void psxBios_TestEvent() { // 0b
2008         u32 base = loadRam32(A_TT_EvCB);
2009         u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2010         u32 ret = 0;
2011         PSXBIOS_LOG("psxBios_%s    %x %x\n", biosB0n[0x0b], a0, status);
2012         if (status == EvStALREADY) {
2013                 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2014                 ret = 1;
2015         }
2016
2017         mips_return_c(ret, 15);
2018 }
2019
2020 static void psxBios_EnableEvent() { // 0c
2021         u32 base = loadRam32(A_TT_EvCB);
2022         u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2023         PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
2024         if (status != EvStUNUSED)
2025                 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2026
2027         mips_return_c(1, 15);
2028 }
2029
2030 static void psxBios_DisableEvent() { // 0d
2031         u32 base = loadRam32(A_TT_EvCB);
2032         u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2033         PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2034         if (status != EvStUNUSED)
2035                 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2036
2037         mips_return_c(1, 15);
2038 }
2039
2040 /*
2041  *      long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2042  */
2043
2044 void psxBios_OpenTh() { // 0e
2045         TCB *tcb = loadRam32ptr(A_TT_TCB);
2046         u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2047         int th;
2048
2049         for (th = 1; th < limit; th++)
2050         {
2051                 if (tcb[th].status != SWAP32(0x4000)) break;
2052
2053         }
2054         if (th == limit) {
2055                 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2056                 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2057 #ifdef PSXBIOS_LOG
2058                 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2059 #endif
2060                 mips_return_c(0xffffffff, 20);
2061                 return;
2062         }
2063         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
2064
2065         tcb[th].status  = SWAP32(0x4000);
2066         tcb[th].mode    = SWAP32(0x1000);
2067         tcb[th].epc     = SWAP32(a0);
2068         tcb[th].reg[30] = SWAP32(a1); // fp
2069         tcb[th].reg[29] = SWAP32(a1); // sp
2070         tcb[th].reg[28] = SWAP32(a2); // gp
2071
2072         mips_return_c(0xff000000 + th, 34);
2073 }
2074
2075 /*
2076  *      int CloseTh(long thread);
2077  */
2078
2079 void psxBios_CloseTh() { // 0f
2080         TCB *tcb = loadRam32ptr(A_TT_TCB);
2081         u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2082         u32 th = a0 & 0xff;
2083
2084 #ifdef PSXBIOS_LOG
2085         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
2086 #endif
2087         /* The return value is always 1 (even if the handle was already closed). */
2088         v0 = 1;
2089         if (th < limit && tcb[th].status == SWAP32(0x4000)) {
2090                 tcb[th].status = SWAP32(0x1000);
2091         }
2092
2093         pc0 = ra;
2094 }
2095
2096 /*
2097  *      int ChangeTh(long thread);
2098  */
2099
2100 void psxBios_ChangeTh() { // 10
2101         u32 tcbBase = loadRam32(A_TT_TCB);
2102         u32 th = a0 & 0xffff;
2103
2104         // this is quite spammy
2105         //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2106
2107         // without doing any argument checks, just issue a syscall
2108         // (like the real bios does)
2109         a0 = 3;
2110         a1 = tcbBase + th * sizeof(TCB);
2111         pc0 = A_SYSCALL;
2112         use_cycles(15);
2113 }
2114
2115 void psxBios_InitPAD() { // 0x12
2116         u32 i, *ram32 = (u32 *)psxM;
2117         PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2118
2119         // printf("%s", "PS-X Control PAD Driver  Ver 3.0");
2120         ram32[A_PAD_DR_DST/4] = 0;
2121         ram32[A_PAD_OUTBUF/4 + 0] = 0;
2122         ram32[A_PAD_OUTBUF/4 + 1] = 0;
2123         ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2124         ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2125         ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2126         ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2127         ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2128         ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2129
2130         for (i = 0; i < a1; i++) {
2131                 use_cycles(4);
2132                 storeRam8(a0 + i, 0);
2133         }
2134         for (i = 0; i < a3; i++) {
2135                 use_cycles(4);
2136                 storeRam8(a2 + i, 0);
2137         }
2138         write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2139
2140         ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2141
2142         mips_return_c(1, 200);
2143 }
2144
2145 void psxBios_StartPAD() { // 13
2146         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2147
2148         psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2149         psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2150         psxHwWrite16(0x1f801070, ~1);
2151         psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2152         storeRam32(A_PAD_ACK_VBL, 1);
2153         storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2154         psxRegs.CP0.n.SR |= 0x401;
2155
2156         mips_return_c(1, 300);
2157 }
2158
2159 void psxBios_StopPAD() { // 14
2160         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2161         storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2162         psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2163         psxRegs.CP0.n.SR |= 0x401;
2164         mips_return_void_c(200);
2165 }
2166
2167 static void psxBios_PAD_init() { // 15
2168         u32 ret = 0;
2169         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2170         if (a0 == 0x20000000 || a0 == 0x20000001)
2171         {
2172                 u32 dst = a1;
2173                 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2174                 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2175                 psxBios_InitPAD();
2176                 psxBios_StartPAD();
2177                 storeRam32(A_PAD_DR_DST, dst);
2178                 ret = 2;
2179         }
2180         mips_return_c(ret, 100);
2181 }
2182
2183 static u32 psxBios_PAD_dr_() {
2184         u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2185         u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2186         u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2187         dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2188         if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2189         {
2190                 dst[0] = buf1[3], dst[1] = buf1[2];
2191                 if (buf1[1] == 0x23) {
2192                         dst[0] |= 0xc7, dst[1] |= 7;
2193                         if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2194                         if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2195                 }
2196         }
2197         if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2198         {
2199                 dst[2] = buf2[3], dst[3] = buf2[2];
2200                 if (buf2[1] == 0x23) {
2201                         dst[2] |= 0xc7, dst[3] |= 7;
2202                         if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2203                         if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2204                 }
2205         }
2206         use_cycles(55);
2207         return SWAP32(*(u32 *)dst);
2208 }
2209
2210 static void psxBios_PAD_dr() { // 16
2211         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2212         u32 ret = psxBios_PAD_dr_();
2213         mips_return(ret);
2214 }
2215
2216 static void psxBios_ReturnFromException() { // 17
2217         u32 tcbPtr = loadRam32(A_TT_PCB);
2218         const TCB *tcb = loadRam32ptr(tcbPtr);
2219         u32 sr;
2220         int i;
2221
2222         for (i = 1; i < 32; i++)
2223                 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2224         psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2225         psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2226         sr = SWAP32(tcb->sr);
2227
2228         //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2229         pc0 = k0 = SWAP32(tcb->epc);
2230
2231         // the interpreter wants to know about sr changes, so do a MTC0
2232         sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2233         MTC0(&psxRegs, 12, sr);
2234
2235         use_cycles(53);
2236         psxBranchTest();
2237 }
2238
2239 void psxBios_ResetEntryInt() { // 18
2240         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2241
2242         storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2243         mips_return_void_c(5);
2244 }
2245
2246 void psxBios_HookEntryInt() { // 19
2247         PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2248
2249         storeRam32(A_EEXIT_PTR, a0);
2250         mips_return_void_c(3);
2251 }
2252
2253 static void psxBios_UnDeliverEvent() { // 0x20
2254         u32 ret;
2255         PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2256
2257         ret = UnDeliverEvent(a0, a1);
2258         mips_return(ret);
2259 }
2260
2261 static void buopen(int mcd, char *ptr, char *cfg)
2262 {
2263         int i;
2264         char *mcd_data = ptr;
2265
2266         strcpy(FDesc[1 + mcd].name, Ra0+5);
2267         FDesc[1 + mcd].offset = 0;
2268         FDesc[1 + mcd].mode   = a1;
2269
2270         for (i=1; i<16; i++) {
2271                 const char *fptr = mcd_data + 128 * i;
2272                 if ((*fptr & 0xF0) != 0x50) continue;
2273                 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2274                 FDesc[1 + mcd].mcfile = i;
2275                 PSXBIOS_LOG("open %s\n", fptr+0xa);
2276                 v0 = 1 + mcd;
2277                 break;
2278         }
2279         if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2280                 for (i=1; i<16; i++) {
2281                         int j, xor, nblk = a1 >> 16;
2282                         char *pptr, *fptr2;
2283                         char *fptr = mcd_data + 128 * i;
2284
2285                         if ((*fptr & 0xF0) != 0xa0) continue;
2286
2287                         FDesc[1 + mcd].mcfile = i;
2288                         fptr[0] = 0x51;
2289                         fptr[4] = 0x00;
2290                         fptr[5] = 0x20 * nblk;
2291                         fptr[6] = 0x00;
2292                         fptr[7] = 0x00;
2293                         strcpy(fptr+0xa, FDesc[1 + mcd].name);
2294                         pptr = fptr2 = fptr;
2295                         for(j=2; j<=nblk; j++) {
2296                                 int k;
2297                                 for(i++; i<16; i++) {
2298                                         fptr2 += 128;
2299
2300                                         memset(fptr2, 0, 128);
2301                                         fptr2[0] = j < nblk ? 0x52 : 0x53;
2302                                         pptr[8] = i - 1;
2303                                         pptr[9] = 0;
2304                                         for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2305                                         pptr[127] = xor;
2306                                         pptr = fptr2;
2307                                         break;
2308                                 }
2309                                 /* shouldn't this return ENOSPC if i == 16? */
2310                         }
2311                         pptr[8] = pptr[9] = 0xff;
2312                         for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2313                         pptr[127] = xor;
2314                         PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2315                         v0 = 1 + mcd;
2316                         /* just go ahead and resave them all */
2317                         SaveMcd(cfg, ptr, 128, 128 * 15);
2318                         break;
2319                 }
2320                 /* shouldn't this return ENOSPC if i == 16? */
2321         }
2322 }
2323
2324 /*
2325  *      int open(char *name , int mode);
2326  */
2327
2328 void psxBios_open() { // 0x32
2329         void *pa0 = Ra0;
2330
2331 #ifdef PSXBIOS_LOG
2332         PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2333 #endif
2334
2335         v0 = -1;
2336
2337         if (pa0 != INVALID_PTR) {
2338                 if (!strncmp(pa0, "bu00", 4)) {
2339                         buopen(1, Mcd1Data, Config.Mcd1);
2340                 }
2341
2342                 if (!strncmp(pa0, "bu10", 4)) {
2343                         buopen(2, Mcd2Data, Config.Mcd2);
2344                 }
2345         }
2346
2347         pc0 = ra;
2348 }
2349
2350 /*
2351  *      int lseek(int fd , int offset , int whence);
2352  */
2353
2354 void psxBios_lseek() { // 0x33
2355 #ifdef PSXBIOS_LOG
2356         PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2357 #endif
2358
2359         switch (a2) {
2360                 case 0: // SEEK_SET
2361                         FDesc[a0].offset = a1;
2362                         v0 = a1;
2363 //                      DeliverEvent(0xf0000011, 0x0004);
2364 //                      DeliverEvent(0xf4000001, 0x0004);
2365                         break;
2366
2367                 case 1: // SEEK_CUR
2368                         FDesc[a0].offset+= a1;
2369                         v0 = FDesc[a0].offset;
2370                         break;
2371         }
2372
2373         pc0 = ra;
2374 }
2375
2376
2377 /*
2378  *      int read(int fd , void *buf , int nbytes);
2379  */
2380
2381 void psxBios_read() { // 0x34
2382         char *ptr;
2383         void *pa1 = Ra1;
2384
2385 #ifdef PSXBIOS_LOG
2386         PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2387 #endif
2388
2389         v0 = -1;
2390
2391         if (pa1 != INVALID_PTR) {
2392                 switch (a0) {
2393                         case 2: buread(pa1, 1, a2); break;
2394                         case 3: buread(pa1, 2, a2); break;
2395                 }
2396         }
2397
2398         pc0 = ra;
2399 }
2400
2401 /*
2402  *      int write(int fd , void *buf , int nbytes);
2403  */
2404
2405 void psxBios_write() { // 0x35/0x03
2406         char *ptr;
2407         void *pa1 = Ra1;
2408
2409         if (a0 != 1) // stdout
2410                 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2411
2412         v0 = -1;
2413         if (pa1 == INVALID_PTR) {
2414                 pc0 = ra;
2415                 return;
2416         }
2417
2418         if (a0 == 1) { // stdout
2419                 char *ptr = pa1;
2420
2421                 v0 = a2;
2422                 if (Config.PsxOut) while (a2 > 0) {
2423                         SysPrintf("%c", *ptr++); a2--;
2424                 }
2425                 pc0 = ra; return;
2426         }
2427
2428         switch (a0) {
2429                 case 2: buwrite(pa1, 1, a2); break;
2430                 case 3: buwrite(pa1, 2, a2); break;
2431         }
2432
2433         pc0 = ra;
2434 }
2435
2436 static void psxBios_write_psxout() {
2437         if (a0 == 1) { // stdout
2438                 const char *ptr = Ra1;
2439                 int len = a2;
2440
2441                 if (ptr != INVALID_PTR)
2442                         while (len-- > 0)
2443                                 SysPrintf("%c", *ptr++);
2444         }
2445 }
2446
2447 static void psxBios_putchar_psxout() { // 3d
2448         SysPrintf("%c", (char)a0);
2449 }
2450
2451 static void psxBios_puts_psxout() { // 3e/3f
2452         SysPrintf("%s", Ra0);
2453 }
2454
2455 /*
2456  *      int close(int fd);
2457  */
2458
2459 void psxBios_close() { // 0x36
2460 #ifdef PSXBIOS_LOG
2461         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2462 #endif
2463
2464         v0 = a0;
2465         pc0 = ra;
2466 }
2467
2468 void psxBios_putchar() { // 3d
2469         if (Config.PsxOut) SysPrintf("%c", (char)a0);
2470         pc0 = ra;
2471 }
2472
2473 void psxBios_puts() { // 3e/3f
2474         if (Config.PsxOut) SysPrintf("%s", Ra0);
2475         pc0 = ra;
2476 }
2477
2478
2479 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2480  * We want to mimic the PSX's behaviour in this case for bufile. */
2481 static size_t strlen_internal(char* p)
2482 {
2483         size_t size_of_array = 0;
2484         while (*p++) size_of_array++;
2485         return size_of_array;
2486 }
2487
2488 #define bufile(mcd) { \
2489         size_t size_of_name = strlen_internal(dir->name); \
2490         while (nfile < 16) { \
2491                 int match=1; \
2492  \
2493                 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2494                 nfile++; \
2495                 if ((*ptr & 0xF0) != 0x50) continue; \
2496                 /* Bug link files show up as free block. */ \
2497                 if (!ptr[0xa]) continue; \
2498                 ptr+= 0xa; \
2499                 if (pfile[0] == 0) { \
2500                         strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2501                         if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2502                 } else for (i=0; i<20; i++) { \
2503                         if (pfile[i] == ptr[i]) { \
2504                                                                 dir->name[i] = ptr[i]; continue; } \
2505                         if (pfile[i] == '?') { \
2506                                 dir->name[i] = ptr[i]; continue; } \
2507                         if (pfile[i] == '*') { \
2508                                 strcpy(dir->name+i, ptr+i); break; } \
2509                         match = 0; break; \
2510                 } \
2511                 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2512                 if (match == 0) { continue; } \
2513                 dir->size = 8192; \
2514                 v0 = _dir; \
2515                 break; \
2516         } \
2517 }
2518
2519 /*
2520  *      struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2521  */
2522
2523 void psxBios_firstfile() { // 42
2524         struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2525         void *pa0 = Ra0;
2526         u32 _dir = a1;
2527         char *ptr;
2528         int i;
2529
2530 #ifdef PSXBIOS_LOG
2531         PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2532 #endif
2533
2534         v0 = 0;
2535
2536         if (pa0 != INVALID_PTR) {
2537                 strcpy(ffile, pa0);
2538                 pfile = ffile+5;
2539                 nfile = 0;
2540                 if (!strncmp(pa0, "bu00", 4)) {
2541                         // firstfile() calls _card_read() internally, so deliver it's event
2542                         DeliverEvent(0xf0000011, 0x0004);
2543                         bufile(1);
2544                 } else if (!strncmp(pa0, "bu10", 4)) {
2545                         // firstfile() calls _card_read() internally, so deliver it's event
2546                         DeliverEvent(0xf0000011, 0x0004);
2547                         bufile(2);
2548                 }
2549         }
2550
2551         pc0 = ra;
2552 }
2553
2554 /*
2555  *      struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2556  */
2557
2558 void psxBios_nextfile() { // 43
2559         struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2560         u32 _dir = a0;
2561         char *ptr;
2562         int i;
2563
2564 #ifdef PSXBIOS_LOG
2565         PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2566 #endif
2567
2568         v0 = 0;
2569
2570         if (!strncmp(ffile, "bu00", 4)) {
2571                 bufile(1);
2572         }
2573
2574         if (!strncmp(ffile, "bu10", 4)) {
2575                 bufile(2);
2576         }
2577
2578         pc0 = ra;
2579 }
2580
2581 #define burename(mcd) { \
2582         for (i=1; i<16; i++) { \
2583                 int namelen, j, xor = 0; \
2584                 ptr = Mcd##mcd##Data + 128 * i; \
2585                 if ((*ptr & 0xF0) != 0x50) continue; \
2586                 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2587                 namelen = strlen(Ra1+5); \
2588                 memcpy(ptr+0xa, Ra1+5, namelen); \
2589                 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2590                 for (j=0; j<127; j++) xor^= ptr[j]; \
2591                 ptr[127] = xor; \
2592                 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2593                 v0 = 1; \
2594                 break; \
2595         } \
2596 }
2597
2598 /*
2599  *      int rename(char *old, char *new);
2600  */
2601
2602 void psxBios_rename() { // 44
2603         void *pa0 = Ra0;
2604         void *pa1 = Ra1;
2605         char *ptr;
2606         int i;
2607
2608 #ifdef PSXBIOS_LOG
2609         PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2610 #endif
2611
2612         v0 = 0;
2613
2614         if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2615                 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2616                         burename(1);
2617                 }
2618
2619                 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2620                         burename(2);
2621                 }
2622         }
2623
2624         pc0 = ra;
2625 }
2626
2627
2628 #define budelete(mcd) { \
2629         for (i=1; i<16; i++) { \
2630                 ptr = Mcd##mcd##Data + 128 * i; \
2631                 if ((*ptr & 0xF0) != 0x50) continue; \
2632                 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2633                 *ptr = (*ptr & 0xf) | 0xA0; \
2634                 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2635                 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2636                 v0 = 1; \
2637                 break; \
2638         } \
2639 }
2640
2641 /*
2642  *      int delete(char *name);
2643  */
2644
2645 void psxBios_delete() { // 45
2646         void *pa0 = Ra0;
2647         char *ptr;
2648         int i;
2649
2650 #ifdef PSXBIOS_LOG
2651         PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2652 #endif
2653
2654         v0 = 0;
2655
2656         if (pa0 != INVALID_PTR) {
2657                 if (!strncmp(pa0, "bu00", 4)) {
2658                         budelete(1);
2659                 }
2660
2661                 if (!strncmp(pa0, "bu10", 4)) {
2662                         budelete(2);
2663                 }
2664         }
2665
2666         pc0 = ra;
2667 }
2668
2669 void psxBios_InitCARD() { // 4a
2670         u32 *ram32 = (u32 *)psxM;
2671         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2672         write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2673         // (maybe) todo: early_card_irq, FlushCache etc
2674
2675         ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2676
2677         mips_return_c(0, 300);
2678 }
2679
2680 void psxBios_StartCARD() { // 4b
2681         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2682         psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2683         psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2684
2685         psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2686         storeRam32(A_PAD_ACK_VBL, 1);
2687         storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2688         storeRam32(A_CARD_IRQR_ENA, 1);
2689         psxRegs.CP0.n.SR |= 0x401;
2690
2691         mips_return_c(1, 200);
2692 }
2693
2694 void psxBios_StopCARD() { // 4c
2695         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2696         storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2697         psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2698         storeRam32(A_CARD_IRQR_ENA, 0);
2699         psxRegs.CP0.n.SR |= 0x401;
2700         mips_return_void_c(200);
2701 }
2702
2703 void psxBios__card_write() { // 0x4e
2704         void *pa2 = Ra2;
2705         int port;
2706
2707 #ifdef PSXBIOS_LOG
2708         PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2709 #endif
2710         /*
2711         Function also accepts sector 400h (a bug).
2712         But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2713         */
2714         if (!(a1 <= 0x3FF))
2715         {
2716                 /* Invalid sectors */
2717                 v0 = 0; pc0 = ra;
2718                 return;
2719         }
2720         storeRam32(A_CARD_CHAN1, a0);
2721         port = a0 >> 4;
2722
2723         if (pa2 != INVALID_PTR) {
2724                 if (port == 0) {
2725                         memcpy(Mcd1Data + a1 * 128, pa2, 128);
2726                         SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2727                 } else {
2728                         memcpy(Mcd2Data + a1 * 128, pa2, 128);
2729                         SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2730                 }
2731         }
2732
2733         DeliverEvent(0xf0000011, 0x0004);
2734 //      DeliverEvent(0xf4000001, 0x0004);
2735
2736         v0 = 1; pc0 = ra;
2737 }
2738
2739 void psxBios__card_read() { // 0x4f
2740         void *pa2 = Ra2;
2741         int port;
2742
2743 #ifdef PSXBIOS_LOG
2744         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2745 #endif
2746         /*
2747         Function also accepts sector 400h (a bug).
2748         But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2749         */
2750         if (!(a1 <= 0x3FF))
2751         {
2752                 /* Invalid sectors */
2753                 v0 = 0; pc0 = ra;
2754                 return;
2755         }
2756         storeRam32(A_CARD_CHAN1, a0);
2757         port = a0 >> 4;
2758
2759         if (pa2 != INVALID_PTR) {
2760                 if (port == 0) {
2761                         memcpy(pa2, Mcd1Data + a1 * 128, 128);
2762                 } else {
2763                         memcpy(pa2, Mcd2Data + a1 * 128, 128);
2764                 }
2765         }
2766
2767         DeliverEvent(0xf0000011, 0x0004);
2768 //      DeliverEvent(0xf4000001, 0x0004);
2769
2770         v0 = 1; pc0 = ra;
2771 }
2772
2773 void psxBios__new_card() { // 0x50
2774 #ifdef PSXBIOS_LOG
2775         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2776 #endif
2777
2778         pc0 = ra;
2779 }
2780
2781 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2782 void psxBios__get_error(void) // 55
2783 {
2784         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2785         v0 = 0;
2786         pc0 = ra;
2787 }
2788
2789 void psxBios_Krom2RawAdd() { // 0x51
2790         int i = 0;
2791
2792         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2793         const u32 table_8140[][2] = {
2794                 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2795                 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2796                 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2797                 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2798                 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2799                 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2800                 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2801                 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2802                 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2803                 {0xffff, 0}
2804         };
2805
2806         const u32 table_889f[][2] = {
2807                 {0x889f, 0x3d68},  {0x8900, 0x40ec},  {0x897f, 0x4fb0},  {0x8a00, 0x56f4},
2808                 {0x8a7f, 0x65b8},  {0x8b00, 0x6cfc},  {0x8b7f, 0x7bc0},  {0x8c00, 0x8304},
2809                 {0x8c7f, 0x91c8},  {0x8d00, 0x990c},  {0x8d7f, 0xa7d0},  {0x8e00, 0xaf14},
2810                 {0x8e7f, 0xbdd8},  {0x8f00, 0xc51c},  {0x8f7f, 0xd3e0},  {0x9000, 0xdb24},
2811                 {0x907f, 0xe9e8},  {0x9100, 0xf12c},  {0x917f, 0xfff0},  {0x9200, 0x10734},
2812                 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2813                 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2814                 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2815                 {0xffff, 0}
2816         };
2817
2818         if (a0 >= 0x8140 && a0 <= 0x84be) {
2819                 while (table_8140[i][0] <= a0) i++;
2820                 a0 -= table_8140[i - 1][0];
2821                 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2822         } else if (a0 >= 0x889f && a0 <= 0x9872) {
2823                 while (table_889f[i][0] <= a0) i++;
2824                 a0 -= table_889f[i - 1][0];
2825                 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2826         } else {
2827                 v0 = 0xffffffff;
2828         }
2829
2830         pc0 = ra;
2831 }
2832
2833 void psxBios_GetC0Table() { // 56
2834         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2835         log_unhandled("GetC0Table @%08x\n", ra);
2836
2837         mips_return_c(A_C0_TABLE, 3);
2838 }
2839
2840 void psxBios_GetB0Table() { // 57
2841         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2842         log_unhandled("GetB0Table @%08x\n", ra);
2843
2844         mips_return_c(A_B0_TABLE, 3);
2845 }
2846
2847 static void psxBios__card_chan() { // 0x58
2848         u32 ret;
2849         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2850
2851         // todo: should return active slot chan
2852         // (active - which was last processed by irq code)
2853         ret = loadRam32(A_CARD_CHAN1);
2854         mips_return_c(ret, 8);
2855 }
2856
2857 static void psxBios_ChangeClearPad() { // 5b
2858         u32 ret;
2859         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2860         ret = loadRam32(A_PAD_ACK_VBL);
2861         storeRam32(A_PAD_ACK_VBL, a0);
2862
2863         mips_return_c(ret, 6);
2864 }
2865
2866 static void psxBios__card_status() { // 5c
2867         PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
2868
2869         v0 = 1; // ready
2870         pc0 = ra;
2871 }
2872
2873 static void psxBios__card_wait() { // 5d
2874         PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
2875
2876         v0 = 1; // ready
2877         pc0 = ra;
2878 }
2879
2880 /* System calls C0 */
2881
2882 static void psxBios_InitRCnt() { // 00
2883         int i;
2884         PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2885         psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2886         for (i = 0; i < 3; i++) {
2887                 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2888                 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2889                 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2890         }
2891         psxBios_SysEnqIntRP_(a0, 0x6d88);
2892         mips_return_c(0, 9);
2893 }
2894
2895 static void psxBios_InitException() { // 01
2896         PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2897         psxBios_SysEnqIntRP_(a0, 0x6da8);
2898         mips_return_c(0, 9);
2899 }
2900
2901 /*
2902  * int SysEnqIntRP(int index , long *queue);
2903  */
2904
2905 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2906         u32 old, base = loadRam32(A_TT_ExCB);
2907
2908         old = loadRam32(base + (priority << 3));
2909         storeRam32(base + (priority << 3), chain_eptr);
2910         storeRam32(chain_eptr, old);
2911         mips_return_c(0, 9);
2912 }
2913
2914 static void psxBios_SysEnqIntRP() { // 02
2915         PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2916         psxBios_SysEnqIntRP_(a0, a1);
2917 }
2918
2919 /*
2920  * int SysDeqIntRP(int index , long *queue);
2921  */
2922
2923 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
2924         u32 ptr, next, base = loadRam32(A_TT_ExCB);
2925         u32 lim = 0, ret = 0;
2926
2927         // as in original: no arg checks of any kind, bug if a1 == 0
2928         ptr = loadRam32(base + (priority << 3));
2929         while (ptr) {
2930                 next = loadRam32(ptr);
2931                 if (ptr == chain_rm_eptr) {
2932                         storeRam32(base + (priority << 3), next);
2933                         ret = ptr;
2934                         use_cycles(6);
2935                         break;
2936                 }
2937                 while (next && next != chain_rm_eptr && lim++ < 100) {
2938                         ptr = next;
2939                         next = loadRam32(ptr);
2940                         use_cycles(8);
2941                 }
2942                 if (next == chain_rm_eptr) {
2943                         next = loadRam32(next);
2944                         storeRam32(ptr, next);
2945                         ret = ptr;
2946                         use_cycles(6);
2947                 }
2948                 break;
2949         }
2950         if (lim == 100)
2951                 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
2952
2953         mips_return_c(ret, 12);
2954 }
2955
2956 static void psxBios_SysDeqIntRP() { // 03
2957         PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
2958         psxBios_SysDeqIntRP_(a0, a1);
2959 }
2960
2961 static void psxBios_get_free_EvCB_slot() { // 04
2962         PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
2963         s32 ret = get_free_EvCB_slot();
2964         mips_return_c(ret, 0);
2965 }
2966         
2967 static void psxBios_SysInitMemory_(u32 base, u32 size) {
2968         storeRam32(base, 0);
2969         storeRam32(A_KMALLOC_PTR, base);
2970         storeRam32(A_KMALLOC_SIZE, size);
2971         storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
2972 }
2973
2974 // this should be much more complicated, but maybe that'll be enough
2975 static u32 psxBios_SysMalloc_(u32 size) {
2976         u32 ptr = loadRam32(A_KMALLOC_PTR);
2977
2978         size = (size + 3) & ~3;
2979         storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
2980         storeRam32(ptr, size);
2981         return ptr + 4;
2982 }
2983
2984 static void psxBios_SysInitMemory() { // 08
2985         PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
2986
2987         psxBios_SysInitMemory_(a0, a1);
2988         mips_return_void_c(12);
2989 }
2990
2991 static void psxBios_ChangeClearRCnt() { // 0a
2992         u32 ret;
2993
2994         PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2995
2996         ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
2997         storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
2998         mips_return_c(ret, 8);
2999 }
3000
3001 static void psxBios_InitDefInt() { // 0c
3002         PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3003         // should also clear the autoack table
3004         psxBios_SysEnqIntRP_(a0, 0x6d98);
3005         mips_return_c(0, 20 + 6*2);
3006 }
3007
3008 void psxBios_dummy() {
3009         u32 pc = (pc0 & 0x1fffff) - 4;
3010         char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
3011                 : pc == 0xc0 ? biosC0n : NULL;
3012         PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
3013                 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
3014         (void)pc; (void)ntab;
3015         mips_return_c(0, 100);
3016 }
3017
3018 void (*biosA0[256])();
3019 // C0 and B0 overlap (end of C0 is start of B0)
3020 void (*biosC0[256+128])();
3021 void (**biosB0)() = biosC0 + 128;
3022
3023 static void setup_mips_code()
3024 {
3025         u32 *ptr;
3026         ptr = (u32 *)&psxM[A_SYSCALL];
3027         ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3028         ptr[0x04/4] = SWAPu32(0x03e00008); // jr    $ra
3029         ptr[0x08/4] = SWAPu32(0x00000000); // nop
3030
3031         ptr = (u32 *)&psxM[A_EXCEPTION];
3032         memset(ptr, 0, 0xc0);              // nops (to be patched by games sometimes)
3033         ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw    $k0, (0x108)   // PCB
3034         ptr[0x14/4] = SWAPu32(0x00000000); // nop
3035         ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw    $k0, ($k0)     // TCB
3036         ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3037         ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8    // regs
3038         ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw    $ra, 0x7c($k0)
3039         ptr[0x28/4] = SWAPu32(0xaf410004); // sw    $at, 0x04($k0)
3040         ptr[0x2c/4] = SWAPu32(0xaf420008); // sw    $v0, 0x08($k0)
3041         ptr[0x30/4] = SWAPu32(0xaf43000c); // sw    $v1, 0x0c($k0)
3042
3043         ptr[0x60/4] = SWAPu32(0x40037000); // mfc0  $v1, EPC
3044         ptr[0x64/4] = SWAPu32(0x40026800); // mfc0  $v0, Cause
3045         ptr[0x6c/4] = SWAPu32(0xaf430080); // sw    $v1, 0x80($k0)
3046
3047         ptr[0xb0/4] = HLEOP(hleop_exception);
3048 }
3049
3050 static const struct {
3051         u32 addr;
3052         enum hle_op op;
3053 } chainfns[] = {
3054         { 0xbfc050a4, hleop_exc0_0_1 },
3055         { 0xbfc04fbc, hleop_exc0_0_2 },
3056         { 0xbfc0506c, hleop_exc0_1_1 },
3057         { 0xbfc04dec, hleop_exc0_1_2 },
3058         {     0x1a00, hleop_exc0_2_2 },
3059         {     0x19c8, hleop_exc1_0_1 },
3060         {     0x18bc, hleop_exc1_0_2 },
3061         {     0x1990, hleop_exc1_1_1 },
3062         {     0x1858, hleop_exc1_1_2 },
3063         {     0x1958, hleop_exc1_2_1 },
3064         {     0x17f4, hleop_exc1_2_2 },
3065         {     0x1920, hleop_exc1_3_1 },
3066         {     0x1794, hleop_exc1_3_2 },
3067         {     0x2458, hleop_exc3_0_2 },
3068         {     0x49bc, hleop_exc_padcard1 },
3069         {     0x4a4c, hleop_exc_padcard2 },
3070 };
3071
3072 static int chain_hle_op(u32 handler)
3073 {
3074         size_t i;
3075
3076         for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3077                 if (chainfns[i].addr == handler)
3078                         return chainfns[i].op;
3079         return hleop_dummy;
3080 }
3081
3082 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3083 {
3084         d[0] = SWAPu32(next);
3085         d[1] = SWAPu32(handler1);
3086         d[2] = SWAPu32(handler2);
3087
3088         // install the hle traps
3089         PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3090         PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3091 }
3092
3093 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt)
3094 {
3095         u32 *ram32 = (u32 *)psxM;
3096         u32 s_excb = 0x20, s_evcb = 0x1c * evcb_cnt;
3097         u32 s_pcb = 4, s_tcb = 0xc0 * tcb_cnt;
3098         u32 p_excb, p_evcb, p_pcb, p_tcb;
3099
3100         memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3101         psxBios_SysInitMemory_(0xa000e000, 0x2000);
3102         p_excb = psxBios_SysMalloc_(s_excb);
3103         p_evcb = psxBios_SysMalloc_(s_evcb);
3104         p_pcb  = psxBios_SysMalloc_(s_pcb);
3105         p_tcb  = psxBios_SysMalloc_(s_tcb);
3106
3107         // "table of tables". Some games modify it
3108         assert(A_TT_ExCB == 0x0100);
3109         ram32[0x0100/4] = SWAPu32(p_excb);  // ExCB - exception chains
3110         ram32[0x0104/4] = SWAPu32(s_excb);  // ExCB size
3111         ram32[0x0108/4] = SWAPu32(p_pcb);   // PCB - process control
3112         ram32[0x010c/4] = SWAPu32(s_pcb);   // PCB size
3113         ram32[0x0110/4] = SWAPu32(p_tcb);   // TCB - thread control
3114         ram32[0x0114/4] = SWAPu32(s_tcb);   // TCB size
3115         ram32[0x0120/4] = SWAPu32(p_evcb);  // EvCB - event control
3116         ram32[0x0124/4] = SWAPu32(s_evcb);  // EvCB size
3117         ram32[0x0140/4] = SWAPu32(0x8648);  // FCB - file control
3118         ram32[0x0144/4] = SWAPu32(0x02c0);  // FCB size
3119         ram32[0x0150/4] = SWAPu32(0x6ee0);  // DCB - device control
3120         ram32[0x0154/4] = SWAPu32(0x0320);  // DCB size
3121
3122         storeRam32(p_excb + 0*4, 0x91e0);   // chain0
3123         storeRam32(p_excb + 2*4, 0x6d88);   // chain1
3124         storeRam32(p_excb + 4*4, 0x0000);   // chain2
3125         storeRam32(p_excb + 6*4, 0x6d98);   // chain3
3126
3127         storeRam32(p_pcb, p_tcb);
3128         storeRam32(p_tcb, 0x4000);          // first TCB
3129
3130         // default events
3131         storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3132         storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3133         storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3134         storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3135         storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3136         DeliverEvent(0xf0000003, 0x0010);
3137 }
3138
3139 static const u32 gpu_ctl_def[] = {
3140         0x00000000, 0x01000000, 0x03000000, 0x04000000,
3141         0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3142 };
3143
3144 static const u32 gpu_data_def[] = {
3145         0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3146         0xe5001000, 0xe6000000,
3147         0x02000000, 0x00000000, 0x01ff03ff
3148 };
3149
3150 // from 1f801d80
3151 static const u16 spu_config[] = {
3152         0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3153         0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3154         0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3155         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3156         0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3157         0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3158         0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3159         0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3160 };
3161
3162 void psxBiosSetupBootState(void)
3163 {
3164         boolean hle = Config.HLE;
3165         u32 *hw = (u32 *)psxH;
3166         int i;
3167
3168         // see also SetBootRegs()
3169         if (hle) {
3170                 v0 = 1; v1 = 4;
3171                 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3172                 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3173                 s0 = 0xa000b870;
3174                 k0 = 0xbfc0d968; k1 = 0xf1c;
3175                 ra = 0xf0001234; // just to easily detect attempts to return
3176                 psxRegs.CP0.n.Cause = 0x20;
3177                 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3178
3179                 hw[0x1000/4] = SWAP32(0x1f000000);
3180                 hw[0x1004/4] = SWAP32(0x1f802000);
3181                 hw[0x1008/4] = SWAP32(0x0013243f);
3182                 hw[0x100c/4] = SWAP32(0x00003022);
3183                 hw[0x1010/4] = SWAP32(0x0013243f);
3184                 hw[0x1014/4] = SWAP32(0x200931e1);
3185                 hw[0x1018/4] = SWAP32(0x00020943);
3186                 hw[0x101c/4] = SWAP32(0x00070777);
3187                 hw[0x1020/4] = SWAP32(0x0000132c);
3188                 hw[0x1060/4] = SWAP32(0x00000b88);
3189                 hw[0x1070/4] = SWAP32(0x00000001);
3190                 hw[0x1074/4] = SWAP32(0x0000000c);
3191                 hw[0x2040/4] = SWAP32(0x00000900);
3192         }
3193
3194         hw[0x10a0/4] = SWAP32(0x00ffffff);
3195         hw[0x10a8/4] = SWAP32(0x00000401);
3196         hw[0x10b0/4] = SWAP32(0x0008b000);
3197         hw[0x10b4/4] = SWAP32(0x00010200);
3198         hw[0x10e0/4] = SWAP32(0x000eccf4);
3199         hw[0x10e4/4] = SWAP32(0x00000400);
3200         hw[0x10e8/4] = SWAP32(0x00000002);
3201         hw[0x10f0/4] = SWAP32(0x00009099);
3202         hw[0x10f4/4] = SWAP32(0x8c8c0000);
3203
3204         if (hle) {
3205                 psxRcntWmode(0, 0);
3206                 psxRcntWmode(1, 0);
3207                 psxRcntWmode(2, 0);
3208         }
3209
3210         // gpu
3211         for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3212                 GPU_writeStatus(gpu_ctl_def[i]);
3213         for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3214                 GPU_writeData(gpu_data_def[i]);
3215         HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
3216
3217         // spu
3218         for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3219                 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3220 }
3221
3222 #include "sjisfont.h"
3223
3224 void psxBiosInit() {
3225         u32 *ptr, *ram32, *rom32;
3226         int i;
3227         uLongf len;
3228
3229         memset(psxM, 0, 0x10000);
3230         for(i = 0; i < 256; i++) {
3231                 biosA0[i] = NULL;
3232                 biosB0[i] = NULL;
3233                 biosC0[i] = NULL;
3234         }
3235         biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3236         biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3237         biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3238         biosA0[0x3f] = psxBios_printf_psxout;
3239
3240         if (!Config.HLE) return;
3241
3242         for(i = 0; i < 256; i++) {
3243                 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3244                 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3245                 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3246         }
3247
3248         biosA0[0x00] = psxBios_open;
3249         biosA0[0x01] = psxBios_lseek;
3250         biosA0[0x02] = psxBios_read;
3251         biosA0[0x03] = psxBios_write;
3252         biosA0[0x04] = psxBios_close;
3253         //biosA0[0x05] = psxBios_ioctl;
3254         //biosA0[0x06] = psxBios_exit;
3255         //biosA0[0x07] = psxBios_sys_a0_07;
3256         biosA0[0x08] = psxBios_getc;
3257         biosA0[0x09] = psxBios_putc;
3258         biosA0[0x0a] = psxBios_todigit;
3259         //biosA0[0x0b] = psxBios_atof;
3260         //biosA0[0x0c] = psxBios_strtoul;
3261         //biosA0[0x0d] = psxBios_strtol;
3262         biosA0[0x0e] = psxBios_abs;
3263         biosA0[0x0f] = psxBios_labs;
3264         biosA0[0x10] = psxBios_atoi;
3265         biosA0[0x11] = psxBios_atol;
3266         //biosA0[0x12] = psxBios_atob;
3267         biosA0[0x13] = psxBios_setjmp;
3268         biosA0[0x14] = psxBios_longjmp;
3269         biosA0[0x15] = psxBios_strcat;
3270         biosA0[0x16] = psxBios_strncat;
3271         biosA0[0x17] = psxBios_strcmp;
3272         biosA0[0x18] = psxBios_strncmp;
3273         biosA0[0x19] = psxBios_strcpy;
3274         biosA0[0x1a] = psxBios_strncpy;
3275         biosA0[0x1b] = psxBios_strlen;
3276         biosA0[0x1c] = psxBios_index;
3277         biosA0[0x1d] = psxBios_rindex;
3278         biosA0[0x1e] = psxBios_strchr;
3279         biosA0[0x1f] = psxBios_strrchr;
3280         biosA0[0x20] = psxBios_strpbrk;
3281         biosA0[0x21] = psxBios_strspn;
3282         biosA0[0x22] = psxBios_strcspn;
3283         biosA0[0x23] = psxBios_strtok;
3284         biosA0[0x24] = psxBios_strstr;
3285         biosA0[0x25] = psxBios_toupper;
3286         biosA0[0x26] = psxBios_tolower;
3287         biosA0[0x27] = psxBios_bcopy;
3288         biosA0[0x28] = psxBios_bzero;
3289         biosA0[0x29] = psxBios_bcmp;
3290         biosA0[0x2a] = psxBios_memcpy;
3291         biosA0[0x2b] = psxBios_memset;
3292         biosA0[0x2c] = psxBios_memmove;
3293         biosA0[0x2d] = psxBios_memcmp;
3294         biosA0[0x2e] = psxBios_memchr;
3295         biosA0[0x2f] = psxBios_rand;
3296         biosA0[0x30] = psxBios_srand;
3297         biosA0[0x31] = psxBios_qsort;
3298         //biosA0[0x32] = psxBios_strtod;
3299         biosA0[0x33] = psxBios_malloc;
3300         biosA0[0x34] = psxBios_free;
3301         //biosA0[0x35] = psxBios_lsearch;
3302         //biosA0[0x36] = psxBios_bsearch;
3303         biosA0[0x37] = psxBios_calloc;
3304         biosA0[0x38] = psxBios_realloc;
3305         biosA0[0x39] = psxBios_InitHeap;
3306         //biosA0[0x3a] = psxBios__exit;
3307         biosA0[0x3b] = psxBios_getchar;
3308         biosA0[0x3c] = psxBios_putchar;
3309         //biosA0[0x3d] = psxBios_gets;
3310         biosA0[0x3e] = psxBios_puts;
3311         biosA0[0x3f] = psxBios_printf;
3312         biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3313         //biosA0[0x41] = psxBios_LoadTest;
3314         biosA0[0x42] = psxBios_Load;
3315         biosA0[0x43] = psxBios_Exec;
3316         biosA0[0x44] = psxBios_FlushCache;
3317         //biosA0[0x45] = psxBios_InstallInterruptHandler;
3318         biosA0[0x46] = psxBios_GPU_dw;
3319         biosA0[0x47] = psxBios_mem2vram;
3320         biosA0[0x48] = psxBios_SendGPU;
3321         biosA0[0x49] = psxBios_GPU_cw;
3322         biosA0[0x4a] = psxBios_GPU_cwb;
3323         biosA0[0x4b] = psxBios_GPU_SendPackets;
3324         biosA0[0x4c] = psxBios_sys_a0_4c;
3325         biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3326         //biosA0[0x4e] = psxBios_GPU_sync;
3327         //biosA0[0x4f] = psxBios_sys_a0_4f;
3328         //biosA0[0x50] = psxBios_sys_a0_50;
3329         biosA0[0x51] = psxBios_LoadExec;
3330         //biosA0[0x52] = psxBios_GetSysSp;
3331         //biosA0[0x53] = psxBios_sys_a0_53;
3332         //biosA0[0x54] = psxBios__96_init_a54;
3333         //biosA0[0x55] = psxBios__bu_init_a55;
3334         biosA0[0x56] = psxBios_CdRemove;
3335         //biosA0[0x57] = psxBios_sys_a0_57;
3336         //biosA0[0x58] = psxBios_sys_a0_58;
3337         //biosA0[0x59] = psxBios_sys_a0_59;
3338         //biosA0[0x5a] = psxBios_sys_a0_5a;
3339         //biosA0[0x5b] = psxBios_dev_tty_init;
3340         //biosA0[0x5c] = psxBios_dev_tty_open;
3341         //biosA0[0x5d] = psxBios_sys_a0_5d;
3342         //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3343         //biosA0[0x5f] = psxBios_dev_cd_open;
3344         //biosA0[0x60] = psxBios_dev_cd_read;
3345         //biosA0[0x61] = psxBios_dev_cd_close;
3346         //biosA0[0x62] = psxBios_dev_cd_firstfile;
3347         //biosA0[0x63] = psxBios_dev_cd_nextfile;
3348         //biosA0[0x64] = psxBios_dev_cd_chdir;
3349         //biosA0[0x65] = psxBios_dev_card_open;
3350         //biosA0[0x66] = psxBios_dev_card_read;
3351         //biosA0[0x67] = psxBios_dev_card_write;
3352         //biosA0[0x68] = psxBios_dev_card_close;
3353         //biosA0[0x69] = psxBios_dev_card_firstfile;
3354         //biosA0[0x6a] = psxBios_dev_card_nextfile;
3355         //biosA0[0x6b] = psxBios_dev_card_erase;
3356         //biosA0[0x6c] = psxBios_dev_card_undelete;
3357         //biosA0[0x6d] = psxBios_dev_card_format;
3358         //biosA0[0x6e] = psxBios_dev_card_rename;
3359         //biosA0[0x6f] = psxBios_dev_card_6f;
3360         biosA0[0x70] = psxBios__bu_init;
3361         biosA0[0x71] = psxBios__96_init;
3362         biosA0[0x72] = psxBios_CdRemove;
3363         //biosA0[0x73] = psxBios_sys_a0_73;
3364         //biosA0[0x74] = psxBios_sys_a0_74;
3365         //biosA0[0x75] = psxBios_sys_a0_75;
3366         //biosA0[0x76] = psxBios_sys_a0_76;
3367         //biosA0[0x77] = psxBios_sys_a0_77;
3368         //biosA0[0x78] = psxBios__96_CdSeekL;
3369         //biosA0[0x79] = psxBios_sys_a0_79;
3370         //biosA0[0x7a] = psxBios_sys_a0_7a;
3371         //biosA0[0x7b] = psxBios_sys_a0_7b;
3372         //biosA0[0x7c] = psxBios__96_CdGetStatus;
3373         //biosA0[0x7d] = psxBios_sys_a0_7d;
3374         //biosA0[0x7e] = psxBios__96_CdRead;
3375         //biosA0[0x7f] = psxBios_sys_a0_7f;
3376         //biosA0[0x80] = psxBios_sys_a0_80;
3377         //biosA0[0x81] = psxBios_sys_a0_81;
3378         //biosA0[0x82] = psxBios_sys_a0_82;
3379         //biosA0[0x83] = psxBios_sys_a0_83;
3380         //biosA0[0x84] = psxBios_sys_a0_84;
3381         //biosA0[0x85] = psxBios__96_CdStop;
3382         //biosA0[0x86] = psxBios_sys_a0_86;
3383         //biosA0[0x87] = psxBios_sys_a0_87;
3384         //biosA0[0x88] = psxBios_sys_a0_88;
3385         //biosA0[0x89] = psxBios_sys_a0_89;
3386         //biosA0[0x8a] = psxBios_sys_a0_8a;
3387         //biosA0[0x8b] = psxBios_sys_a0_8b;
3388         //biosA0[0x8c] = psxBios_sys_a0_8c;
3389         //biosA0[0x8d] = psxBios_sys_a0_8d;
3390         //biosA0[0x8e] = psxBios_sys_a0_8e;
3391         //biosA0[0x8f] = psxBios_sys_a0_8f;
3392         biosA0[0x90] = hleExc0_1_2;
3393         biosA0[0x91] = hleExc0_0_2;
3394         biosA0[0x92] = hleExc0_1_1;
3395         biosA0[0x93] = hleExc0_0_1;
3396         //biosA0[0x94] = psxBios_sys_a0_94;
3397         //biosA0[0x95] = psxBios_sys_a0_95;
3398         //biosA0[0x96] = psxBios_AddCDROMDevice;
3399         //biosA0[0x97] = psxBios_AddMemCardDevide;
3400         //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3401         //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3402         //biosA0[0x9a] = psxBios_sys_a0_9a;
3403         //biosA0[0x9b] = psxBios_sys_a0_9b;
3404         //biosA0[0x9c] = psxBios_SetConf;
3405         //biosA0[0x9d] = psxBios_GetConf;
3406         //biosA0[0x9e] = psxBios_sys_a0_9e;
3407         biosA0[0x9f] = psxBios_SetMem;
3408         //biosA0[0xa0] = psxBios__boot;
3409         //biosA0[0xa1] = psxBios_SystemError;
3410         //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3411         biosA0[0xa3] = psxBios_DequeueCdIntr;
3412         //biosA0[0xa4] = psxBios_sys_a0_a4;
3413         //biosA0[0xa5] = psxBios_ReadSector;
3414         biosA0[0xa6] = psxBios_get_cd_status;
3415         //biosA0[0xa7] = psxBios_bufs_cb_0;
3416         //biosA0[0xa8] = psxBios_bufs_cb_1;
3417         //biosA0[0xa9] = psxBios_bufs_cb_2;
3418         //biosA0[0xaa] = psxBios_bufs_cb_3;
3419         biosA0[0xab] = psxBios__card_info;
3420         biosA0[0xac] = psxBios__card_load;
3421         //biosA0[0axd] = psxBios__card_auto;
3422         //biosA0[0xae] = psxBios_bufs_cd_4;
3423         //biosA0[0xaf] = psxBios_sys_a0_af;
3424         //biosA0[0xb0] = psxBios_sys_a0_b0;
3425         //biosA0[0xb1] = psxBios_sys_a0_b1;
3426         //biosA0[0xb2] = psxBios_do_a_long_jmp
3427         //biosA0[0xb3] = psxBios_sys_a0_b3;
3428         biosA0[0xb4] = psxBios_GetSystemInfo;
3429 //*******************B0 CALLS****************************
3430         biosB0[0x00] = psxBios_SysMalloc;
3431         //biosB0[0x01] = psxBios_sys_b0_01;
3432         biosB0[0x02] = psxBios_SetRCnt;
3433         biosB0[0x03] = psxBios_GetRCnt;
3434         biosB0[0x04] = psxBios_StartRCnt;
3435         biosB0[0x05] = psxBios_StopRCnt;
3436         biosB0[0x06] = psxBios_ResetRCnt;
3437         biosB0[0x07] = psxBios_DeliverEvent;
3438         biosB0[0x08] = psxBios_OpenEvent;
3439         biosB0[0x09] = psxBios_CloseEvent;
3440         biosB0[0x0a] = psxBios_WaitEvent;
3441         biosB0[0x0b] = psxBios_TestEvent;
3442         biosB0[0x0c] = psxBios_EnableEvent;
3443         biosB0[0x0d] = psxBios_DisableEvent;
3444         biosB0[0x0e] = psxBios_OpenTh;
3445         biosB0[0x0f] = psxBios_CloseTh;
3446         biosB0[0x10] = psxBios_ChangeTh;
3447         //biosB0[0x11] = psxBios_psxBios_b0_11;
3448         biosB0[0x12] = psxBios_InitPAD;
3449         biosB0[0x13] = psxBios_StartPAD;
3450         biosB0[0x14] = psxBios_StopPAD;
3451         biosB0[0x15] = psxBios_PAD_init;
3452         biosB0[0x16] = psxBios_PAD_dr;
3453         biosB0[0x17] = psxBios_ReturnFromException;
3454         biosB0[0x18] = psxBios_ResetEntryInt;
3455         biosB0[0x19] = psxBios_HookEntryInt;
3456         //biosB0[0x1a] = psxBios_sys_b0_1a;
3457         //biosB0[0x1b] = psxBios_sys_b0_1b;
3458         //biosB0[0x1c] = psxBios_sys_b0_1c;
3459         //biosB0[0x1d] = psxBios_sys_b0_1d;
3460         //biosB0[0x1e] = psxBios_sys_b0_1e;
3461         //biosB0[0x1f] = psxBios_sys_b0_1f;
3462         biosB0[0x20] = psxBios_UnDeliverEvent;
3463         //biosB0[0x21] = psxBios_sys_b0_21;
3464         //biosB0[0x22] = psxBios_sys_b0_22;
3465         //biosB0[0x23] = psxBios_sys_b0_23;
3466         //biosB0[0x24] = psxBios_sys_b0_24;
3467         //biosB0[0x25] = psxBios_sys_b0_25;
3468         //biosB0[0x26] = psxBios_sys_b0_26;
3469         //biosB0[0x27] = psxBios_sys_b0_27;
3470         //biosB0[0x28] = psxBios_sys_b0_28;
3471         //biosB0[0x29] = psxBios_sys_b0_29;
3472         //biosB0[0x2a] = psxBios_sys_b0_2a;
3473         //biosB0[0x2b] = psxBios_sys_b0_2b;
3474         //biosB0[0x2c] = psxBios_sys_b0_2c;
3475         //biosB0[0x2d] = psxBios_sys_b0_2d;
3476         //biosB0[0x2e] = psxBios_sys_b0_2e;
3477         //biosB0[0x2f] = psxBios_sys_b0_2f;
3478         //biosB0[0x30] = psxBios_sys_b0_30;
3479         //biosB0[0x31] = psxBios_sys_b0_31;
3480         biosB0[0x32] = psxBios_open;
3481         biosB0[0x33] = psxBios_lseek;
3482         biosB0[0x34] = psxBios_read;
3483         biosB0[0x35] = psxBios_write;
3484         biosB0[0x36] = psxBios_close;
3485         //biosB0[0x37] = psxBios_ioctl;
3486         //biosB0[0x38] = psxBios_exit;
3487         //biosB0[0x39] = psxBios_sys_b0_39;
3488         //biosB0[0x3a] = psxBios_getc;
3489         //biosB0[0x3b] = psxBios_putc;
3490         biosB0[0x3c] = psxBios_getchar;
3491         biosB0[0x3d] = psxBios_putchar;
3492         //biosB0[0x3e] = psxBios_gets;
3493         biosB0[0x3f] = psxBios_puts;
3494         //biosB0[0x40] = psxBios_cd;
3495         biosB0[0x41] = psxBios_format;
3496         biosB0[0x42] = psxBios_firstfile;
3497         biosB0[0x43] = psxBios_nextfile;
3498         biosB0[0x44] = psxBios_rename;
3499         biosB0[0x45] = psxBios_delete;
3500         //biosB0[0x46] = psxBios_undelete;
3501         //biosB0[0x47] = psxBios_AddDevice;
3502         //biosB0[0x48] = psxBios_RemoteDevice;
3503         //biosB0[0x49] = psxBios_PrintInstalledDevices;
3504         biosB0[0x4a] = psxBios_InitCARD;
3505         biosB0[0x4b] = psxBios_StartCARD;
3506         biosB0[0x4c] = psxBios_StopCARD;
3507         //biosB0[0x4d] = psxBios_sys_b0_4d;
3508         biosB0[0x4e] = psxBios__card_write;
3509         biosB0[0x4f] = psxBios__card_read;
3510         biosB0[0x50] = psxBios__new_card;
3511         biosB0[0x51] = psxBios_Krom2RawAdd;
3512         //biosB0[0x52] = psxBios_sys_b0_52;
3513         //biosB0[0x53] = psxBios_sys_b0_53;
3514         //biosB0[0x54] = psxBios__get_errno;
3515         biosB0[0x55] = psxBios__get_error;
3516         biosB0[0x56] = psxBios_GetC0Table;
3517         biosB0[0x57] = psxBios_GetB0Table;
3518         biosB0[0x58] = psxBios__card_chan;
3519         //biosB0[0x59] = psxBios_sys_b0_59;
3520         //biosB0[0x5a] = psxBios_sys_b0_5a;
3521         biosB0[0x5b] = psxBios_ChangeClearPad;
3522         biosB0[0x5c] = psxBios__card_status;
3523         biosB0[0x5d] = psxBios__card_wait;
3524 //*******************C0 CALLS****************************
3525         biosC0[0x00] = psxBios_InitRCnt;
3526         biosC0[0x01] = psxBios_InitException;
3527         biosC0[0x02] = psxBios_SysEnqIntRP;
3528         biosC0[0x03] = psxBios_SysDeqIntRP;
3529         biosC0[0x04] = psxBios_get_free_EvCB_slot;
3530         //biosC0[0x05] = psxBios_get_free_TCB_slot;
3531         //biosC0[0x06] = psxBios_ExceptionHandler;
3532         //biosC0[0x07] = psxBios_InstallExeptionHandler;
3533         biosC0[0x08] = psxBios_SysInitMemory;
3534         //biosC0[0x09] = psxBios_SysInitKMem;
3535         biosC0[0x0a] = psxBios_ChangeClearRCnt;
3536         //biosC0[0x0b] = psxBios_SystemError;
3537         biosC0[0x0c] = psxBios_InitDefInt;
3538         //biosC0[0x0d] = psxBios_sys_c0_0d;
3539         //biosC0[0x0e] = psxBios_sys_c0_0e;
3540         //biosC0[0x0f] = psxBios_sys_c0_0f;
3541         //biosC0[0x10] = psxBios_sys_c0_10;
3542         //biosC0[0x11] = psxBios_sys_c0_11;
3543         //biosC0[0x12] = psxBios_InstallDevices;
3544         //biosC0[0x13] = psxBios_FlushStfInOutPut;
3545         //biosC0[0x14] = psxBios_sys_c0_14;
3546         //biosC0[0x15] = psxBios__cdevinput;
3547         //biosC0[0x16] = psxBios__cdevscan;
3548         //biosC0[0x17] = psxBios__circgetc;
3549         //biosC0[0x18] = psxBios__circputc;
3550         //biosC0[0x19] = psxBios_ioabort;
3551         //biosC0[0x1a] = psxBios_sys_c0_1a
3552         //biosC0[0x1b] = psxBios_KernelRedirect;
3553         //biosC0[0x1c] = psxBios_PatchAOTable;
3554 //************** THE END ***************************************
3555 /**/
3556
3557         memset(FDesc, 0, sizeof(FDesc));
3558
3559         // initial RNG seed
3560         psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3561
3562         // somewhat pretend to be a SCPH1001 BIOS
3563         // some games look for these and take an exception if they're missing
3564         rom32 = (u32 *)psxR;
3565         rom32[0x100/4] = SWAP32(0x19951204);
3566         rom32[0x104/4] = SWAP32(3);
3567         strcpy(psxR + 0x108, "PCSX authors");
3568         strcpy(psxR + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3569         strcpy(psxR + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3570         strcpy(psxR + 0x7ff54, "GPL-2.0-or-later");
3571
3572         // fonts
3573         len = 0x80000 - 0x66000;
3574         uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3575         len = 0x80000 - 0x69d68;
3576         uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3577
3578         /*      Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3579                 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3580                 Here are some examples of games not working with this fix in place :
3581                 R-type won't get past the Irem logo if not implemented.
3582                 Crash Team Racing will softlock after the Sony logo.
3583         */
3584
3585         ram32 = (u32 *)psxM;
3586         ram32[0x0000/4] = SWAPu32(0x00000003); // lui   $k0, 0  (overwritten by 3)
3587         ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3588         ram32[0x0008/4] = SWAPu32(0x03400008); // jr    $k0
3589         ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3590
3591         ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3592         ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3593
3594         ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui   $k0, 0  // exception vector
3595         ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3596         ram32[0x0088/4] = SWAPu32(0x03400008); // jr    $k0
3597         ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3598
3599         ram32[0x00a0/4] = HLEOP(hleop_a0);
3600         ram32[0x00b0/4] = HLEOP(hleop_b0);
3601         ram32[0x00c0/4] = HLEOP(hleop_c0);
3602
3603         setup_tt(4, 16);
3604
3605         ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3606         strcpy((char *)&ram32[0xeff0/4], "bu");
3607
3608         // default exception handler chains
3609         write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3610         write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3611         write_chain(&ram32[0x6da8/4],      0,          0,     0x1a00); // chain0.e2
3612         write_chain(&ram32[0x6d88/4], 0x6d78,     0x19c8,     0x18bc); // chain1.e0
3613         write_chain(&ram32[0x6d78/4], 0x6d68,     0x1990,     0x1858); // chain1.e1
3614         write_chain(&ram32[0x6d68/4], 0x6d58,     0x1958,     0x17f4); // chain1.e2
3615         write_chain(&ram32[0x6d58/4],      0,     0x1920,     0x1794); // chain1.e3
3616         write_chain(&ram32[0x6d98/4],      0,          0,     0x2458); // chain3.e0
3617
3618         setup_mips_code();
3619
3620         // fill the api jumptables with fake entries as some games patch them
3621         // (or rather the funcs listed there)
3622         ptr = (u32 *)&psxM[A_A0_TABLE];
3623         for (i = 0; i < 256; i++)
3624                 ptr[i] = SWAP32(0x1000);
3625
3626         ptr = (u32 *)&psxM[A_B0_TABLE];
3627         for (i = 0; i < 256; i++)
3628                 ptr[i] = SWAP32(0x2000);
3629         // B(5b) is special because games patch (sometimes even jump to)
3630         // code at fixed offsets from it, nocash lists offsets:
3631         //  patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3632         //  call:  +7a0=4b70, +884=4c54, +894=4c64
3633         ptr[0x5b] = SWAP32(0x43d0);
3634         ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3635
3636         ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3637         ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3638         ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3639
3640         ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3641         ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3642
3643         ptr = (u32 *)&psxM[A_C0_TABLE];
3644         for (i = 0; i < 256/2; i++)
3645                 ptr[i] = SWAP32(0x3000);
3646         ptr[6] = SWAP32(A_EXCEPTION);
3647
3648         // more HLE traps
3649         ram32[0x1000/4] = HLEOP(hleop_dummy);
3650         ram32[0x2000/4] = HLEOP(hleop_dummy);
3651         ram32[0x3000/4] = HLEOP(hleop_dummy);
3652         ram32[0x4c54/4] = HLEOP(hleop_dummy);   // for B12_InitPad?
3653         ram32[0x8000/4] = HLEOP(hleop_execret);
3654
3655         ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3656         ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3657         ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3658         ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3659         ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3660         ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3661 }
3662
3663 void psxBiosShutdown() {
3664 }
3665
3666 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt) {
3667         if (tcb_cnt != 4 || evcb_cnt != 16)
3668                 setup_tt(tcb_cnt, evcb_cnt);
3669 }
3670
3671 #define psxBios_PADpoll(pad) { \
3672         PAD##pad##_startPoll(pad); \
3673         pad_buf##pad[0] = 0; \
3674         pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3675         if (!(pad_buf##pad[1] & 0x0f)) { \
3676                 bufcount = 32; \
3677         } else { \
3678                 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3679         } \
3680         PAD##pad##_poll(0); \
3681         i = 2; \
3682         while (bufcount--) { \
3683                 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3684         } \
3685 }
3686
3687 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3688 {
3689         use_cycles(10);
3690         if (enable) {
3691                 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3692                 psxBios_ReturnFromException();
3693         }
3694         else
3695                 pc0 = ra;
3696 }
3697
3698 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3699 // so this is only partially implemented
3700 void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3701 {
3702         u32 cdrom_dma_ack_enable = 1; // a000b93c
3703         handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3704 }
3705
3706 void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3707 {
3708         u32 ret = 0;
3709         //PSXBIOS_LOG("%s\n", __func__);
3710
3711         if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3712                 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3713                 //if (--cdrom_irq_counter == 0) // 0xa0009180
3714                 //      DeliverEvent(0xf0000003, 0x10);
3715                 use_cycles(22);
3716                 ret = 1;
3717         }
3718         mips_return_c(ret, 20);
3719 }
3720
3721 void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3722 {
3723         u32 cdrom_irq_ack_enable = 1; // a000b938
3724         handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3725 }
3726
3727 void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3728 {
3729         u32 ret = 0;
3730         if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3731                 PSXBIOS_LOG("%s TODO\n", __func__);
3732                 ret = 1;
3733         }
3734         mips_return_c(ret, 20);
3735 }
3736
3737 void hleExc0_2_2_syscall() // not in any A/B/C table
3738 {
3739         u32 code = (psxRegs.CP0.n.Cause & 0x3c) >> 2;
3740         u32 tcbPtr = loadRam32(A_TT_PCB);
3741         TCB *tcb = loadRam32ptr(tcbPtr);
3742
3743         if (code != R3000E_Syscall) {
3744                 if (code != 0) {
3745                         DeliverEvent(0xf0000010, 0x1000);
3746                         //psxBios_SystemErrorUnresolvedException();
3747                 }
3748                 mips_return_c(0, 17);
3749                 return;
3750         }
3751
3752         //printf("%s c=%d a0=%d\n", __func__, code, a0);
3753         tcb->epc += SWAP32(4);
3754         switch (a0) {
3755                 case 0: // noop
3756                         break;
3757
3758                 case 1: { // EnterCritical - disable irqs
3759                         u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3760                         tcb->reg[2] = SWAP32(was_enabled);
3761                         tcb->sr &= SWAP32(~0x404);
3762                         break;
3763                 }
3764                 case 2: // ExitCritical - enable irqs
3765                         tcb->sr |= SWAP32(0x404);
3766                         break;
3767
3768                 case 3: { // ChangeThreadSubFunction
3769                         u32 tcbPtr = loadRam32(A_TT_PCB);
3770                         storeRam32(tcbPtr, a1);
3771                         break;
3772                 }
3773                 default:
3774                         DeliverEvent(0xf0000010, 0x4000);
3775                         break;
3776         }
3777         use_cycles(30);
3778         psxBios_ReturnFromException();
3779 }
3780
3781 void hleExc1_0_1(void)
3782 {
3783         u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3784         handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3785 }
3786
3787 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3788 {
3789         u32 ret = 0;
3790         if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3791                 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3792                 ret = 1;
3793         }
3794         mips_return_c(ret, 22);
3795 }
3796
3797 void hleExc1_0_2(void)
3798 {
3799         handle_chain_1_x_2(3, 0); // IRQ0 vblank
3800 }
3801
3802 void hleExc1_1_1(void)
3803 {
3804         u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3805         handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3806 }
3807
3808 void hleExc1_1_2(void)
3809 {
3810         handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3811 }
3812
3813 void hleExc1_2_1(void)
3814 {
3815         u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3816         handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3817 }
3818
3819 void hleExc1_2_2(void)
3820 {
3821         handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3822 }
3823
3824 void hleExc1_3_1(void)
3825 {
3826         u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3827         handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3828 }
3829
3830 void hleExc1_3_2(void)
3831 {
3832         handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3833 }
3834
3835 void hleExc3_0_2_defint(void)
3836 {
3837         static const struct {
3838                 u8 ev, irqbit;
3839         } tab[] = {
3840                 {  3,  2 }, // cdrom
3841                 {  9,  9 }, // spu
3842                 {  2,  1 }, // gpu
3843                 { 10, 10 }, // io
3844                 { 11,  8 }, // sio
3845                 {  1,  0 }, // vbl
3846                 {  5,  4 }, // rcnt0
3847                 {  6,  5 }, // rcnt1
3848                 {  6,  6 }, // rcnt2 (bug)
3849                 {  8,  7 }, // sio rx
3850                 {  4,  3 }, // sio
3851         };
3852         size_t i;
3853         for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3854                 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3855                         DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3856                         use_cycles(7);
3857                 }
3858
3859         }
3860         mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3861 }
3862
3863 void hleExcPadCard1(void)
3864 {
3865         if (loadRam32(A_PAD_IRQR_ENA)) {
3866                 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3867                 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
3868                 int i, bufcount;
3869
3870                 psxBios_PADpoll(1);
3871                 psxBios_PADpoll(2);
3872                 use_cycles(100);
3873                 if (loadRam32(A_PAD_DR_DST))
3874                         psxBios_PAD_dr_();
3875         }
3876         if (loadRam32(A_PAD_ACK_VBL))
3877                 psxHwWrite16(0x1f801070, ~1);
3878         if (loadRam32(A_CARD_IRQR_ENA)) {
3879                 // todo, maybe
3880         }
3881
3882         mips_return_c(0, 18);
3883 }
3884
3885 void hleExcPadCard2(void)
3886 {
3887         u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
3888         mips_return_c(ret, 15);
3889 }
3890
3891 void psxBiosException() {
3892         u32 tcbPtr = loadRam32(A_TT_PCB);
3893         u32 *chains = loadRam32ptr(A_TT_ExCB);
3894         TCB *tcb = loadRam32ptr(tcbPtr);
3895         u32 ptr, *chain;
3896         int c, lim;
3897         int i;
3898
3899         // save the regs
3900         // $at, $v0, $v1 already saved by the mips code at A_EXCEPTION
3901         for (i = 4; i < 32; i++) {
3902                 if (i == 26) // $k0
3903                         continue;
3904                 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
3905         }
3906         tcb->lo = SWAP32(psxRegs.GPR.n.lo);
3907         tcb->hi = SWAP32(psxRegs.GPR.n.hi);
3908         //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
3909         tcb->sr = SWAP32(psxRegs.CP0.n.SR);
3910         tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
3911         sp = fp = loadRam32(A_EXC_SP);
3912         gp = A_EXC_GP;
3913         use_cycles(46);
3914
3915         // do the chains (always 4)
3916         for (c = lim = 0; c < 4; c++) {
3917                 if (chains[c * 2] == 0)
3918                         continue;
3919                 ptr = SWAP32(chains[c * 2]);
3920                 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
3921                         chain = castRam32ptr(ptr);
3922                         use_cycles(14);
3923                         lim++;
3924                         if (chain[2] == 0)
3925                                 continue;
3926                         softCallInException(SWAP32(chain[2]));
3927                         if (returned_from_exception())
3928                                 return;
3929
3930                         if (v0 == 0 || chain[1] == 0)
3931                                 continue;
3932                         softCallInException(SWAP32(chain[1]));
3933                         if (returned_from_exception())
3934                                 return;
3935                 }
3936         }
3937         assert(lim < 100);
3938
3939         // return from exception (custom or default)
3940         use_cycles(23);
3941         ptr = loadRam32(A_EEXIT_PTR);
3942         if (ptr != A_EEXIT_DEF) {
3943                 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
3944                 longjmp_load(jmp_buf);
3945                 v0 = 1;
3946                 pc0 = ra;
3947                 return;
3948         }
3949         psxBios_ReturnFromException();
3950 }
3951
3952 #define bfreeze(ptr, size) { \
3953         if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3954         if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3955         base += size; \
3956 }
3957
3958 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3959 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3960
3961 #define bfreezepsxMptr(ptr, type) { \
3962         if (Mode == 1) { \
3963                 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3964                 else psxRu32ref(base) = 0; \
3965         } else { \
3966                 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3967                 else (ptr) = NULL; \
3968         } \
3969         base += sizeof(u32); \
3970 }
3971
3972 void psxBiosFreeze(int Mode) {
3973         u32 base = 0x40000;
3974
3975         bfreezes(FDesc);
3976 }