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