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