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