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