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