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