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