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