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