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