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