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