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