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