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