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