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