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