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, *
2db412ad 3 * dmitrysmagin, senquack *
ef79bbde
P
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
19 ***************************************************************************/
20
7a8d521f 21/* Gameblabla 2018-2019 :
8254b5a7 22 * Numerous changes to bios calls as well as improvements in order to conform to nocash's findings
23 * for the PSX bios calls. Thanks senquack for helping out with some of the changes
24 * and helping to spot issues and refine my patches.
25 * */
26
ef79bbde
P
27/*
28 * Internal simulated HLE BIOS.
29 */
30
31// TODO: implement all system calls, count the exact CPU cycles of system calls.
32
33#include "psxbios.h"
34#include "psxhw.h"
ddbaf678 35#include "gpu.h"
7a8d521f 36#include "sio.h"
dc4fa8bc 37#include "psxhle.h"
31cd6032 38#include "psxinterpreter.h"
496d88d4 39#include <zlib.h>
ef79bbde 40
31cd6032 41#ifndef PSXBIOS_LOG
42//#define PSXBIOS_LOG printf
43#define PSXBIOS_LOG(...)
44#endif
452b85f9 45
1da9b9ae 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
31cd6032 70 "SystemErrorUnresolvedException", "LoadTest", "Load", "Exec",
ef79bbde 71 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
31cd6032 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
dc4fa8bc 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",
31cd6032 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)
14b3bd95 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 {
4d2f73bb 197 u32 class;
198 u32 status;
199 u32 spec;
200 u32 mode;
ef79bbde 201 u32 fhandler;
4d2f73bb 202 u32 unused[2];
203} EvCB;
ef79bbde 204
4d2f73bb 205#define EvStUNUSED 0x0000
206#define EvStDISABLED 0x1000
207#define EvStACTIVE 0x2000
208#define EvStALREADY 0x4000
ef79bbde 209
4d2f73bb 210#define EvMdCALL 0x1000
211#define EvMdMARK 0x2000
ef79bbde
P
212
213typedef struct {
dc4fa8bc 214 u32 status;
215 u32 mode;
ef79bbde 216 u32 reg[32];
dc4fa8bc 217 u32 epc;
218 u32 hi, lo;
219 u32 sr, cause;
220 u32 unused[9];
ef79bbde
P
221} TCB;
222
7a8d521f 223typedef struct {
ef79bbde
P
224 u32 _pc0;
225 u32 gp0;
226 u32 t_addr;
227 u32 t_size;
31cd6032 228 u32 d_addr; // 10
ef79bbde
P
229 u32 d_size;
230 u32 b_addr;
31cd6032 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
1e50f05b 254// todo: FileDesc layout is wrong
255// todo: get rid of these globals
ef79bbde 256static FileDesc FDesc[32];
7c3332fb 257static char ffile[64];
1e50f05b 258static int nfile;
0a50313e 259static char cdir[8*8+8];
260static u32 floodchk;
ef79bbde 261
dc4fa8bc 262// fixed RAM offsets, SCPH1001 compatible
263#define A_TT_ExCB 0x0100
264#define A_TT_PCB 0x0108
265#define A_TT_TCB 0x0110
4d2f73bb 266#define A_TT_EvCB 0x0120
dc4fa8bc 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
7650b754 274#define A_KMALLOC_PTR 0x7460
275#define A_KMALLOC_SIZE 0x7464
276#define A_KMALLOC_END 0x7468
2bce5171 277#define A_PADCRD_CHN_E 0x74a8 // pad/card irq chain entry, see hleExcPadCard1()
ea72f34a 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
2bce5171 284#define A_PAD_DR_DST 0x74c4
1e50f05b 285#define A_CARD_CHAN1 0x7500
2bce5171 286#define A_PAD_DR_BUF1 0x7570
287#define A_PAD_DR_BUF2 0x7598
dc4fa8bc 288#define A_EEXIT_PTR 0x75d0
289#define A_EXC_STACK 0x85d8 // exception stack top
290#define A_RCNT_VBL_ACK 0x8600
ea72f34a 291#define A_PAD_ACK_VBL 0x8914 // enable vint ack by pad reading code
1e50f05b 292#define A_HEAP_BASE 0x9000
293#define A_HEAP_SIZE 0x9004
294#define A_HEAP_END 0x9008
46fe9496 295#define A_HEAP_INIT_FLG 0x900c
7c3332fb 296#define A_RND_SEED 0x9010
46fe9496 297#define A_HEAP_FRSTCHNK 0xb060
298#define A_HEAP_CURCHNK 0xb064
5c8119b8 299#define A_CONF_TCB 0xb940
300#define A_CONF_EvCB 0xb944
301#define A_CONF_SP 0xb948
4d2f73bb 302#define A_CD_EVENTS 0xb9b8
dc4fa8bc 303#define A_EXC_GP 0xf450
304
0890ae15 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
dc4fa8bc 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
ea72f34a 318static void *castRam8ptr(u32 addr)
319{
320 assert(!(addr & 0x5f800000));
321 return psxM + (addr & 0x1fffff);
322}
323
dc4fa8bc 324static void *castRam32ptr(u32 addr)
325{
326 assert(!(addr & 0x5f800003));
327 return psxM + (addr & 0x1ffffc);
328}
329
ea72f34a 330static void *loadRam8ptr(u32 addr)
331{
332 return castRam8ptr(loadRam32(addr));
333}
334
dc4fa8bc 335static void *loadRam32ptr(u32 addr)
336{
337 return castRam32ptr(loadRam32(addr));
338}
339
ea72f34a 340static void storeRam8(u32 addr, u8 d)
341{
342 assert(!(addr & 0x5f800000));
343 *((u8 *)psxM + (addr & 0x1fffff)) = d;
344}
345
dc4fa8bc 346static void storeRam32(u32 addr, u32 d)
347{
348 assert(!(addr & 0x5f800000));
349 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
350}
ef79bbde 351
dc4fa8bc 352static void mips_return(u32 val)
353{
354 v0 = val;
355 pc0 = ra;
356}
ef79bbde 357
fed9fd6f 358static void mips_return_void(void)
359{
360 pc0 = ra;
361}
362
dc4fa8bc 363static void use_cycles(u32 cycle)
364{
365 psxRegs.cycle += cycle * 2;
366}
ef79bbde 367
dc4fa8bc 368static void mips_return_c(u32 val, u32 cycle)
369{
370 use_cycles(cycle);
371 mips_return(val);
ef79bbde
P
372}
373
dc4fa8bc 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;
dc4fa8bc 388 u32 ssr = psxRegs.CP0.n.SR;
31cd6032 389 u32 lim = 0;
ef79bbde
P
390 pc0 = pc;
391 ra = 0x80001000;
dc4fa8bc 392 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
ef79bbde 393
1da9b9ae 394 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
395
31cd6032 396 while (pc0 != 0x80001000 && ++lim < 1000000)
dc4fa8bc 397 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
ef79bbde 398
1da9b9ae 399 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
400
31cd6032 401 if (lim == 1000000)
402 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
ef79bbde 403 ra = sra;
31cd6032 404 psxRegs.CP0.n.SR |= ssr & 0x404;
dc4fa8bc 405}
ef79bbde 406
dc4fa8bc 407static inline void softCallInException(u32 pc) {
408 u32 sra = ra;
31cd6032 409 u32 lim = 0;
dc4fa8bc 410 pc0 = pc;
7c3332fb 411
412 assert(ra != 0x80001000);
413 if (ra == 0x80001000)
414 return;
dc4fa8bc 415 ra = 0x80001000;
416
1da9b9ae 417 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
418
31cd6032 419 while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 1000000)
dc4fa8bc 420 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
421
1da9b9ae 422 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
423
31cd6032 424 if (lim == 1000000)
425 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
dc4fa8bc 426 if (pc0 == 0x80001000)
427 ra = sra;
ef79bbde
P
428}
429
4d2f73bb 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
d99f6068 440
441#define buread(Ra1, mcd, length) { \
31cd6032 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); \
86c70511 445 psxCpu->Clear(a1, (length + 3) / 4); \
f1514614 446 if (FDesc[1 + mcd].mode & 0x8000) { \
4d2f73bb 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; \
31cd6032 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; \
e49ac7a5 460 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
f1514614 461 if (FDesc[1 + mcd].mode & 0x8000) { \
4d2f73bb 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
7a8d521f 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;
7a8d521f 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
dc4fa8bc 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
dc4fa8bc 595 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
ef79bbde 596
dc4fa8bc 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
dc4fa8bc 601 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
602 jmp_buf->gp_ = SWAP32(gp);
ef79bbde 603
dc4fa8bc 604 mips_return_c(0, 15);
ef79bbde
P
605}
606
dc4fa8bc 607static void longjmp_load(const struct jmp_buf_ *jmp_buf)
608{
ef79bbde
P
609 int i;
610
dc4fa8bc 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
dc4fa8bc 615 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
616 gp = SWAP32(jmp_buf->gp_);;
617}
ef79bbde 618
dc4fa8bc 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 }
7a8d521f 815
ef79bbde
P
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
86c70511 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 }
86c70511 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
660b4e51 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
1e50f05b 985static void psxBios_bzero() { // 0x28
01724d23 986 /* Same as memset here (See memset below) */
86c70511 987 u32 ret = a0, cycles;
1e50f05b 988 if (a0 == 0 || (s32)a1 <= 0)
01724d23 989 {
1e50f05b 990 mips_return_c(0, 6);
01724d23 991 return;
992 }
86c70511 993 do_memset(a0, 0, a1);
994 cycles = a1 * 4;
995 a0 += a1;
996 a1 = 0;
1e50f05b 997 // todo: many more cycles due to uncached bios mem
86c70511 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
86c70511 1017static void psxBios_memcpy() { // 0x2a
1018 u32 ret = a0, cycles = 0;
1019 if (a0 == 0)
ef1da3dc 1020 {
86c70511 1021 mips_return_c(0, 4);
ef1da3dc 1022 return;
1023 }
fed9fd6f 1024 v1 = a0;
86c70511 1025 if ((s32)a2 > 0) {
1026 do_memcpy(a0, a1, a2);
1027 cycles = a2 * 6;
86c70511 1028 a0 += a2;
1029 a1 += a2;
1030 a2 = 0;
ef1da3dc 1031 }
86c70511 1032 mips_return_c(ret, cycles + 5);
ef79bbde
P
1033}
1034
1e50f05b 1035static void psxBios_memset() { // 0x2b
86c70511 1036 u32 ret = a0, cycles;
1e50f05b 1037 if (a0 == 0 || (s32)a2 <= 0)
3f28b64f 1038 {
1e50f05b 1039 mips_return_c(0, 6);
3f28b64f 1040 return;
1041 }
86c70511 1042 do_memset(a0, a1, a2);
1043 cycles = a2 * 4;
1044 a0 += a2;
1045 a2 = 0;
1e50f05b 1046 // todo: many more cycles due to uncached bios mem
86c70511 1047 mips_return_c(ret, cycles + 5);
ef79bbde
P
1048}
1049
1050void psxBios_memmove() { // 0x2c
86c70511 1051 u32 ret = a0, cycles = 0;
1052 if (a0 == 0)
112dddf5 1053 {
86c70511 1054 mips_return_c(0, 4);
112dddf5 1055 return;
1056 }
86c70511 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 }
86c70511 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;
7a8d521f 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
7c3332fb 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
7c3332fb 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
dc4fa8bc 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
46fe9496 1224static int malloc_heap_grow(u32 size) {
1225 u32 heap_addr, heap_end, heap_addr_new;
ef79bbde 1226
46fe9496 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 }
46fe9496 1257 storeRam32(A_HEAP_INIT_FLG, 1);
1258 }
26b964b5 1259
46fe9496 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 }
46fe9496 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 {
46fe9496 1295 // go to the next chunk
1296 storeRam32(A_HEAP_CURCHNK, next_chunk);
ef79bbde 1297 }
ef79bbde
P
1298 }
1299
46fe9496 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
46fe9496 1310 PSXBIOS_LOG(" -> %08x\n", ret);
1311 mips_return_c(ret, 40);
ef79bbde
P
1312}
1313
1e50f05b 1314static void psxBios_free() { // 0x34
46fe9496 1315 PSXBIOS_LOG("psxBios_%s %x (%d bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1e50f05b 1316 storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1317 mips_return_void_c(5);
ef79bbde
P
1318}
1319
1e50f05b 1320static void psxBios_calloc() { // 0x37
1321 u32 ret, size;
1322 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
ef79bbde 1323
1e50f05b 1324 a0 = size = a0 * a1;
ef79bbde 1325 psxBios_malloc();
1e50f05b 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) */
1e50f05b 1364static void psxBios_InitHeap() { // 0x39
1365 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
ef79bbde 1366
1e50f05b 1367 storeRam32(A_HEAP_BASE, a0);
1368 storeRam32(A_HEAP_SIZE, a1);
1369 storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
46fe9496 1370 storeRam32(A_HEAP_INIT_FLG, 0);
1e50f05b 1371 storeRam32(a0, 0);
ef79bbde 1372
1e50f05b 1373 mips_return_void_c(14);
ef79bbde
P
1374}
1375
1376void psxBios_getchar() { //0x3b
1377 v0 = getchar(); pc0 = ra;
1378}
1379
a94ccc7f 1380static void psxBios_printf_psxout() { // 0x3f
ef79bbde
P
1381 char tmp[1024];
1382 char tmp2[1024];
0890ae15 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);
7a8d521f 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
a94ccc7f 1445 if (psp != INVALID_PTR)
02949f79 1446 memcpy(psp, save, 4 * 4);
ef79bbde 1447
31cd6032 1448 if (Config.PsxOut)
1449 SysPrintf("%s", tmp);
a94ccc7f 1450}
ef79bbde 1451
a94ccc7f 1452void psxBios_printf() { // 0x3f
1453 psxBios_printf_psxout();
ef79bbde
P
1454 pc0 = ra;
1455}
1456
0a50313e 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
dc4fa8bc 1489static void psxBios_SystemErrorUnresolvedException() {
0a50313e 1490 if (floodchk != 0x12340a40) { // prevent log flood
31cd6032 1491 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
0a50313e 1492 floodchk = 0x12340a40;
dc4fa8bc 1493 }
1494 mips_return_void_c(1000);
1495}
1496
fed9fd6f 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;
0a50313e 1511 char path[256];
1512 char *pa0, *p;
02949f79 1513 void *pa1;
ef79bbde 1514
0a50313e 1515 pa0 = Ra0;
02949f79 1516 pa1 = Ra1;
0a50313e 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));
86c70511 1533 psxCpu->Clear(a1, sizeof(EXEC) / 4);
fed9fd6f 1534 FlushCache();
ef79bbde
P
1535 v0 = 1;
1536 } else v0 = 0;
0a50313e 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
31cd6032 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
31cd6032 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
31cd6032 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
31cd6032 1570 gp = SWAP32(header->gp0);
ef79bbde
P
1571
1572 s0 = a0;
1573
1574 a0 = a1;
1575 a1 = a2;
1576
1577 ra = 0x8000;
31cd6032 1578 pc0 = SWAP32(header->_pc0);
ef79bbde
P
1579}
1580
fed9fd6f 1581static void psxBios_FlushCache() { // 44
ef79bbde 1582 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
fed9fd6f 1583 FlushCache();
1584 mips_return_void();
ef79bbde
P
1585}
1586
1587void psxBios_GPU_dw() { // 0x46
1588 int size;
3a284665 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);
3a284665 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;
7a8d521f 1606}
ef79bbde
P
1607
1608void psxBios_mem2vram() { // 0x47
1609 int size;
7c3332fb 1610 gpuSyncPluginSR(); // flush
ef79bbde 1611 GPU_writeData(0xa0000000);
3a284665 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...
3a284665 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);
7c3332fb 1633 gpuSyncPluginSR();
3a284665 1634 v0 = HW_GPU_STATUS;
7a8d521f 1635 pc0 = ra;
ef79bbde
P
1636}
1637
1638void psxBios_GPU_cwb() { // 0x4a
3a284665 1639 u32 *ptr = (u32*)Ra0;
ef79bbde 1640 int size = a1;
3a284665 1641 gpuSyncPluginSR();
1642 while(size--)
1643 {
1644 GPU_writeData(SWAPu32(*ptr++));
ef79bbde
P
1645 }
1646
1647 pc0 = ra;
1648}
1649
1650void psxBios_GPU_SendPackets() { //4b:
3a284665 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
7a8d521f 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
4d2f73bb 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
ea72f34a 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);
dc4fa8bc 1718
1719static void psxBios_DequeueCdIntr_() {
ea72f34a 1720 psxBios_SysDeqIntRP_(0, 0x91d0);
1721 psxBios_SysDeqIntRP_(0, 0x91e0);
dc4fa8bc 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
4d2f73bb 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));
dc4fa8bc 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
5c8119b8 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;
31cd6032 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;
31cd6032 1781 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
7a8d521f 1782
ef79bbde 1783 default:
31cd6032 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. */
1e50f05b 1792static void psxBios_get_cd_status() // a6
18dd7e9e 1793{
1e50f05b 1794 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
18dd7e9e 1795 v0 = 1;
1796 pc0 = ra;
1797}
1798
1e50f05b 1799static void psxBios__card_info() { // ab
ef79bbde 1800 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
7a8d521f 1801 u32 ret, port;
1e50f05b 1802 storeRam32(A_CARD_CHAN1, a0);
1803 port = a0 >> 4;
7a8d521f 1804
1805 switch (port) {
1806 case 0x0:
1807 case 0x1:
4d2f73bb 1808 ret = 0x0004;
7a8d521f 1809 if (McdDisable[port & 1])
4d2f73bb 1810 ret = 0x0100;
76b81516 1811 break;
1812 default:
1e50f05b 1813 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
4d2f73bb 1814 ret = 0x0302;
76b81516 1815 break;
1816 }
7a8d521f 1817
1818 if (McdDisable[0] && McdDisable[1])
4d2f73bb 1819 ret = 0x0100;
7a8d521f 1820
4d2f73bb 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
1e50f05b 1832 storeRam32(A_CARD_CHAN1, a0);
e9fda093 1833
4d2f73bb 1834// DeliverEvent(0xf0000011, 0x0004);
1835 DeliverEvent(0xf4000001, 0x0004);
ef79bbde
P
1836
1837 v0 = 1; pc0 = ra;
1838}
1839
31cd6032 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
7650b754 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
11d23573 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
4d2f73bb 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
7c3332fb 1942 //printf("%s %08x %x\n", __func__, class, spec);
4d2f73bb 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 }
0a50313e 1969 floodchk = 0;
4d2f73bb 1970 use_cycles(29);
1971 return ret;
1972}
ef79bbde 1973
4d2f73bb 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
4d2f73bb 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
4d2f73bb 1998static void psxBios_DeliverEvent() { // 07
1999 u32 ret;
2000 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
ef79bbde 2001
4d2f73bb 2002 ret = DeliverEvent(a0, a1);
2003 mips_return(ret);
2004}
ef79bbde 2005
4d2f73bb 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
4d2f73bb 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
4d2f73bb 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
4d2f73bb 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
4d2f73bb 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
4d2f73bb 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
4d2f73bb 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
4d2f73bb 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 }
4d2f73bb 2064 if (status != EvStACTIVE)
d95c9dcb 2065 {
4d2f73bb 2066 mips_return_c(0, 2);
d95c9dcb 2067 return;
2068 }
ef79bbde 2069
4d2f73bb 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
4d2f73bb 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;
0a50313e 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 }
4d2f73bb 2086 if (status == EvStALREADY) {
2087 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2088 ret = 1;
b4ae2532 2089 }
ef79bbde 2090
4d2f73bb 2091 mips_return_c(ret, 15);
ef79bbde
P
2092}
2093
4d2f73bb 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
4d2f73bb 2101 mips_return_c(1, 15);
ef79bbde
P
2102}
2103
4d2f73bb 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
4d2f73bb 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
dc4fa8bc 2119 TCB *tcb = loadRam32ptr(A_TT_TCB);
2120 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
ef79bbde
P
2121 int th;
2122
dc4fa8bc 2123 for (th = 1; th < limit; th++)
a66d3058 2124 {
dc4fa8bc 2125 if (tcb[th].status != SWAP32(0x4000)) break;
ef79bbde 2126
a66d3058 2127 }
dc4fa8bc 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
dc4fa8bc 2134 mips_return_c(0xffffffff, 20);
a66d3058 2135 return;
2136 }
5c8119b8 2137 PSXBIOS_LOG("psxBios_%s -> %x\n", biosB0n[0x0e], 0xff000000 + th);
ef79bbde 2138
dc4fa8bc 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
dc4fa8bc 2146 mips_return_c(0xff000000 + th, 34);
ef79bbde
P
2147}
2148
2149/*
2150 * int CloseTh(long thread);
2151 */
2152
5c8119b8 2153static void psxBios_CloseTh() { // 0f
2154 u32 tcb = loadRam32(A_TT_TCB);
2155 u32 th = a0 & 0xffff;
ef79bbde 2156
5c8119b8 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
5c8119b8 2161 mips_return_c(1, 11);
ef79bbde
P
2162}
2163
2164/*
2165 * int ChangeTh(long thread);
2166 */
2167
2168void psxBios_ChangeTh() { // 10
dc4fa8bc 2169 u32 tcbBase = loadRam32(A_TT_TCB);
2170 u32 th = a0 & 0xffff;
ef79bbde 2171
31cd6032 2172 // this is quite spammy
2173 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2174
dc4fa8bc 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
ea72f34a 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");
2bce5171 2188 ram32[A_PAD_DR_DST/4] = 0;
ea72f34a 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
ea72f34a 2208 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
ef79bbde 2209
ea72f34a 2210 mips_return_c(1, 200);
ef79bbde
P
2211}
2212
2213void psxBios_StartPAD() { // 13
ef79bbde 2214 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
ea72f34a 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);
bc7c5acb 2222 psxRegs.CP0.n.SR |= 0x401;
ea72f34a 2223
2224 mips_return_c(1, 300);
ef79bbde
P
2225}
2226
2227void psxBios_StopPAD() { // 14
ef79bbde 2228 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
ea72f34a 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
2bce5171 2235static void psxBios_PAD_init() { // 15
2236 u32 ret = 0;
ef79bbde 2237 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2bce5171 2238 if (a0 == 0x20000000 || a0 == 0x20000001)
a824e83d 2239 {
2bce5171 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 }
2bce5171 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
2bce5171 2278static void psxBios_PAD_dr() { // 16
ef79bbde 2279 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2bce5171 2280 u32 ret = psxBios_PAD_dr_();
2281 mips_return(ret);
ef79bbde
P
2282}
2283
dc4fa8bc 2284static void psxBios_ReturnFromException() { // 17
2285 u32 tcbPtr = loadRam32(A_TT_PCB);
2286 const TCB *tcb = loadRam32ptr(tcbPtr);
31cd6032 2287 u32 sr;
dc4fa8bc 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);
31cd6032 2294 sr = SWAP32(tcb->sr);
ef79bbde 2295
dc4fa8bc 2296 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2297 pc0 = k0 = SWAP32(tcb->epc);
ef79bbde 2298
31cd6032 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
dc4fa8bc 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
dc4fa8bc 2310 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2311 mips_return_void_c(5);
ef79bbde
P
2312}
2313
2314void psxBios_HookEntryInt() { // 19
dc4fa8bc 2315 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
ef79bbde 2316
dc4fa8bc 2317 storeRam32(A_EEXIT_PTR, a0);
2318 mips_return_void_c(3);
ef79bbde
P
2319}
2320
4d2f73bb 2321static void psxBios_UnDeliverEvent() { // 0x20
2322 u32 ret;
2323 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
ef79bbde 2324
4d2f73bb 2325 ret = UnDeliverEvent(a0, a1);
2326 mips_return(ret);
ef79bbde
P
2327}
2328
857275a9 2329static void buopen(int mcd, char *ptr, char *cfg)
595a136b 2330{
2331 int i;
7a8d521f 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++) {
7a8d521f 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;
31cd6032 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;
7a8d521f 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);
7a8d521f 2362 pptr = fptr2 = fptr;
595a136b 2363 for(j=2; j<=nblk; j++) {
2364 int k;
2365 for(i++; i<16; i++) {
2366 fptr2 += 128;
7a8d521f 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;
31cd6032 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
7c3332fb 2399 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x32], Ra0, a1);
ef79bbde
P
2400
2401 v0 = -1;
2402
7a8d521f 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;
4d2f73bb 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
595a136b 2442
ef79bbde
P
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
7a8d521f 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 }
7a8d521f 2463
ef79bbde
P
2464 pc0 = ra;
2465}
2466
ef79bbde
P
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
31cd6032 2475 if (a0 != 1) // stdout
2476 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
02949f79 2477
2478 v0 = -1;
7a8d521f 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;
31cd6032 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
a94ccc7f 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
31cd6032 2535 if (Config.PsxOut) SysPrintf("%c", (char)a0);
ef79bbde
P
2536 pc0 = ra;
2537}
2538
2539void psxBios_puts() { // 3e/3f
31cd6032 2540 if (Config.PsxOut) SysPrintf("%s", Ra0);
ef79bbde
P
2541 pc0 = ra;
2542}
2543
f7cfdeaf 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
f7cfdeaf 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;
27f734f9 2586 const char *name = (const char *)data2 + 0x0a;
f7cfdeaf 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 */
7a8d521f 2604
7c3332fb 2605static void psxBios_firstfile() { // 42
7c3332fb 2606 char *pa0 = castRam8ptr(a0);
ef79bbde 2607
f7cfdeaf 2608 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x42], pa0, a1);
ef79bbde
P
2609 v0 = 0;
2610
7c3332fb 2611 {
2612 snprintf(ffile, sizeof(ffile), "%s", pa0);
f7cfdeaf 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
4d2f73bb 2618 DeliverEvent(0xf0000011, 0x0004);
27f734f9 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
4d2f73bb 2622 DeliverEvent(0xf0000011, 0x0004);
27f734f9 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
f7cfdeaf 2635 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x43], a0);
ef79bbde 2636
ef79bbde 2637 v0 = 0;
f7cfdeaf 2638 if (!strncmp(ffile, "bu00", 4))
27f734f9 2639 bufile((u8 *)Mcd1Data, a0);
f7cfdeaf 2640 else if (!strncmp(ffile, "bu10", 4))
27f734f9 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
7a8d521f 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); \
31cd6032 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
7a8d521f 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
ea72f34a 2735 u32 *ram32 = (u32 *)psxM;
ef79bbde 2736 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
ea72f34a 2737 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
fed9fd6f 2738 // (maybe) todo: early_card_irq, etc
ef79bbde 2739
ea72f34a 2740 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2741
fed9fd6f 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]);
ea72f34a 2748 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2749 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
ef79bbde 2750
ea72f34a 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]);
ea72f34a 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 }
1e50f05b 2786 storeRam32(A_CARD_CHAN1, a0);
ef79bbde
P
2787 port = a0 >> 4;
2788
7a8d521f 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
4d2f73bb 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 }
1e50f05b 2822 storeRam32(A_CARD_CHAN1, a0);
ef79bbde
P
2823 port = a0 >> 4;
2824
7a8d521f 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
4d2f73bb 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
7a8d521f 2849{
dc4fa8bc 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
dc4fa8bc 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]);
dc4fa8bc 2901 log_unhandled("GetC0Table @%08x\n", ra);
ef79bbde 2902
dc4fa8bc 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]);
dc4fa8bc 2908 log_unhandled("GetB0Table @%08x\n", ra);
ef79bbde 2909
dc4fa8bc 2910 mips_return_c(A_B0_TABLE, 3);
ef79bbde
P
2911}
2912
1e50f05b 2913static void psxBios__card_chan() { // 0x58
2914 u32 ret;
e9fda093 2915 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
e9fda093 2916
1e50f05b 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
ea72f34a 2923static void psxBios_ChangeClearPad() { // 5b
2924 u32 ret;
ef79bbde 2925 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
ea72f34a 2926 ret = loadRam32(A_PAD_ACK_VBL);
2927 storeRam32(A_PAD_ACK_VBL, a0);
ef79bbde 2928
ea72f34a 2929 mips_return_c(ret, 6);
ef79bbde
P
2930}
2931
1e50f05b 2932static void psxBios__card_status() { // 5c
2933 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
21af3ff6 2934
1e50f05b 2935 v0 = 1; // ready
21af3ff6 2936 pc0 = ra;
2937}
2938
1e50f05b 2939static void psxBios__card_wait() { // 5d
2940 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
5f652aa9 2941
1e50f05b 2942 v0 = 1; // ready
5f652aa9 2943 pc0 = ra;
2944}
2945
ef79bbde
P
2946/* System calls C0 */
2947
7650b754 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 }
ea72f34a 2957 psxBios_SysEnqIntRP_(a0, 0x6d88);
7650b754 2958 mips_return_c(0, 9);
2959}
2960
2961static void psxBios_InitException() { // 01
2962 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
ea72f34a 2963 psxBios_SysEnqIntRP_(a0, 0x6da8);
7650b754 2964 mips_return_c(0, 9);
2965}
2966
ef79bbde
P
2967/*
2968 * int SysEnqIntRP(int index , long *queue);
2969 */
2970
ea72f34a 2971static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
dc4fa8bc 2972 u32 old, base = loadRam32(A_TT_ExCB);
ef79bbde 2973
ea72f34a 2974 old = loadRam32(base + (priority << 3));
2975 storeRam32(base + (priority << 3), chain_eptr);
2976 storeRam32(chain_eptr, old);
dc4fa8bc 2977 mips_return_c(0, 9);
ef79bbde
P
2978}
2979
ea72f34a 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
ea72f34a 2989static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
dc4fa8bc 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
ea72f34a 2994 ptr = loadRam32(base + (priority << 3));
dc4fa8bc 2995 while (ptr) {
2996 next = loadRam32(ptr);
ea72f34a 2997 if (ptr == chain_rm_eptr) {
2998 storeRam32(base + (priority << 3), next);
dc4fa8bc 2999 ret = ptr;
3000 use_cycles(6);
3001 break;
3002 }
ea72f34a 3003 while (next && next != chain_rm_eptr && lim++ < 100) {
dc4fa8bc 3004 ptr = next;
3005 next = loadRam32(ptr);
3006 use_cycles(8);
3007 }
ea72f34a 3008 if (next == chain_rm_eptr) {
dc4fa8bc 3009 next = loadRam32(next);
3010 storeRam32(ptr, next);
3011 ret = ptr;
3012 use_cycles(6);
3013 }
3014 break;
3015 }
3016 if (lim == 100)
ea72f34a 3017 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
ef79bbde 3018
dc4fa8bc 3019 mips_return_c(ret, 12);
3020}
ef79bbde 3021
dc4fa8bc 3022static void psxBios_SysDeqIntRP() { // 03
3023 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
ea72f34a 3024 psxBios_SysDeqIntRP_(a0, a1);
ef79bbde
P
3025}
3026
4d2f73bb 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
7650b754 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
dc4fa8bc 3058 u32 ret;
ef79bbde 3059
ef79bbde 3060 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
ef79bbde 3061
dc4fa8bc 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
7650b754 3067static void psxBios_InitDefInt() { // 0c
3068 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3069 // should also clear the autoack table
ea72f34a 3070 psxBios_SysEnqIntRP_(a0, 0x6d98);
7650b754 3071 mips_return_c(0, 20 + 6*2);
3072}
3073
7a8d521f 3074void psxBios_dummy() {
dc4fa8bc 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])();
dc4fa8bc 3085// C0 and B0 overlap (end of C0 is start of B0)
3086void (*biosC0[256+128])();
3087void (**biosB0)() = biosC0 + 128;
ef79bbde 3088
14b3bd95 3089static void setup_mips_code()
dc4fa8bc 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
dc4fa8bc 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 },
ea72f34a 3134 { 0x49bc, hleop_exc_padcard1 },
3135 { 0x4a4c, hleop_exc_padcard2 },
dc4fa8bc 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
ea72f34a 3154 // install the hle traps
fed9fd6f 3155 if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3156 if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
dc4fa8bc 3157}
3158
5c8119b8 3159static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack)
7650b754 3160{
3161 u32 *ram32 = (u32 *)psxM;
5c8119b8 3162 u32 s_excb = 0x20, s_evcb, s_pcb = 4, s_tcb;
7650b754 3163 u32 p_excb, p_evcb, p_pcb, p_tcb;
5c8119b8 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;
7650b754 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
5c8119b8 3204 for (i = 1; i < tcb_cnt; i++)
3205 storeRam32(p_tcb + sizeof(TCB) * i, 0x1000);
4d2f73bb 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));
5c8119b8 3213
3214 storeRam32(A_CONF_EvCB, evcb_cnt);
3215 storeRam32(A_CONF_TCB, tcb_cnt);
3216 storeRam32(A_CONF_SP, stack);
7650b754 3217}
3218
14b3bd95 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
0890ae15 3302static void hleExc0_0_1();
3303static void hleExc0_0_2();
3304static void hleExc0_1_1();
3305static void hleExc0_1_2();
3306
14b3bd95 3307#include "sjisfont.h"
3308
ef79bbde 3309void psxBiosInit() {
4d2f73bb 3310 u32 *ptr, *ram32, *rom32;
27f734f9 3311 char *romc;
ef79bbde
P
3312 int i;
3313 uLongf len;
3314
dc4fa8bc 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 }
a94ccc7f 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;
7a8d521f 3394 biosA0[0x3c] = psxBios_putchar;
ef79bbde 3395 //biosA0[0x3d] = psxBios_gets;
31cd6032 3396 biosA0[0x3e] = psxBios_puts;
3397 biosA0[0x3f] = psxBios_printf;
dc4fa8bc 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;
7a8d521f 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;
dc4fa8bc 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;
dc4fa8bc 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;
7a8d521f 3464 //biosA0[0x82] = psxBios_sys_a0_82;
ef79bbde
P
3465 //biosA0[0x83] = psxBios_sys_a0_83;
3466 //biosA0[0x84] = psxBios_sys_a0_84;
7a8d521f 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;
dc4fa8bc 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;
5c8119b8 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;
dc4fa8bc 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;
31cd6032 3514 biosA0[0xb4] = psxBios_GetSystemInfo;
ef79bbde 3515//*******************B0 CALLS****************************
7650b754 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;
31cd6032 3577 biosB0[0x3d] = psxBios_putchar;
ef79bbde 3578 //biosB0[0x3e] = psxBios_gets;
31cd6032 3579 biosB0[0x3f] = psxBios_puts;
0a50313e 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;
21af3ff6 3608 biosB0[0x5c] = psxBios__card_status;
5f652aa9 3609 biosB0[0x5d] = psxBios__card_wait;
ef79bbde 3610//*******************C0 CALLS****************************
7650b754 3611 biosC0[0x00] = psxBios_InitRCnt;
3612 biosC0[0x01] = psxBios_InitException;
ef79bbde
P
3613 biosC0[0x02] = psxBios_SysEnqIntRP;
3614 biosC0[0x03] = psxBios_SysDeqIntRP;
4d2f73bb 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;
7650b754 3619 biosC0[0x08] = psxBios_SysInitMemory;
ef79bbde 3620 //biosC0[0x09] = psxBios_SysInitKMem;
7a8d521f 3621 biosC0[0x0a] = psxBios_ChangeClearRCnt;
ef79bbde 3622 //biosC0[0x0b] = psxBios_SystemError;
7650b754 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));
0a50313e 3644 memset(cdir, 0, sizeof(cdir));
3645 floodchk = 0;
c62b43c9 3646
31cd6032 3647 // somewhat pretend to be a SCPH1001 BIOS
3648 // some games look for these and take an exception if they're missing
4d2f73bb 3649 rom32 = (u32 *)psxR;
3650 rom32[0x100/4] = SWAP32(0x19951204);
3651 rom32[0x104/4] = SWAP32(3);
27f734f9 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");
4d2f73bb 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
fed9fd6f 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 */
7a8d521f 3677
dc4fa8bc 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
5c8119b8 3696 setup_tt(4, 16, 0x801fff00);
3697 DeliverEvent(0xf0000003, 0x0010);
dc4fa8bc 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++)
0890ae15 3718 ptr[i] = SWAP32(A_A0_DUMMY);
dc4fa8bc 3719
3720 ptr = (u32 *)&psxM[A_B0_TABLE];
3721 for (i = 0; i < 256; i++)
0890ae15 3722 ptr[i] = SWAP32(A_B0_DUMMY);
dc4fa8bc 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
0890ae15 3727 ptr[0x5b] = SWAP32(A_B0_5B_DUMMY); // 0x43d0
ea72f34a 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
dc4fa8bc 3734 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
ea72f34a 3735 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
dc4fa8bc 3736
3737 ptr = (u32 *)&psxM[A_C0_TABLE];
3738 for (i = 0; i < 256/2; i++)
0890ae15 3739 ptr[i] = SWAP32(A_C0_DUMMY);
dc4fa8bc 3740 ptr[6] = SWAP32(A_EXCEPTION);
3741
3742 // more HLE traps
0890ae15 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);
dc4fa8bc 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);
7c3332fb 3755 ram32[A_RND_SEED/4] = SWAPu32(0x24040001); // was 0xac20cc00
ef79bbde
P
3756}
3757
3758void psxBiosShutdown() {
3759}
3760
5c8119b8 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);
dc4fa8bc 3769}
3770
ef79bbde 3771#define psxBios_PADpoll(pad) { \
2db412ad 3772 int i, more_data = 0; \
8aecce15 3773 PAD##pad##_startPoll(pad); \
2db412ad 3774 pad_buf##pad[1] = PAD##pad##_poll(0x42, &more_data); \
8aecce15 3775 pad_buf##pad[0] = more_data ? 0 : 0xff; \
3776 PAD##pad##_poll(0, &more_data); \
ef79bbde 3777 i = 2; \
2db412ad 3778 while (more_data) { \
3779 pad_buf##pad[i++] = PAD##pad##_poll(0, &more_data); \
ef79bbde
P
3780 } \
3781}
3782
dc4fa8bc 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
dc4fa8bc 3794// hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3795// so this is only partially implemented
0890ae15 3796static void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
dc4fa8bc 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
0890ae15 3802static void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
dc4fa8bc 3803{
3804 u32 ret = 0;
3805 //PSXBIOS_LOG("%s\n", __func__);
ef79bbde 3806
dc4fa8bc 3807 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3808 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3809 //if (--cdrom_irq_counter == 0) // 0xa0009180
4d2f73bb 3810 // DeliverEvent(0xf0000003, 0x10);
dc4fa8bc 3811 use_cycles(22);
3812 ret = 1;
3813 }
3814 mips_return_c(ret, 20);
3815}
ef79bbde 3816
0890ae15 3817static void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
dc4fa8bc 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
0890ae15 3823static void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
dc4fa8bc 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
0890ae15 3833static void hleExc0_2_2_syscall() // not in any A/B/C table
dc4fa8bc 3834{
dc4fa8bc 3835 u32 tcbPtr = loadRam32(A_TT_PCB);
3836 TCB *tcb = loadRam32ptr(tcbPtr);
7c3332fb 3837 u32 code = (SWAP32(tcb->cause) & 0x3c) >> 2;
dc4fa8bc 3838
3839 if (code != R3000E_Syscall) {
3840 if (code != 0) {
4d2f73bb 3841 DeliverEvent(0xf0000010, 0x1000);
31cd6032 3842 //psxBios_SystemErrorUnresolvedException();
ef79bbde 3843 }
dc4fa8bc 3844 mips_return_c(0, 17);
3845 return;
ef79bbde
P
3846 }
3847
4d4e34c6 3848 //printf("%s c=%d a0=%d\n", __func__, code, SWAP32(tcb->reg[4]));
dc4fa8bc 3849 tcb->epc += SWAP32(4);
4d4e34c6 3850 switch (SWAP32(tcb->reg[4])) { // a0
dc4fa8bc 3851 case 0: // noop
3852 break;
ef79bbde 3853
dc4fa8bc 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);
4d4e34c6 3866 storeRam32(tcbPtr, SWAP32(tcb->reg[5])); // a1
dc4fa8bc 3867 break;
ef79bbde 3868 }
dc4fa8bc 3869 default:
4d2f73bb 3870 DeliverEvent(0xf0000010, 0x4000);
dc4fa8bc 3871 break;
ef79bbde 3872 }
dc4fa8bc 3873 use_cycles(30);
3874 psxBios_ReturnFromException();
ef79bbde
P
3875}
3876
0890ae15 3877static void hleExc1_0_1(void)
dc4fa8bc 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
dc4fa8bc 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)) {
4d2f73bb 3887 DeliverEvent(0xf2000000 + ev_index, 0x0002);
dc4fa8bc 3888 ret = 1;
3889 }
3890 mips_return_c(ret, 22);
3891}
ef79bbde 3892
0890ae15 3893static void hleExc1_0_2(void)
dc4fa8bc 3894{
3895 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3896}
ef79bbde 3897
0890ae15 3898static void hleExc1_1_1(void)
dc4fa8bc 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
0890ae15 3904static void hleExc1_1_2(void)
dc4fa8bc 3905{
3906 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3907}
ef79bbde 3908
0890ae15 3909static void hleExc1_2_1(void)
dc4fa8bc 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
0890ae15 3915static void hleExc1_2_2(void)
dc4fa8bc 3916{
3917 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3918}
ef79bbde 3919
0890ae15 3920static void hleExc1_3_1(void)
dc4fa8bc 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
0890ae15 3926static void hleExc1_3_2(void)
dc4fa8bc 3927{
3928 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3929}
ef79bbde 3930
0890ae15 3931static void hleExc3_0_2_defint(void)
dc4fa8bc 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)) {
4d2f73bb 3951 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
dc4fa8bc 3952 use_cycles(7);
3953 }
ef79bbde 3954
dc4fa8bc 3955 }
3956 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3957}
ef79bbde 3958
0890ae15 3959static void hleExcPadCard1(void)
ea72f34a 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);
ea72f34a 3964
3965 psxBios_PADpoll(1);
3966 psxBios_PADpoll(2);
ea72f34a 3967 use_cycles(100);
2bce5171 3968 if (loadRam32(A_PAD_DR_DST))
3969 psxBios_PAD_dr_();
ea72f34a 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
0890ae15 3980static void hleExcPadCard2(void)
ea72f34a 3981{
3982 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
3983 mips_return_c(ret, 15);
3984}
3985
dc4fa8bc 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
dc4fa8bc 3994 // save the regs
82575753 3995 // $at, $v0, $v1, $ra already saved by the mips code at A_EXCEPTION
3996 for (i = 4; i < 31; i++) {
dc4fa8bc 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);
14b3bd95 4003 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
dc4fa8bc 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
dc4fa8bc 4025 if (v0 == 0 || chain[1] == 0)
4026 continue;
4027 softCallInException(SWAP32(chain[1]));
4028 if (returned_from_exception())
4029 return;
4030 }
ef79bbde 4031 }
dc4fa8bc 4032 assert(lim < 100);
ef79bbde 4033
dc4fa8bc 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
0890ae15 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))
7c3332fb 4154#define bfreezel(ptr) bfreeze(ptr, sizeof(*(ptr)))
ef79bbde
P
4155
4156void psxBiosFreeze(int Mode) {
4157 u32 base = 0x40000;
4158
ef79bbde 4159 bfreezes(FDesc);
7c3332fb 4160 bfreezes(ffile);
4161 bfreezel(&nfile);
0a50313e 4162 bfreezes(cdir);
ef79bbde 4163}