psxbios: add missing clearing for copy related functions
[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
939         psxBios_memcpy(); // identical
940 }
941
942 static void psxBios_bzero() { // 0x28
943         /* Same as memset here (See memset below) */
944         u32 ret = a0, cycles;
945         if (a0 == 0 || (s32)a1 <= 0)
946         {
947                 mips_return_c(0, 6);
948                 return;
949         }
950         do_memset(a0, 0, a1);
951         cycles = a1 * 4;
952         a0 += a1;
953         a1 = 0;
954         // todo: many more cycles due to uncached bios mem
955         mips_return_c(ret, cycles + 5);
956 }
957
958 void psxBios_bcmp() { // 0x29
959         char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
960
961         if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
962
963         while ((s32)a2-- > 0) {
964                 if (*p1++ != *p2++) {
965                         v0 = *p1 - *p2; // BUG: compare the NEXT byte
966                         pc0 = ra;
967                         return;
968                 }
969         }
970
971         v0 = 0; pc0 = ra;
972 }
973
974 static void psxBios_memcpy() { // 0x2a
975         u32 ret = a0, cycles = 0;
976         if (a0 == 0)
977         {
978                 mips_return_c(0, 4);
979                 return;
980         }
981         if ((s32)a2 > 0) {
982                 do_memcpy(a0, a1, a2);
983                 cycles = a2 * 6;
984                 v1 = a0;
985                 a0 += a2;
986                 a1 += a2;
987                 a2 = 0;
988         }
989         mips_return_c(ret, cycles + 5);
990 }
991
992 static void psxBios_memset() { // 0x2b
993         u32 ret = a0, cycles;
994         if (a0 == 0 || (s32)a2 <= 0)
995         {
996                 mips_return_c(0, 6);
997                 return;
998         }
999         do_memset(a0, a1, a2);
1000         cycles = a2 * 4;
1001         a0 += a2;
1002         a2 = 0;
1003         // todo: many more cycles due to uncached bios mem
1004         mips_return_c(ret, cycles + 5);
1005 }
1006
1007 void psxBios_memmove() { // 0x2c
1008         u32 ret = a0, cycles = 0;
1009         if (a0 == 0)
1010         {
1011                 mips_return_c(0, 4);
1012                 return;
1013         }
1014         v1 = a0;
1015         if ((s32)a2 > 0 && a0 > a1 && a0 < a1 + a2) {
1016                 u32 dst = a0, len = a2 + 1;
1017                 a0 += a2;
1018                 a1 += a2;
1019                 while ((s32)a2 >= 0) { // BUG: copies one more byte here
1020                         const u8 *sb = PSXM(a1);
1021                         u8 *db = PSXM(a0);
1022                         if (db != INVALID_PTR && sb != INVALID_PTR)
1023                                 *db = *sb;
1024                         a0--;
1025                         a1--;
1026                         a2--;
1027                 }
1028                 psxCpu->Clear(dst, (len + 3) / 4);
1029                 cycles = 10 + len * 8;
1030         } else if ((s32)a2 > 0) {
1031                 do_memcpy(a0, a1, a2);
1032                 cycles = a2 * 6;
1033                 a0 += a2;
1034                 a1 += a2;
1035                 a2 = 0;
1036         }
1037         mips_return_c(ret, cycles + 5);
1038 }
1039
1040 void psxBios_memcmp() { // 0x2d
1041         psxBios_bcmp();
1042 }
1043
1044 void psxBios_memchr() { // 0x2e
1045         char *p = (char *)Ra0;
1046
1047         if (a0 == 0 || a2 > 0x7FFFFFFF)
1048         {
1049                 pc0 = ra;
1050                 return;
1051         }
1052
1053         while ((s32)a2-- > 0) {
1054                 if (*p++ != (s8)a1) continue;
1055                 v0 = a0 + (p - (char *)Ra0 - 1);
1056                 pc0 = ra;
1057                 return;
1058         }
1059
1060         v0 = 0; pc0 = ra;
1061 }
1062
1063 void psxBios_rand() { // 0x2f
1064         u32 s = psxMu32(0x9010) * 1103515245 + 12345;
1065         v0 = (s >> 16) & 0x7fff;
1066         psxMu32ref(0x9010) = SWAPu32(s);
1067         pc0 = ra;
1068 }
1069
1070 void psxBios_srand() { // 0x30
1071         psxMu32ref(0x9010) = SWAPu32(a0);
1072         pc0 = ra;
1073 }
1074
1075 static u32 qscmpfunc, qswidth;
1076
1077 static inline int qscmp(char *a, char *b) {
1078         u32 sa0 = a0;
1079
1080         a0 = sa0 + (a - (char *)PSXM(sa0));
1081         a1 = sa0 + (b - (char *)PSXM(sa0));
1082
1083         softCall(qscmpfunc);
1084
1085         a0 = sa0;
1086         return (s32)v0;
1087 }
1088
1089 static inline void qexchange(char *i, char *j) {
1090         char t;
1091         int n = qswidth;
1092
1093         do {
1094                 t = *i;
1095                 *i++ = *j;
1096                 *j++ = t;
1097         } while (--n);
1098 }
1099
1100 static inline void q3exchange(char *i, char *j, char *k) {
1101         char t;
1102         int n = qswidth;
1103
1104         do {
1105                 t = *i;
1106                 *i++ = *k;
1107                 *k++ = *j;
1108                 *j++ = t;
1109         } while (--n);
1110 }
1111
1112 static void qsort_main(char *a, char *l) {
1113         char *i, *j, *lp, *hp;
1114         int c;
1115         unsigned int n;
1116
1117 start:
1118         if ((n = l - a) <= qswidth)
1119                 return;
1120         n = qswidth * (n / (2 * qswidth));
1121         hp = lp = a + n;
1122         i = a;
1123         j = l - qswidth;
1124         while (TRUE) {
1125                 if (i < lp) {
1126                         if ((c = qscmp(i, lp)) == 0) {
1127                                 qexchange(i, lp -= qswidth);
1128                                 continue;
1129                         }
1130                         if (c < 0) {
1131                                 i += qswidth;
1132                                 continue;
1133                         }
1134                 }
1135
1136 loop:
1137                 if (j > hp) {
1138                         if ((c = qscmp(hp, j)) == 0) {
1139                                 qexchange(hp += qswidth, j);
1140                                 goto loop;
1141                         }
1142                         if (c > 0) {
1143                                 if (i == lp) {
1144                                         q3exchange(i, hp += qswidth, j);
1145                                         i = lp += qswidth;
1146                                         goto loop;
1147                                 }
1148                                 qexchange(i, j);
1149                                 j -= qswidth;
1150                                 i += qswidth;
1151                                 continue;
1152                         }
1153                         j -= qswidth;
1154                         goto loop;
1155                 }
1156
1157                 if (i == lp) {
1158                         if (lp - a >= l - hp) {
1159                                 qsort_main(hp + qswidth, l);
1160                                 l = lp;
1161                         } else {
1162                                 qsort_main(a, lp);
1163                                 a = hp + qswidth;
1164                         }
1165                         goto start;
1166                 }
1167
1168                 q3exchange(j, lp -= qswidth, i);
1169                 j = hp -= qswidth;
1170         }
1171 }
1172
1173 void psxBios_qsort() { // 0x31
1174         qswidth = a2;
1175         qscmpfunc = a3;
1176         qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1177
1178         pc0 = ra;
1179 }
1180
1181 // this isn't how the real bios works, but maybe good enough
1182 static void psxBios_malloc() { // 0x33
1183         u32 *heap_addr, *heap_end;
1184         u32 *chunk, *newchunk = NULL;
1185         unsigned int dsize = 0, csize, cstat;
1186         int colflag;
1187         PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x33], a0);
1188         heap_addr = loadRam32ptr(A_HEAP_BASE);
1189         heap_end = loadRam32ptr(A_HEAP_END);
1190         if (heap_addr >= heap_end) {
1191                 v0 = 0;
1192                 pc0 = ra;
1193                 return;
1194         }
1195
1196         // scan through heap and combine free chunks of space
1197         chunk = heap_addr;
1198         colflag = 0;
1199         while(chunk < heap_end) {
1200                 // get size and status of actual chunk
1201                 csize = ((u32)*chunk) & 0xfffffffc;
1202                 cstat = ((u32)*chunk) & 1;
1203
1204                 // most probably broken heap descriptor
1205                 // this fixes Burning Road
1206                 if (*chunk == 0) {
1207                         newchunk = chunk;
1208                         dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1209                         colflag = 1;
1210                         break;
1211                 }
1212
1213                 // it's a free chunk
1214                 if(cstat == 1) {
1215                         if(colflag == 0) {
1216                                 newchunk = chunk;
1217                                 dsize = csize;
1218                                 colflag = 1;                    // let's begin a new collection of free memory
1219                         }
1220                         else dsize += (csize+4);        // add the new size including header
1221                 }
1222                 // not a free chunk: did we start a collection ?
1223                 else {
1224                         if(colflag == 1) {                      // collection is over
1225                                 colflag = 0;
1226                                 *newchunk = SWAP32(dsize | 1);
1227                         }
1228                 }
1229
1230                 // next chunk
1231                 chunk = (u32*)((uptr)chunk + csize + 4);
1232         }
1233         // if neccessary free memory on end of heap
1234         if (colflag == 1)
1235                 *newchunk = SWAP32(dsize | 1);
1236
1237         chunk = heap_addr;
1238         csize = ((u32)*chunk) & 0xfffffffc;
1239         cstat = ((u32)*chunk) & 1;
1240         dsize = (a0 + 3) & 0xfffffffc;
1241
1242         // exit on uninitialized heap
1243         if (chunk == NULL) {
1244                 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1245                 v0 = 0;
1246                 pc0 = ra;
1247                 return;
1248         }
1249
1250         // search an unused chunk that is big enough until the end of the heap
1251         while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1252                 chunk = (u32*)((uptr)chunk + csize + 4);
1253
1254                         // catch out of memory
1255                         if(chunk >= heap_end) {
1256                                 printf("malloc %x,%x: Out of memory error!\n",
1257                                         v0, a0);
1258                                 v0 = 0; pc0 = ra;
1259                                 return;
1260                         }
1261
1262                 csize = ((u32)*chunk) & 0xfffffffc;
1263                 cstat = ((u32)*chunk) & 1;
1264         }
1265
1266         // allocate memory
1267         if(dsize == csize) {
1268                 // chunk has same size
1269                 *chunk &= 0xfffffffc;
1270         } else if (dsize > csize) {
1271                 v0 = 0; pc0 = ra;
1272                 return;
1273         } else {
1274                 // split free chunk
1275                 *chunk = SWAP32(dsize);
1276                 newchunk = (u32*)((uptr)chunk + dsize + 4);
1277                 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1278         }
1279
1280         // return pointer to allocated memory
1281         v0 = ((uptr)chunk - (uptr)psxM) + 4;
1282         v0|= 0x80000000;
1283         //printf ("malloc %x,%x\n", v0, a0);
1284         pc0 = ra;
1285 }
1286
1287 static void psxBios_free() { // 0x34
1288         PSXBIOS_LOG("psxBios_%s %x (%x bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1289         storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1290         mips_return_void_c(5);
1291 }
1292
1293 static void psxBios_calloc() { // 0x37
1294         u32 ret, size;
1295         PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
1296
1297         a0 = size = a0 * a1;
1298         psxBios_malloc();
1299         ret = v0;
1300         if (ret) {
1301                 a0 = ret; a1 = size;
1302                 psxBios_bzero();
1303         }
1304         mips_return_c(ret, 21);
1305 }
1306
1307 void psxBios_realloc() { // 0x38
1308         u32 block = a0;
1309         u32 size = a1;
1310 #ifdef PSXBIOS_LOG
1311         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1312 #endif
1313
1314         a0 = block;
1315         /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1316         if (block == 0)
1317         {
1318                 psxBios_malloc();
1319         }
1320         /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1321         else if (size == 0)
1322         {
1323                 psxBios_free();
1324         }
1325         /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1326         /* Note that it is not quite implemented this way here. */
1327         else
1328         {
1329                 psxBios_free();
1330                 a0 = size;
1331                 psxBios_malloc();
1332         }
1333 }
1334
1335
1336 /* InitHeap(void *block , int n) */
1337 static void psxBios_InitHeap() { // 0x39
1338         PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
1339
1340         storeRam32(A_HEAP_BASE, a0);
1341         storeRam32(A_HEAP_SIZE, a1);
1342         storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
1343         storeRam32(A_HEAP_FLAG, 0);
1344         storeRam32(a0, 0);
1345
1346         mips_return_void_c(14);
1347 }
1348
1349 void psxBios_getchar() { //0x3b
1350         v0 = getchar(); pc0 = ra;
1351 }
1352
1353 static void psxBios_printf_psxout() { // 0x3f
1354         char tmp[1024];
1355         char tmp2[1024];
1356         u32 save[4];
1357         char *ptmp = tmp;
1358         int n=1, i=0, j;
1359         void *psp;
1360
1361         psp = PSXM(sp);
1362         if (psp != INVALID_PTR) {
1363                 memcpy(save, psp, 4 * 4);
1364                 psxMu32ref(sp) = SWAP32((u32)a0);
1365                 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1366                 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1367                 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1368         }
1369
1370         while (Ra0[i]) {
1371                 switch (Ra0[i]) {
1372                         case '%':
1373                                 j = 0;
1374                                 tmp2[j++] = '%';
1375 _start:
1376                                 switch (Ra0[++i]) {
1377                                         case '.':
1378                                         case 'l':
1379                                                 tmp2[j++] = Ra0[i]; goto _start;
1380                                         default:
1381                                                 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1382                                                         tmp2[j++] = Ra0[i];
1383                                                         goto _start;
1384                                                 }
1385                                                 break;
1386                                 }
1387                                 tmp2[j++] = Ra0[i];
1388                                 tmp2[j] = 0;
1389
1390                                 switch (Ra0[i]) {
1391                                         case 'f': case 'F':
1392                                                 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1393                                         case 'a': case 'A':
1394                                         case 'e': case 'E':
1395                                         case 'g': case 'G':
1396                                                 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1397                                         case 'p':
1398                                         case 'i': case 'u':
1399                                         case 'd': case 'D':
1400                                         case 'o': case 'O':
1401                                         case 'x': case 'X':
1402                                                 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1403                                         case 'c':
1404                                                 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1405                                         case 's':
1406                                                 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1407                                         case '%':
1408                                                 *ptmp++ = Ra0[i]; break;
1409                                 }
1410                                 i++;
1411                                 break;
1412                         default:
1413                                 *ptmp++ = Ra0[i++];
1414                 }
1415         }
1416         *ptmp = 0;
1417
1418         if (psp != INVALID_PTR)
1419                 memcpy(psp, save, 4 * 4);
1420
1421         if (Config.PsxOut)
1422                 SysPrintf("%s", tmp);
1423 }
1424
1425 void psxBios_printf() { // 0x3f
1426         psxBios_printf_psxout();
1427         pc0 = ra;
1428 }
1429
1430 void psxBios_format() { // 0x41
1431         if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1432         {
1433                 CreateMcd(Config.Mcd1);
1434                 LoadMcd(1, Config.Mcd1);
1435                 v0 = 1;
1436         }
1437         else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1438         {
1439                 CreateMcd(Config.Mcd2);
1440                 LoadMcd(2, Config.Mcd2);
1441                 v0 = 1;
1442         }
1443         else
1444         {
1445                 v0 = 0;
1446         }
1447         pc0 = ra;
1448 }
1449
1450 static void psxBios_SystemErrorUnresolvedException() {
1451         if (loadRam32(0xfffc) != 0x12345678) { // prevent log flood
1452                 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1453                 storeRam32(0xfffc, 0x12345678);
1454         }
1455         mips_return_void_c(1000);
1456 }
1457
1458 /*
1459  *      long Load(char *name, struct EXEC *header);
1460  */
1461
1462 void psxBios_Load() { // 0x42
1463         EXE_HEADER eheader;
1464         void *pa1;
1465
1466         pa1 = Ra1;
1467         if (pa1 != INVALID_PTR && LoadCdromFile(Ra0, &eheader) == 0) {
1468                 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1469                 psxCpu->Clear(a1, sizeof(EXEC) / 4);
1470                 v0 = 1;
1471         } else v0 = 0;
1472         PSXBIOS_LOG("psxBios_%s: %s, %d -> %d\n", biosA0n[0x42], Ra0, a1, v0);
1473
1474         pc0 = ra;
1475 }
1476
1477 /*
1478  *      int Exec(struct EXEC *header , int argc , char **argv);
1479  */
1480
1481 void psxBios_Exec() { // 43
1482         EXEC *header = (EXEC *)castRam32ptr(a0);
1483         u32 ptr;
1484         s32 len;
1485
1486         PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1487
1488         header->_sp = SWAP32(sp);
1489         header->_fp = SWAP32(fp);
1490         header->_sp = SWAP32(sp);
1491         header->_gp = SWAP32(gp);
1492         header->ret = SWAP32(ra);
1493         header->base = SWAP32(s0);
1494
1495         ptr = SWAP32(header->b_addr);
1496         len = SWAP32(header->b_size);
1497         if (len != 0) do {
1498                 storeRam32(ptr, 0);
1499                 len -= 4; ptr += 4;
1500         } while (len > 0);
1501
1502         if (header->S_addr != 0)
1503                 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1504
1505         gp = SWAP32(header->gp0);
1506
1507         s0 = a0;
1508
1509         a0 = a1;
1510         a1 = a2;
1511
1512         ra = 0x8000;
1513         pc0 = SWAP32(header->_pc0);
1514 }
1515
1516 void psxBios_FlushCache() { // 44
1517 #ifdef PSXBIOS_LOG
1518         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1519 #endif
1520         psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1521         psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1522         pc0 = ra;
1523 }
1524
1525 void psxBios_GPU_dw() { // 0x46
1526         int size;
1527         u32 *ptr;
1528
1529 #ifdef PSXBIOS_LOG
1530         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1531 #endif
1532
1533         GPU_writeData(0xa0000000);
1534         GPU_writeData((a1<<0x10)|(a0&0xffff));
1535         GPU_writeData((a3<<0x10)|(a2&0xffff));
1536         size = (a2*a3)/2;
1537         ptr = (u32*)PSXM(Rsp[4]);  //that is correct?
1538         while(size--)
1539         {
1540                 GPU_writeData(SWAPu32(*ptr++));
1541         } 
1542
1543         pc0 = ra;
1544 }
1545
1546 void psxBios_mem2vram() { // 0x47
1547         int size;
1548         gpuSyncPluginSR();
1549         GPU_writeData(0xa0000000);
1550         GPU_writeData((a1<<0x10)|(a0&0xffff));
1551         GPU_writeData((a3<<0x10)|(a2&0xffff));
1552         size = ((((a2 * a3) / 2) >> 4) << 16);
1553         GPU_writeStatus(0x04000002);
1554         psxHwWrite32(0x1f8010f4,0);
1555         psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1556         psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1557         psxHwWrite32(0x1f8010a4, size | 0x10);
1558         psxHwWrite32(0x1f8010a8,0x01000201);
1559
1560         pc0 = ra;
1561 }
1562
1563 void psxBios_SendGPU() { // 0x48
1564         GPU_writeStatus(a0);
1565         gpuSyncPluginSR();
1566         pc0 = ra;
1567 }
1568
1569 void psxBios_GPU_cw() { // 0x49
1570         gpuSyncPluginSR();
1571         GPU_writeData(a0);
1572         v0 = HW_GPU_STATUS;
1573         pc0 = ra;
1574 }
1575
1576 void psxBios_GPU_cwb() { // 0x4a
1577         u32 *ptr = (u32*)Ra0;
1578         int size = a1;
1579         gpuSyncPluginSR();
1580         while(size--)
1581         {
1582                 GPU_writeData(SWAPu32(*ptr++));
1583         }
1584
1585         pc0 = ra;
1586 }
1587    
1588 void psxBios_GPU_SendPackets() { //4b:  
1589         gpuSyncPluginSR();
1590         GPU_writeStatus(0x04000002);
1591         psxHwWrite32(0x1f8010f4,0);
1592         psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1593         psxHwWrite32(0x1f8010a0,a0);
1594         psxHwWrite32(0x1f8010a4,0);
1595         psxHwWrite32(0x1f8010a8,0x010000401);
1596         pc0 = ra;
1597 }
1598
1599 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1600         psxHwWrite32(0x1f8010a8,0x00000401);
1601         GPU_writeData(0x0400000);
1602         GPU_writeData(0x0200000);
1603         GPU_writeData(0x0100000);
1604         v0 = 0x1f801814;
1605         pc0 = ra;
1606 }
1607
1608 void psxBios_GPU_GetGPUStatus() { // 0x4d
1609         v0 = GPU_readStatus();
1610         pc0 = ra;
1611 }
1612
1613 #undef s_addr
1614
1615 void psxBios_LoadExec() { // 51
1616         EXEC *header = (EXEC*)PSXM(0xf000);
1617         u32 s_addr, s_size;
1618
1619 #ifdef PSXBIOS_LOG
1620         PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1621 #endif
1622         s_addr = a1; s_size = a2;
1623
1624         a1 = 0xf000;
1625         psxBios_Load();
1626
1627         header->S_addr = s_addr;
1628         header->s_size = s_size;
1629
1630         a0 = 0xf000; a1 = 0; a2 = 0;
1631         psxBios_Exec();
1632 }
1633
1634 void psxBios__bu_init() { // 70
1635 #ifdef PSXBIOS_LOG
1636         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1637 #endif
1638
1639         DeliverEvent(0xf0000011, 0x0004);
1640         DeliverEvent(0xf4000001, 0x0004);
1641
1642         pc0 = ra;
1643 }
1644
1645 void psxBios__96_init() { // 71
1646 #ifdef PSXBIOS_LOG
1647         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1648 #endif
1649
1650         pc0 = ra;
1651 }
1652
1653 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1654 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1655 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1656
1657 static void psxBios_DequeueCdIntr_() {
1658         psxBios_SysDeqIntRP_(0, 0x91d0);
1659         psxBios_SysDeqIntRP_(0, 0x91e0);
1660         use_cycles(16);
1661 }
1662
1663 static void psxBios_DequeueCdIntr() { // a3
1664         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1665         psxBios_DequeueCdIntr_();
1666 }
1667
1668 static void psxBios_CdRemove() { // 56, 72
1669         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1670
1671         CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1672         CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1673         CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1674         CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1675         CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1676         psxBios_DequeueCdIntr_();
1677
1678         // EnterCriticalSection - should be done at the beginning,
1679         // but this way is much easier to implement
1680         a0 = 1;
1681         pc0 = A_SYSCALL;
1682         use_cycles(30);
1683 }
1684
1685 void psxBios_SetMem() { // 9f
1686         u32 new = psxHu32(0x1060);
1687
1688 #ifdef PSXBIOS_LOG
1689         PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1690 #endif
1691
1692         switch(a0) {
1693                 case 2:
1694                         psxHu32ref(0x1060) = SWAP32(new);
1695                         psxMu32ref(0x060) = a0;
1696                         PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1697                         break;
1698
1699                 case 8:
1700                         psxHu32ref(0x1060) = SWAP32(new | 0x300);
1701                         psxMu32ref(0x060) = a0;
1702                         PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1703
1704                 default:
1705                         PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
1706                 break;
1707         }
1708
1709         pc0 = ra;
1710 }
1711
1712 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1713 static void psxBios_get_cd_status() // a6
1714 {
1715         PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
1716         v0 = 1;
1717         pc0 = ra;
1718 }
1719
1720 static void psxBios__card_info() { // ab
1721         PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1722         u32 ret, port;
1723         storeRam32(A_CARD_CHAN1, a0);
1724         port = a0 >> 4;
1725
1726         switch (port) {
1727         case 0x0:
1728         case 0x1:
1729                 ret = 0x0004;
1730                 if (McdDisable[port & 1])
1731                         ret = 0x0100;
1732                 break;
1733         default:
1734                 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
1735                 ret = 0x0302;
1736                 break;
1737         }
1738
1739         if (McdDisable[0] && McdDisable[1])
1740                 ret = 0x0100;
1741
1742         DeliverEvent(0xf0000011, 0x0004);
1743 //      DeliverEvent(0xf4000001, 0x0004);
1744         DeliverEvent(0xf4000001, ret);
1745         v0 = 1; pc0 = ra;
1746 }
1747
1748 void psxBios__card_load() { // ac
1749 #ifdef PSXBIOS_LOG
1750         PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1751 #endif
1752
1753         storeRam32(A_CARD_CHAN1, a0);
1754
1755 //      DeliverEvent(0xf0000011, 0x0004);
1756         DeliverEvent(0xf4000001, 0x0004);
1757
1758         v0 = 1; pc0 = ra;
1759 }
1760
1761 static void psxBios_GetSystemInfo() { // b4
1762         u32 ret = 0;
1763         //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
1764         SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
1765         switch (a0) {
1766         case 0:
1767         case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
1768         case 2: ret = 0xbfc0012c; break;
1769         case 5: ret = loadRam32(0x60) << 10; break;
1770         }
1771         mips_return_c(ret, 20);
1772 }
1773
1774 /* System calls B0 */
1775
1776 static u32 psxBios_SysMalloc_(u32 size);
1777
1778 static void psxBios_SysMalloc() { // B 00
1779         u32 ret = psxBios_SysMalloc_(a0);
1780
1781         PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1782         mips_return_c(ret, 33);
1783 }
1784
1785 void psxBios_SetRCnt() { // 02
1786 #ifdef PSXBIOS_LOG
1787         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1788 #endif
1789
1790         a0&= 0x3;
1791         if (a0 != 3) {
1792                 u32 mode=0;
1793
1794                 psxRcntWtarget(a0, a1);
1795                 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1796                 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1797                 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1798                 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1799                 else         { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1800
1801                 psxRcntWmode(a0, mode);
1802         }
1803         pc0 = ra;
1804 }
1805
1806 void psxBios_GetRCnt() { // 03
1807 #ifdef PSXBIOS_LOG
1808         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1809 #endif
1810
1811         a0&= 0x3;
1812         if (a0 != 3) v0 = psxRcntRcount(a0);
1813         else v0 = 0;
1814         pc0 = ra;
1815 }
1816
1817 void psxBios_StartRCnt() { // 04
1818 #ifdef PSXBIOS_LOG
1819         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1820 #endif
1821
1822         a0&= 0x3;
1823         if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1824         else psxHu32ref(0x1074)|= SWAPu32(0x1);
1825         v0 = 1; pc0 = ra;
1826 }
1827
1828 void psxBios_StopRCnt() { // 05
1829 #ifdef PSXBIOS_LOG
1830         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1831 #endif
1832
1833         a0&= 0x3;
1834         if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1835         else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1836         pc0 = ra;
1837 }
1838
1839 void psxBios_ResetRCnt() { // 06
1840 #ifdef PSXBIOS_LOG
1841         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1842 #endif
1843
1844         a0&= 0x3;
1845         if (a0 != 3) {
1846                 psxRcntWmode(a0, 0);
1847                 psxRcntWtarget(a0, 0);
1848                 psxRcntWcount(a0, 0);
1849         }
1850         pc0 = ra;
1851 }
1852
1853 static u32 DeliverEvent(u32 class, u32 spec) {
1854         EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1855         u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1856         u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1857         u32 i, lim = evcb_len / 0x1c;
1858
1859         for (i = 0; i < lim; i++, ev++) {
1860                 use_cycles(8);
1861                 if (SWAP32(ev->status) != EvStACTIVE)
1862                         continue;
1863                 use_cycles(4);
1864                 if (SWAP32(ev->class) != class)
1865                         continue;
1866                 use_cycles(4);
1867                 if (SWAP32(ev->spec) != spec)
1868                         continue;
1869                 use_cycles(6);
1870                 ret = SWAP32(ev->mode);
1871                 if (ret == EvMdMARK) {
1872                         ev->status = SWAP32(EvStALREADY);
1873                         continue;
1874                 }
1875                 use_cycles(8);
1876                 if (ret == EvMdCALL) {
1877                         ret = SWAP32(ev->fhandler);
1878                         if (ret) {
1879                                 v0 = ret;
1880                                 softCall(ret);
1881                                 ret = v0;
1882                         }
1883                 }
1884         }
1885         use_cycles(29);
1886         return ret;
1887 }
1888
1889 static u32 UnDeliverEvent(u32 class, u32 spec) {
1890         EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1891         u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1892         u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1893         u32 i, lim = evcb_len / 0x1c;
1894
1895         for (i = 0; i < lim; i++, ev++) {
1896                 use_cycles(8);
1897                 if (SWAP32(ev->status) != EvStALREADY)
1898                         continue;
1899                 use_cycles(4);
1900                 if (SWAP32(ev->class) != class)
1901                         continue;
1902                 use_cycles(4);
1903                 if (SWAP32(ev->spec) != spec)
1904                         continue;
1905                 use_cycles(6);
1906                 if (SWAP32(ev->mode) == EvMdMARK)
1907                         ev->status = SWAP32(EvStACTIVE);
1908         }
1909         use_cycles(28);
1910         return ret;
1911 }
1912
1913 static void psxBios_DeliverEvent() { // 07
1914         u32 ret;
1915         PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
1916
1917         ret = DeliverEvent(a0, a1);
1918         mips_return(ret);
1919 }
1920
1921 static s32 get_free_EvCB_slot() {
1922         EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1923         u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
1924
1925         use_cycles(19);
1926         for (i = 0; i < lim; i++, ev++) {
1927                 use_cycles(8);
1928                 if (ev->status == SWAP32(EvStUNUSED))
1929                         return i;
1930         }
1931         return -1;
1932 }
1933
1934 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
1935         u32 ret = get_free_EvCB_slot();
1936         if ((s32)ret >= 0) {
1937                 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
1938                 ev->class = SWAP32(class);
1939                 ev->status = SWAP32(EvStDISABLED);
1940                 ev->spec = SWAP32(spec);
1941                 ev->mode = SWAP32(mode);
1942                 ev->fhandler = SWAP32(func);
1943                 ret |= 0xf1000000u;
1944         }
1945         return ret;
1946 }
1947
1948 static void psxBios_OpenEvent() { // 08
1949         u32 ret = OpenEvent(a0, a1, a2, a3);
1950         PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
1951                 biosB0n[0x08], a0, a1, a2, a3, ret);
1952         mips_return_c(ret, 36);
1953 }
1954
1955 static void CloseEvent(u32 ev)
1956 {
1957         u32 base = loadRam32(A_TT_EvCB);
1958         storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
1959 }
1960
1961 static void psxBios_CloseEvent() { // 09
1962         PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
1963                 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
1964         CloseEvent(a0);
1965         mips_return_c(1, 10);
1966 }
1967
1968 static void psxBios_WaitEvent() { // 0a
1969         u32 base = loadRam32(A_TT_EvCB);
1970         u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1971         PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
1972
1973         use_cycles(15);
1974         if (status == EvStALREADY) {
1975                 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
1976                 mips_return(1);
1977                 return;
1978         }
1979         if (status != EvStACTIVE)
1980         {
1981                 mips_return_c(0, 2);
1982                 return;
1983         }
1984
1985         // retrigger this hlecall after the next emulation event
1986         pc0 -= 4;
1987         if ((s32)(next_interupt - psxRegs.cycle) > 0)
1988                 psxRegs.cycle = next_interupt;
1989         psxBranchTest();
1990 }
1991
1992 static void psxBios_TestEvent() { // 0b
1993         u32 base = loadRam32(A_TT_EvCB);
1994         u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1995         u32 ret = 0;
1996         PSXBIOS_LOG("psxBios_%s    %x %x\n", biosB0n[0x0b], a0, status);
1997         if (status == EvStALREADY) {
1998                 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
1999                 ret = 1;
2000         }
2001
2002         mips_return_c(ret, 15);
2003 }
2004
2005 static void psxBios_EnableEvent() { // 0c
2006         u32 base = loadRam32(A_TT_EvCB);
2007         u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2008         PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
2009         if (status != EvStUNUSED)
2010                 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2011
2012         mips_return_c(1, 15);
2013 }
2014
2015 static void psxBios_DisableEvent() { // 0d
2016         u32 base = loadRam32(A_TT_EvCB);
2017         u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2018         PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2019         if (status != EvStUNUSED)
2020                 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2021
2022         mips_return_c(1, 15);
2023 }
2024
2025 /*
2026  *      long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2027  */
2028
2029 void psxBios_OpenTh() { // 0e
2030         TCB *tcb = loadRam32ptr(A_TT_TCB);
2031         u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2032         int th;
2033
2034         for (th = 1; th < limit; th++)
2035         {
2036                 if (tcb[th].status != SWAP32(0x4000)) break;
2037
2038         }
2039         if (th == limit) {
2040                 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2041                 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2042 #ifdef PSXBIOS_LOG
2043                 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2044 #endif
2045                 mips_return_c(0xffffffff, 20);
2046                 return;
2047         }
2048         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
2049
2050         tcb[th].status  = SWAP32(0x4000);
2051         tcb[th].mode    = SWAP32(0x1000);
2052         tcb[th].epc     = SWAP32(a0);
2053         tcb[th].reg[30] = SWAP32(a1); // fp
2054         tcb[th].reg[29] = SWAP32(a1); // sp
2055         tcb[th].reg[28] = SWAP32(a2); // gp
2056
2057         mips_return_c(0xff000000 + th, 34);
2058 }
2059
2060 /*
2061  *      int CloseTh(long thread);
2062  */
2063
2064 void psxBios_CloseTh() { // 0f
2065         TCB *tcb = loadRam32ptr(A_TT_TCB);
2066         u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2067         u32 th = a0 & 0xff;
2068
2069 #ifdef PSXBIOS_LOG
2070         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
2071 #endif
2072         /* The return value is always 1 (even if the handle was already closed). */
2073         v0 = 1;
2074         if (th < limit && tcb[th].status == SWAP32(0x4000)) {
2075                 tcb[th].status = SWAP32(0x1000);
2076         }
2077
2078         pc0 = ra;
2079 }
2080
2081 /*
2082  *      int ChangeTh(long thread);
2083  */
2084
2085 void psxBios_ChangeTh() { // 10
2086         u32 tcbBase = loadRam32(A_TT_TCB);
2087         u32 th = a0 & 0xffff;
2088
2089         // this is quite spammy
2090         //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2091
2092         // without doing any argument checks, just issue a syscall
2093         // (like the real bios does)
2094         a0 = 3;
2095         a1 = tcbBase + th * sizeof(TCB);
2096         pc0 = A_SYSCALL;
2097         use_cycles(15);
2098 }
2099
2100 void psxBios_InitPAD() { // 0x12
2101         u32 i, *ram32 = (u32 *)psxM;
2102         PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2103
2104         // printf("%s", "PS-X Control PAD Driver  Ver 3.0");
2105         ram32[A_PAD_DR_DST/4] = 0;
2106         ram32[A_PAD_OUTBUF/4 + 0] = 0;
2107         ram32[A_PAD_OUTBUF/4 + 1] = 0;
2108         ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2109         ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2110         ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2111         ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2112         ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2113         ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2114
2115         for (i = 0; i < a1; i++) {
2116                 use_cycles(4);
2117                 storeRam8(a0 + i, 0);
2118         }
2119         for (i = 0; i < a3; i++) {
2120                 use_cycles(4);
2121                 storeRam8(a2 + i, 0);
2122         }
2123         write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2124
2125         ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2126
2127         mips_return_c(1, 200);
2128 }
2129
2130 void psxBios_StartPAD() { // 13
2131         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2132
2133         psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2134         psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2135         psxHwWrite16(0x1f801070, ~1);
2136         psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2137         storeRam32(A_PAD_ACK_VBL, 1);
2138         storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2139         psxRegs.CP0.n.SR |= 0x401;
2140
2141         mips_return_c(1, 300);
2142 }
2143
2144 void psxBios_StopPAD() { // 14
2145         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2146         storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2147         psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2148         psxRegs.CP0.n.SR |= 0x401;
2149         mips_return_void_c(200);
2150 }
2151
2152 static void psxBios_PAD_init() { // 15
2153         u32 ret = 0;
2154         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2155         if (a0 == 0x20000000 || a0 == 0x20000001)
2156         {
2157                 u32 dst = a1;
2158                 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2159                 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2160                 psxBios_InitPAD();
2161                 psxBios_StartPAD();
2162                 storeRam32(A_PAD_DR_DST, dst);
2163                 ret = 2;
2164         }
2165         mips_return_c(ret, 100);
2166 }
2167
2168 static u32 psxBios_PAD_dr_() {
2169         u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2170         u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2171         u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2172         dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2173         if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2174         {
2175                 dst[0] = buf1[3], dst[1] = buf1[2];
2176                 if (buf1[1] == 0x23) {
2177                         dst[0] |= 0xc7, dst[1] |= 7;
2178                         if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2179                         if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2180                 }
2181         }
2182         if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2183         {
2184                 dst[2] = buf2[3], dst[3] = buf2[2];
2185                 if (buf2[1] == 0x23) {
2186                         dst[2] |= 0xc7, dst[3] |= 7;
2187                         if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2188                         if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2189                 }
2190         }
2191         use_cycles(55);
2192         return SWAP32(*(u32 *)dst);
2193 }
2194
2195 static void psxBios_PAD_dr() { // 16
2196         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2197         u32 ret = psxBios_PAD_dr_();
2198         mips_return(ret);
2199 }
2200
2201 static void psxBios_ReturnFromException() { // 17
2202         u32 tcbPtr = loadRam32(A_TT_PCB);
2203         const TCB *tcb = loadRam32ptr(tcbPtr);
2204         u32 sr;
2205         int i;
2206
2207         for (i = 1; i < 32; i++)
2208                 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2209         psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2210         psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2211         sr = SWAP32(tcb->sr);
2212
2213         //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2214         pc0 = k0 = SWAP32(tcb->epc);
2215
2216         // the interpreter wants to know about sr changes, so do a MTC0
2217         sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2218         MTC0(&psxRegs, 12, sr);
2219
2220         use_cycles(53);
2221         psxBranchTest();
2222 }
2223
2224 void psxBios_ResetEntryInt() { // 18
2225         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2226
2227         storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2228         mips_return_void_c(5);
2229 }
2230
2231 void psxBios_HookEntryInt() { // 19
2232         PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2233
2234         storeRam32(A_EEXIT_PTR, a0);
2235         mips_return_void_c(3);
2236 }
2237
2238 static void psxBios_UnDeliverEvent() { // 0x20
2239         u32 ret;
2240         PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2241
2242         ret = UnDeliverEvent(a0, a1);
2243         mips_return(ret);
2244 }
2245
2246 static void buopen(int mcd, char *ptr, char *cfg)
2247 {
2248         int i;
2249         char *mcd_data = ptr;
2250
2251         strcpy(FDesc[1 + mcd].name, Ra0+5);
2252         FDesc[1 + mcd].offset = 0;
2253         FDesc[1 + mcd].mode   = a1;
2254
2255         for (i=1; i<16; i++) {
2256                 const char *fptr = mcd_data + 128 * i;
2257                 if ((*fptr & 0xF0) != 0x50) continue;
2258                 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2259                 FDesc[1 + mcd].mcfile = i;
2260                 PSXBIOS_LOG("open %s\n", fptr+0xa);
2261                 v0 = 1 + mcd;
2262                 break;
2263         }
2264         if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2265                 for (i=1; i<16; i++) {
2266                         int j, xor, nblk = a1 >> 16;
2267                         char *pptr, *fptr2;
2268                         char *fptr = mcd_data + 128 * i;
2269
2270                         if ((*fptr & 0xF0) != 0xa0) continue;
2271
2272                         FDesc[1 + mcd].mcfile = i;
2273                         fptr[0] = 0x51;
2274                         fptr[4] = 0x00;
2275                         fptr[5] = 0x20 * nblk;
2276                         fptr[6] = 0x00;
2277                         fptr[7] = 0x00;
2278                         strcpy(fptr+0xa, FDesc[1 + mcd].name);
2279                         pptr = fptr2 = fptr;
2280                         for(j=2; j<=nblk; j++) {
2281                                 int k;
2282                                 for(i++; i<16; i++) {
2283                                         fptr2 += 128;
2284
2285                                         memset(fptr2, 0, 128);
2286                                         fptr2[0] = j < nblk ? 0x52 : 0x53;
2287                                         pptr[8] = i - 1;
2288                                         pptr[9] = 0;
2289                                         for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2290                                         pptr[127] = xor;
2291                                         pptr = fptr2;
2292                                         break;
2293                                 }
2294                                 /* shouldn't this return ENOSPC if i == 16? */
2295                         }
2296                         pptr[8] = pptr[9] = 0xff;
2297                         for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2298                         pptr[127] = xor;
2299                         PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2300                         v0 = 1 + mcd;
2301                         /* just go ahead and resave them all */
2302                         SaveMcd(cfg, ptr, 128, 128 * 15);
2303                         break;
2304                 }
2305                 /* shouldn't this return ENOSPC if i == 16? */
2306         }
2307 }
2308
2309 /*
2310  *      int open(char *name , int mode);
2311  */
2312
2313 void psxBios_open() { // 0x32
2314         void *pa0 = Ra0;
2315
2316 #ifdef PSXBIOS_LOG
2317         PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2318 #endif
2319
2320         v0 = -1;
2321
2322         if (pa0 != INVALID_PTR) {
2323                 if (!strncmp(pa0, "bu00", 4)) {
2324                         buopen(1, Mcd1Data, Config.Mcd1);
2325                 }
2326
2327                 if (!strncmp(pa0, "bu10", 4)) {
2328                         buopen(2, Mcd2Data, Config.Mcd2);
2329                 }
2330         }
2331
2332         pc0 = ra;
2333 }
2334
2335 /*
2336  *      int lseek(int fd , int offset , int whence);
2337  */
2338
2339 void psxBios_lseek() { // 0x33
2340 #ifdef PSXBIOS_LOG
2341         PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2342 #endif
2343
2344         switch (a2) {
2345                 case 0: // SEEK_SET
2346                         FDesc[a0].offset = a1;
2347                         v0 = a1;
2348 //                      DeliverEvent(0xf0000011, 0x0004);
2349 //                      DeliverEvent(0xf4000001, 0x0004);
2350                         break;
2351
2352                 case 1: // SEEK_CUR
2353                         FDesc[a0].offset+= a1;
2354                         v0 = FDesc[a0].offset;
2355                         break;
2356         }
2357
2358         pc0 = ra;
2359 }
2360
2361
2362 /*
2363  *      int read(int fd , void *buf , int nbytes);
2364  */
2365
2366 void psxBios_read() { // 0x34
2367         char *ptr;
2368         void *pa1 = Ra1;
2369
2370 #ifdef PSXBIOS_LOG
2371         PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2372 #endif
2373
2374         v0 = -1;
2375
2376         if (pa1 != INVALID_PTR) {
2377                 switch (a0) {
2378                         case 2: buread(pa1, 1, a2); break;
2379                         case 3: buread(pa1, 2, a2); break;
2380                 }
2381         }
2382
2383         pc0 = ra;
2384 }
2385
2386 /*
2387  *      int write(int fd , void *buf , int nbytes);
2388  */
2389
2390 void psxBios_write() { // 0x35/0x03
2391         char *ptr;
2392         void *pa1 = Ra1;
2393
2394         if (a0 != 1) // stdout
2395                 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2396
2397         v0 = -1;
2398         if (pa1 == INVALID_PTR) {
2399                 pc0 = ra;
2400                 return;
2401         }
2402
2403         if (a0 == 1) { // stdout
2404                 char *ptr = pa1;
2405
2406                 v0 = a2;
2407                 if (Config.PsxOut) while (a2 > 0) {
2408                         SysPrintf("%c", *ptr++); a2--;
2409                 }
2410                 pc0 = ra; return;
2411         }
2412
2413         switch (a0) {
2414                 case 2: buwrite(pa1, 1, a2); break;
2415                 case 3: buwrite(pa1, 2, a2); break;
2416         }
2417
2418         pc0 = ra;
2419 }
2420
2421 static void psxBios_write_psxout() {
2422         if (a0 == 1) { // stdout
2423                 const char *ptr = Ra1;
2424                 int len = a2;
2425
2426                 if (ptr != INVALID_PTR)
2427                         while (len-- > 0)
2428                                 SysPrintf("%c", *ptr++);
2429         }
2430 }
2431
2432 static void psxBios_putchar_psxout() { // 3d
2433         SysPrintf("%c", (char)a0);
2434 }
2435
2436 static void psxBios_puts_psxout() { // 3e/3f
2437         SysPrintf("%s", Ra0);
2438 }
2439
2440 /*
2441  *      int close(int fd);
2442  */
2443
2444 void psxBios_close() { // 0x36
2445 #ifdef PSXBIOS_LOG
2446         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2447 #endif
2448
2449         v0 = a0;
2450         pc0 = ra;
2451 }
2452
2453 void psxBios_putchar() { // 3d
2454         if (Config.PsxOut) SysPrintf("%c", (char)a0);
2455         pc0 = ra;
2456 }
2457
2458 void psxBios_puts() { // 3e/3f
2459         if (Config.PsxOut) SysPrintf("%s", Ra0);
2460         pc0 = ra;
2461 }
2462
2463
2464 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2465  * We want to mimic the PSX's behaviour in this case for bufile. */
2466 static size_t strlen_internal(char* p)
2467 {
2468         size_t size_of_array = 0;
2469         while (*p++) size_of_array++;
2470         return size_of_array;
2471 }
2472
2473 #define bufile(mcd) { \
2474         size_t size_of_name = strlen_internal(dir->name); \
2475         while (nfile < 16) { \
2476                 int match=1; \
2477  \
2478                 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2479                 nfile++; \
2480                 if ((*ptr & 0xF0) != 0x50) continue; \
2481                 /* Bug link files show up as free block. */ \
2482                 if (!ptr[0xa]) continue; \
2483                 ptr+= 0xa; \
2484                 if (pfile[0] == 0) { \
2485                         strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2486                         if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2487                 } else for (i=0; i<20; i++) { \
2488                         if (pfile[i] == ptr[i]) { \
2489                                                                 dir->name[i] = ptr[i]; continue; } \
2490                         if (pfile[i] == '?') { \
2491                                 dir->name[i] = ptr[i]; continue; } \
2492                         if (pfile[i] == '*') { \
2493                                 strcpy(dir->name+i, ptr+i); break; } \
2494                         match = 0; break; \
2495                 } \
2496                 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2497                 if (match == 0) { continue; } \
2498                 dir->size = 8192; \
2499                 v0 = _dir; \
2500                 break; \
2501         } \
2502 }
2503
2504 /*
2505  *      struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2506  */
2507
2508 void psxBios_firstfile() { // 42
2509         struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2510         void *pa0 = Ra0;
2511         u32 _dir = a1;
2512         char *ptr;
2513         int i;
2514
2515 #ifdef PSXBIOS_LOG
2516         PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2517 #endif
2518
2519         v0 = 0;
2520
2521         if (pa0 != INVALID_PTR) {
2522                 strcpy(ffile, pa0);
2523                 pfile = ffile+5;
2524                 nfile = 0;
2525                 if (!strncmp(pa0, "bu00", 4)) {
2526                         // firstfile() calls _card_read() internally, so deliver it's event
2527                         DeliverEvent(0xf0000011, 0x0004);
2528                         bufile(1);
2529                 } else if (!strncmp(pa0, "bu10", 4)) {
2530                         // firstfile() calls _card_read() internally, so deliver it's event
2531                         DeliverEvent(0xf0000011, 0x0004);
2532                         bufile(2);
2533                 }
2534         }
2535
2536         pc0 = ra;
2537 }
2538
2539 /*
2540  *      struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2541  */
2542
2543 void psxBios_nextfile() { // 43
2544         struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2545         u32 _dir = a0;
2546         char *ptr;
2547         int i;
2548
2549 #ifdef PSXBIOS_LOG
2550         PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2551 #endif
2552
2553         v0 = 0;
2554
2555         if (!strncmp(ffile, "bu00", 4)) {
2556                 bufile(1);
2557         }
2558
2559         if (!strncmp(ffile, "bu10", 4)) {
2560                 bufile(2);
2561         }
2562
2563         pc0 = ra;
2564 }
2565
2566 #define burename(mcd) { \
2567         for (i=1; i<16; i++) { \
2568                 int namelen, j, xor = 0; \
2569                 ptr = Mcd##mcd##Data + 128 * i; \
2570                 if ((*ptr & 0xF0) != 0x50) continue; \
2571                 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2572                 namelen = strlen(Ra1+5); \
2573                 memcpy(ptr+0xa, Ra1+5, namelen); \
2574                 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2575                 for (j=0; j<127; j++) xor^= ptr[j]; \
2576                 ptr[127] = xor; \
2577                 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2578                 v0 = 1; \
2579                 break; \
2580         } \
2581 }
2582
2583 /*
2584  *      int rename(char *old, char *new);
2585  */
2586
2587 void psxBios_rename() { // 44
2588         void *pa0 = Ra0;
2589         void *pa1 = Ra1;
2590         char *ptr;
2591         int i;
2592
2593 #ifdef PSXBIOS_LOG
2594         PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2595 #endif
2596
2597         v0 = 0;
2598
2599         if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2600                 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2601                         burename(1);
2602                 }
2603
2604                 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2605                         burename(2);
2606                 }
2607         }
2608
2609         pc0 = ra;
2610 }
2611
2612
2613 #define budelete(mcd) { \
2614         for (i=1; i<16; i++) { \
2615                 ptr = Mcd##mcd##Data + 128 * i; \
2616                 if ((*ptr & 0xF0) != 0x50) continue; \
2617                 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2618                 *ptr = (*ptr & 0xf) | 0xA0; \
2619                 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2620                 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2621                 v0 = 1; \
2622                 break; \
2623         } \
2624 }
2625
2626 /*
2627  *      int delete(char *name);
2628  */
2629
2630 void psxBios_delete() { // 45
2631         void *pa0 = Ra0;
2632         char *ptr;
2633         int i;
2634
2635 #ifdef PSXBIOS_LOG
2636         PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2637 #endif
2638
2639         v0 = 0;
2640
2641         if (pa0 != INVALID_PTR) {
2642                 if (!strncmp(pa0, "bu00", 4)) {
2643                         budelete(1);
2644                 }
2645
2646                 if (!strncmp(pa0, "bu10", 4)) {
2647                         budelete(2);
2648                 }
2649         }
2650
2651         pc0 = ra;
2652 }
2653
2654 void psxBios_InitCARD() { // 4a
2655         u32 *ram32 = (u32 *)psxM;
2656         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2657         write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2658         // (maybe) todo: early_card_irq, FlushCache etc
2659
2660         ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2661
2662         mips_return_c(0, 300);
2663 }
2664
2665 void psxBios_StartCARD() { // 4b
2666         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2667         psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2668         psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2669
2670         psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2671         storeRam32(A_PAD_ACK_VBL, 1);
2672         storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2673         storeRam32(A_CARD_IRQR_ENA, 1);
2674         psxRegs.CP0.n.SR |= 0x401;
2675
2676         mips_return_c(1, 200);
2677 }
2678
2679 void psxBios_StopCARD() { // 4c
2680         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2681         storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2682         psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2683         storeRam32(A_CARD_IRQR_ENA, 0);
2684         psxRegs.CP0.n.SR |= 0x401;
2685         mips_return_void_c(200);
2686 }
2687
2688 void psxBios__card_write() { // 0x4e
2689         void *pa2 = Ra2;
2690         int port;
2691
2692 #ifdef PSXBIOS_LOG
2693         PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2694 #endif
2695         /*
2696         Function also accepts sector 400h (a bug).
2697         But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2698         */
2699         if (!(a1 <= 0x3FF))
2700         {
2701                 /* Invalid sectors */
2702                 v0 = 0; pc0 = ra;
2703                 return;
2704         }
2705         storeRam32(A_CARD_CHAN1, a0);
2706         port = a0 >> 4;
2707
2708         if (pa2 != INVALID_PTR) {
2709                 if (port == 0) {
2710                         memcpy(Mcd1Data + a1 * 128, pa2, 128);
2711                         SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2712                 } else {
2713                         memcpy(Mcd2Data + a1 * 128, pa2, 128);
2714                         SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2715                 }
2716         }
2717
2718         DeliverEvent(0xf0000011, 0x0004);
2719 //      DeliverEvent(0xf4000001, 0x0004);
2720
2721         v0 = 1; pc0 = ra;
2722 }
2723
2724 void psxBios__card_read() { // 0x4f
2725         void *pa2 = Ra2;
2726         int port;
2727
2728 #ifdef PSXBIOS_LOG
2729         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2730 #endif
2731         /*
2732         Function also accepts sector 400h (a bug).
2733         But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2734         */
2735         if (!(a1 <= 0x3FF))
2736         {
2737                 /* Invalid sectors */
2738                 v0 = 0; pc0 = ra;
2739                 return;
2740         }
2741         storeRam32(A_CARD_CHAN1, a0);
2742         port = a0 >> 4;
2743
2744         if (pa2 != INVALID_PTR) {
2745                 if (port == 0) {
2746                         memcpy(pa2, Mcd1Data + a1 * 128, 128);
2747                 } else {
2748                         memcpy(pa2, Mcd2Data + a1 * 128, 128);
2749                 }
2750         }
2751
2752         DeliverEvent(0xf0000011, 0x0004);
2753 //      DeliverEvent(0xf4000001, 0x0004);
2754
2755         v0 = 1; pc0 = ra;
2756 }
2757
2758 void psxBios__new_card() { // 0x50
2759 #ifdef PSXBIOS_LOG
2760         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2761 #endif
2762
2763         pc0 = ra;
2764 }
2765
2766 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2767 void psxBios__get_error(void) // 55
2768 {
2769         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2770         v0 = 0;
2771         pc0 = ra;
2772 }
2773
2774 void psxBios_Krom2RawAdd() { // 0x51
2775         int i = 0;
2776
2777         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2778         const u32 table_8140[][2] = {
2779                 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2780                 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2781                 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2782                 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2783                 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2784                 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2785                 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2786                 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2787                 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2788                 {0xffff, 0}
2789         };
2790
2791         const u32 table_889f[][2] = {
2792                 {0x889f, 0x3d68},  {0x8900, 0x40ec},  {0x897f, 0x4fb0},  {0x8a00, 0x56f4},
2793                 {0x8a7f, 0x65b8},  {0x8b00, 0x6cfc},  {0x8b7f, 0x7bc0},  {0x8c00, 0x8304},
2794                 {0x8c7f, 0x91c8},  {0x8d00, 0x990c},  {0x8d7f, 0xa7d0},  {0x8e00, 0xaf14},
2795                 {0x8e7f, 0xbdd8},  {0x8f00, 0xc51c},  {0x8f7f, 0xd3e0},  {0x9000, 0xdb24},
2796                 {0x907f, 0xe9e8},  {0x9100, 0xf12c},  {0x917f, 0xfff0},  {0x9200, 0x10734},
2797                 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2798                 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2799                 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2800                 {0xffff, 0}
2801         };
2802
2803         if (a0 >= 0x8140 && a0 <= 0x84be) {
2804                 while (table_8140[i][0] <= a0) i++;
2805                 a0 -= table_8140[i - 1][0];
2806                 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2807         } else if (a0 >= 0x889f && a0 <= 0x9872) {
2808                 while (table_889f[i][0] <= a0) i++;
2809                 a0 -= table_889f[i - 1][0];
2810                 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2811         } else {
2812                 v0 = 0xffffffff;
2813         }
2814
2815         pc0 = ra;
2816 }
2817
2818 void psxBios_GetC0Table() { // 56
2819         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2820         log_unhandled("GetC0Table @%08x\n", ra);
2821
2822         mips_return_c(A_C0_TABLE, 3);
2823 }
2824
2825 void psxBios_GetB0Table() { // 57
2826         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2827         log_unhandled("GetB0Table @%08x\n", ra);
2828
2829         mips_return_c(A_B0_TABLE, 3);
2830 }
2831
2832 static void psxBios__card_chan() { // 0x58
2833         u32 ret;
2834         PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2835
2836         // todo: should return active slot chan
2837         // (active - which was last processed by irq code)
2838         ret = loadRam32(A_CARD_CHAN1);
2839         mips_return_c(ret, 8);
2840 }
2841
2842 static void psxBios_ChangeClearPad() { // 5b
2843         u32 ret;
2844         PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2845         ret = loadRam32(A_PAD_ACK_VBL);
2846         storeRam32(A_PAD_ACK_VBL, a0);
2847
2848         mips_return_c(ret, 6);
2849 }
2850
2851 static void psxBios__card_status() { // 5c
2852         PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
2853
2854         v0 = 1; // ready
2855         pc0 = ra;
2856 }
2857
2858 static void psxBios__card_wait() { // 5d
2859         PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
2860
2861         v0 = 1; // ready
2862         pc0 = ra;
2863 }
2864
2865 /* System calls C0 */
2866
2867 static void psxBios_InitRCnt() { // 00
2868         int i;
2869         PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2870         psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2871         for (i = 0; i < 3; i++) {
2872                 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2873                 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2874                 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2875         }
2876         psxBios_SysEnqIntRP_(a0, 0x6d88);
2877         mips_return_c(0, 9);
2878 }
2879
2880 static void psxBios_InitException() { // 01
2881         PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2882         psxBios_SysEnqIntRP_(a0, 0x6da8);
2883         mips_return_c(0, 9);
2884 }
2885
2886 /*
2887  * int SysEnqIntRP(int index , long *queue);
2888  */
2889
2890 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2891         u32 old, base = loadRam32(A_TT_ExCB);
2892
2893         old = loadRam32(base + (priority << 3));
2894         storeRam32(base + (priority << 3), chain_eptr);
2895         storeRam32(chain_eptr, old);
2896         mips_return_c(0, 9);
2897 }
2898
2899 static void psxBios_SysEnqIntRP() { // 02
2900         PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2901         psxBios_SysEnqIntRP_(a0, a1);
2902 }
2903
2904 /*
2905  * int SysDeqIntRP(int index , long *queue);
2906  */
2907
2908 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
2909         u32 ptr, next, base = loadRam32(A_TT_ExCB);
2910         u32 lim = 0, ret = 0;
2911
2912         // as in original: no arg checks of any kind, bug if a1 == 0
2913         ptr = loadRam32(base + (priority << 3));
2914         while (ptr) {
2915                 next = loadRam32(ptr);
2916                 if (ptr == chain_rm_eptr) {
2917                         storeRam32(base + (priority << 3), next);
2918                         ret = ptr;
2919                         use_cycles(6);
2920                         break;
2921                 }
2922                 while (next && next != chain_rm_eptr && lim++ < 100) {
2923                         ptr = next;
2924                         next = loadRam32(ptr);
2925                         use_cycles(8);
2926                 }
2927                 if (next == chain_rm_eptr) {
2928                         next = loadRam32(next);
2929                         storeRam32(ptr, next);
2930                         ret = ptr;
2931                         use_cycles(6);
2932                 }
2933                 break;
2934         }
2935         if (lim == 100)
2936                 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
2937
2938         mips_return_c(ret, 12);
2939 }
2940
2941 static void psxBios_SysDeqIntRP() { // 03
2942         PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
2943         psxBios_SysDeqIntRP_(a0, a1);
2944 }
2945
2946 static void psxBios_get_free_EvCB_slot() { // 04
2947         PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
2948         s32 ret = get_free_EvCB_slot();
2949         mips_return_c(ret, 0);
2950 }
2951         
2952 static void psxBios_SysInitMemory_(u32 base, u32 size) {
2953         storeRam32(base, 0);
2954         storeRam32(A_KMALLOC_PTR, base);
2955         storeRam32(A_KMALLOC_SIZE, size);
2956         storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
2957 }
2958
2959 // this should be much more complicated, but maybe that'll be enough
2960 static u32 psxBios_SysMalloc_(u32 size) {
2961         u32 ptr = loadRam32(A_KMALLOC_PTR);
2962
2963         size = (size + 3) & ~3;
2964         storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
2965         storeRam32(ptr, size);
2966         return ptr + 4;
2967 }
2968
2969 static void psxBios_SysInitMemory() { // 08
2970         PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
2971
2972         psxBios_SysInitMemory_(a0, a1);
2973         mips_return_void_c(12);
2974 }
2975
2976 static void psxBios_ChangeClearRCnt() { // 0a
2977         u32 ret;
2978
2979         PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2980
2981         ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
2982         storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
2983         mips_return_c(ret, 8);
2984 }
2985
2986 static void psxBios_InitDefInt() { // 0c
2987         PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
2988         // should also clear the autoack table
2989         psxBios_SysEnqIntRP_(a0, 0x6d98);
2990         mips_return_c(0, 20 + 6*2);
2991 }
2992
2993 void psxBios_dummy() {
2994         u32 pc = (pc0 & 0x1fffff) - 4;
2995         char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
2996                 : pc == 0xc0 ? biosC0n : NULL;
2997         PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
2998                 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
2999         (void)pc; (void)ntab;
3000         mips_return_c(0, 100);
3001 }
3002
3003 void (*biosA0[256])();
3004 // C0 and B0 overlap (end of C0 is start of B0)
3005 void (*biosC0[256+128])();
3006 void (**biosB0)() = biosC0 + 128;
3007
3008 static void setup_mips_code()
3009 {
3010         u32 *ptr;
3011         ptr = (u32 *)&psxM[A_SYSCALL];
3012         ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3013         ptr[0x04/4] = SWAPu32(0x03e00008); // jr    $ra
3014         ptr[0x08/4] = SWAPu32(0x00000000); // nop
3015
3016         ptr = (u32 *)&psxM[A_EXCEPTION];
3017         memset(ptr, 0, 0xc0);              // nops (to be patched by games sometimes)
3018         ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw    $k0, (0x108)   // PCB
3019         ptr[0x14/4] = SWAPu32(0x00000000); // nop
3020         ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw    $k0, ($k0)     // TCB
3021         ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3022         ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8    // regs
3023         ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw    $ra, 0x7c($k0)
3024         ptr[0x28/4] = SWAPu32(0xaf410004); // sw    $at, 0x04($k0)
3025         ptr[0x2c/4] = SWAPu32(0xaf420008); // sw    $v0, 0x08($k0)
3026         ptr[0x30/4] = SWAPu32(0xaf43000c); // sw    $v1, 0x0c($k0)
3027
3028         ptr[0x60/4] = SWAPu32(0x40037000); // mfc0  $v1, EPC
3029         ptr[0x64/4] = SWAPu32(0x40026800); // mfc0  $v0, Cause
3030         ptr[0x6c/4] = SWAPu32(0xaf430080); // sw    $v1, 0x80($k0)
3031
3032         ptr[0xb0/4] = HLEOP(hleop_exception);
3033 }
3034
3035 static const struct {
3036         u32 addr;
3037         enum hle_op op;
3038 } chainfns[] = {
3039         { 0xbfc050a4, hleop_exc0_0_1 },
3040         { 0xbfc04fbc, hleop_exc0_0_2 },
3041         { 0xbfc0506c, hleop_exc0_1_1 },
3042         { 0xbfc04dec, hleop_exc0_1_2 },
3043         {     0x1a00, hleop_exc0_2_2 },
3044         {     0x19c8, hleop_exc1_0_1 },
3045         {     0x18bc, hleop_exc1_0_2 },
3046         {     0x1990, hleop_exc1_1_1 },
3047         {     0x1858, hleop_exc1_1_2 },
3048         {     0x1958, hleop_exc1_2_1 },
3049         {     0x17f4, hleop_exc1_2_2 },
3050         {     0x1920, hleop_exc1_3_1 },
3051         {     0x1794, hleop_exc1_3_2 },
3052         {     0x2458, hleop_exc3_0_2 },
3053         {     0x49bc, hleop_exc_padcard1 },
3054         {     0x4a4c, hleop_exc_padcard2 },
3055 };
3056
3057 static int chain_hle_op(u32 handler)
3058 {
3059         size_t i;
3060
3061         for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3062                 if (chainfns[i].addr == handler)
3063                         return chainfns[i].op;
3064         return hleop_dummy;
3065 }
3066
3067 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3068 {
3069         d[0] = SWAPu32(next);
3070         d[1] = SWAPu32(handler1);
3071         d[2] = SWAPu32(handler2);
3072
3073         // install the hle traps
3074         PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3075         PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3076 }
3077
3078 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt)
3079 {
3080         u32 *ram32 = (u32 *)psxM;
3081         u32 s_excb = 0x20, s_evcb = 0x1c * evcb_cnt;
3082         u32 s_pcb = 4, s_tcb = 0xc0 * tcb_cnt;
3083         u32 p_excb, p_evcb, p_pcb, p_tcb;
3084
3085         memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3086         psxBios_SysInitMemory_(0xa000e000, 0x2000);
3087         p_excb = psxBios_SysMalloc_(s_excb);
3088         p_evcb = psxBios_SysMalloc_(s_evcb);
3089         p_pcb  = psxBios_SysMalloc_(s_pcb);
3090         p_tcb  = psxBios_SysMalloc_(s_tcb);
3091
3092         // "table of tables". Some games modify it
3093         assert(A_TT_ExCB == 0x0100);
3094         ram32[0x0100/4] = SWAPu32(p_excb);  // ExCB - exception chains
3095         ram32[0x0104/4] = SWAPu32(s_excb);  // ExCB size
3096         ram32[0x0108/4] = SWAPu32(p_pcb);   // PCB - process control
3097         ram32[0x010c/4] = SWAPu32(s_pcb);   // PCB size
3098         ram32[0x0110/4] = SWAPu32(p_tcb);   // TCB - thread control
3099         ram32[0x0114/4] = SWAPu32(s_tcb);   // TCB size
3100         ram32[0x0120/4] = SWAPu32(p_evcb);  // EvCB - event control
3101         ram32[0x0124/4] = SWAPu32(s_evcb);  // EvCB size
3102         ram32[0x0140/4] = SWAPu32(0x8648);  // FCB - file control
3103         ram32[0x0144/4] = SWAPu32(0x02c0);  // FCB size
3104         ram32[0x0150/4] = SWAPu32(0x6ee0);  // DCB - device control
3105         ram32[0x0154/4] = SWAPu32(0x0320);  // DCB size
3106
3107         storeRam32(p_excb + 0*4, 0x91e0);   // chain0
3108         storeRam32(p_excb + 2*4, 0x6d88);   // chain1
3109         storeRam32(p_excb + 4*4, 0x0000);   // chain2
3110         storeRam32(p_excb + 6*4, 0x6d98);   // chain3
3111
3112         storeRam32(p_pcb, p_tcb);
3113         storeRam32(p_tcb, 0x4000);          // first TCB
3114
3115         // default events
3116         storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3117         storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3118         storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3119         storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3120         storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3121         DeliverEvent(0xf0000003, 0x0010);
3122 }
3123
3124 static const u32 gpu_ctl_def[] = {
3125         0x00000000, 0x01000000, 0x03000000, 0x04000000,
3126         0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3127 };
3128
3129 static const u32 gpu_data_def[] = {
3130         0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3131         0xe5001000, 0xe6000000,
3132         0x02000000, 0x00000000, 0x01ff03ff
3133 };
3134
3135 // from 1f801d80
3136 static const u16 spu_config[] = {
3137         0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3138         0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3139         0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3140         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3141         0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3142         0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3143         0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3144         0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3145 };
3146
3147 void psxBiosSetupBootState(void)
3148 {
3149         boolean hle = Config.HLE;
3150         u32 *hw = (u32 *)psxH;
3151         int i;
3152
3153         // see also SetBootRegs()
3154         if (hle) {
3155                 v0 = 1; v1 = 4;
3156                 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3157                 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3158                 s0 = 0xa000b870;
3159                 k0 = 0xbfc0d968; k1 = 0xf1c;
3160                 ra = 0xf0001234; // just to easily detect attempts to return
3161                 psxRegs.CP0.n.Cause = 0x20;
3162                 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3163
3164                 hw[0x1000/4] = SWAP32(0x1f000000);
3165                 hw[0x1004/4] = SWAP32(0x1f802000);
3166                 hw[0x1008/4] = SWAP32(0x0013243f);
3167                 hw[0x100c/4] = SWAP32(0x00003022);
3168                 hw[0x1010/4] = SWAP32(0x0013243f);
3169                 hw[0x1014/4] = SWAP32(0x200931e1);
3170                 hw[0x1018/4] = SWAP32(0x00020943);
3171                 hw[0x101c/4] = SWAP32(0x00070777);
3172                 hw[0x1020/4] = SWAP32(0x0000132c);
3173                 hw[0x1060/4] = SWAP32(0x00000b88);
3174                 hw[0x1070/4] = SWAP32(0x00000001);
3175                 hw[0x1074/4] = SWAP32(0x0000000c);
3176                 hw[0x2040/4] = SWAP32(0x00000900);
3177         }
3178
3179         hw[0x10a0/4] = SWAP32(0x00ffffff);
3180         hw[0x10a8/4] = SWAP32(0x00000401);
3181         hw[0x10b0/4] = SWAP32(0x0008b000);
3182         hw[0x10b4/4] = SWAP32(0x00010200);
3183         hw[0x10e0/4] = SWAP32(0x000eccf4);
3184         hw[0x10e4/4] = SWAP32(0x00000400);
3185         hw[0x10e8/4] = SWAP32(0x00000002);
3186         hw[0x10f0/4] = SWAP32(0x00009099);
3187         hw[0x10f4/4] = SWAP32(0x8c8c0000);
3188
3189         if (hle) {
3190                 psxRcntWmode(0, 0);
3191                 psxRcntWmode(1, 0);
3192                 psxRcntWmode(2, 0);
3193         }
3194
3195         // gpu
3196         for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3197                 GPU_writeStatus(gpu_ctl_def[i]);
3198         for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3199                 GPU_writeData(gpu_data_def[i]);
3200         HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
3201
3202         // spu
3203         for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3204                 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3205 }
3206
3207 #include "sjisfont.h"
3208
3209 void psxBiosInit() {
3210         u32 *ptr, *ram32, *rom32;
3211         int i;
3212         uLongf len;
3213
3214         memset(psxM, 0, 0x10000);
3215         for(i = 0; i < 256; i++) {
3216                 biosA0[i] = NULL;
3217                 biosB0[i] = NULL;
3218                 biosC0[i] = NULL;
3219         }
3220         biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3221         biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3222         biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3223         biosA0[0x3f] = psxBios_printf_psxout;
3224
3225         if (!Config.HLE) return;
3226
3227         for(i = 0; i < 256; i++) {
3228                 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3229                 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3230                 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3231         }
3232
3233         biosA0[0x00] = psxBios_open;
3234         biosA0[0x01] = psxBios_lseek;
3235         biosA0[0x02] = psxBios_read;
3236         biosA0[0x03] = psxBios_write;
3237         biosA0[0x04] = psxBios_close;
3238         //biosA0[0x05] = psxBios_ioctl;
3239         //biosA0[0x06] = psxBios_exit;
3240         //biosA0[0x07] = psxBios_sys_a0_07;
3241         biosA0[0x08] = psxBios_getc;
3242         biosA0[0x09] = psxBios_putc;
3243         biosA0[0x0a] = psxBios_todigit;
3244         //biosA0[0x0b] = psxBios_atof;
3245         //biosA0[0x0c] = psxBios_strtoul;
3246         //biosA0[0x0d] = psxBios_strtol;
3247         biosA0[0x0e] = psxBios_abs;
3248         biosA0[0x0f] = psxBios_labs;
3249         biosA0[0x10] = psxBios_atoi;
3250         biosA0[0x11] = psxBios_atol;
3251         //biosA0[0x12] = psxBios_atob;
3252         biosA0[0x13] = psxBios_setjmp;
3253         biosA0[0x14] = psxBios_longjmp;
3254         biosA0[0x15] = psxBios_strcat;
3255         biosA0[0x16] = psxBios_strncat;
3256         biosA0[0x17] = psxBios_strcmp;
3257         biosA0[0x18] = psxBios_strncmp;
3258         biosA0[0x19] = psxBios_strcpy;
3259         biosA0[0x1a] = psxBios_strncpy;
3260         biosA0[0x1b] = psxBios_strlen;
3261         biosA0[0x1c] = psxBios_index;
3262         biosA0[0x1d] = psxBios_rindex;
3263         biosA0[0x1e] = psxBios_strchr;
3264         biosA0[0x1f] = psxBios_strrchr;
3265         biosA0[0x20] = psxBios_strpbrk;
3266         biosA0[0x21] = psxBios_strspn;
3267         biosA0[0x22] = psxBios_strcspn;
3268         biosA0[0x23] = psxBios_strtok;
3269         biosA0[0x24] = psxBios_strstr;
3270         biosA0[0x25] = psxBios_toupper;
3271         biosA0[0x26] = psxBios_tolower;
3272         biosA0[0x27] = psxBios_bcopy;
3273         biosA0[0x28] = psxBios_bzero;
3274         biosA0[0x29] = psxBios_bcmp;
3275         biosA0[0x2a] = psxBios_memcpy;
3276         biosA0[0x2b] = psxBios_memset;
3277         biosA0[0x2c] = psxBios_memmove;
3278         biosA0[0x2d] = psxBios_memcmp;
3279         biosA0[0x2e] = psxBios_memchr;
3280         biosA0[0x2f] = psxBios_rand;
3281         biosA0[0x30] = psxBios_srand;
3282         biosA0[0x31] = psxBios_qsort;
3283         //biosA0[0x32] = psxBios_strtod;
3284         biosA0[0x33] = psxBios_malloc;
3285         biosA0[0x34] = psxBios_free;
3286         //biosA0[0x35] = psxBios_lsearch;
3287         //biosA0[0x36] = psxBios_bsearch;
3288         biosA0[0x37] = psxBios_calloc;
3289         biosA0[0x38] = psxBios_realloc;
3290         biosA0[0x39] = psxBios_InitHeap;
3291         //biosA0[0x3a] = psxBios__exit;
3292         biosA0[0x3b] = psxBios_getchar;
3293         biosA0[0x3c] = psxBios_putchar;
3294         //biosA0[0x3d] = psxBios_gets;
3295         biosA0[0x3e] = psxBios_puts;
3296         biosA0[0x3f] = psxBios_printf;
3297         biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3298         //biosA0[0x41] = psxBios_LoadTest;
3299         biosA0[0x42] = psxBios_Load;
3300         biosA0[0x43] = psxBios_Exec;
3301         biosA0[0x44] = psxBios_FlushCache;
3302         //biosA0[0x45] = psxBios_InstallInterruptHandler;
3303         biosA0[0x46] = psxBios_GPU_dw;
3304         biosA0[0x47] = psxBios_mem2vram;
3305         biosA0[0x48] = psxBios_SendGPU;
3306         biosA0[0x49] = psxBios_GPU_cw;
3307         biosA0[0x4a] = psxBios_GPU_cwb;
3308         biosA0[0x4b] = psxBios_GPU_SendPackets;
3309         biosA0[0x4c] = psxBios_sys_a0_4c;
3310         biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3311         //biosA0[0x4e] = psxBios_GPU_sync;
3312         //biosA0[0x4f] = psxBios_sys_a0_4f;
3313         //biosA0[0x50] = psxBios_sys_a0_50;
3314         biosA0[0x51] = psxBios_LoadExec;
3315         //biosA0[0x52] = psxBios_GetSysSp;
3316         //biosA0[0x53] = psxBios_sys_a0_53;
3317         //biosA0[0x54] = psxBios__96_init_a54;
3318         //biosA0[0x55] = psxBios__bu_init_a55;
3319         biosA0[0x56] = psxBios_CdRemove;
3320         //biosA0[0x57] = psxBios_sys_a0_57;
3321         //biosA0[0x58] = psxBios_sys_a0_58;
3322         //biosA0[0x59] = psxBios_sys_a0_59;
3323         //biosA0[0x5a] = psxBios_sys_a0_5a;
3324         //biosA0[0x5b] = psxBios_dev_tty_init;
3325         //biosA0[0x5c] = psxBios_dev_tty_open;
3326         //biosA0[0x5d] = psxBios_sys_a0_5d;
3327         //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3328         //biosA0[0x5f] = psxBios_dev_cd_open;
3329         //biosA0[0x60] = psxBios_dev_cd_read;
3330         //biosA0[0x61] = psxBios_dev_cd_close;
3331         //biosA0[0x62] = psxBios_dev_cd_firstfile;
3332         //biosA0[0x63] = psxBios_dev_cd_nextfile;
3333         //biosA0[0x64] = psxBios_dev_cd_chdir;
3334         //biosA0[0x65] = psxBios_dev_card_open;
3335         //biosA0[0x66] = psxBios_dev_card_read;
3336         //biosA0[0x67] = psxBios_dev_card_write;
3337         //biosA0[0x68] = psxBios_dev_card_close;
3338         //biosA0[0x69] = psxBios_dev_card_firstfile;
3339         //biosA0[0x6a] = psxBios_dev_card_nextfile;
3340         //biosA0[0x6b] = psxBios_dev_card_erase;
3341         //biosA0[0x6c] = psxBios_dev_card_undelete;
3342         //biosA0[0x6d] = psxBios_dev_card_format;
3343         //biosA0[0x6e] = psxBios_dev_card_rename;
3344         //biosA0[0x6f] = psxBios_dev_card_6f;
3345         biosA0[0x70] = psxBios__bu_init;
3346         biosA0[0x71] = psxBios__96_init;
3347         biosA0[0x72] = psxBios_CdRemove;
3348         //biosA0[0x73] = psxBios_sys_a0_73;
3349         //biosA0[0x74] = psxBios_sys_a0_74;
3350         //biosA0[0x75] = psxBios_sys_a0_75;
3351         //biosA0[0x76] = psxBios_sys_a0_76;
3352         //biosA0[0x77] = psxBios_sys_a0_77;
3353         //biosA0[0x78] = psxBios__96_CdSeekL;
3354         //biosA0[0x79] = psxBios_sys_a0_79;
3355         //biosA0[0x7a] = psxBios_sys_a0_7a;
3356         //biosA0[0x7b] = psxBios_sys_a0_7b;
3357         //biosA0[0x7c] = psxBios__96_CdGetStatus;
3358         //biosA0[0x7d] = psxBios_sys_a0_7d;
3359         //biosA0[0x7e] = psxBios__96_CdRead;
3360         //biosA0[0x7f] = psxBios_sys_a0_7f;
3361         //biosA0[0x80] = psxBios_sys_a0_80;
3362         //biosA0[0x81] = psxBios_sys_a0_81;
3363         //biosA0[0x82] = psxBios_sys_a0_82;
3364         //biosA0[0x83] = psxBios_sys_a0_83;
3365         //biosA0[0x84] = psxBios_sys_a0_84;
3366         //biosA0[0x85] = psxBios__96_CdStop;
3367         //biosA0[0x86] = psxBios_sys_a0_86;
3368         //biosA0[0x87] = psxBios_sys_a0_87;
3369         //biosA0[0x88] = psxBios_sys_a0_88;
3370         //biosA0[0x89] = psxBios_sys_a0_89;
3371         //biosA0[0x8a] = psxBios_sys_a0_8a;
3372         //biosA0[0x8b] = psxBios_sys_a0_8b;
3373         //biosA0[0x8c] = psxBios_sys_a0_8c;
3374         //biosA0[0x8d] = psxBios_sys_a0_8d;
3375         //biosA0[0x8e] = psxBios_sys_a0_8e;
3376         //biosA0[0x8f] = psxBios_sys_a0_8f;
3377         biosA0[0x90] = hleExc0_1_2;
3378         biosA0[0x91] = hleExc0_0_2;
3379         biosA0[0x92] = hleExc0_1_1;
3380         biosA0[0x93] = hleExc0_0_1;
3381         //biosA0[0x94] = psxBios_sys_a0_94;
3382         //biosA0[0x95] = psxBios_sys_a0_95;
3383         //biosA0[0x96] = psxBios_AddCDROMDevice;
3384         //biosA0[0x97] = psxBios_AddMemCardDevide;
3385         //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3386         //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3387         //biosA0[0x9a] = psxBios_sys_a0_9a;
3388         //biosA0[0x9b] = psxBios_sys_a0_9b;
3389         //biosA0[0x9c] = psxBios_SetConf;
3390         //biosA0[0x9d] = psxBios_GetConf;
3391         //biosA0[0x9e] = psxBios_sys_a0_9e;
3392         biosA0[0x9f] = psxBios_SetMem;
3393         //biosA0[0xa0] = psxBios__boot;
3394         //biosA0[0xa1] = psxBios_SystemError;
3395         //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3396         biosA0[0xa3] = psxBios_DequeueCdIntr;
3397         //biosA0[0xa4] = psxBios_sys_a0_a4;
3398         //biosA0[0xa5] = psxBios_ReadSector;
3399         biosA0[0xa6] = psxBios_get_cd_status;
3400         //biosA0[0xa7] = psxBios_bufs_cb_0;
3401         //biosA0[0xa8] = psxBios_bufs_cb_1;
3402         //biosA0[0xa9] = psxBios_bufs_cb_2;
3403         //biosA0[0xaa] = psxBios_bufs_cb_3;
3404         biosA0[0xab] = psxBios__card_info;
3405         biosA0[0xac] = psxBios__card_load;
3406         //biosA0[0axd] = psxBios__card_auto;
3407         //biosA0[0xae] = psxBios_bufs_cd_4;
3408         //biosA0[0xaf] = psxBios_sys_a0_af;
3409         //biosA0[0xb0] = psxBios_sys_a0_b0;
3410         //biosA0[0xb1] = psxBios_sys_a0_b1;
3411         //biosA0[0xb2] = psxBios_do_a_long_jmp
3412         //biosA0[0xb3] = psxBios_sys_a0_b3;
3413         biosA0[0xb4] = psxBios_GetSystemInfo;
3414 //*******************B0 CALLS****************************
3415         biosB0[0x00] = psxBios_SysMalloc;
3416         //biosB0[0x01] = psxBios_sys_b0_01;
3417         biosB0[0x02] = psxBios_SetRCnt;
3418         biosB0[0x03] = psxBios_GetRCnt;
3419         biosB0[0x04] = psxBios_StartRCnt;
3420         biosB0[0x05] = psxBios_StopRCnt;
3421         biosB0[0x06] = psxBios_ResetRCnt;
3422         biosB0[0x07] = psxBios_DeliverEvent;
3423         biosB0[0x08] = psxBios_OpenEvent;
3424         biosB0[0x09] = psxBios_CloseEvent;
3425         biosB0[0x0a] = psxBios_WaitEvent;
3426         biosB0[0x0b] = psxBios_TestEvent;
3427         biosB0[0x0c] = psxBios_EnableEvent;
3428         biosB0[0x0d] = psxBios_DisableEvent;
3429         biosB0[0x0e] = psxBios_OpenTh;
3430         biosB0[0x0f] = psxBios_CloseTh;
3431         biosB0[0x10] = psxBios_ChangeTh;
3432         //biosB0[0x11] = psxBios_psxBios_b0_11;
3433         biosB0[0x12] = psxBios_InitPAD;
3434         biosB0[0x13] = psxBios_StartPAD;
3435         biosB0[0x14] = psxBios_StopPAD;
3436         biosB0[0x15] = psxBios_PAD_init;
3437         biosB0[0x16] = psxBios_PAD_dr;
3438         biosB0[0x17] = psxBios_ReturnFromException;
3439         biosB0[0x18] = psxBios_ResetEntryInt;
3440         biosB0[0x19] = psxBios_HookEntryInt;
3441         //biosB0[0x1a] = psxBios_sys_b0_1a;
3442         //biosB0[0x1b] = psxBios_sys_b0_1b;
3443         //biosB0[0x1c] = psxBios_sys_b0_1c;
3444         //biosB0[0x1d] = psxBios_sys_b0_1d;
3445         //biosB0[0x1e] = psxBios_sys_b0_1e;
3446         //biosB0[0x1f] = psxBios_sys_b0_1f;
3447         biosB0[0x20] = psxBios_UnDeliverEvent;
3448         //biosB0[0x21] = psxBios_sys_b0_21;
3449         //biosB0[0x22] = psxBios_sys_b0_22;
3450         //biosB0[0x23] = psxBios_sys_b0_23;
3451         //biosB0[0x24] = psxBios_sys_b0_24;
3452         //biosB0[0x25] = psxBios_sys_b0_25;
3453         //biosB0[0x26] = psxBios_sys_b0_26;
3454         //biosB0[0x27] = psxBios_sys_b0_27;
3455         //biosB0[0x28] = psxBios_sys_b0_28;
3456         //biosB0[0x29] = psxBios_sys_b0_29;
3457         //biosB0[0x2a] = psxBios_sys_b0_2a;
3458         //biosB0[0x2b] = psxBios_sys_b0_2b;
3459         //biosB0[0x2c] = psxBios_sys_b0_2c;
3460         //biosB0[0x2d] = psxBios_sys_b0_2d;
3461         //biosB0[0x2e] = psxBios_sys_b0_2e;
3462         //biosB0[0x2f] = psxBios_sys_b0_2f;
3463         //biosB0[0x30] = psxBios_sys_b0_30;
3464         //biosB0[0x31] = psxBios_sys_b0_31;
3465         biosB0[0x32] = psxBios_open;
3466         biosB0[0x33] = psxBios_lseek;
3467         biosB0[0x34] = psxBios_read;
3468         biosB0[0x35] = psxBios_write;
3469         biosB0[0x36] = psxBios_close;
3470         //biosB0[0x37] = psxBios_ioctl;
3471         //biosB0[0x38] = psxBios_exit;
3472         //biosB0[0x39] = psxBios_sys_b0_39;
3473         //biosB0[0x3a] = psxBios_getc;
3474         //biosB0[0x3b] = psxBios_putc;
3475         biosB0[0x3c] = psxBios_getchar;
3476         biosB0[0x3d] = psxBios_putchar;
3477         //biosB0[0x3e] = psxBios_gets;
3478         biosB0[0x3f] = psxBios_puts;
3479         //biosB0[0x40] = psxBios_cd;
3480         biosB0[0x41] = psxBios_format;
3481         biosB0[0x42] = psxBios_firstfile;
3482         biosB0[0x43] = psxBios_nextfile;
3483         biosB0[0x44] = psxBios_rename;
3484         biosB0[0x45] = psxBios_delete;
3485         //biosB0[0x46] = psxBios_undelete;
3486         //biosB0[0x47] = psxBios_AddDevice;
3487         //biosB0[0x48] = psxBios_RemoteDevice;
3488         //biosB0[0x49] = psxBios_PrintInstalledDevices;
3489         biosB0[0x4a] = psxBios_InitCARD;
3490         biosB0[0x4b] = psxBios_StartCARD;
3491         biosB0[0x4c] = psxBios_StopCARD;
3492         //biosB0[0x4d] = psxBios_sys_b0_4d;
3493         biosB0[0x4e] = psxBios__card_write;
3494         biosB0[0x4f] = psxBios__card_read;
3495         biosB0[0x50] = psxBios__new_card;
3496         biosB0[0x51] = psxBios_Krom2RawAdd;
3497         //biosB0[0x52] = psxBios_sys_b0_52;
3498         //biosB0[0x53] = psxBios_sys_b0_53;
3499         //biosB0[0x54] = psxBios__get_errno;
3500         biosB0[0x55] = psxBios__get_error;
3501         biosB0[0x56] = psxBios_GetC0Table;
3502         biosB0[0x57] = psxBios_GetB0Table;
3503         biosB0[0x58] = psxBios__card_chan;
3504         //biosB0[0x59] = psxBios_sys_b0_59;
3505         //biosB0[0x5a] = psxBios_sys_b0_5a;
3506         biosB0[0x5b] = psxBios_ChangeClearPad;
3507         biosB0[0x5c] = psxBios__card_status;
3508         biosB0[0x5d] = psxBios__card_wait;
3509 //*******************C0 CALLS****************************
3510         biosC0[0x00] = psxBios_InitRCnt;
3511         biosC0[0x01] = psxBios_InitException;
3512         biosC0[0x02] = psxBios_SysEnqIntRP;
3513         biosC0[0x03] = psxBios_SysDeqIntRP;
3514         biosC0[0x04] = psxBios_get_free_EvCB_slot;
3515         //biosC0[0x05] = psxBios_get_free_TCB_slot;
3516         //biosC0[0x06] = psxBios_ExceptionHandler;
3517         //biosC0[0x07] = psxBios_InstallExeptionHandler;
3518         biosC0[0x08] = psxBios_SysInitMemory;
3519         //biosC0[0x09] = psxBios_SysInitKMem;
3520         biosC0[0x0a] = psxBios_ChangeClearRCnt;
3521         //biosC0[0x0b] = psxBios_SystemError;
3522         biosC0[0x0c] = psxBios_InitDefInt;
3523         //biosC0[0x0d] = psxBios_sys_c0_0d;
3524         //biosC0[0x0e] = psxBios_sys_c0_0e;
3525         //biosC0[0x0f] = psxBios_sys_c0_0f;
3526         //biosC0[0x10] = psxBios_sys_c0_10;
3527         //biosC0[0x11] = psxBios_sys_c0_11;
3528         //biosC0[0x12] = psxBios_InstallDevices;
3529         //biosC0[0x13] = psxBios_FlushStfInOutPut;
3530         //biosC0[0x14] = psxBios_sys_c0_14;
3531         //biosC0[0x15] = psxBios__cdevinput;
3532         //biosC0[0x16] = psxBios__cdevscan;
3533         //biosC0[0x17] = psxBios__circgetc;
3534         //biosC0[0x18] = psxBios__circputc;
3535         //biosC0[0x19] = psxBios_ioabort;
3536         //biosC0[0x1a] = psxBios_sys_c0_1a
3537         //biosC0[0x1b] = psxBios_KernelRedirect;
3538         //biosC0[0x1c] = psxBios_PatchAOTable;
3539 //************** THE END ***************************************
3540 /**/
3541
3542         memset(FDesc, 0, sizeof(FDesc));
3543
3544         // initial RNG seed
3545         psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3546
3547         // somewhat pretend to be a SCPH1001 BIOS
3548         // some games look for these and take an exception if they're missing
3549         rom32 = (u32 *)psxR;
3550         rom32[0x100/4] = SWAP32(0x19951204);
3551         rom32[0x104/4] = SWAP32(3);
3552         strcpy(psxR + 0x108, "PCSX authors");
3553         strcpy(psxR + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3554         strcpy(psxR + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3555         strcpy(psxR + 0x7ff54, "GPL-2.0-or-later");
3556
3557         // fonts
3558         len = 0x80000 - 0x66000;
3559         uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3560         len = 0x80000 - 0x69d68;
3561         uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3562
3563         /*      Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3564                 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3565                 Here are some examples of games not working with this fix in place :
3566                 R-type won't get past the Irem logo if not implemented.
3567                 Crash Team Racing will softlock after the Sony logo.
3568         */
3569
3570         ram32 = (u32 *)psxM;
3571         ram32[0x0000/4] = SWAPu32(0x00000003); // lui   $k0, 0  (overwritten by 3)
3572         ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3573         ram32[0x0008/4] = SWAPu32(0x03400008); // jr    $k0
3574         ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3575
3576         ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3577         ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3578
3579         ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui   $k0, 0  // exception vector
3580         ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3581         ram32[0x0088/4] = SWAPu32(0x03400008); // jr    $k0
3582         ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3583
3584         ram32[0x00a0/4] = HLEOP(hleop_a0);
3585         ram32[0x00b0/4] = HLEOP(hleop_b0);
3586         ram32[0x00c0/4] = HLEOP(hleop_c0);
3587
3588         setup_tt(4, 16);
3589
3590         ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3591         strcpy((char *)&ram32[0xeff0/4], "bu");
3592
3593         // default exception handler chains
3594         write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3595         write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3596         write_chain(&ram32[0x6da8/4],      0,          0,     0x1a00); // chain0.e2
3597         write_chain(&ram32[0x6d88/4], 0x6d78,     0x19c8,     0x18bc); // chain1.e0
3598         write_chain(&ram32[0x6d78/4], 0x6d68,     0x1990,     0x1858); // chain1.e1
3599         write_chain(&ram32[0x6d68/4], 0x6d58,     0x1958,     0x17f4); // chain1.e2
3600         write_chain(&ram32[0x6d58/4],      0,     0x1920,     0x1794); // chain1.e3
3601         write_chain(&ram32[0x6d98/4],      0,          0,     0x2458); // chain3.e0
3602
3603         setup_mips_code();
3604
3605         // fill the api jumptables with fake entries as some games patch them
3606         // (or rather the funcs listed there)
3607         ptr = (u32 *)&psxM[A_A0_TABLE];
3608         for (i = 0; i < 256; i++)
3609                 ptr[i] = SWAP32(0x1000);
3610
3611         ptr = (u32 *)&psxM[A_B0_TABLE];
3612         for (i = 0; i < 256; i++)
3613                 ptr[i] = SWAP32(0x2000);
3614         // B(5b) is special because games patch (sometimes even jump to)
3615         // code at fixed offsets from it, nocash lists offsets:
3616         //  patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3617         //  call:  +7a0=4b70, +884=4c54, +894=4c64
3618         ptr[0x5b] = SWAP32(0x43d0);
3619         ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3620
3621         ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3622         ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3623         ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3624
3625         ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3626         ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3627
3628         ptr = (u32 *)&psxM[A_C0_TABLE];
3629         for (i = 0; i < 256/2; i++)
3630                 ptr[i] = SWAP32(0x3000);
3631         ptr[6] = SWAP32(A_EXCEPTION);
3632
3633         // more HLE traps
3634         ram32[0x1000/4] = HLEOP(hleop_dummy);
3635         ram32[0x2000/4] = HLEOP(hleop_dummy);
3636         ram32[0x3000/4] = HLEOP(hleop_dummy);
3637         ram32[0x4c54/4] = HLEOP(hleop_dummy);   // for B12_InitPad?
3638         ram32[0x8000/4] = HLEOP(hleop_execret);
3639
3640         ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3641         ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3642         ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3643         ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3644         ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3645         ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3646 }
3647
3648 void psxBiosShutdown() {
3649 }
3650
3651 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt) {
3652         if (tcb_cnt != 4 || evcb_cnt != 16)
3653                 setup_tt(tcb_cnt, evcb_cnt);
3654 }
3655
3656 #define psxBios_PADpoll(pad) { \
3657         PAD##pad##_startPoll(pad); \
3658         pad_buf##pad[0] = 0; \
3659         pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3660         if (!(pad_buf##pad[1] & 0x0f)) { \
3661                 bufcount = 32; \
3662         } else { \
3663                 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3664         } \
3665         PAD##pad##_poll(0); \
3666         i = 2; \
3667         while (bufcount--) { \
3668                 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3669         } \
3670 }
3671
3672 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3673 {
3674         use_cycles(10);
3675         if (enable) {
3676                 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3677                 psxBios_ReturnFromException();
3678         }
3679         else
3680                 pc0 = ra;
3681 }
3682
3683 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3684 // so this is only partially implemented
3685 void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3686 {
3687         u32 cdrom_dma_ack_enable = 1; // a000b93c
3688         handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3689 }
3690
3691 void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3692 {
3693         u32 ret = 0;
3694         //PSXBIOS_LOG("%s\n", __func__);
3695
3696         if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3697                 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3698                 //if (--cdrom_irq_counter == 0) // 0xa0009180
3699                 //      DeliverEvent(0xf0000003, 0x10);
3700                 use_cycles(22);
3701                 ret = 1;
3702         }
3703         mips_return_c(ret, 20);
3704 }
3705
3706 void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3707 {
3708         u32 cdrom_irq_ack_enable = 1; // a000b938
3709         handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3710 }
3711
3712 void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3713 {
3714         u32 ret = 0;
3715         if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3716                 PSXBIOS_LOG("%s TODO\n", __func__);
3717                 ret = 1;
3718         }
3719         mips_return_c(ret, 20);
3720 }
3721
3722 void hleExc0_2_2_syscall() // not in any A/B/C table
3723 {
3724         u32 code = (psxRegs.CP0.n.Cause & 0x3c) >> 2;
3725         u32 tcbPtr = loadRam32(A_TT_PCB);
3726         TCB *tcb = loadRam32ptr(tcbPtr);
3727
3728         if (code != R3000E_Syscall) {
3729                 if (code != 0) {
3730                         DeliverEvent(0xf0000010, 0x1000);
3731                         //psxBios_SystemErrorUnresolvedException();
3732                 }
3733                 mips_return_c(0, 17);
3734                 return;
3735         }
3736
3737         //printf("%s c=%d a0=%d\n", __func__, code, a0);
3738         tcb->epc += SWAP32(4);
3739         switch (a0) {
3740                 case 0: // noop
3741                         break;
3742
3743                 case 1: { // EnterCritical - disable irqs
3744                         u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3745                         tcb->reg[2] = SWAP32(was_enabled);
3746                         tcb->sr &= SWAP32(~0x404);
3747                         break;
3748                 }
3749                 case 2: // ExitCritical - enable irqs
3750                         tcb->sr |= SWAP32(0x404);
3751                         break;
3752
3753                 case 3: { // ChangeThreadSubFunction
3754                         u32 tcbPtr = loadRam32(A_TT_PCB);
3755                         storeRam32(tcbPtr, a1);
3756                         break;
3757                 }
3758                 default:
3759                         DeliverEvent(0xf0000010, 0x4000);
3760                         break;
3761         }
3762         use_cycles(30);
3763         psxBios_ReturnFromException();
3764 }
3765
3766 void hleExc1_0_1(void)
3767 {
3768         u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3769         handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3770 }
3771
3772 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3773 {
3774         u32 ret = 0;
3775         if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3776                 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3777                 ret = 1;
3778         }
3779         mips_return_c(ret, 22);
3780 }
3781
3782 void hleExc1_0_2(void)
3783 {
3784         handle_chain_1_x_2(3, 0); // IRQ0 vblank
3785 }
3786
3787 void hleExc1_1_1(void)
3788 {
3789         u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3790         handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3791 }
3792
3793 void hleExc1_1_2(void)
3794 {
3795         handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3796 }
3797
3798 void hleExc1_2_1(void)
3799 {
3800         u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3801         handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3802 }
3803
3804 void hleExc1_2_2(void)
3805 {
3806         handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3807 }
3808
3809 void hleExc1_3_1(void)
3810 {
3811         u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3812         handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3813 }
3814
3815 void hleExc1_3_2(void)
3816 {
3817         handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3818 }
3819
3820 void hleExc3_0_2_defint(void)
3821 {
3822         static const struct {
3823                 u8 ev, irqbit;
3824         } tab[] = {
3825                 {  3,  2 }, // cdrom
3826                 {  9,  9 }, // spu
3827                 {  2,  1 }, // gpu
3828                 { 10, 10 }, // io
3829                 { 11,  8 }, // sio
3830                 {  1,  0 }, // vbl
3831                 {  5,  4 }, // rcnt0
3832                 {  6,  5 }, // rcnt1
3833                 {  6,  6 }, // rcnt2 (bug)
3834                 {  8,  7 }, // sio rx
3835                 {  4,  3 }, // sio
3836         };
3837         size_t i;
3838         for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3839                 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3840                         DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3841                         use_cycles(7);
3842                 }
3843
3844         }
3845         mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3846 }
3847
3848 void hleExcPadCard1(void)
3849 {
3850         if (loadRam32(A_PAD_IRQR_ENA)) {
3851                 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3852                 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
3853                 int i, bufcount;
3854
3855                 psxBios_PADpoll(1);
3856                 psxBios_PADpoll(2);
3857                 use_cycles(100);
3858                 if (loadRam32(A_PAD_DR_DST))
3859                         psxBios_PAD_dr_();
3860         }
3861         if (loadRam32(A_PAD_ACK_VBL))
3862                 psxHwWrite16(0x1f801070, ~1);
3863         if (loadRam32(A_CARD_IRQR_ENA)) {
3864                 // todo, maybe
3865         }
3866
3867         mips_return_c(0, 18);
3868 }
3869
3870 void hleExcPadCard2(void)
3871 {
3872         u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
3873         mips_return_c(ret, 15);
3874 }
3875
3876 void psxBiosException() {
3877         u32 tcbPtr = loadRam32(A_TT_PCB);
3878         u32 *chains = loadRam32ptr(A_TT_ExCB);
3879         TCB *tcb = loadRam32ptr(tcbPtr);
3880         u32 ptr, *chain;
3881         int c, lim;
3882         int i;
3883
3884         // save the regs
3885         // $at, $v0, $v1 already saved by the mips code at A_EXCEPTION
3886         for (i = 4; i < 32; i++) {
3887                 if (i == 26) // $k0
3888                         continue;
3889                 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
3890         }
3891         tcb->lo = SWAP32(psxRegs.GPR.n.lo);
3892         tcb->hi = SWAP32(psxRegs.GPR.n.hi);
3893         //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
3894         tcb->sr = SWAP32(psxRegs.CP0.n.SR);
3895         tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
3896         sp = fp = loadRam32(A_EXC_SP);
3897         gp = A_EXC_GP;
3898         use_cycles(46);
3899
3900         // do the chains (always 4)
3901         for (c = lim = 0; c < 4; c++) {
3902                 if (chains[c * 2] == 0)
3903                         continue;
3904                 ptr = SWAP32(chains[c * 2]);
3905                 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
3906                         chain = castRam32ptr(ptr);
3907                         use_cycles(14);
3908                         lim++;
3909                         if (chain[2] == 0)
3910                                 continue;
3911                         softCallInException(SWAP32(chain[2]));
3912                         if (returned_from_exception())
3913                                 return;
3914
3915                         if (v0 == 0 || chain[1] == 0)
3916                                 continue;
3917                         softCallInException(SWAP32(chain[1]));
3918                         if (returned_from_exception())
3919                                 return;
3920                 }
3921         }
3922         assert(lim < 100);
3923
3924         // return from exception (custom or default)
3925         use_cycles(23);
3926         ptr = loadRam32(A_EEXIT_PTR);
3927         if (ptr != A_EEXIT_DEF) {
3928                 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
3929                 longjmp_load(jmp_buf);
3930                 v0 = 1;
3931                 pc0 = ra;
3932                 return;
3933         }
3934         psxBios_ReturnFromException();
3935 }
3936
3937 #define bfreeze(ptr, size) { \
3938         if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3939         if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3940         base += size; \
3941 }
3942
3943 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3944 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3945
3946 #define bfreezepsxMptr(ptr, type) { \
3947         if (Mode == 1) { \
3948                 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3949                 else psxRu32ref(base) = 0; \
3950         } else { \
3951                 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3952                 else (ptr) = NULL; \
3953         } \
3954         base += sizeof(u32); \
3955 }
3956
3957 void psxBiosFreeze(int Mode) {
3958         u32 base = 0x40000;
3959
3960         bfreezes(FDesc);
3961 }