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