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, *
8ec1e4de 3 * dmitrysmagin, senquack *
ef79bbde
P
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
19 ***************************************************************************/
20
8ec1e4de 21/* Gameblabla 2018-2019 :
8254b5a7 22 * Numerous changes to bios calls as well as improvements in order to conform to nocash's findings
23 * for the PSX bios calls. Thanks senquack for helping out with some of the changes
24 * and helping to spot issues and refine my patches.
25 * */
26
ef79bbde
P
27/*
28 * Internal simulated HLE BIOS.
29 */
30
31// TODO: implement all system calls, count the exact CPU cycles of system calls.
32
33#include "psxbios.h"
34#include "psxhw.h"
ddbaf678 35#include "gpu.h"
5bf56268 36#include "sio.h"
9415f066 37#include "psxhle.h"
2bbcfe6b 38#include "psxinterpreter.h"
496d88d4 39#include <zlib.h>
ef79bbde 40
2bbcfe6b 41#ifndef PSXBIOS_LOG
42//#define PSXBIOS_LOG printf
43#define PSXBIOS_LOG(...)
44#endif
452b85f9 45
ec4baa7d 46#define PTR_1 (void *)(size_t)1
47
ef79bbde
P
48char *biosA0n[256] = {
49// 0x00
50 "open", "lseek", "read", "write",
51 "close", "ioctl", "exit", "sys_a0_07",
52 "getc", "putc", "todigit", "atof",
53 "strtoul", "strtol", "abs", "labs",
54// 0x10
55 "atoi", "atol", "atob", "setjmp",
56 "longjmp", "strcat", "strncat", "strcmp",
57 "strncmp", "strcpy", "strncpy", "strlen",
58 "index", "rindex", "strchr", "strrchr",
59// 0x20
60 "strpbrk", "strspn", "strcspn", "strtok",
61 "strstr", "toupper", "tolower", "bcopy",
62 "bzero", "bcmp", "memcpy", "memset",
63 "memmove", "memcmp", "memchr", "rand",
64// 0x30
65 "srand", "qsort", "strtod", "malloc",
66 "free", "lsearch", "bsearch", "calloc",
67 "realloc", "InitHeap", "_exit", "getchar",
68 "putchar", "gets", "puts", "printf",
69// 0x40
2bbcfe6b 70 "SystemErrorUnresolvedException", "LoadTest", "Load", "Exec",
ef79bbde 71 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
2bbcfe6b 72 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
ef79bbde
P
73 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
74// 0x50
75 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
76 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
77 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
78 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
79// 0x60
80 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
81 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
82 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
83 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
84// 0x70
9415f066 85 "_bu_init", "_96_init", "CdRemove", "sys_a0_73",
ef79bbde
P
86 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
87 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
88 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
89// 0x80
90 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
91 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
92 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
93 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
94// 0x90
95 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
96 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
97 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
98 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
99// 0xa0
100 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
101 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
102 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
103 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
104// 0xb0
105 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
2bbcfe6b 106 "GetSystemInfo",
ef79bbde
P
107};
108
109char *biosB0n[256] = {
110// 0x00
111 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
112 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
113 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
114 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
115// 0x10
116 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
117 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
118 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
119 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
120// 0x20
121 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
122 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
123 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
124 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
125// 0x30
126 "sys_b0_30", "sys_b0_31", "open", "lseek",
127 "read", "write", "close", "ioctl",
128 "exit", "sys_b0_39", "getc", "putc",
129 "getchar", "putchar", "gets", "puts",
130// 0x40
131 "cd", "format", "firstfile", "nextfile",
132 "rename", "delete", "undelete", "AddDevice",
133 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
134 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
135// 0x50
136 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
137 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
138 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
139 "_card_status", "_card_wait",
140};
141
142char *biosC0n[256] = {
143// 0x00
144 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
145 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
146 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
147 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
148// 0x10
149 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
150 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
151 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
152 "PatchAOTable",
153};
154
155//#define r0 (psxRegs.GPR.n.r0)
156#define at (psxRegs.GPR.n.at)
157#define v0 (psxRegs.GPR.n.v0)
158#define v1 (psxRegs.GPR.n.v1)
159#define a0 (psxRegs.GPR.n.a0)
160#define a1 (psxRegs.GPR.n.a1)
161#define a2 (psxRegs.GPR.n.a2)
162#define a3 (psxRegs.GPR.n.a3)
163#define t0 (psxRegs.GPR.n.t0)
164#define t1 (psxRegs.GPR.n.t1)
165#define t2 (psxRegs.GPR.n.t2)
166#define t3 (psxRegs.GPR.n.t3)
167#define t4 (psxRegs.GPR.n.t4)
168#define t5 (psxRegs.GPR.n.t5)
169#define t6 (psxRegs.GPR.n.t6)
170#define t7 (psxRegs.GPR.n.t7)
171#define t8 (psxRegs.GPR.n.t8)
172#define t9 (psxRegs.GPR.n.t9)
173#define s0 (psxRegs.GPR.n.s0)
174#define s1 (psxRegs.GPR.n.s1)
175#define s2 (psxRegs.GPR.n.s2)
176#define s3 (psxRegs.GPR.n.s3)
177#define s4 (psxRegs.GPR.n.s4)
178#define s5 (psxRegs.GPR.n.s5)
179#define s6 (psxRegs.GPR.n.s6)
180#define s7 (psxRegs.GPR.n.s7)
181#define k0 (psxRegs.GPR.n.k0)
182#define k1 (psxRegs.GPR.n.k1)
183#define gp (psxRegs.GPR.n.gp)
184#define sp (psxRegs.GPR.n.sp)
7575a4aa 185#define fp (psxRegs.GPR.n.fp)
ef79bbde
P
186#define ra (psxRegs.GPR.n.ra)
187#define pc0 (psxRegs.pc)
188
189#define Ra0 ((char *)PSXM(a0))
190#define Ra1 ((char *)PSXM(a1))
191#define Ra2 ((char *)PSXM(a2))
192#define Ra3 ((char *)PSXM(a3))
193#define Rv0 ((char *)PSXM(v0))
194#define Rsp ((char *)PSXM(sp))
195
196typedef struct {
1fe066c6 197 u32 class;
198 u32 status;
199 u32 spec;
200 u32 mode;
ef79bbde 201 u32 fhandler;
1fe066c6 202 u32 unused[2];
203} EvCB;
ef79bbde 204
1fe066c6 205#define EvStUNUSED 0x0000
206#define EvStDISABLED 0x1000
207#define EvStACTIVE 0x2000
208#define EvStALREADY 0x4000
ef79bbde 209
1fe066c6 210#define EvMdCALL 0x1000
211#define EvMdMARK 0x2000
ef79bbde
P
212
213typedef struct {
9415f066 214 u32 status;
215 u32 mode;
ef79bbde 216 u32 reg[32];
9415f066 217 u32 epc;
218 u32 hi, lo;
219 u32 sr, cause;
220 u32 unused[9];
ef79bbde
P
221} TCB;
222
8ec1e4de 223typedef struct {
ef79bbde
P
224 u32 _pc0;
225 u32 gp0;
226 u32 t_addr;
227 u32 t_size;
2bbcfe6b 228 u32 d_addr; // 10
ef79bbde
P
229 u32 d_size;
230 u32 b_addr;
2bbcfe6b 231 u32 b_size; // 1c
ef79bbde
P
232 u32 S_addr;
233 u32 s_size;
234 u32 _sp, _fp, _gp, ret, base;
235} EXEC;
236
237struct DIRENTRY {
238 char name[20];
239 s32 attr;
240 s32 size;
241 u32 next;
242 s32 head;
243 char system[4];
244};
245
246typedef struct {
247 char name[32];
248 u32 mode;
249 u32 offset;
250 u32 size;
251 u32 mcfile;
252} FileDesc;
253
9ca104f3 254// todo: FileDesc layout is wrong
255// todo: get rid of these globals
ef79bbde 256static FileDesc FDesc[32];
52cf8a87 257static char ffile[64];
9ca104f3 258static int nfile;
c35a25f6 259static char cdir[8*8+8];
260static u32 floodchk;
ef79bbde 261
9415f066 262// fixed RAM offsets, SCPH1001 compatible
263#define A_TT_ExCB 0x0100
264#define A_TT_PCB 0x0108
265#define A_TT_TCB 0x0110
1fe066c6 266#define A_TT_EvCB 0x0120
9415f066 267#define A_A0_TABLE 0x0200
268#define A_B0_TABLE 0x0874
269#define A_C0_TABLE 0x0674
270#define A_SYSCALL 0x0650
271#define A_EXCEPTION 0x0c80
272#define A_EXC_SP 0x6cf0
273#define A_EEXIT_DEF 0x6cf4
3807a976 274#define A_KMALLOC_PTR 0x7460
275#define A_KMALLOC_SIZE 0x7464
276#define A_KMALLOC_END 0x7468
e2f9c5e9 277#define A_PADCRD_CHN_E 0x74a8 // pad/card irq chain entry, see hleExcPadCard1()
340addc5 278#define A_PAD_IRQR_ENA 0x74b8 // pad read on vint irq (nocash 'pad_enable_flag')
279#define A_CARD_IRQR_ENA 0x74bc // same for card
280#define A_PAD_INBUF 0x74c8 // 2x buffers for rx pad data
281#define A_PAD_OUTBUF 0x74d0 // 2x buffers for tx pad data
282#define A_PAD_IN_LEN 0x74d8
283#define A_PAD_OUT_LEN 0x74e0
e2f9c5e9 284#define A_PAD_DR_DST 0x74c4
9ca104f3 285#define A_CARD_CHAN1 0x7500
e2f9c5e9 286#define A_PAD_DR_BUF1 0x7570
287#define A_PAD_DR_BUF2 0x7598
9415f066 288#define A_EEXIT_PTR 0x75d0
289#define A_EXC_STACK 0x85d8 // exception stack top
290#define A_RCNT_VBL_ACK 0x8600
340addc5 291#define A_PAD_ACK_VBL 0x8914 // enable vint ack by pad reading code
9ca104f3 292#define A_HEAP_BASE 0x9000
293#define A_HEAP_SIZE 0x9004
294#define A_HEAP_END 0x9008
85a4e43d 295#define A_HEAP_INIT_FLG 0x900c
52cf8a87 296#define A_RND_SEED 0x9010
85a4e43d 297#define A_HEAP_FRSTCHNK 0xb060
298#define A_HEAP_CURCHNK 0xb064
c89fac55 299#define A_CONF_TCB 0xb940
300#define A_CONF_EvCB 0xb944
301#define A_CONF_SP 0xb948
1fe066c6 302#define A_CD_EVENTS 0xb9b8
9415f066 303#define A_EXC_GP 0xf450
304
dc6c7f24 305#define A_A0_DUMMY 0x1010
306#define A_B0_DUMMY 0x2010
307#define A_C0_DUMMY 0x3010
308#define A_B0_5B_DUMMY 0x43d0
309
9415f066 310#define HLEOP(n) SWAPu32((0x3b << 26) | (n));
311
3b55b1a6 312static u8 loadRam8(u32 addr)
313{
314 assert(!(addr & 0x5f800000));
315 return psxM[addr & 0x1fffff];
316}
317
9415f066 318static u32 loadRam32(u32 addr)
319{
320 assert(!(addr & 0x5f800000));
321 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
322}
ef79bbde 323
340addc5 324static void *castRam8ptr(u32 addr)
325{
326 assert(!(addr & 0x5f800000));
327 return psxM + (addr & 0x1fffff);
328}
329
9415f066 330static void *castRam32ptr(u32 addr)
331{
332 assert(!(addr & 0x5f800003));
333 return psxM + (addr & 0x1ffffc);
334}
335
340addc5 336static void *loadRam8ptr(u32 addr)
337{
338 return castRam8ptr(loadRam32(addr));
339}
340
9415f066 341static void *loadRam32ptr(u32 addr)
342{
343 return castRam32ptr(loadRam32(addr));
344}
345
340addc5 346static void storeRam8(u32 addr, u8 d)
347{
348 assert(!(addr & 0x5f800000));
349 *((u8 *)psxM + (addr & 0x1fffff)) = d;
350}
351
9415f066 352static void storeRam32(u32 addr, u32 d)
353{
354 assert(!(addr & 0x5f800000));
355 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
356}
ef79bbde 357
9415f066 358static void mips_return(u32 val)
359{
360 v0 = val;
361 pc0 = ra;
362}
ef79bbde 363
4ebf5791 364static void mips_return_void(void)
365{
366 pc0 = ra;
367}
368
9415f066 369static void use_cycles(u32 cycle)
370{
371 psxRegs.cycle += cycle * 2;
372}
ef79bbde 373
9415f066 374static void mips_return_c(u32 val, u32 cycle)
375{
376 use_cycles(cycle);
377 mips_return(val);
ef79bbde
P
378}
379
9415f066 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;
9415f066 394 u32 ssr = psxRegs.CP0.n.SR;
2bbcfe6b 395 u32 lim = 0;
ef79bbde
P
396 pc0 = pc;
397 ra = 0x80001000;
9415f066 398 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
ef79bbde 399
ec4baa7d 400 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
401
2bbcfe6b 402 while (pc0 != 0x80001000 && ++lim < 1000000)
9415f066 403 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
ef79bbde 404
ec4baa7d 405 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
406
2bbcfe6b 407 if (lim == 1000000)
408 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
ef79bbde 409 ra = sra;
2bbcfe6b 410 psxRegs.CP0.n.SR |= ssr & 0x404;
9415f066 411}
ef79bbde 412
9415f066 413static inline void softCallInException(u32 pc) {
414 u32 sra = ra;
2bbcfe6b 415 u32 lim = 0;
9415f066 416 pc0 = pc;
52cf8a87 417
418 assert(ra != 0x80001000);
419 if (ra == 0x80001000)
420 return;
9415f066 421 ra = 0x80001000;
422
ec4baa7d 423 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
424
2bbcfe6b 425 while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 1000000)
9415f066 426 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
427
ec4baa7d 428 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
429
2bbcfe6b 430 if (lim == 1000000)
431 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
9415f066 432 if (pc0 == 0x80001000)
433 ra = sra;
ef79bbde
P
434}
435
1fe066c6 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
446
d99f6068 447#define buread(Ra1, mcd, length) { \
2bbcfe6b 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); \
de6bb534 451 psxCpu->Clear(a1, (length + 3) / 4); \
f1514614 452 if (FDesc[1 + mcd].mode & 0x8000) { \
1fe066c6 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; \
2bbcfe6b 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; \
6e522b2b 466 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
f1514614 467 if (FDesc[1 + mcd].mode & 0x8000) { \
1fe066c6 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
b012a437 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;
b012a437 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
3b55b1a6 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;
3b55b1a6 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
9415f066 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
9415f066 607 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
ef79bbde 608
9415f066 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
9415f066 613 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
614 jmp_buf->gp_ = SWAP32(gp);
ef79bbde 615
9415f066 616 mips_return_c(0, 15);
ef79bbde
P
617}
618
9415f066 619static void longjmp_load(const struct jmp_buf_ *jmp_buf)
620{
ef79bbde
P
621 int i;
622
9415f066 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
9415f066 627 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
628 gp = SWAP32(jmp_buf->gp_);;
629}
ef79bbde 630
9415f066 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
3b55b1a6 640 u8 *p2 = (u8 *)Ra1;
641 u32 p1 = a0;
ef79bbde 642
3b55b1a6 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 {
3b55b1a6 646 mips_return_c(0, 6);
bee52312 647 return;
648 }
3b55b1a6 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
3b55b1a6 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;
3b55b1a6 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 }
ef79bbde
P
830
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;
3b55b1a6 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;
3b55b1a6 931 PSXBIOS_LOG(" -> %x\n", v0);
ef79bbde
P
932 return;
933 }
934
3b55b1a6 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
de6bb534 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 }
de6bb534 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
12742a5c 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
9ca104f3 1003static void psxBios_bzero() { // 0x28
01724d23 1004 /* Same as memset here (See memset below) */
de6bb534 1005 u32 ret = a0, cycles;
9ca104f3 1006 if (a0 == 0 || (s32)a1 <= 0)
01724d23 1007 {
9ca104f3 1008 mips_return_c(0, 6);
01724d23 1009 return;
1010 }
de6bb534 1011 do_memset(a0, 0, a1);
1012 cycles = a1 * 4;
1013 a0 += a1;
1014 a1 = 0;
9ca104f3 1015 // todo: many more cycles due to uncached bios mem
de6bb534 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
de6bb534 1035static void psxBios_memcpy() { // 0x2a
1036 u32 ret = a0, cycles = 0;
1037 if (a0 == 0)
ef1da3dc 1038 {
de6bb534 1039 mips_return_c(0, 4);
ef1da3dc 1040 return;
1041 }
4ebf5791 1042 v1 = a0;
de6bb534 1043 if ((s32)a2 > 0) {
1044 do_memcpy(a0, a1, a2);
1045 cycles = a2 * 6;
de6bb534 1046 a0 += a2;
1047 a1 += a2;
1048 a2 = 0;
ef1da3dc 1049 }
de6bb534 1050 mips_return_c(ret, cycles + 5);
ef79bbde
P
1051}
1052
9ca104f3 1053static void psxBios_memset() { // 0x2b
de6bb534 1054 u32 ret = a0, cycles;
9ca104f3 1055 if (a0 == 0 || (s32)a2 <= 0)
3f28b64f 1056 {
9ca104f3 1057 mips_return_c(0, 6);
3f28b64f 1058 return;
1059 }
de6bb534 1060 do_memset(a0, a1, a2);
1061 cycles = a2 * 4;
1062 a0 += a2;
1063 a2 = 0;
9ca104f3 1064 // todo: many more cycles due to uncached bios mem
de6bb534 1065 mips_return_c(ret, cycles + 5);
ef79bbde
P
1066}
1067
1068void psxBios_memmove() { // 0x2c
de6bb534 1069 u32 ret = a0, cycles = 0;
1070 if (a0 == 0)
112dddf5 1071 {
de6bb534 1072 mips_return_c(0, 4);
112dddf5 1073 return;
1074 }
de6bb534 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 }
de6bb534 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;
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
52cf8a87 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
52cf8a87 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
9415f066 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
85a4e43d 1242static int malloc_heap_grow(u32 size) {
1243 u32 heap_addr, heap_end, heap_addr_new;
ef79bbde 1244
85a4e43d 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 }
85a4e43d 1275 storeRam32(A_HEAP_INIT_FLG, 1);
1276 }
26b964b5 1277
85a4e43d 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 }
85a4e43d 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 {
85a4e43d 1313 // go to the next chunk
1314 storeRam32(A_HEAP_CURCHNK, next_chunk);
ef79bbde 1315 }
ef79bbde
P
1316 }
1317
85a4e43d 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
85a4e43d 1328 PSXBIOS_LOG(" -> %08x\n", ret);
1329 mips_return_c(ret, 40);
ef79bbde
P
1330}
1331
9ca104f3 1332static void psxBios_free() { // 0x34
85a4e43d 1333 PSXBIOS_LOG("psxBios_%s %x (%d bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
9ca104f3 1334 storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1335 mips_return_void_c(5);
ef79bbde
P
1336}
1337
9ca104f3 1338static void psxBios_calloc() { // 0x37
1339 u32 ret, size;
1340 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
ef79bbde 1341
9ca104f3 1342 a0 = size = a0 * a1;
ef79bbde 1343 psxBios_malloc();
9ca104f3 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) */
9ca104f3 1382static void psxBios_InitHeap() { // 0x39
1383 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
ef79bbde 1384
9ca104f3 1385 storeRam32(A_HEAP_BASE, a0);
1386 storeRam32(A_HEAP_SIZE, a1);
1387 storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
85a4e43d 1388 storeRam32(A_HEAP_INIT_FLG, 0);
9ca104f3 1389 storeRam32(a0, 0);
ef79bbde 1390
9ca104f3 1391 mips_return_void_c(14);
ef79bbde
P
1392}
1393
1394void psxBios_getchar() { //0x3b
1395 v0 = getchar(); pc0 = ra;
1396}
1397
c02b90b2 1398static void psxBios_printf_psxout() { // 0x3f
ef79bbde
P
1399 char tmp[1024];
1400 char tmp2[1024];
dc6c7f24 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);
b012a437 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
c02b90b2 1463 if (psp != INVALID_PTR)
02949f79 1464 memcpy(psp, save, 4 * 4);
ef79bbde 1465
2bbcfe6b 1466 if (Config.PsxOut)
1467 SysPrintf("%s", tmp);
c02b90b2 1468}
ef79bbde 1469
c02b90b2 1470void psxBios_printf() { // 0x3f
1471 psxBios_printf_psxout();
ef79bbde
P
1472 pc0 = ra;
1473}
1474
c35a25f6 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
9415f066 1507static void psxBios_SystemErrorUnresolvedException() {
c35a25f6 1508 if (floodchk != 0x12340a40) { // prevent log flood
2bbcfe6b 1509 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
c35a25f6 1510 floodchk = 0x12340a40;
9415f066 1511 }
1512 mips_return_void_c(1000);
1513}
1514
4ebf5791 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;
c35a25f6 1529 char path[256];
1530 char *pa0, *p;
02949f79 1531 void *pa1;
ef79bbde 1532
c35a25f6 1533 pa0 = Ra0;
02949f79 1534 pa1 = Ra1;
c35a25f6 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));
de6bb534 1551 psxCpu->Clear(a1, sizeof(EXEC) / 4);
4ebf5791 1552 FlushCache();
ef79bbde
P
1553 v0 = 1;
1554 } else v0 = 0;
c35a25f6 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
2bbcfe6b 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
2bbcfe6b 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
2bbcfe6b 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
2bbcfe6b 1588 gp = SWAP32(header->gp0);
ef79bbde
P
1589
1590 s0 = a0;
1591
1592 a0 = a1;
1593 a1 = a2;
1594
1595 ra = 0x8000;
2bbcfe6b 1596 pc0 = SWAP32(header->_pc0);
ef79bbde
P
1597}
1598
4ebf5791 1599static void psxBios_FlushCache() { // 44
ef79bbde 1600 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
4ebf5791 1601 FlushCache();
1602 mips_return_void();
ef79bbde
P
1603}
1604
1605void psxBios_GPU_dw() { // 0x46
1606 int size;
355c9136 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);
355c9136 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;
8ec1e4de 1624}
ef79bbde
P
1625
1626void psxBios_mem2vram() { // 0x47
1627 int size;
52cf8a87 1628 gpuSyncPluginSR(); // flush
ef79bbde 1629 GPU_writeData(0xa0000000);
355c9136 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...
355c9136 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);
52cf8a87 1651 gpuSyncPluginSR();
355c9136 1652 v0 = HW_GPU_STATUS;
ef79bbde
P
1653 pc0 = ra;
1654}
1655
1656void psxBios_GPU_cwb() { // 0x4a
355c9136 1657 u32 *ptr = (u32*)Ra0;
ef79bbde 1658 int size = a1;
355c9136 1659 gpuSyncPluginSR();
1660 while(size--)
1661 {
1662 GPU_writeData(SWAPu32(*ptr++));
ef79bbde
P
1663 }
1664
1665 pc0 = ra;
1666}
355c9136 1667
1668void psxBios_GPU_SendPackets() { //4b:
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
8ec1e4de 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
1fe066c6 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
340addc5 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);
9415f066 1736
1737static void psxBios_DequeueCdIntr_() {
340addc5 1738 psxBios_SysDeqIntRP_(0, 0x91d0);
1739 psxBios_SysDeqIntRP_(0, 0x91e0);
9415f066 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
1fe066c6 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));
9415f066 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
c89fac55 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;
2bbcfe6b 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;
2bbcfe6b 1799 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
8ec1e4de 1800
ef79bbde 1801 default:
2bbcfe6b 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. */
9ca104f3 1810static void psxBios_get_cd_status() // a6
18dd7e9e 1811{
9ca104f3 1812 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
18dd7e9e 1813 v0 = 1;
1814 pc0 = ra;
1815}
1816
9ca104f3 1817static void psxBios__card_info() { // ab
ef79bbde 1818 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
8ec1e4de 1819 u32 ret, port;
9ca104f3 1820 storeRam32(A_CARD_CHAN1, a0);
1821 port = a0 >> 4;
5bf56268 1822
1823 switch (port) {
1824 case 0x0:
1825 case 0x1:
1fe066c6 1826 ret = 0x0004;
5bf56268 1827 if (McdDisable[port & 1])
1fe066c6 1828 ret = 0x0100;
5bf56268 1829 break;
1830 default:
9ca104f3 1831 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
1fe066c6 1832 ret = 0x0302;
5bf56268 1833 break;
1834 }
1835
1836 if (McdDisable[0] && McdDisable[1])
1fe066c6 1837 ret = 0x0100;
e9fda093 1838
1fe066c6 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
9ca104f3 1850 storeRam32(A_CARD_CHAN1, a0);
e9fda093 1851
1fe066c6 1852// DeliverEvent(0xf0000011, 0x0004);
1853 DeliverEvent(0xf4000001, 0x0004);
ef79bbde
P
1854
1855 v0 = 1; pc0 = ra;
1856}
1857
2bbcfe6b 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
3807a976 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
d3d41455 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
1fe066c6 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
52cf8a87 1960 //printf("%s %08x %x\n", __func__, class, spec);
1fe066c6 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 }
c35a25f6 1987 floodchk = 0;
1fe066c6 1988 use_cycles(29);
1989 return ret;
1990}
ef79bbde 1991
1fe066c6 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
1fe066c6 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
1fe066c6 2016static void psxBios_DeliverEvent() { // 07
2017 u32 ret;
2018 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
ef79bbde 2019
1fe066c6 2020 ret = DeliverEvent(a0, a1);
2021 mips_return(ret);
2022}
ef79bbde 2023
1fe066c6 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
1fe066c6 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
1fe066c6 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
1fe066c6 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
1fe066c6 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
1fe066c6 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
1fe066c6 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
1fe066c6 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 }
1fe066c6 2082 if (status != EvStACTIVE)
d95c9dcb 2083 {
1fe066c6 2084 mips_return_c(0, 2);
d95c9dcb 2085 return;
2086 }
ef79bbde 2087
1fe066c6 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
1fe066c6 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;
c35a25f6 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 }
1fe066c6 2104 if (status == EvStALREADY) {
2105 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2106 ret = 1;
b4ae2532 2107 }
ef79bbde 2108
1fe066c6 2109 mips_return_c(ret, 15);
ef79bbde
P
2110}
2111
1fe066c6 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
1fe066c6 2119 mips_return_c(1, 15);
ef79bbde
P
2120}
2121
1fe066c6 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
1fe066c6 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
9415f066 2137 TCB *tcb = loadRam32ptr(A_TT_TCB);
2138 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
ef79bbde
P
2139 int th;
2140
9415f066 2141 for (th = 1; th < limit; th++)
a66d3058 2142 {
9415f066 2143 if (tcb[th].status != SWAP32(0x4000)) break;
ef79bbde 2144
a66d3058 2145 }
9415f066 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
9415f066 2152 mips_return_c(0xffffffff, 20);
a66d3058 2153 return;
2154 }
c89fac55 2155 PSXBIOS_LOG("psxBios_%s -> %x\n", biosB0n[0x0e], 0xff000000 + th);
ef79bbde 2156
9415f066 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
9415f066 2164 mips_return_c(0xff000000 + th, 34);
ef79bbde
P
2165}
2166
2167/*
2168 * int CloseTh(long thread);
2169 */
2170
c89fac55 2171static void psxBios_CloseTh() { // 0f
2172 u32 tcb = loadRam32(A_TT_TCB);
2173 u32 th = a0 & 0xffff;
ef79bbde 2174
c89fac55 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
c89fac55 2179 mips_return_c(1, 11);
ef79bbde
P
2180}
2181
2182/*
2183 * int ChangeTh(long thread);
2184 */
2185
2186void psxBios_ChangeTh() { // 10
9415f066 2187 u32 tcbBase = loadRam32(A_TT_TCB);
2188 u32 th = a0 & 0xffff;
ef79bbde 2189
2bbcfe6b 2190 // this is quite spammy
2191 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2192
9415f066 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
340addc5 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");
e2f9c5e9 2206 ram32[A_PAD_DR_DST/4] = 0;
340addc5 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
340addc5 2226 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
ef79bbde 2227
340addc5 2228 mips_return_c(1, 200);
ef79bbde
P
2229}
2230
2231void psxBios_StartPAD() { // 13
ef79bbde 2232 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
340addc5 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);
6d79a06f 2240 psxRegs.CP0.n.SR |= 0x401;
340addc5 2241
2242 mips_return_c(1, 300);
ef79bbde
P
2243}
2244
2245void psxBios_StopPAD() { // 14
ef79bbde 2246 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
340addc5 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
e2f9c5e9 2253static void psxBios_PAD_init() { // 15
2254 u32 ret = 0;
ef79bbde 2255 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
e2f9c5e9 2256 if (a0 == 0x20000000 || a0 == 0x20000001)
a824e83d 2257 {
e2f9c5e9 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 }
e2f9c5e9 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
e2f9c5e9 2296static void psxBios_PAD_dr() { // 16
ef79bbde 2297 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
e2f9c5e9 2298 u32 ret = psxBios_PAD_dr_();
2299 mips_return(ret);
ef79bbde
P
2300}
2301
9415f066 2302static void psxBios_ReturnFromException() { // 17
2303 u32 tcbPtr = loadRam32(A_TT_PCB);
2304 const TCB *tcb = loadRam32ptr(tcbPtr);
2bbcfe6b 2305 u32 sr;
9415f066 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);
2bbcfe6b 2312 sr = SWAP32(tcb->sr);
ef79bbde 2313
9415f066 2314 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2315 pc0 = k0 = SWAP32(tcb->epc);
ef79bbde 2316
2bbcfe6b 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
9415f066 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
9415f066 2328 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2329 mips_return_void_c(5);
ef79bbde
P
2330}
2331
2332void psxBios_HookEntryInt() { // 19
9415f066 2333 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
ef79bbde 2334
9415f066 2335 storeRam32(A_EEXIT_PTR, a0);
2336 mips_return_void_c(3);
ef79bbde
P
2337}
2338
1fe066c6 2339static void psxBios_UnDeliverEvent() { // 0x20
2340 u32 ret;
2341 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
ef79bbde 2342
1fe066c6 2343 ret = UnDeliverEvent(a0, a1);
2344 mips_return(ret);
ef79bbde
P
2345}
2346
a6a44e96 2347static void buopen(int mcd, char *ptr, char *cfg)
595a136b 2348{
2349 int i;
a6a44e96 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++) {
a6a44e96 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;
2bbcfe6b 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;
a6a44e96 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);
2380 pptr = fptr2 = fptr;
2381 for(j=2; j<=nblk; j++) {
2382 int k;
2383 for(i++; i<16; i++) {
2384 fptr2 += 128;
8ec1e4de 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;
2bbcfe6b 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
52cf8a87 2417 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x32], Ra0, a1);
ef79bbde
P
2418
2419 v0 = -1;
2420
b012a437 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;
1fe066c6 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
ef79bbde
P
2460
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
b012a437 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 }
ef79bbde 2481
ef79bbde 2482 pc0 = ra;
ef79bbde
P
2483}
2484
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
2bbcfe6b 2493 if (a0 != 1) // stdout
2494 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
02949f79 2495
2496 v0 = -1;
b012a437 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;
2bbcfe6b 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
c02b90b2 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
2bbcfe6b 2553 if (Config.PsxOut) SysPrintf("%c", (char)a0);
ef79bbde
P
2554 pc0 = ra;
2555}
2556
2557void psxBios_puts() { // 3e/3f
2bbcfe6b 2558 if (Config.PsxOut) SysPrintf("%s", Ra0);
ef79bbde
P
2559 pc0 = ra;
2560}
2561
ff49d6b3 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
ff49d6b3 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;
aff84614 2604 const char *name = (const char *)data2 + 0x0a;
ff49d6b3 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 */
8ec1e4de 2622
52cf8a87 2623static void psxBios_firstfile() { // 42
52cf8a87 2624 char *pa0 = castRam8ptr(a0);
ef79bbde 2625
ff49d6b3 2626 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x42], pa0, a1);
ef79bbde
P
2627 v0 = 0;
2628
52cf8a87 2629 {
2630 snprintf(ffile, sizeof(ffile), "%s", pa0);
ff49d6b3 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
1fe066c6 2636 DeliverEvent(0xf0000011, 0x0004);
aff84614 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
1fe066c6 2640 DeliverEvent(0xf0000011, 0x0004);
aff84614 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
ff49d6b3 2653 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x43], a0);
ef79bbde 2654
ef79bbde 2655 v0 = 0;
ff49d6b3 2656 if (!strncmp(ffile, "bu00", 4))
aff84614 2657 bufile((u8 *)Mcd1Data, a0);
ff49d6b3 2658 else if (!strncmp(ffile, "bu10", 4))
aff84614 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
b012a437 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); \
2bbcfe6b 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
b012a437 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
340addc5 2753 u32 *ram32 = (u32 *)psxM;
ef79bbde 2754 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
340addc5 2755 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
4ebf5791 2756 // (maybe) todo: early_card_irq, etc
ef79bbde 2757
340addc5 2758 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2759
4ebf5791 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]);
340addc5 2766 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2767 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
ef79bbde 2768
340addc5 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]);
340addc5 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 }
9ca104f3 2804 storeRam32(A_CARD_CHAN1, a0);
ef79bbde
P
2805 port = a0 >> 4;
2806
b012a437 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
1fe066c6 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 }
9ca104f3 2840 storeRam32(A_CARD_CHAN1, a0);
ef79bbde
P
2841 port = a0 >> 4;
2842
b012a437 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
1fe066c6 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
8ec1e4de 2867{
9415f066 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
9415f066 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]);
9415f066 2919 log_unhandled("GetC0Table @%08x\n", ra);
ef79bbde 2920
9415f066 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]);
9415f066 2926 log_unhandled("GetB0Table @%08x\n", ra);
ef79bbde 2927
9415f066 2928 mips_return_c(A_B0_TABLE, 3);
ef79bbde
P
2929}
2930
9ca104f3 2931static void psxBios__card_chan() { // 0x58
2932 u32 ret;
e9fda093 2933 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
e9fda093 2934
9ca104f3 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
340addc5 2941static void psxBios_ChangeClearPad() { // 5b
2942 u32 ret;
ef79bbde 2943 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
340addc5 2944 ret = loadRam32(A_PAD_ACK_VBL);
2945 storeRam32(A_PAD_ACK_VBL, a0);
ef79bbde 2946
340addc5 2947 mips_return_c(ret, 6);
ef79bbde
P
2948}
2949
9ca104f3 2950static void psxBios__card_status() { // 5c
2951 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
872515f9 2952
9ca104f3 2953 v0 = 1; // ready
21af3ff6 2954 pc0 = ra;
2955}
2956
9ca104f3 2957static void psxBios__card_wait() { // 5d
2958 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
5f652aa9 2959
9ca104f3 2960 v0 = 1; // ready
5f652aa9 2961 pc0 = ra;
872515f9 2962}
2963
ef79bbde
P
2964/* System calls C0 */
2965
3807a976 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 }
340addc5 2975 psxBios_SysEnqIntRP_(a0, 0x6d88);
3807a976 2976 mips_return_c(0, 9);
2977}
2978
2979static void psxBios_InitException() { // 01
2980 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
340addc5 2981 psxBios_SysEnqIntRP_(a0, 0x6da8);
3807a976 2982 mips_return_c(0, 9);
2983}
2984
ef79bbde
P
2985/*
2986 * int SysEnqIntRP(int index , long *queue);
2987 */
2988
340addc5 2989static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
9415f066 2990 u32 old, base = loadRam32(A_TT_ExCB);
ef79bbde 2991
340addc5 2992 old = loadRam32(base + (priority << 3));
2993 storeRam32(base + (priority << 3), chain_eptr);
2994 storeRam32(chain_eptr, old);
9415f066 2995 mips_return_c(0, 9);
ef79bbde
P
2996}
2997
340addc5 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
340addc5 3007static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
9415f066 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
340addc5 3012 ptr = loadRam32(base + (priority << 3));
9415f066 3013 while (ptr) {
3014 next = loadRam32(ptr);
340addc5 3015 if (ptr == chain_rm_eptr) {
3016 storeRam32(base + (priority << 3), next);
9415f066 3017 ret = ptr;
3018 use_cycles(6);
3019 break;
3020 }
340addc5 3021 while (next && next != chain_rm_eptr && lim++ < 100) {
9415f066 3022 ptr = next;
3023 next = loadRam32(ptr);
3024 use_cycles(8);
3025 }
340addc5 3026 if (next == chain_rm_eptr) {
9415f066 3027 next = loadRam32(next);
3028 storeRam32(ptr, next);
3029 ret = ptr;
3030 use_cycles(6);
3031 }
3032 break;
3033 }
3034 if (lim == 100)
340addc5 3035 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
ef79bbde 3036
9415f066 3037 mips_return_c(ret, 12);
3038}
ef79bbde 3039
9415f066 3040static void psxBios_SysDeqIntRP() { // 03
3041 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
340addc5 3042 psxBios_SysDeqIntRP_(a0, a1);
ef79bbde
P
3043}
3044
1fe066c6 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
3807a976 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
9415f066 3076 u32 ret;
ef79bbde 3077
ef79bbde 3078 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
ef79bbde 3079
9415f066 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
3807a976 3085static void psxBios_InitDefInt() { // 0c
3086 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3087 // should also clear the autoack table
340addc5 3088 psxBios_SysEnqIntRP_(a0, 0x6d98);
3807a976 3089 mips_return_c(0, 20 + 6*2);
3090}
3091
8ec1e4de 3092void psxBios_dummy() {
9415f066 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])();
9415f066 3103// C0 and B0 overlap (end of C0 is start of B0)
3104void (*biosC0[256+128])();
3105void (**biosB0)() = biosC0 + 128;
ef79bbde 3106
7575a4aa 3107static void setup_mips_code()
9415f066 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
9415f066 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 },
340addc5 3152 { 0x49bc, hleop_exc_padcard1 },
3153 { 0x4a4c, hleop_exc_padcard2 },
9415f066 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
340addc5 3172 // install the hle traps
4ebf5791 3173 if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3174 if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
9415f066 3175}
3176
c89fac55 3177static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack)
3807a976 3178{
3179 u32 *ram32 = (u32 *)psxM;
c89fac55 3180 u32 s_excb = 0x20, s_evcb, s_pcb = 4, s_tcb;
3807a976 3181 u32 p_excb, p_evcb, p_pcb, p_tcb;
c89fac55 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;
3807a976 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
c89fac55 3222 for (i = 1; i < tcb_cnt; i++)
3223 storeRam32(p_tcb + sizeof(TCB) * i, 0x1000);
1fe066c6 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));
c89fac55 3231
3232 storeRam32(A_CONF_EvCB, evcb_cnt);
3233 storeRam32(A_CONF_TCB, tcb_cnt);
3234 storeRam32(A_CONF_SP, stack);
3807a976 3235}
3236
7575a4aa 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
dc6c7f24 3320static void hleExc0_0_1();
3321static void hleExc0_0_2();
3322static void hleExc0_1_1();
3323static void hleExc0_1_2();
3324
7575a4aa 3325#include "sjisfont.h"
3326
ef79bbde 3327void psxBiosInit() {
1fe066c6 3328 u32 *ptr, *ram32, *rom32;
aff84614 3329 char *romc;
ef79bbde
P
3330 int i;
3331 uLongf len;
3332
9415f066 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 }
c02b90b2 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
b6cd25ed 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;
8ec1e4de 3420 biosA0[0x3c] = psxBios_putchar;
ef79bbde 3421 //biosA0[0x3d] = psxBios_gets;
2bbcfe6b 3422 biosA0[0x3e] = psxBios_puts;
3423 biosA0[0x3f] = psxBios_printf;
9415f066 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;
8ec1e4de 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;
9415f066 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;
9415f066 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;
8ec1e4de 3490 //biosA0[0x82] = psxBios_sys_a0_82;
ef79bbde
P
3491 //biosA0[0x83] = psxBios_sys_a0_83;
3492 //biosA0[0x84] = psxBios_sys_a0_84;
8ec1e4de 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;
9415f066 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;
c89fac55 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;
9415f066 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;
2bbcfe6b 3540 biosA0[0xb4] = psxBios_GetSystemInfo;
ef79bbde 3541//*******************B0 CALLS****************************
3807a976 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;
2bbcfe6b 3603 biosB0[0x3d] = psxBios_putchar;
ef79bbde 3604 //biosB0[0x3e] = psxBios_gets;
2bbcfe6b 3605 biosB0[0x3f] = psxBios_puts;
c35a25f6 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;
872515f9 3634 biosB0[0x5c] = psxBios__card_status;
5f652aa9 3635 biosB0[0x5d] = psxBios__card_wait;
ef79bbde 3636//*******************C0 CALLS****************************
3807a976 3637 biosC0[0x00] = psxBios_InitRCnt;
3638 biosC0[0x01] = psxBios_InitException;
ef79bbde
P
3639 biosC0[0x02] = psxBios_SysEnqIntRP;
3640 biosC0[0x03] = psxBios_SysDeqIntRP;
1fe066c6 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;
3807a976 3645 biosC0[0x08] = psxBios_SysInitMemory;
ef79bbde 3646 //biosC0[0x09] = psxBios_SysInitKMem;
8ec1e4de 3647 biosC0[0x0a] = psxBios_ChangeClearRCnt;
ef79bbde 3648 //biosC0[0x0b] = psxBios_SystemError;
3807a976 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));
c35a25f6 3670 memset(cdir, 0, sizeof(cdir));
3671 floodchk = 0;
c62b43c9 3672
2bbcfe6b 3673 // somewhat pretend to be a SCPH1001 BIOS
3674 // some games look for these and take an exception if they're missing
1fe066c6 3675 rom32 = (u32 *)psxR;
3676 rom32[0x100/4] = SWAP32(0x19951204);
3677 rom32[0x104/4] = SWAP32(3);
aff84614 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");
1fe066c6 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
4ebf5791 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 */
8ec1e4de 3703
9415f066 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
c89fac55 3722 setup_tt(4, 16, 0x801fff00);
3723 DeliverEvent(0xf0000003, 0x0010);
9415f066 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++)
dc6c7f24 3744 ptr[i] = SWAP32(A_A0_DUMMY);
9415f066 3745
3746 ptr = (u32 *)&psxM[A_B0_TABLE];
3747 for (i = 0; i < 256; i++)
dc6c7f24 3748 ptr[i] = SWAP32(A_B0_DUMMY);
9415f066 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
dc6c7f24 3753 ptr[0x5b] = SWAP32(A_B0_5B_DUMMY); // 0x43d0
340addc5 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
9415f066 3760 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
340addc5 3761 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
9415f066 3762
3763 ptr = (u32 *)&psxM[A_C0_TABLE];
3764 for (i = 0; i < 256/2; i++)
dc6c7f24 3765 ptr[i] = SWAP32(A_C0_DUMMY);
9415f066 3766 ptr[6] = SWAP32(A_EXCEPTION);
3767
3768 // more HLE traps
dc6c7f24 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);
9415f066 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);
52cf8a87 3781 ram32[A_RND_SEED/4] = SWAPu32(0x24040001); // was 0xac20cc00
ef79bbde
P
3782}
3783
3784void psxBiosShutdown() {
3785}
3786
c89fac55 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);
9415f066 3795}
3796
ef79bbde 3797#define psxBios_PADpoll(pad) { \
1e774d8e 3798 int i, more_data = 0; \
9fb965e0 3799 PAD##pad##_startPoll(pad); \
1e774d8e 3800 pad_buf##pad[1] = PAD##pad##_poll(0x42, &more_data); \
9fb965e0 3801 pad_buf##pad[0] = more_data ? 0 : 0xff; \
3802 PAD##pad##_poll(0, &more_data); \
ef79bbde 3803 i = 2; \
1e774d8e 3804 while (more_data) { \
3805 pad_buf##pad[i++] = PAD##pad##_poll(0, &more_data); \
ef79bbde
P
3806 } \
3807}
3808
9415f066 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
9415f066 3820// hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3821// so this is only partially implemented
dc6c7f24 3822static void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
9415f066 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
dc6c7f24 3828static void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
9415f066 3829{
3830 u32 ret = 0;
3831 //PSXBIOS_LOG("%s\n", __func__);
ef79bbde 3832
9415f066 3833 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3834 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3835 //if (--cdrom_irq_counter == 0) // 0xa0009180
1fe066c6 3836 // DeliverEvent(0xf0000003, 0x10);
9415f066 3837 use_cycles(22);
3838 ret = 1;
3839 }
3840 mips_return_c(ret, 20);
3841}
ef79bbde 3842
dc6c7f24 3843static void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
9415f066 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
dc6c7f24 3849static void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
9415f066 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
dc6c7f24 3859static void hleExc0_2_2_syscall() // not in any A/B/C table
9415f066 3860{
9415f066 3861 u32 tcbPtr = loadRam32(A_TT_PCB);
3862 TCB *tcb = loadRam32ptr(tcbPtr);
52cf8a87 3863 u32 code = (SWAP32(tcb->cause) & 0x3c) >> 2;
9415f066 3864
3865 if (code != R3000E_Syscall) {
3866 if (code != 0) {
1fe066c6 3867 DeliverEvent(0xf0000010, 0x1000);
2bbcfe6b 3868 //psxBios_SystemErrorUnresolvedException();
ef79bbde 3869 }
9415f066 3870 mips_return_c(0, 17);
3871 return;
ef79bbde
P
3872 }
3873
607dd967 3874 //printf("%s c=%d a0=%d\n", __func__, code, SWAP32(tcb->reg[4]));
9415f066 3875 tcb->epc += SWAP32(4);
607dd967 3876 switch (SWAP32(tcb->reg[4])) { // a0
9415f066 3877 case 0: // noop
3878 break;
ef79bbde 3879
9415f066 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);
607dd967 3892 storeRam32(tcbPtr, SWAP32(tcb->reg[5])); // a1
9415f066 3893 break;
ef79bbde 3894 }
9415f066 3895 default:
1fe066c6 3896 DeliverEvent(0xf0000010, 0x4000);
9415f066 3897 break;
ef79bbde 3898 }
9415f066 3899 use_cycles(30);
3900 psxBios_ReturnFromException();
ef79bbde
P
3901}
3902
dc6c7f24 3903static void hleExc1_0_1(void)
9415f066 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
9415f066 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)) {
1fe066c6 3913 DeliverEvent(0xf2000000 + ev_index, 0x0002);
9415f066 3914 ret = 1;
3915 }
3916 mips_return_c(ret, 22);
3917}
ef79bbde 3918
dc6c7f24 3919static void hleExc1_0_2(void)
9415f066 3920{
3921 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3922}
ef79bbde 3923
dc6c7f24 3924static void hleExc1_1_1(void)
9415f066 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
dc6c7f24 3930static void hleExc1_1_2(void)
9415f066 3931{
3932 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3933}
ef79bbde 3934
dc6c7f24 3935static void hleExc1_2_1(void)
9415f066 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
dc6c7f24 3941static void hleExc1_2_2(void)
9415f066 3942{
3943 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3944}
ef79bbde 3945
dc6c7f24 3946static void hleExc1_3_1(void)
9415f066 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
dc6c7f24 3952static void hleExc1_3_2(void)
9415f066 3953{
3954 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3955}
ef79bbde 3956
dc6c7f24 3957static void hleExc3_0_2_defint(void)
9415f066 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)) {
1fe066c6 3977 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
9415f066 3978 use_cycles(7);
3979 }
ef79bbde 3980
9415f066 3981 }
3982 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3983}
ef79bbde 3984
dc6c7f24 3985static void hleExcPadCard1(void)
340addc5 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);
340addc5 3990
3991 psxBios_PADpoll(1);
3992 psxBios_PADpoll(2);
340addc5 3993 use_cycles(100);
e2f9c5e9 3994 if (loadRam32(A_PAD_DR_DST))
3995 psxBios_PAD_dr_();
340addc5 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
dc6c7f24 4006static void hleExcPadCard2(void)
340addc5 4007{
4008 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
4009 mips_return_c(ret, 15);
4010}
4011
9415f066 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
9415f066 4020 // save the regs
0066437b 4021 // $at, $v0, $v1, $ra already saved by the mips code at A_EXCEPTION
4022 for (i = 4; i < 31; i++) {
9415f066 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);
7575a4aa 4029 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
9415f066 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
9415f066 4051 if (v0 == 0 || chain[1] == 0)
4052 continue;
4053 softCallInException(SWAP32(chain[1]));
4054 if (returned_from_exception())
4055 return;
4056 }
ef79bbde 4057 }
9415f066 4058 assert(lim < 100);
ef79bbde 4059
9415f066 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
dc6c7f24 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
3b55b1a6 4096 //printf("A(%02x) -> %x\n", call, v0);
dc6c7f24 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
3b55b1a6 4119 //printf("B(%02x) -> %x\n", call, v0);
dc6c7f24 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
3b55b1a6 4137 //printf("C(%02x) -> %x\n", call, v0);
dc6c7f24 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))
52cf8a87 4183#define bfreezel(ptr) bfreeze(ptr, sizeof(*(ptr)))
ef79bbde
P
4184
4185void psxBiosFreeze(int Mode) {
4186 u32 base = 0x40000;
4187
ef79bbde 4188 bfreezes(FDesc);
52cf8a87 4189 bfreezes(ffile);
4190 bfreezel(&nfile);
c35a25f6 4191 bfreezes(cdir);
ef79bbde 4192}