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