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