1 /***************************************************************************
2 * Copyright (C) 2019 Ryan Schultz, PCSX-df Team, PCSX team, gameblabla, *
3 * dmitrysmagin, senquack *
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. *
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. *
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 ***************************************************************************/
21 /* Gameblabla 2018-2019 :
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.
28 * Internal simulated HLE BIOS.
31 // TODO: implement all system calls, count the exact CPU cycles of system calls.
38 #include "psxinterpreter.h"
39 #include "new_dynarec/events.h"
43 //#define PSXBIOS_LOG printf
44 #define PSXBIOS_LOG(...)
47 #define PTR_1 (void *)(size_t)1
49 char *biosA0n[256] = {
51 "open", "lseek", "read", "write",
52 "close", "ioctl", "exit", "sys_a0_07",
53 "getc", "putc", "todigit", "atof",
54 "strtoul", "strtol", "abs", "labs",
56 "atoi", "atol", "atob", "setjmp",
57 "longjmp", "strcat", "strncat", "strcmp",
58 "strncmp", "strcpy", "strncpy", "strlen",
59 "index", "rindex", "strchr", "strrchr",
61 "strpbrk", "strspn", "strcspn", "strtok",
62 "strstr", "toupper", "tolower", "bcopy",
63 "bzero", "bcmp", "memcpy", "memset",
64 "memmove", "memcmp", "memchr", "rand",
66 "srand", "qsort", "strtod", "malloc",
67 "free", "lsearch", "bsearch", "calloc",
68 "realloc", "InitHeap", "_exit", "getchar",
69 "putchar", "gets", "puts", "printf",
71 "SystemErrorUnresolvedException", "LoadTest", "Load", "Exec",
72 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
73 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
74 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
76 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
77 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
78 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
79 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
81 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
82 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
83 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
84 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
86 "_bu_init", "_96_init", "CdRemove", "sys_a0_73",
87 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
88 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
89 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
91 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
92 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
93 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
94 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
96 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
97 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
98 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
99 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
101 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
102 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
103 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
104 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
106 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
110 char *biosB0n[256] = {
112 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
113 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
114 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
115 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
117 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
118 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
119 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
120 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
122 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
123 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
124 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
125 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
127 "sys_b0_30", "sys_b0_31", "open", "lseek",
128 "read", "write", "close", "ioctl",
129 "exit", "sys_b0_39", "getc", "putc",
130 "getchar", "putchar", "gets", "puts",
132 "cd", "format", "firstfile", "nextfile",
133 "rename", "delete", "undelete", "AddDevice",
134 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
135 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
137 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
138 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
139 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
140 "_card_status", "_card_wait",
143 char *biosC0n[256] = {
145 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
146 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
147 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
148 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
150 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
151 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
152 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
156 //#define r0 (psxRegs.GPR.n.r0)
157 #define at (psxRegs.GPR.n.at)
158 #define v0 (psxRegs.GPR.n.v0)
159 #define v1 (psxRegs.GPR.n.v1)
160 #define a0 (psxRegs.GPR.n.a0)
161 #define a1 (psxRegs.GPR.n.a1)
162 #define a2 (psxRegs.GPR.n.a2)
163 #define a3 (psxRegs.GPR.n.a3)
164 #define t0 (psxRegs.GPR.n.t0)
165 #define t1 (psxRegs.GPR.n.t1)
166 #define t2 (psxRegs.GPR.n.t2)
167 #define t3 (psxRegs.GPR.n.t3)
168 #define t4 (psxRegs.GPR.n.t4)
169 #define t5 (psxRegs.GPR.n.t5)
170 #define t6 (psxRegs.GPR.n.t6)
171 #define t7 (psxRegs.GPR.n.t7)
172 #define t8 (psxRegs.GPR.n.t8)
173 #define t9 (psxRegs.GPR.n.t9)
174 #define s0 (psxRegs.GPR.n.s0)
175 #define s1 (psxRegs.GPR.n.s1)
176 #define s2 (psxRegs.GPR.n.s2)
177 #define s3 (psxRegs.GPR.n.s3)
178 #define s4 (psxRegs.GPR.n.s4)
179 #define s5 (psxRegs.GPR.n.s5)
180 #define s6 (psxRegs.GPR.n.s6)
181 #define s7 (psxRegs.GPR.n.s7)
182 #define k0 (psxRegs.GPR.n.k0)
183 #define k1 (psxRegs.GPR.n.k1)
184 #define gp (psxRegs.GPR.n.gp)
185 #define sp (psxRegs.GPR.n.sp)
186 #define fp (psxRegs.GPR.n.fp)
187 #define ra (psxRegs.GPR.n.ra)
188 #define pc0 (psxRegs.pc)
190 #define Ra0 ((char *)PSXM(a0))
191 #define Ra1 ((char *)PSXM(a1))
192 #define Ra2 ((char *)PSXM(a2))
193 #define Ra3 ((char *)PSXM(a3))
194 #define Rv0 ((char *)PSXM(v0))
195 #define Rsp ((char *)PSXM(sp))
206 #define EvStUNUSED 0x0000
207 #define EvStDISABLED 0x1000
208 #define EvStACTIVE 0x2000
209 #define EvStALREADY 0x4000
211 #define EvMdCALL 0x1000
212 #define EvMdMARK 0x2000
235 u32 _sp, _fp, _gp, ret, base;
255 // todo: FileDesc layout is wrong
256 // todo: get rid of these globals
257 static FileDesc FDesc[32];
258 static char ffile[64];
260 static char cdir[8*8+8];
263 // fixed RAM offsets, SCPH1001 compatible
264 #define A_TT_ExCB 0x0100
265 #define A_TT_PCB 0x0108
266 #define A_TT_TCB 0x0110
267 #define A_TT_EvCB 0x0120
268 #define A_A0_TABLE 0x0200
269 #define A_B0_TABLE 0x0874
270 #define A_C0_TABLE 0x0674
271 #define A_SYSCALL 0x0650
272 #define A_EXCEPTION 0x0c80
273 #define A_EXC_SP 0x6cf0
274 #define A_EEXIT_DEF 0x6cf4
275 #define A_KMALLOC_PTR 0x7460
276 #define A_KMALLOC_SIZE 0x7464
277 #define A_KMALLOC_END 0x7468
278 #define A_PADCRD_CHN_E 0x74a8 // pad/card irq chain entry, see hleExcPadCard1()
279 #define A_PAD_IRQR_ENA 0x74b8 // pad read on vint irq (nocash 'pad_enable_flag')
280 #define A_CARD_IRQR_ENA 0x74bc // same for card
281 #define A_PAD_INBUF 0x74c8 // 2x buffers for rx pad data
282 #define A_PAD_OUTBUF 0x74d0 // 2x buffers for tx pad data
283 #define A_PAD_IN_LEN 0x74d8
284 #define A_PAD_OUT_LEN 0x74e0
285 #define A_PAD_DR_DST 0x74c4
286 #define A_CARD_CHAN1 0x7500
287 #define A_PAD_DR_BUF1 0x7570
288 #define A_PAD_DR_BUF2 0x7598
289 #define A_EEXIT_PTR 0x75d0
290 #define A_EXC_STACK 0x85d8 // exception stack top
291 #define A_RCNT_VBL_ACK 0x8600
292 #define A_PAD_ACK_VBL 0x8914 // enable vint ack by pad reading code
293 #define A_HEAP_BASE 0x9000
294 #define A_HEAP_SIZE 0x9004
295 #define A_HEAP_END 0x9008
296 #define A_HEAP_INIT_FLG 0x900c
297 #define A_RND_SEED 0x9010
298 #define A_HEAP_FRSTCHNK 0xb060
299 #define A_HEAP_CURCHNK 0xb064
300 #define A_CONF_TCB 0xb940
301 #define A_CONF_EvCB 0xb944
302 #define A_CONF_SP 0xb948
303 #define A_CD_EVENTS 0xb9b8
304 #define A_EXC_GP 0xf450
306 #define A_A0_DUMMY 0x1010
307 #define A_B0_DUMMY 0x2010
308 #define A_C0_DUMMY 0x3010
309 #define A_B0_5B_DUMMY 0x43d0
311 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
313 static u8 loadRam8(u32 addr)
315 assert(!(addr & 0x5f800000));
316 return psxM[addr & 0x1fffff];
319 static u32 loadRam32(u32 addr)
321 assert(!(addr & 0x5f800000));
322 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
325 static void *castRam8ptr(u32 addr)
327 assert(!(addr & 0x5f800000));
328 return psxM + (addr & 0x1fffff);
331 static void *castRam32ptr(u32 addr)
333 assert(!(addr & 0x5f800003));
334 return psxM + (addr & 0x1ffffc);
337 static void *loadRam8ptr(u32 addr)
339 return castRam8ptr(loadRam32(addr));
342 static void *loadRam32ptr(u32 addr)
344 return castRam32ptr(loadRam32(addr));
347 static void storeRam8(u32 addr, u8 d)
349 assert(!(addr & 0x5f800000));
350 *((u8 *)psxM + (addr & 0x1fffff)) = d;
353 static void storeRam32(u32 addr, u32 d)
355 assert(!(addr & 0x5f800000));
356 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
359 static void mips_return(u32 val)
365 static void mips_return_void(void)
370 static void use_cycles(u32 cycle)
372 psxRegs.cycle += cycle * 2;
375 static void mips_return_c(u32 val, u32 cycle)
381 static void mips_return_void_c(u32 cycle)
387 static int returned_from_exception(void)
389 // 0x80000080 means it took another exception just after return
390 return pc0 == k0 || pc0 == 0x80000080;
393 static inline void softCall(u32 pc) {
395 u32 ssr = psxRegs.CP0.n.SR;
399 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
401 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
403 while (pc0 != 0x80001000 && ++lim < 1000000)
404 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
406 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
409 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
411 psxRegs.CP0.n.SR |= ssr & 0x404;
414 static inline void softCallInException(u32 pc) {
419 assert(ra != 0x80001000);
420 if (ra == 0x80001000)
424 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
426 while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 1000000)
427 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
429 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
432 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
433 if (pc0 == 0x80001000)
437 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
438 static u32 DeliverEvent(u32 class, u32 spec);
439 static u32 UnDeliverEvent(u32 class, u32 spec);
440 static void CloseEvent(u32 ev);
445 // System calls A0 */
448 #define buread(Ra1, mcd, length) { \
449 PSXBIOS_LOG("read %d: %x,%x (%s)\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2, Mcd##mcd##Data + 128 * FDesc[1 + mcd].mcfile + 0xa); \
450 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
451 memcpy(Ra1, ptr, length); \
452 psxCpu->Clear(a1, (length + 3) / 4); \
453 if (FDesc[1 + mcd].mode & 0x8000) { \
454 DeliverEvent(0xf0000011, 0x0004); \
455 DeliverEvent(0xf4000001, 0x0004); \
458 FDesc[1 + mcd].offset += v0; \
461 #define buwrite(Ra1, mcd, length) { \
462 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
463 PSXBIOS_LOG("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
464 ptr = Mcd##mcd##Data + offset; \
465 memcpy(ptr, Ra1, length); \
466 FDesc[1 + mcd].offset += length; \
467 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
468 if (FDesc[1 + mcd].mode & 0x8000) { \
469 DeliverEvent(0xf0000011, 0x0004); \
470 DeliverEvent(0xf4000001, 0x0004); \
475 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
476 /* For some strange reason, the returned character is sign-expanded; */
477 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
478 /* TODO FIX ME : Properly implement this behaviour */
479 void psxBios_getc(void) // 0x03, 0x35
484 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
488 if (pa1 != INVALID_PTR) {
490 case 2: buread(pa1, 1, 1); break;
491 case 3: buread(pa1, 2, 1); break;
498 /* Copy of psxBios_write, except size is 1. */
499 void psxBios_putc(void) // 0x09, 0x3B
504 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
507 if (pa1 == INVALID_PTR) {
512 if (a0 == 1) { // stdout
513 char *ptr = (char *)pa1;
517 printf("%c", *ptr++); a2--;
523 case 2: buwrite(pa1, 1, 1); break;
524 case 3: buwrite(pa1, 2, 1); break;
530 void psxBios_todigit(void) // 0x0a
534 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
537 if (c >= 0x30 && c < 0x3A) {
540 else if (c > 0x60 && c < 0x7B) {
543 else if (c > 0x40 && c < 0x5B) {
546 else if (c >= 0x80) {
557 void psxBios_abs() { // 0x0e
558 if ((s32)a0 < 0) v0 = -(s32)a0;
563 void psxBios_labs() { // 0x0f
567 void psxBios_atoi() { // 0x10
569 char *p = (char *)Ra0;
571 if (p == INVALID_PTR) {
578 case ' ': case '\t': continue;
585 while (*p >= '0' && *p <= '9') {
586 n = n * 10 + *p++ - '0';
591 PSXBIOS_LOG("psxBios_%s %s (%x) -> 0x%x\n", biosA0n[0x10], Ra0, a0, v0);
594 void psxBios_atol() { // 0x11
604 static void psxBios_setjmp() { // 0x13
605 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
608 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
610 jmp_buf->ra_ = SWAP32(ra);
611 jmp_buf->sp_ = SWAP32(sp);
612 jmp_buf->fp_ = SWAP32(fp);
613 for (i = 0; i < 8; i++) // s0-s7
614 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
615 jmp_buf->gp_ = SWAP32(gp);
617 mips_return_c(0, 15);
620 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
624 ra = SWAP32(jmp_buf->ra_);
625 sp = SWAP32(jmp_buf->sp_);
626 fp = SWAP32(jmp_buf->fp_);
627 for (i = 0; i < 8; i++) // s0-s7
628 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
629 gp = SWAP32(jmp_buf->gp_);;
632 void psxBios_longjmp() { // 0x14
633 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
635 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
636 longjmp_load(jmp_buf);
637 mips_return_c(a1, 15);
640 void psxBios_strcat() { // 0x15
644 PSXBIOS_LOG("psxBios_%s %s (%x), %s (%x)\n", biosA0n[0x15], Ra0, a0, Ra1, a1);
645 if (a0 == 0 || a1 == 0 || p2 == INVALID_PTR)
650 while (loadRam8(p1)) {
654 for (; *p2; p1++, p2++)
658 mips_return_c(a0, 22);
661 void psxBios_strncat() { // 0x16
662 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
666 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
668 if (a0 == 0 || a1 == 0)
676 while ((*p1++ = *p2++) != '\0') {
686 void psxBios_strcmp() { // 0x17
687 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
689 if (a0 == 0 && a1 == 0)
695 else if (a0 == 0 && a1 != 0)
701 else if (a0 != 0 && a1 == 0)
708 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
711 while (*p1 == *p2++) {
730 void psxBios_strncmp() { // 0x18
731 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
733 if (a0 == 0 && a1 == 0)
739 else if (a0 == 0 && a1 != 0)
745 else if (a0 != 0 && a1 == 0)
752 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
755 while (--n >= 0 && *p1 == *p2++) {
759 v1 = a2 - ((a2-n) - 1);
767 v0 = (n < 0 ? 0 : *p1 - *--p2);
769 v1 = a2 - ((a2-n) - 1);
775 void psxBios_strcpy() { // 0x19
776 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
777 PSXBIOS_LOG("psxBios_%s %x, %s (%x)\n", biosA0n[0x19], a0, p2, a1);
778 if (a0 == 0 || a1 == 0)
784 while ((*p1++ = *p2++) != '\0');
789 void psxBios_strncpy() { // 0x1a
790 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
792 if (a0 == 0 || a1 == 0)
798 for (i = 0; i < n; i++) {
799 if ((*p1++ = *p2++) == '\0') {
811 void psxBios_strlen() { // 0x1b
812 char *p = (char *)Ra0;
823 void psxBios_index() { // 0x1c
824 char *p = (char *)Ra0;
834 v0 = a0 + (p - (char *)Ra0);
838 } while (*p++ != '\0');
843 void psxBios_rindex() { // 0x1d
844 char *p = (char *)Ra0;
854 v0 = a0 + (p - (char *)Ra0);
855 } while (*p++ != '\0');
860 void psxBios_strchr() { // 0x1e
864 void psxBios_strrchr() { // 0x1f
868 void psxBios_strpbrk() { // 0x20
869 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
871 while ((c = *p1++) != '\0') {
872 for (scanp = p2; (sc = *scanp++) != '\0';) {
874 v0 = a0 + (p1 - 1 - (char *)Ra0);
881 // BUG: return a0 instead of NULL if not found
885 void psxBios_strspn() { // 0x21
888 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
889 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
890 if (*p2 == '\0') break;
893 v0 = p1 - (char *)Ra0; pc0 = ra;
896 void psxBios_strcspn() { // 0x22
899 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
900 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
901 if (*p2 != '\0') break;
904 v0 = p1 - (char *)Ra0; pc0 = ra;
907 void psxBios_strtok() { // 0x23
908 char *pcA0 = (char *)Ra0;
909 char *pcRet = strtok(pcA0, (char *)Ra1);
911 v0 = a0 + pcRet - pcA0;
917 void psxBios_strstr() { // 0x24
918 char *p = (char *)Ra0, *p1, *p2;
919 PSXBIOS_LOG("psxBios_%s %s (%x), %s (%x)\n", biosA0n[0x24], p, a0, Ra1, a1);
925 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
930 v0 = a0 + (p - (char *)Ra0);
932 PSXBIOS_LOG(" -> %x\n", v0);
936 // bug: skips the whole matched substring + 1
943 void psxBios_toupper() { // 0x25
944 v0 = (s8)(a0 & 0xff);
945 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
949 void psxBios_tolower() { // 0x26
950 v0 = (s8)(a0 & 0xff);
951 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
955 static void do_memset(u32 dst, u32 v, s32 len)
961 if (db != INVALID_PTR)
965 psxCpu->Clear(dst, (len + 3) / 4);
968 static void do_memcpy(u32 dst, u32 src, s32 len)
970 u32 d = dst, s = src;
973 const u8 *sb = PSXM(s);
975 if (db != INVALID_PTR && sb != INVALID_PTR)
980 psxCpu->Clear(dst, (len + 3) / 4);
983 static void psxBios_memcpy();
985 static void psxBios_bcopy() { // 0x27 - memcpy with args swapped
986 //PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x27], a0, a1, a2);
987 u32 ret = a0, cycles = 0;
988 if (a0 == 0) // ...but it checks src this time
995 do_memcpy(a1, a0, a2);
1001 mips_return_c(ret, cycles + 5);
1004 static void psxBios_bzero() { // 0x28
1005 /* Same as memset here (See memset below) */
1006 u32 ret = a0, cycles;
1007 if (a0 == 0 || (s32)a1 <= 0)
1009 mips_return_c(0, 6);
1012 do_memset(a0, 0, a1);
1016 // todo: many more cycles due to uncached bios mem
1017 mips_return_c(ret, cycles + 5);
1020 void psxBios_bcmp() { // 0x29
1021 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
1023 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
1025 while ((s32)a2-- > 0) {
1026 if (*p1++ != *p2++) {
1027 v0 = *p1 - *p2; // BUG: compare the NEXT byte
1036 static void psxBios_memcpy() { // 0x2a
1037 u32 ret = a0, cycles = 0;
1040 mips_return_c(0, 4);
1045 do_memcpy(a0, a1, a2);
1051 mips_return_c(ret, cycles + 5);
1054 static void psxBios_memset() { // 0x2b
1055 u32 ret = a0, cycles;
1056 if (a0 == 0 || (s32)a2 <= 0)
1058 mips_return_c(0, 6);
1061 do_memset(a0, a1, a2);
1065 // todo: many more cycles due to uncached bios mem
1066 mips_return_c(ret, cycles + 5);
1069 void psxBios_memmove() { // 0x2c
1070 u32 ret = a0, cycles = 0;
1073 mips_return_c(0, 4);
1077 if ((s32)a2 > 0 && a0 > a1 && a0 < a1 + a2) {
1078 u32 dst = a0, len = a2 + 1;
1081 while ((s32)a2 >= 0) { // BUG: copies one more byte here
1082 const u8 *sb = PSXM(a1);
1084 if (db != INVALID_PTR && sb != INVALID_PTR)
1090 psxCpu->Clear(dst, (len + 3) / 4);
1091 cycles = 10 + len * 8;
1092 } else if ((s32)a2 > 0) {
1093 do_memcpy(a0, a1, a2);
1099 mips_return_c(ret, cycles + 5);
1102 void psxBios_memcmp() { // 0x2d
1106 void psxBios_memchr() { // 0x2e
1107 char *p = (char *)Ra0;
1109 if (a0 == 0 || a2 > 0x7FFFFFFF)
1115 while ((s32)a2-- > 0) {
1116 if (*p++ != (s8)a1) continue;
1117 v0 = a0 + (p - (char *)Ra0 - 1);
1125 static void psxBios_rand() { // 0x2f
1126 u32 s = loadRam32(A_RND_SEED) * 1103515245 + 12345;
1127 storeRam32(A_RND_SEED, s);
1129 mips_return_c((s >> 16) & 0x7fff, 12+37);
1132 static void psxBios_srand() { // 0x30
1133 storeRam32(A_RND_SEED, a0);
1134 mips_return_void_c(3);
1137 static u32 qscmpfunc, qswidth;
1139 static inline int qscmp(char *a, char *b) {
1142 a0 = sa0 + (a - (char *)PSXM(sa0));
1143 a1 = sa0 + (b - (char *)PSXM(sa0));
1145 softCall(qscmpfunc);
1151 static inline void qexchange(char *i, char *j) {
1162 static inline void q3exchange(char *i, char *j, char *k) {
1174 static void qsort_main(char *a, char *l) {
1175 char *i, *j, *lp, *hp;
1180 if ((n = l - a) <= qswidth)
1182 n = qswidth * (n / (2 * qswidth));
1188 if ((c = qscmp(i, lp)) == 0) {
1189 qexchange(i, lp -= qswidth);
1200 if ((c = qscmp(hp, j)) == 0) {
1201 qexchange(hp += qswidth, j);
1206 q3exchange(i, hp += qswidth, j);
1220 if (lp - a >= l - hp) {
1221 qsort_main(hp + qswidth, l);
1230 q3exchange(j, lp -= qswidth, i);
1235 void psxBios_qsort() { // 0x31
1238 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1243 static int malloc_heap_grow(u32 size) {
1244 u32 heap_addr, heap_end, heap_addr_new;
1246 heap_addr = loadRam32(A_HEAP_BASE);
1247 heap_end = loadRam32(A_HEAP_END);
1248 heap_addr_new = heap_addr + 4 + size;
1249 if (heap_addr_new >= heap_end)
1251 storeRam32(A_HEAP_BASE, heap_addr_new);
1252 storeRam32(heap_addr - 4, size | 1);
1253 storeRam32(heap_addr + size, ~1); // terminator
1257 static void psxBios_malloc() { // 0x33
1258 u32 size = (a0 + 3) & ~3;
1259 u32 limit = 32*1024;
1263 PSXBIOS_LOG("psxBios_%s %d\n", biosA0n[0x33], a0);
1265 if (!loadRam32(A_HEAP_INIT_FLG)) {
1266 u32 heap_addr = loadRam32(A_HEAP_BASE);
1267 storeRam32(heap_addr, ~1);
1268 storeRam32(A_HEAP_FRSTCHNK, heap_addr);
1269 storeRam32(A_HEAP_CURCHNK, heap_addr);
1270 storeRam32(A_HEAP_BASE, heap_addr + 4);
1271 if (malloc_heap_grow(size)) {
1272 PSXBIOS_LOG("malloc: init OOM\n");
1273 mips_return_c(0, 20);
1276 storeRam32(A_HEAP_INIT_FLG, 1);
1279 for (i = 0; tries > 0 && i < limit; i++)
1281 u32 chunk = loadRam32(A_HEAP_CURCHNK);
1282 u32 chunk_hdr = loadRam32(chunk);
1283 u32 next_chunk = chunk + 4 + (chunk_hdr & ~3);
1284 u32 next_chunk_hdr = loadRam32(next_chunk);
1286 //printf(" c %08x %08x\n", chunk, chunk_hdr);
1287 if (chunk_hdr & 1) {
1289 if (chunk_hdr > (size | 1)) {
1291 u32 p2size = (chunk_hdr & ~3) - size - 4;
1292 storeRam32(chunk + 4 + size, p2size | 1);
1293 chunk_hdr = size | 1;
1295 if (chunk_hdr == (size | 1)) {
1296 storeRam32(chunk, size);
1300 if (next_chunk_hdr & 1) {
1302 u32 msize = (chunk_hdr & ~3) + 4 + (next_chunk_hdr & ~3);
1303 storeRam32(chunk, msize | 1);
1307 if (chunk_hdr == ~1) {
1310 storeRam32(A_HEAP_CURCHNK, loadRam32(A_HEAP_FRSTCHNK));
1314 // go to the next chunk
1315 storeRam32(A_HEAP_CURCHNK, next_chunk);
1321 else if (tries == 0 && malloc_heap_grow(size))
1324 u32 chunk = loadRam32(A_HEAP_CURCHNK);
1325 storeRam32(chunk, loadRam32(chunk) & ~3);
1329 PSXBIOS_LOG(" -> %08x\n", ret);
1330 mips_return_c(ret, 40);
1333 static void psxBios_free() { // 0x34
1334 PSXBIOS_LOG("psxBios_%s %x (%d bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1335 storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1336 mips_return_void_c(5);
1339 static void psxBios_calloc() { // 0x37
1341 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
1343 a0 = size = a0 * a1;
1347 a0 = ret; a1 = size;
1350 mips_return_c(ret, 21);
1353 void psxBios_realloc() { // 0x38
1357 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1361 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1366 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1371 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1372 /* Note that it is not quite implemented this way here. */
1382 /* InitHeap(void *block , int n) */
1383 static void psxBios_InitHeap() { // 0x39
1384 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
1386 storeRam32(A_HEAP_BASE, a0);
1387 storeRam32(A_HEAP_SIZE, a1);
1388 storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
1389 storeRam32(A_HEAP_INIT_FLG, 0);
1392 mips_return_void_c(14);
1395 void psxBios_getchar() { //0x3b
1396 v0 = getchar(); pc0 = ra;
1399 static void psxBios_printf_psxout() { // 0x3f
1402 u32 save[4] = { 0, };
1408 if (psp != INVALID_PTR) {
1409 memcpy(save, psp, 4 * 4);
1410 psxMu32ref(sp) = SWAP32((u32)a0);
1411 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1412 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1413 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1425 tmp2[j++] = Ra0[i]; goto _start;
1427 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1438 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1442 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1448 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1450 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1452 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1454 *ptmp++ = Ra0[i]; break;
1464 if (psp != INVALID_PTR)
1465 memcpy(psp, save, 4 * 4);
1468 SysPrintf("%s", tmp);
1471 void psxBios_printf() { // 0x3f
1472 psxBios_printf_psxout();
1476 static void psxBios_cd() { // 0x40
1477 const char *p, *dir = castRam8ptr(a0);
1478 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x40], a0, dir);
1479 if ((p = strchr(dir, ':')))
1483 snprintf(cdir, sizeof(cdir), "%s", dir);
1484 mips_return_c(1, 100);
1487 static void psxBios_format() { // 0x41
1488 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x41], a0, Ra0);
1489 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1491 CreateMcd(Config.Mcd1);
1492 LoadMcd(1, Config.Mcd1);
1495 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1497 CreateMcd(Config.Mcd2);
1498 LoadMcd(2, Config.Mcd2);
1508 static void psxBios_SystemErrorUnresolvedException() {
1509 if (floodchk != 0x12340a40) { // prevent log flood
1510 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1511 floodchk = 0x12340a40;
1513 mips_return_void_c(1000);
1516 static void FlushCache() {
1517 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1518 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1520 // runs from uncached mem so tons of cycles
1525 * long Load(char *name, struct EXEC *header);
1528 void psxBios_Load() { // 0x42
1536 PSXBIOS_LOG("psxBios_%s %x(%s), %x\n", biosA0n[0x42], a0, pa0, a1);
1537 if (pa0 == INVALID_PTR || pa1 == INVALID_PTR) {
1541 if ((p = strchr(pa0, ':')))
1546 snprintf(path, sizeof(path), "%s\\%s", cdir, (char *)pa0);
1548 snprintf(path, sizeof(path), "%s", (char *)pa0);
1550 if (LoadCdromFile(path, &eheader) == 0) {
1551 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1552 psxCpu->Clear(a1, sizeof(EXEC) / 4);
1556 PSXBIOS_LOG(" -> %d\n", v0);
1562 * int Exec(struct EXEC *header , int argc , char **argv);
1565 void psxBios_Exec() { // 43
1566 EXEC *header = (EXEC *)castRam32ptr(a0);
1570 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1572 header->_sp = SWAP32(sp);
1573 header->_fp = SWAP32(fp);
1574 header->_sp = SWAP32(sp);
1575 header->_gp = SWAP32(gp);
1576 header->ret = SWAP32(ra);
1577 header->base = SWAP32(s0);
1579 ptr = SWAP32(header->b_addr);
1580 len = SWAP32(header->b_size);
1586 if (header->S_addr != 0)
1587 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1589 gp = SWAP32(header->gp0);
1597 pc0 = SWAP32(header->_pc0);
1600 static void psxBios_FlushCache() { // 44
1601 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1606 void psxBios_GPU_dw() { // 0x46
1611 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1614 GPU_writeData(0xa0000000);
1615 GPU_writeData((a1<<0x10)|(a0&0xffff));
1616 GPU_writeData((a3<<0x10)|(a2&0xffff));
1618 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1621 GPU_writeData(SWAPu32(*ptr++));
1627 void psxBios_mem2vram() { // 0x47
1629 gpuSyncPluginSR(); // flush
1630 GPU_writeData(0xa0000000);
1631 GPU_writeData((a1<<0x10)|(a0&0xffff));
1632 GPU_writeData((a3<<0x10)|(a2&0xffff));
1633 size = ((((a2 * a3) / 2) >> 4) << 16);
1634 GPU_writeStatus(0x04000002);
1635 psxHwWrite32(0x1f8010f4,0);
1636 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1637 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1638 psxHwWrite32(0x1f8010a4, size | 0x10);
1639 psxHwWrite32(0x1f8010a8,0x01000201);
1644 void psxBios_SendGPU() { // 0x48
1645 GPU_writeStatus(a0);
1650 void psxBios_GPU_cw() { // 0x49
1657 void psxBios_GPU_cwb() { // 0x4a
1658 u32 *ptr = (u32*)Ra0;
1663 GPU_writeData(SWAPu32(*ptr++));
1669 void psxBios_GPU_SendPackets() { //4b:
1671 GPU_writeStatus(0x04000002);
1672 psxHwWrite32(0x1f8010f4,0);
1673 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1674 psxHwWrite32(0x1f8010a0,a0);
1675 psxHwWrite32(0x1f8010a4,0);
1676 psxHwWrite32(0x1f8010a8,0x010000401);
1680 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1681 psxHwWrite32(0x1f8010a8,0x00000401);
1682 GPU_writeData(0x0400000);
1683 GPU_writeData(0x0200000);
1684 GPU_writeData(0x0100000);
1689 void psxBios_GPU_GetGPUStatus() { // 0x4d
1690 v0 = GPU_readStatus();
1696 void psxBios_LoadExec() { // 51
1697 EXEC *header = (EXEC*)PSXM(0xf000);
1701 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1703 s_addr = a1; s_size = a2;
1708 header->S_addr = s_addr;
1709 header->s_size = s_size;
1711 a0 = 0xf000; a1 = 0; a2 = 0;
1715 void psxBios__bu_init() { // 70
1717 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1720 DeliverEvent(0xf0000011, 0x0004);
1721 DeliverEvent(0xf4000001, 0x0004);
1726 void psxBios__96_init() { // 71
1728 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1734 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1735 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1736 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1738 static void psxBios_DequeueCdIntr_() {
1739 psxBios_SysDeqIntRP_(0, 0x91d0);
1740 psxBios_SysDeqIntRP_(0, 0x91e0);
1744 static void psxBios_DequeueCdIntr() { // a3
1745 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1746 psxBios_DequeueCdIntr_();
1749 static void psxBios_CdRemove() { // 56, 72
1750 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1752 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1753 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1754 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1755 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1756 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1757 psxBios_DequeueCdIntr_();
1759 // EnterCriticalSection - should be done at the beginning,
1760 // but this way is much easier to implement
1766 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack);
1768 static void psxBios_SetConf() { // 9c
1769 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9c], a0, a1, a2);
1770 setup_tt(a1, a0, a2);
1771 psxRegs.CP0.n.SR |= 0x401;
1772 mips_return_void_c(500);
1775 static void psxBios_GetConf() { // 9d
1776 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9d], a0, a1, a2);
1777 storeRam32(a0, loadRam32(A_CONF_EvCB));
1778 storeRam32(a1, loadRam32(A_CONF_TCB));
1779 storeRam32(a2, loadRam32(A_CONF_SP));
1780 mips_return_void_c(10);
1783 void psxBios_SetMem() { // 9f
1784 u32 new = psxHu32(0x1060);
1787 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1792 psxHu32ref(0x1060) = SWAP32(new);
1793 psxMu32ref(0x060) = a0;
1794 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1798 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1799 psxMu32ref(0x060) = a0;
1800 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1803 PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
1810 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1811 static void psxBios_get_cd_status() // a6
1813 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
1818 static void psxBios__card_info() { // ab
1819 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1821 storeRam32(A_CARD_CHAN1, a0);
1828 if (McdDisable[port & 1])
1832 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
1837 if (McdDisable[0] && McdDisable[1])
1840 DeliverEvent(0xf0000011, 0x0004);
1841 // DeliverEvent(0xf4000001, 0x0004);
1842 DeliverEvent(0xf4000001, ret);
1846 void psxBios__card_load() { // ac
1848 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1851 storeRam32(A_CARD_CHAN1, a0);
1853 // DeliverEvent(0xf0000011, 0x0004);
1854 DeliverEvent(0xf4000001, 0x0004);
1859 static void psxBios_GetSystemInfo() { // b4
1861 //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
1862 SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
1865 case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
1866 case 2: ret = 0xbfc0012c; break;
1867 case 5: ret = loadRam32(0x60) << 10; break;
1869 mips_return_c(ret, 20);
1872 /* System calls B0 */
1874 static u32 psxBios_SysMalloc_(u32 size);
1876 static void psxBios_SysMalloc() { // B 00
1877 u32 ret = psxBios_SysMalloc_(a0);
1879 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1880 mips_return_c(ret, 33);
1883 void psxBios_SetRCnt() { // 02
1885 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1892 psxRcntWtarget(a0, a1);
1893 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1894 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1895 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1896 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1897 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1899 psxRcntWmode(a0, mode);
1904 void psxBios_GetRCnt() { // 03
1906 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1911 case 0: v0 = psxRcntRcount0(); break;
1912 case 1: v0 = psxRcntRcount1(); break;
1913 case 2: v0 = psxRcntRcount2(); break;
1914 case 3: v0 = 0; break;
1919 void psxBios_StartRCnt() { // 04
1921 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1925 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1926 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1930 void psxBios_StopRCnt() { // 05
1932 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1936 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1937 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1941 void psxBios_ResetRCnt() { // 06
1943 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1948 psxRcntWmode(a0, 0);
1949 psxRcntWtarget(a0, 0);
1950 psxRcntWcount(a0, 0);
1955 static u32 DeliverEvent(u32 class, u32 spec) {
1956 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1957 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1958 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1959 u32 i, lim = evcb_len / 0x1c;
1961 //printf("%s %08x %x\n", __func__, class, spec);
1962 for (i = 0; i < lim; i++, ev++) {
1964 if (SWAP32(ev->status) != EvStACTIVE)
1967 if (SWAP32(ev->class) != class)
1970 if (SWAP32(ev->spec) != spec)
1973 ret = SWAP32(ev->mode);
1974 if (ret == EvMdMARK) {
1975 ev->status = SWAP32(EvStALREADY);
1979 if (ret == EvMdCALL) {
1980 ret = SWAP32(ev->fhandler);
1993 static u32 UnDeliverEvent(u32 class, u32 spec) {
1994 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1995 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1996 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1997 u32 i, lim = evcb_len / 0x1c;
1999 for (i = 0; i < lim; i++, ev++) {
2001 if (SWAP32(ev->status) != EvStALREADY)
2004 if (SWAP32(ev->class) != class)
2007 if (SWAP32(ev->spec) != spec)
2010 if (SWAP32(ev->mode) == EvMdMARK)
2011 ev->status = SWAP32(EvStACTIVE);
2017 static void psxBios_DeliverEvent() { // 07
2019 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
2021 ret = DeliverEvent(a0, a1);
2025 static s32 get_free_EvCB_slot() {
2026 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
2027 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
2030 for (i = 0; i < lim; i++, ev++) {
2032 if (ev->status == SWAP32(EvStUNUSED))
2038 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
2039 u32 ret = get_free_EvCB_slot();
2040 if ((s32)ret >= 0) {
2041 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
2042 ev->class = SWAP32(class);
2043 ev->status = SWAP32(EvStDISABLED);
2044 ev->spec = SWAP32(spec);
2045 ev->mode = SWAP32(mode);
2046 ev->fhandler = SWAP32(func);
2052 static void psxBios_OpenEvent() { // 08
2053 u32 ret = OpenEvent(a0, a1, a2, a3);
2054 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
2055 biosB0n[0x08], a0, a1, a2, a3, ret);
2056 mips_return_c(ret, 36);
2059 static void CloseEvent(u32 ev)
2061 u32 base = loadRam32(A_TT_EvCB);
2062 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
2065 static void psxBios_CloseEvent() { // 09
2066 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
2067 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
2069 mips_return_c(1, 10);
2072 static void psxBios_WaitEvent() { // 0a
2073 u32 base = loadRam32(A_TT_EvCB);
2074 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2075 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
2078 if (status == EvStALREADY) {
2079 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2083 if (status != EvStACTIVE)
2085 mips_return_c(0, 2);
2089 // retrigger this hlecall after the next emulation event
2091 if ((s32)(next_interupt - psxRegs.cycle) > 0)
2092 psxRegs.cycle = next_interupt;
2096 static void psxBios_TestEvent() { // 0b
2097 u32 base = loadRam32(A_TT_EvCB);
2098 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2101 if (psxRegs.cycle - floodchk > 16*1024u) { // prevent log flood
2102 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
2103 floodchk = psxRegs.cycle;
2105 if (status == EvStALREADY) {
2106 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2110 mips_return_c(ret, 15);
2113 static void psxBios_EnableEvent() { // 0c
2114 u32 base = loadRam32(A_TT_EvCB);
2115 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2116 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
2117 if (status != EvStUNUSED)
2118 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2120 mips_return_c(1, 15);
2123 static void psxBios_DisableEvent() { // 0d
2124 u32 base = loadRam32(A_TT_EvCB);
2125 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2126 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2127 if (status != EvStUNUSED)
2128 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2130 mips_return_c(1, 15);
2134 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2137 void psxBios_OpenTh() { // 0e
2138 TCB *tcb = loadRam32ptr(A_TT_TCB);
2139 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2142 for (th = 1; th < limit; th++)
2144 if (tcb[th].status != SWAP32(0x4000)) break;
2148 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2149 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2151 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2153 mips_return_c(0xffffffff, 20);
2156 PSXBIOS_LOG("psxBios_%s -> %x\n", biosB0n[0x0e], 0xff000000 + th);
2158 tcb[th].status = SWAP32(0x4000);
2159 tcb[th].mode = SWAP32(0x1000);
2160 tcb[th].epc = SWAP32(a0);
2161 tcb[th].reg[30] = SWAP32(a1); // fp
2162 tcb[th].reg[29] = SWAP32(a1); // sp
2163 tcb[th].reg[28] = SWAP32(a2); // gp
2165 mips_return_c(0xff000000 + th, 34);
2169 * int CloseTh(long thread);
2172 static void psxBios_CloseTh() { // 0f
2173 u32 tcb = loadRam32(A_TT_TCB);
2174 u32 th = a0 & 0xffff;
2176 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x0f], a0);
2177 // in the usual bios fashion no checks, just write and return 1
2178 storeRam32(tcb + th * sizeof(TCB), 0x1000);
2180 mips_return_c(1, 11);
2184 * int ChangeTh(long thread);
2187 void psxBios_ChangeTh() { // 10
2188 u32 tcbBase = loadRam32(A_TT_TCB);
2189 u32 th = a0 & 0xffff;
2191 // this is quite spammy
2192 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2194 // without doing any argument checks, just issue a syscall
2195 // (like the real bios does)
2197 a1 = tcbBase + th * sizeof(TCB);
2202 void psxBios_InitPAD() { // 0x12
2203 u32 i, *ram32 = (u32 *)psxM;
2204 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2206 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2207 ram32[A_PAD_DR_DST/4] = 0;
2208 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2209 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2210 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2211 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2212 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2213 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2214 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2215 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2217 for (i = 0; i < a1; i++) {
2219 storeRam8(a0 + i, 0);
2221 for (i = 0; i < a3; i++) {
2223 storeRam8(a2 + i, 0);
2225 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2227 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2229 mips_return_c(1, 200);
2232 void psxBios_StartPAD() { // 13
2233 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2235 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2236 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2237 psxHwWrite16(0x1f801070, ~1);
2238 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2239 storeRam32(A_PAD_ACK_VBL, 1);
2240 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2241 psxRegs.CP0.n.SR |= 0x401;
2243 mips_return_c(1, 300);
2246 void psxBios_StopPAD() { // 14
2247 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2248 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2249 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2250 psxRegs.CP0.n.SR |= 0x401;
2251 mips_return_void_c(200);
2254 static void psxBios_PAD_init() { // 15
2256 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2257 if (a0 == 0x20000000 || a0 == 0x20000001)
2260 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2261 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2264 storeRam32(A_PAD_DR_DST, dst);
2267 mips_return_c(ret, 100);
2270 static u32 psxBios_PAD_dr_() {
2271 u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2272 u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2273 u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2274 dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2275 if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2277 dst[0] = buf1[3], dst[1] = buf1[2];
2278 if (buf1[1] == 0x23) {
2279 dst[0] |= 0xc7, dst[1] |= 7;
2280 if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2281 if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2284 if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2286 dst[2] = buf2[3], dst[3] = buf2[2];
2287 if (buf2[1] == 0x23) {
2288 dst[2] |= 0xc7, dst[3] |= 7;
2289 if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2290 if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2294 return SWAP32(*(u32 *)dst);
2297 static void psxBios_PAD_dr() { // 16
2298 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2299 u32 ret = psxBios_PAD_dr_();
2303 static void psxBios_ReturnFromException() { // 17
2304 u32 tcbPtr = loadRam32(A_TT_PCB);
2305 const TCB *tcb = loadRam32ptr(tcbPtr);
2309 for (i = 1; i < 32; i++)
2310 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2311 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2312 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2313 sr = SWAP32(tcb->sr);
2315 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2316 pc0 = k0 = SWAP32(tcb->epc);
2318 // the interpreter wants to know about sr changes, so do a MTC0
2319 sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2320 MTC0(&psxRegs, 12, sr);
2326 void psxBios_ResetEntryInt() { // 18
2327 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2329 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2330 mips_return_void_c(5);
2333 void psxBios_HookEntryInt() { // 19
2334 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2336 storeRam32(A_EEXIT_PTR, a0);
2337 mips_return_void_c(3);
2340 static void psxBios_UnDeliverEvent() { // 0x20
2342 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2344 ret = UnDeliverEvent(a0, a1);
2348 static void buopen(int mcd, char *ptr, char *cfg)
2351 char *mcd_data = ptr;
2353 strcpy(FDesc[1 + mcd].name, Ra0+5);
2354 FDesc[1 + mcd].offset = 0;
2355 FDesc[1 + mcd].mode = a1;
2357 for (i=1; i<16; i++) {
2358 const char *fptr = mcd_data + 128 * i;
2359 if ((*fptr & 0xF0) != 0x50) continue;
2360 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2361 FDesc[1 + mcd].mcfile = i;
2362 PSXBIOS_LOG("open %s\n", fptr+0xa);
2366 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2367 for (i=1; i<16; i++) {
2368 int j, xor, nblk = a1 >> 16;
2370 char *fptr = mcd_data + 128 * i;
2372 if ((*fptr & 0xF0) != 0xa0) continue;
2374 FDesc[1 + mcd].mcfile = i;
2377 fptr[5] = 0x20 * nblk;
2380 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2381 pptr = fptr2 = fptr;
2382 for(j=2; j<=nblk; j++) {
2384 for(i++; i<16; i++) {
2387 memset(fptr2, 0, 128);
2388 fptr2[0] = j < nblk ? 0x52 : 0x53;
2391 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2396 /* shouldn't this return ENOSPC if i == 16? */
2398 pptr[8] = pptr[9] = 0xff;
2399 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2401 PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2403 /* just go ahead and resave them all */
2404 SaveMcd(cfg, ptr, 128, 128 * 15);
2407 /* shouldn't this return ENOSPC if i == 16? */
2412 * int open(char *name , int mode);
2415 void psxBios_open() { // 0x32
2418 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x32], Ra0, a1);
2422 if (pa0 != INVALID_PTR) {
2423 if (!strncmp(pa0, "bu00", 4)) {
2424 buopen(1, Mcd1Data, Config.Mcd1);
2427 if (!strncmp(pa0, "bu10", 4)) {
2428 buopen(2, Mcd2Data, Config.Mcd2);
2436 * int lseek(int fd , int offset , int whence);
2439 void psxBios_lseek() { // 0x33
2441 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2446 FDesc[a0].offset = a1;
2448 // DeliverEvent(0xf0000011, 0x0004);
2449 // DeliverEvent(0xf4000001, 0x0004);
2453 FDesc[a0].offset+= a1;
2454 v0 = FDesc[a0].offset;
2463 * int read(int fd , void *buf , int nbytes);
2466 void psxBios_read() { // 0x34
2471 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2476 if (pa1 != INVALID_PTR) {
2478 case 2: buread(pa1, 1, a2); break;
2479 case 3: buread(pa1, 2, a2); break;
2487 * int write(int fd , void *buf , int nbytes);
2490 void psxBios_write() { // 0x35/0x03
2494 if (a0 != 1) // stdout
2495 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2498 if (pa1 == INVALID_PTR) {
2503 if (a0 == 1) { // stdout
2507 if (Config.PsxOut) while (a2 > 0) {
2508 SysPrintf("%c", *ptr++); a2--;
2514 case 2: buwrite(pa1, 1, a2); break;
2515 case 3: buwrite(pa1, 2, a2); break;
2521 static void psxBios_write_psxout() {
2522 if (a0 == 1) { // stdout
2523 const char *ptr = Ra1;
2526 if (ptr != INVALID_PTR)
2528 SysPrintf("%c", *ptr++);
2532 static void psxBios_putchar_psxout() { // 3d
2533 SysPrintf("%c", (char)a0);
2536 static void psxBios_puts_psxout() { // 3e/3f
2537 SysPrintf("%s", Ra0);
2541 * int close(int fd);
2544 void psxBios_close() { // 0x36
2546 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2553 void psxBios_putchar() { // 3d
2554 if (Config.PsxOut) SysPrintf("%c", (char)a0);
2558 void psxBios_puts() { // 3e/3f
2559 if (Config.PsxOut) SysPrintf("%s", Ra0);
2563 static void bufile(const u8 *mcd_data, u32 dir_) {
2564 struct DIRENTRY *dir = (struct DIRENTRY *)castRam8ptr(dir_);
2565 const char *pfile = ffile + 5;
2566 const u8 *data = mcd_data;
2567 int i = 0, match = 0;
2572 for (; nfile <= 15 && !match; nfile++) {
2575 head = nfile * 0x40;
2576 data = mcd_data + 128 * nfile;
2577 name = (const char *)data + 0x0a;
2578 if ((data[0] & 0xF0) != 0x50) continue;
2579 /* Bug link files show up as free block. */
2580 if (!name[0]) continue;
2582 for (i = 0; i < 20; i++) {
2583 if (pfile[i] == name[i] || pfile[i] == '?')
2584 dir->name[i] = name[i];
2585 else if (pfile[i] == '*') {
2586 int len = strlen(name + i);
2589 memcpy(dir->name + i, name + i, len + 1);
2600 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n",
2601 nfile, dir->name, pfile, name, match);
2603 for (; nfile <= 15; nfile++, blocks++) {
2604 const u8 *data2 = mcd_data + 128 * nfile;
2605 const char *name = (const char *)data2 + 0x0a;
2606 if ((data2[0] & 0xF0) != 0x50 || name[0])
2610 // nul char of full lenth name seems to overwrite .attr
2611 dir->attr = SWAP32(i < 20 ? data[0] & 0xf0 : 0); // ?
2612 dir->size = 8192 * blocks;
2616 PSXBIOS_LOG(" -> %x '%s' %x %x %x %x\n", v0, v0 ? dir->name : "",
2617 dir->attr, dir->size, dir->next, dir->head);
2621 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2624 static void psxBios_firstfile() { // 42
2625 char *pa0 = castRam8ptr(a0);
2627 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x42], pa0, a1);
2631 snprintf(ffile, sizeof(ffile), "%s", pa0);
2633 strcpy(ffile + 5, "*"); // maybe?
2635 if (!strncmp(pa0, "bu00", 4)) {
2636 // firstfile() calls _card_read() internally, so deliver it's event
2637 DeliverEvent(0xf0000011, 0x0004);
2638 bufile((u8 *)Mcd1Data, a1);
2639 } else if (!strncmp(pa0, "bu10", 4)) {
2640 // firstfile() calls _card_read() internally, so deliver it's event
2641 DeliverEvent(0xf0000011, 0x0004);
2642 bufile((u8 *)Mcd2Data, a1);
2650 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2653 void psxBios_nextfile() { // 43
2654 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x43], a0);
2657 if (!strncmp(ffile, "bu00", 4))
2658 bufile((u8 *)Mcd1Data, a0);
2659 else if (!strncmp(ffile, "bu10", 4))
2660 bufile((u8 *)Mcd2Data, a0);
2665 #define burename(mcd) { \
2666 for (i=1; i<16; i++) { \
2667 int namelen, j, xor = 0; \
2668 ptr = Mcd##mcd##Data + 128 * i; \
2669 if ((*ptr & 0xF0) != 0x50) continue; \
2670 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2671 namelen = strlen(Ra1+5); \
2672 memcpy(ptr+0xa, Ra1+5, namelen); \
2673 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2674 for (j=0; j<127; j++) xor^= ptr[j]; \
2676 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2683 * int rename(char *old, char *new);
2686 void psxBios_rename() { // 44
2693 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2698 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2699 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2703 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2712 #define budelete(mcd) { \
2713 for (i=1; i<16; i++) { \
2714 ptr = Mcd##mcd##Data + 128 * i; \
2715 if ((*ptr & 0xF0) != 0x50) continue; \
2716 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2717 *ptr = (*ptr & 0xf) | 0xA0; \
2718 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2719 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2726 * int delete(char *name);
2729 void psxBios_delete() { // 45
2735 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2740 if (pa0 != INVALID_PTR) {
2741 if (!strncmp(pa0, "bu00", 4)) {
2745 if (!strncmp(pa0, "bu10", 4)) {
2753 void psxBios_InitCARD() { // 4a
2754 u32 *ram32 = (u32 *)psxM;
2755 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2756 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2757 // (maybe) todo: early_card_irq, etc
2759 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2761 psxBios_FlushCache();
2762 mips_return_c(0, 34+13+15+6);
2765 void psxBios_StartCARD() { // 4b
2766 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2767 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2768 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2770 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2771 storeRam32(A_PAD_ACK_VBL, 1);
2772 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2773 storeRam32(A_CARD_IRQR_ENA, 1);
2774 psxRegs.CP0.n.SR |= 0x401;
2776 mips_return_c(1, 200);
2779 void psxBios_StopCARD() { // 4c
2780 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2781 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2782 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2783 storeRam32(A_CARD_IRQR_ENA, 0);
2784 psxRegs.CP0.n.SR |= 0x401;
2785 mips_return_void_c(200);
2788 void psxBios__card_write() { // 0x4e
2793 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2796 Function also accepts sector 400h (a bug).
2797 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2801 /* Invalid sectors */
2805 storeRam32(A_CARD_CHAN1, a0);
2808 if (pa2 != INVALID_PTR) {
2810 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2811 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2813 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2814 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2818 DeliverEvent(0xf0000011, 0x0004);
2819 // DeliverEvent(0xf4000001, 0x0004);
2824 void psxBios__card_read() { // 0x4f
2829 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2832 Function also accepts sector 400h (a bug).
2833 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2837 /* Invalid sectors */
2841 storeRam32(A_CARD_CHAN1, a0);
2844 if (pa2 != INVALID_PTR) {
2846 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2848 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2852 DeliverEvent(0xf0000011, 0x0004);
2853 // DeliverEvent(0xf4000001, 0x0004);
2858 void psxBios__new_card() { // 0x50
2860 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2866 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2867 void psxBios__get_error(void) // 55
2869 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2874 void psxBios_Krom2RawAdd() { // 0x51
2877 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2878 const u32 table_8140[][2] = {
2879 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2880 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2881 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2882 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2883 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2884 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2885 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2886 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2887 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2891 const u32 table_889f[][2] = {
2892 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2893 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2894 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2895 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2896 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2897 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2898 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2899 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2903 if (a0 >= 0x8140 && a0 <= 0x84be) {
2904 while (table_8140[i][0] <= a0) i++;
2905 a0 -= table_8140[i - 1][0];
2906 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2907 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2908 while (table_889f[i][0] <= a0) i++;
2909 a0 -= table_889f[i - 1][0];
2910 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2918 void psxBios_GetC0Table() { // 56
2919 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2920 log_unhandled("GetC0Table @%08x\n", ra);
2922 mips_return_c(A_C0_TABLE, 3);
2925 void psxBios_GetB0Table() { // 57
2926 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2927 log_unhandled("GetB0Table @%08x\n", ra);
2929 mips_return_c(A_B0_TABLE, 3);
2932 static void psxBios__card_chan() { // 0x58
2934 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2936 // todo: should return active slot chan
2937 // (active - which was last processed by irq code)
2938 ret = loadRam32(A_CARD_CHAN1);
2939 mips_return_c(ret, 8);
2942 static void psxBios_ChangeClearPad() { // 5b
2944 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2945 ret = loadRam32(A_PAD_ACK_VBL);
2946 storeRam32(A_PAD_ACK_VBL, a0);
2948 mips_return_c(ret, 6);
2951 static void psxBios__card_status() { // 5c
2952 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
2958 static void psxBios__card_wait() { // 5d
2959 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
2965 /* System calls C0 */
2967 static void psxBios_InitRCnt() { // 00
2969 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2970 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2971 for (i = 0; i < 3; i++) {
2972 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2973 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2974 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2976 psxBios_SysEnqIntRP_(a0, 0x6d88);
2977 mips_return_c(0, 9);
2980 static void psxBios_InitException() { // 01
2981 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2982 psxBios_SysEnqIntRP_(a0, 0x6da8);
2983 mips_return_c(0, 9);
2987 * int SysEnqIntRP(int index , long *queue);
2990 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2991 u32 old, base = loadRam32(A_TT_ExCB);
2993 old = loadRam32(base + (priority << 3));
2994 storeRam32(base + (priority << 3), chain_eptr);
2995 storeRam32(chain_eptr, old);
2996 mips_return_c(0, 9);
2999 static void psxBios_SysEnqIntRP() { // 02
3000 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
3001 psxBios_SysEnqIntRP_(a0, a1);
3005 * int SysDeqIntRP(int index , long *queue);
3008 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
3009 u32 ptr, next, base = loadRam32(A_TT_ExCB);
3010 u32 lim = 0, ret = 0;
3012 // as in original: no arg checks of any kind, bug if a1 == 0
3013 ptr = loadRam32(base + (priority << 3));
3015 next = loadRam32(ptr);
3016 if (ptr == chain_rm_eptr) {
3017 storeRam32(base + (priority << 3), next);
3022 while (next && next != chain_rm_eptr && lim++ < 100) {
3024 next = loadRam32(ptr);
3027 if (next == chain_rm_eptr) {
3028 next = loadRam32(next);
3029 storeRam32(ptr, next);
3036 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
3038 mips_return_c(ret, 12);
3041 static void psxBios_SysDeqIntRP() { // 03
3042 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
3043 psxBios_SysDeqIntRP_(a0, a1);
3046 static void psxBios_get_free_EvCB_slot() { // 04
3047 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
3048 s32 ret = get_free_EvCB_slot();
3049 mips_return_c(ret, 0);
3052 static void psxBios_SysInitMemory_(u32 base, u32 size) {
3053 storeRam32(base, 0);
3054 storeRam32(A_KMALLOC_PTR, base);
3055 storeRam32(A_KMALLOC_SIZE, size);
3056 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
3059 // this should be much more complicated, but maybe that'll be enough
3060 static u32 psxBios_SysMalloc_(u32 size) {
3061 u32 ptr = loadRam32(A_KMALLOC_PTR);
3063 size = (size + 3) & ~3;
3064 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
3065 storeRam32(ptr, size);
3069 static void psxBios_SysInitMemory() { // 08
3070 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
3072 psxBios_SysInitMemory_(a0, a1);
3073 mips_return_void_c(12);
3076 static void psxBios_ChangeClearRCnt() { // 0a
3079 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
3081 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
3082 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
3083 mips_return_c(ret, 8);
3086 static void psxBios_InitDefInt() { // 0c
3087 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3088 // should also clear the autoack table
3089 psxBios_SysEnqIntRP_(a0, 0x6d98);
3090 mips_return_c(0, 20 + 6*2);
3093 void psxBios_dummy() {
3094 u32 pc = (pc0 & 0x1fffff) - 4;
3095 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
3096 : pc == 0xc0 ? biosC0n : NULL;
3097 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
3098 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
3099 (void)pc; (void)ntab;
3100 mips_return_c(0, 100);
3103 void (*biosA0[256])();
3104 // C0 and B0 overlap (end of C0 is start of B0)
3105 void (*biosC0[256+128])();
3106 void (**biosB0)() = biosC0 + 128;
3108 static void setup_mips_code()
3111 ptr = (u32 *)&psxM[A_SYSCALL];
3112 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3113 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
3114 ptr[0x08/4] = SWAPu32(0x00000000); // nop
3116 ptr = (u32 *)&psxM[A_EXCEPTION];
3117 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
3118 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
3119 ptr[0x14/4] = SWAPu32(0x00000000); // nop
3120 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
3121 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3122 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
3123 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
3124 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
3125 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
3126 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
3128 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
3129 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
3130 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
3132 ptr[0xb0/4] = HLEOP(hleop_exception);
3135 static const struct {
3139 { 0xbfc050a4, hleop_exc0_0_1 },
3140 { 0xbfc04fbc, hleop_exc0_0_2 },
3141 { 0xbfc0506c, hleop_exc0_1_1 },
3142 { 0xbfc04dec, hleop_exc0_1_2 },
3143 { 0x1a00, hleop_exc0_2_2 },
3144 { 0x19c8, hleop_exc1_0_1 },
3145 { 0x18bc, hleop_exc1_0_2 },
3146 { 0x1990, hleop_exc1_1_1 },
3147 { 0x1858, hleop_exc1_1_2 },
3148 { 0x1958, hleop_exc1_2_1 },
3149 { 0x17f4, hleop_exc1_2_2 },
3150 { 0x1920, hleop_exc1_3_1 },
3151 { 0x1794, hleop_exc1_3_2 },
3152 { 0x2458, hleop_exc3_0_2 },
3153 { 0x49bc, hleop_exc_padcard1 },
3154 { 0x4a4c, hleop_exc_padcard2 },
3157 static int chain_hle_op(u32 handler)
3161 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3162 if (chainfns[i].addr == handler)
3163 return chainfns[i].op;
3167 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3169 d[0] = SWAPu32(next);
3170 d[1] = SWAPu32(handler1);
3171 d[2] = SWAPu32(handler2);
3173 // install the hle traps
3174 if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3175 if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3178 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack)
3180 u32 *ram32 = (u32 *)psxM;
3181 u32 s_excb = 0x20, s_evcb, s_pcb = 4, s_tcb;
3182 u32 p_excb, p_evcb, p_pcb, p_tcb;
3185 PSXBIOS_LOG("setup: tcb %u, evcb %u\n", tcb_cnt, evcb_cnt);
3187 // the real bios doesn't care, but we just don't
3188 // want to crash in case of garbage parameters
3189 if (tcb_cnt > 1024) tcb_cnt = 1024;
3190 if (evcb_cnt > 1024) evcb_cnt = 1024;
3191 s_evcb = 0x1c * evcb_cnt;
3192 s_tcb = 0xc0 * tcb_cnt;
3194 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3195 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3196 p_excb = psxBios_SysMalloc_(s_excb);
3197 p_evcb = psxBios_SysMalloc_(s_evcb);
3198 p_pcb = psxBios_SysMalloc_(s_pcb);
3199 p_tcb = psxBios_SysMalloc_(s_tcb);
3201 // "table of tables". Some games modify it
3202 assert(A_TT_ExCB == 0x0100);
3203 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3204 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3205 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3206 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3207 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3208 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3209 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3210 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3211 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3212 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3213 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3214 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3216 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3217 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3218 storeRam32(p_excb + 4*4, 0x0000); // chain2
3219 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3221 storeRam32(p_pcb, p_tcb);
3222 storeRam32(p_tcb, 0x4000); // first TCB
3223 for (i = 1; i < tcb_cnt; i++)
3224 storeRam32(p_tcb + sizeof(TCB) * i, 0x1000);
3227 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3228 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3229 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3230 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3231 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3233 storeRam32(A_CONF_EvCB, evcb_cnt);
3234 storeRam32(A_CONF_TCB, tcb_cnt);
3235 storeRam32(A_CONF_SP, stack);
3238 static const u32 gpu_ctl_def[] = {
3239 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3240 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3243 static const u32 gpu_data_def[] = {
3244 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3245 0xe5001000, 0xe6000000,
3246 0x02000000, 0x00000000, 0x01ff03ff
3250 static const u16 spu_config[] = {
3251 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3252 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3253 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3254 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3255 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3256 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3257 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3258 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3261 void psxBiosSetupBootState(void)
3263 boolean hle = Config.HLE;
3264 u32 *hw = (u32 *)psxH;
3267 // see also SetBootRegs()
3270 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3271 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3273 k0 = 0xbfc0d968; k1 = 0xf1c;
3274 ra = 0xf0001234; // just to easily detect attempts to return
3275 psxRegs.CP0.n.Cause = 0x20;
3276 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3278 hw[0x1000/4] = SWAP32(0x1f000000);
3279 hw[0x1004/4] = SWAP32(0x1f802000);
3280 hw[0x1008/4] = SWAP32(0x0013243f);
3281 hw[0x100c/4] = SWAP32(0x00003022);
3282 hw[0x1010/4] = SWAP32(0x0013243f);
3283 hw[0x1014/4] = SWAP32(0x200931e1);
3284 hw[0x1018/4] = SWAP32(0x00020943);
3285 hw[0x101c/4] = SWAP32(0x00070777);
3286 hw[0x1020/4] = SWAP32(0x0000132c);
3287 hw[0x1060/4] = SWAP32(0x00000b88);
3288 hw[0x1070/4] = SWAP32(0x00000001);
3289 hw[0x1074/4] = SWAP32(0x0000000c);
3290 hw[0x2040/4] = SWAP32(0x00000900);
3293 hw[0x10a0/4] = SWAP32(0x00ffffff);
3294 hw[0x10a8/4] = SWAP32(0x00000401);
3295 hw[0x10b0/4] = SWAP32(0x0008b000);
3296 hw[0x10b4/4] = SWAP32(0x00010200);
3297 hw[0x10e0/4] = SWAP32(0x000eccf4);
3298 hw[0x10e4/4] = SWAP32(0x00000400);
3299 hw[0x10e8/4] = SWAP32(0x00000002);
3300 hw[0x10f0/4] = SWAP32(0x00009099);
3301 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3310 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3311 GPU_writeStatus(gpu_ctl_def[i]);
3312 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3313 GPU_writeData(gpu_data_def[i]);
3314 HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
3317 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3318 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3321 static void hleExc0_0_1();
3322 static void hleExc0_0_2();
3323 static void hleExc0_1_1();
3324 static void hleExc0_1_2();
3326 #include "sjisfont.h"
3328 void psxBiosInit() {
3329 u32 *ptr, *ram32, *rom32;
3334 psxRegs.biosBranchCheck = ~0;
3336 memset(psxM, 0, 0x10000);
3337 for(i = 0; i < 256; i++) {
3342 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3343 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3344 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3345 biosA0[0x3f] = psxBios_printf_psxout;
3348 char verstr[0x24+1];
3349 rom32 = (u32 *)psxR;
3350 memcpy(verstr, psxR + 0x12c, 0x24);
3352 SysPrintf("BIOS: %08x, '%s', '%c'\n", SWAP32(rom32[0x100/4]),
3353 verstr, psxR[0x7ff52]);
3357 for(i = 0; i < 256; i++) {
3358 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3359 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3360 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3363 biosA0[0x00] = psxBios_open;
3364 biosA0[0x01] = psxBios_lseek;
3365 biosA0[0x02] = psxBios_read;
3366 biosA0[0x03] = psxBios_write;
3367 biosA0[0x04] = psxBios_close;
3368 //biosA0[0x05] = psxBios_ioctl;
3369 //biosA0[0x06] = psxBios_exit;
3370 //biosA0[0x07] = psxBios_sys_a0_07;
3371 biosA0[0x08] = psxBios_getc;
3372 biosA0[0x09] = psxBios_putc;
3373 biosA0[0x0a] = psxBios_todigit;
3374 //biosA0[0x0b] = psxBios_atof;
3375 //biosA0[0x0c] = psxBios_strtoul;
3376 //biosA0[0x0d] = psxBios_strtol;
3377 biosA0[0x0e] = psxBios_abs;
3378 biosA0[0x0f] = psxBios_labs;
3379 biosA0[0x10] = psxBios_atoi;
3380 biosA0[0x11] = psxBios_atol;
3381 //biosA0[0x12] = psxBios_atob;
3382 biosA0[0x13] = psxBios_setjmp;
3383 biosA0[0x14] = psxBios_longjmp;
3384 biosA0[0x15] = psxBios_strcat;
3385 biosA0[0x16] = psxBios_strncat;
3386 biosA0[0x17] = psxBios_strcmp;
3387 biosA0[0x18] = psxBios_strncmp;
3388 biosA0[0x19] = psxBios_strcpy;
3389 biosA0[0x1a] = psxBios_strncpy;
3390 biosA0[0x1b] = psxBios_strlen;
3391 biosA0[0x1c] = psxBios_index;
3392 biosA0[0x1d] = psxBios_rindex;
3393 biosA0[0x1e] = psxBios_strchr;
3394 biosA0[0x1f] = psxBios_strrchr;
3395 biosA0[0x20] = psxBios_strpbrk;
3396 biosA0[0x21] = psxBios_strspn;
3397 biosA0[0x22] = psxBios_strcspn;
3398 biosA0[0x23] = psxBios_strtok;
3399 biosA0[0x24] = psxBios_strstr;
3400 biosA0[0x25] = psxBios_toupper;
3401 biosA0[0x26] = psxBios_tolower;
3402 biosA0[0x27] = psxBios_bcopy;
3403 biosA0[0x28] = psxBios_bzero;
3404 biosA0[0x29] = psxBios_bcmp;
3405 biosA0[0x2a] = psxBios_memcpy;
3406 biosA0[0x2b] = psxBios_memset;
3407 biosA0[0x2c] = psxBios_memmove;
3408 biosA0[0x2d] = psxBios_memcmp;
3409 biosA0[0x2e] = psxBios_memchr;
3410 biosA0[0x2f] = psxBios_rand;
3411 biosA0[0x30] = psxBios_srand;
3412 biosA0[0x31] = psxBios_qsort;
3413 //biosA0[0x32] = psxBios_strtod;
3414 biosA0[0x33] = psxBios_malloc;
3415 biosA0[0x34] = psxBios_free;
3416 //biosA0[0x35] = psxBios_lsearch;
3417 //biosA0[0x36] = psxBios_bsearch;
3418 biosA0[0x37] = psxBios_calloc;
3419 biosA0[0x38] = psxBios_realloc;
3420 biosA0[0x39] = psxBios_InitHeap;
3421 //biosA0[0x3a] = psxBios__exit;
3422 biosA0[0x3b] = psxBios_getchar;
3423 biosA0[0x3c] = psxBios_putchar;
3424 //biosA0[0x3d] = psxBios_gets;
3425 biosA0[0x3e] = psxBios_puts;
3426 biosA0[0x3f] = psxBios_printf;
3427 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3428 //biosA0[0x41] = psxBios_LoadTest;
3429 biosA0[0x42] = psxBios_Load;
3430 biosA0[0x43] = psxBios_Exec;
3431 biosA0[0x44] = psxBios_FlushCache;
3432 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3433 biosA0[0x46] = psxBios_GPU_dw;
3434 biosA0[0x47] = psxBios_mem2vram;
3435 biosA0[0x48] = psxBios_SendGPU;
3436 biosA0[0x49] = psxBios_GPU_cw;
3437 biosA0[0x4a] = psxBios_GPU_cwb;
3438 biosA0[0x4b] = psxBios_GPU_SendPackets;
3439 biosA0[0x4c] = psxBios_sys_a0_4c;
3440 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3441 //biosA0[0x4e] = psxBios_GPU_sync;
3442 //biosA0[0x4f] = psxBios_sys_a0_4f;
3443 //biosA0[0x50] = psxBios_sys_a0_50;
3444 biosA0[0x51] = psxBios_LoadExec;
3445 //biosA0[0x52] = psxBios_GetSysSp;
3446 //biosA0[0x53] = psxBios_sys_a0_53;
3447 //biosA0[0x54] = psxBios__96_init_a54;
3448 //biosA0[0x55] = psxBios__bu_init_a55;
3449 biosA0[0x56] = psxBios_CdRemove;
3450 //biosA0[0x57] = psxBios_sys_a0_57;
3451 //biosA0[0x58] = psxBios_sys_a0_58;
3452 //biosA0[0x59] = psxBios_sys_a0_59;
3453 //biosA0[0x5a] = psxBios_sys_a0_5a;
3454 //biosA0[0x5b] = psxBios_dev_tty_init;
3455 //biosA0[0x5c] = psxBios_dev_tty_open;
3456 //biosA0[0x5d] = psxBios_sys_a0_5d;
3457 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3458 //biosA0[0x5f] = psxBios_dev_cd_open;
3459 //biosA0[0x60] = psxBios_dev_cd_read;
3460 //biosA0[0x61] = psxBios_dev_cd_close;
3461 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3462 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3463 //biosA0[0x64] = psxBios_dev_cd_chdir;
3464 //biosA0[0x65] = psxBios_dev_card_open;
3465 //biosA0[0x66] = psxBios_dev_card_read;
3466 //biosA0[0x67] = psxBios_dev_card_write;
3467 //biosA0[0x68] = psxBios_dev_card_close;
3468 //biosA0[0x69] = psxBios_dev_card_firstfile;
3469 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3470 //biosA0[0x6b] = psxBios_dev_card_erase;
3471 //biosA0[0x6c] = psxBios_dev_card_undelete;
3472 //biosA0[0x6d] = psxBios_dev_card_format;
3473 //biosA0[0x6e] = psxBios_dev_card_rename;
3474 //biosA0[0x6f] = psxBios_dev_card_6f;
3475 biosA0[0x70] = psxBios__bu_init;
3476 biosA0[0x71] = psxBios__96_init;
3477 biosA0[0x72] = psxBios_CdRemove;
3478 //biosA0[0x73] = psxBios_sys_a0_73;
3479 //biosA0[0x74] = psxBios_sys_a0_74;
3480 //biosA0[0x75] = psxBios_sys_a0_75;
3481 //biosA0[0x76] = psxBios_sys_a0_76;
3482 //biosA0[0x77] = psxBios_sys_a0_77;
3483 //biosA0[0x78] = psxBios__96_CdSeekL;
3484 //biosA0[0x79] = psxBios_sys_a0_79;
3485 //biosA0[0x7a] = psxBios_sys_a0_7a;
3486 //biosA0[0x7b] = psxBios_sys_a0_7b;
3487 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3488 //biosA0[0x7d] = psxBios_sys_a0_7d;
3489 //biosA0[0x7e] = psxBios__96_CdRead;
3490 //biosA0[0x7f] = psxBios_sys_a0_7f;
3491 //biosA0[0x80] = psxBios_sys_a0_80;
3492 //biosA0[0x81] = psxBios_sys_a0_81;
3493 //biosA0[0x82] = psxBios_sys_a0_82;
3494 //biosA0[0x83] = psxBios_sys_a0_83;
3495 //biosA0[0x84] = psxBios_sys_a0_84;
3496 //biosA0[0x85] = psxBios__96_CdStop;
3497 //biosA0[0x86] = psxBios_sys_a0_86;
3498 //biosA0[0x87] = psxBios_sys_a0_87;
3499 //biosA0[0x88] = psxBios_sys_a0_88;
3500 //biosA0[0x89] = psxBios_sys_a0_89;
3501 //biosA0[0x8a] = psxBios_sys_a0_8a;
3502 //biosA0[0x8b] = psxBios_sys_a0_8b;
3503 //biosA0[0x8c] = psxBios_sys_a0_8c;
3504 //biosA0[0x8d] = psxBios_sys_a0_8d;
3505 //biosA0[0x8e] = psxBios_sys_a0_8e;
3506 //biosA0[0x8f] = psxBios_sys_a0_8f;
3507 biosA0[0x90] = hleExc0_1_2;
3508 biosA0[0x91] = hleExc0_0_2;
3509 biosA0[0x92] = hleExc0_1_1;
3510 biosA0[0x93] = hleExc0_0_1;
3511 //biosA0[0x94] = psxBios_sys_a0_94;
3512 //biosA0[0x95] = psxBios_sys_a0_95;
3513 //biosA0[0x96] = psxBios_AddCDROMDevice;
3514 //biosA0[0x97] = psxBios_AddMemCardDevide;
3515 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3516 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3517 //biosA0[0x9a] = psxBios_sys_a0_9a;
3518 //biosA0[0x9b] = psxBios_sys_a0_9b;
3519 biosA0[0x9c] = psxBios_SetConf;
3520 biosA0[0x9d] = psxBios_GetConf;
3521 //biosA0[0x9e] = psxBios_sys_a0_9e;
3522 biosA0[0x9f] = psxBios_SetMem;
3523 //biosA0[0xa0] = psxBios__boot;
3524 //biosA0[0xa1] = psxBios_SystemError;
3525 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3526 biosA0[0xa3] = psxBios_DequeueCdIntr;
3527 //biosA0[0xa4] = psxBios_sys_a0_a4;
3528 //biosA0[0xa5] = psxBios_ReadSector;
3529 biosA0[0xa6] = psxBios_get_cd_status;
3530 //biosA0[0xa7] = psxBios_bufs_cb_0;
3531 //biosA0[0xa8] = psxBios_bufs_cb_1;
3532 //biosA0[0xa9] = psxBios_bufs_cb_2;
3533 //biosA0[0xaa] = psxBios_bufs_cb_3;
3534 biosA0[0xab] = psxBios__card_info;
3535 biosA0[0xac] = psxBios__card_load;
3536 //biosA0[0axd] = psxBios__card_auto;
3537 //biosA0[0xae] = psxBios_bufs_cd_4;
3538 //biosA0[0xaf] = psxBios_sys_a0_af;
3539 //biosA0[0xb0] = psxBios_sys_a0_b0;
3540 //biosA0[0xb1] = psxBios_sys_a0_b1;
3541 //biosA0[0xb2] = psxBios_do_a_long_jmp
3542 //biosA0[0xb3] = psxBios_sys_a0_b3;
3543 biosA0[0xb4] = psxBios_GetSystemInfo;
3544 //*******************B0 CALLS****************************
3545 biosB0[0x00] = psxBios_SysMalloc;
3546 //biosB0[0x01] = psxBios_sys_b0_01;
3547 biosB0[0x02] = psxBios_SetRCnt;
3548 biosB0[0x03] = psxBios_GetRCnt;
3549 biosB0[0x04] = psxBios_StartRCnt;
3550 biosB0[0x05] = psxBios_StopRCnt;
3551 biosB0[0x06] = psxBios_ResetRCnt;
3552 biosB0[0x07] = psxBios_DeliverEvent;
3553 biosB0[0x08] = psxBios_OpenEvent;
3554 biosB0[0x09] = psxBios_CloseEvent;
3555 biosB0[0x0a] = psxBios_WaitEvent;
3556 biosB0[0x0b] = psxBios_TestEvent;
3557 biosB0[0x0c] = psxBios_EnableEvent;
3558 biosB0[0x0d] = psxBios_DisableEvent;
3559 biosB0[0x0e] = psxBios_OpenTh;
3560 biosB0[0x0f] = psxBios_CloseTh;
3561 biosB0[0x10] = psxBios_ChangeTh;
3562 //biosB0[0x11] = psxBios_psxBios_b0_11;
3563 biosB0[0x12] = psxBios_InitPAD;
3564 biosB0[0x13] = psxBios_StartPAD;
3565 biosB0[0x14] = psxBios_StopPAD;
3566 biosB0[0x15] = psxBios_PAD_init;
3567 biosB0[0x16] = psxBios_PAD_dr;
3568 biosB0[0x17] = psxBios_ReturnFromException;
3569 biosB0[0x18] = psxBios_ResetEntryInt;
3570 biosB0[0x19] = psxBios_HookEntryInt;
3571 //biosB0[0x1a] = psxBios_sys_b0_1a;
3572 //biosB0[0x1b] = psxBios_sys_b0_1b;
3573 //biosB0[0x1c] = psxBios_sys_b0_1c;
3574 //biosB0[0x1d] = psxBios_sys_b0_1d;
3575 //biosB0[0x1e] = psxBios_sys_b0_1e;
3576 //biosB0[0x1f] = psxBios_sys_b0_1f;
3577 biosB0[0x20] = psxBios_UnDeliverEvent;
3578 //biosB0[0x21] = psxBios_sys_b0_21;
3579 //biosB0[0x22] = psxBios_sys_b0_22;
3580 //biosB0[0x23] = psxBios_sys_b0_23;
3581 //biosB0[0x24] = psxBios_sys_b0_24;
3582 //biosB0[0x25] = psxBios_sys_b0_25;
3583 //biosB0[0x26] = psxBios_sys_b0_26;
3584 //biosB0[0x27] = psxBios_sys_b0_27;
3585 //biosB0[0x28] = psxBios_sys_b0_28;
3586 //biosB0[0x29] = psxBios_sys_b0_29;
3587 //biosB0[0x2a] = psxBios_sys_b0_2a;
3588 //biosB0[0x2b] = psxBios_sys_b0_2b;
3589 //biosB0[0x2c] = psxBios_sys_b0_2c;
3590 //biosB0[0x2d] = psxBios_sys_b0_2d;
3591 //biosB0[0x2e] = psxBios_sys_b0_2e;
3592 //biosB0[0x2f] = psxBios_sys_b0_2f;
3593 //biosB0[0x30] = psxBios_sys_b0_30;
3594 //biosB0[0x31] = psxBios_sys_b0_31;
3595 biosB0[0x32] = psxBios_open;
3596 biosB0[0x33] = psxBios_lseek;
3597 biosB0[0x34] = psxBios_read;
3598 biosB0[0x35] = psxBios_write;
3599 biosB0[0x36] = psxBios_close;
3600 //biosB0[0x37] = psxBios_ioctl;
3601 //biosB0[0x38] = psxBios_exit;
3602 //biosB0[0x39] = psxBios_sys_b0_39;
3603 //biosB0[0x3a] = psxBios_getc;
3604 //biosB0[0x3b] = psxBios_putc;
3605 biosB0[0x3c] = psxBios_getchar;
3606 biosB0[0x3d] = psxBios_putchar;
3607 //biosB0[0x3e] = psxBios_gets;
3608 biosB0[0x3f] = psxBios_puts;
3609 biosB0[0x40] = psxBios_cd;
3610 biosB0[0x41] = psxBios_format;
3611 biosB0[0x42] = psxBios_firstfile;
3612 biosB0[0x43] = psxBios_nextfile;
3613 biosB0[0x44] = psxBios_rename;
3614 biosB0[0x45] = psxBios_delete;
3615 //biosB0[0x46] = psxBios_undelete;
3616 //biosB0[0x47] = psxBios_AddDevice;
3617 //biosB0[0x48] = psxBios_RemoteDevice;
3618 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3619 biosB0[0x4a] = psxBios_InitCARD;
3620 biosB0[0x4b] = psxBios_StartCARD;
3621 biosB0[0x4c] = psxBios_StopCARD;
3622 //biosB0[0x4d] = psxBios_sys_b0_4d;
3623 biosB0[0x4e] = psxBios__card_write;
3624 biosB0[0x4f] = psxBios__card_read;
3625 biosB0[0x50] = psxBios__new_card;
3626 biosB0[0x51] = psxBios_Krom2RawAdd;
3627 //biosB0[0x52] = psxBios_sys_b0_52;
3628 //biosB0[0x53] = psxBios_sys_b0_53;
3629 //biosB0[0x54] = psxBios__get_errno;
3630 biosB0[0x55] = psxBios__get_error;
3631 biosB0[0x56] = psxBios_GetC0Table;
3632 biosB0[0x57] = psxBios_GetB0Table;
3633 biosB0[0x58] = psxBios__card_chan;
3634 //biosB0[0x59] = psxBios_sys_b0_59;
3635 //biosB0[0x5a] = psxBios_sys_b0_5a;
3636 biosB0[0x5b] = psxBios_ChangeClearPad;
3637 biosB0[0x5c] = psxBios__card_status;
3638 biosB0[0x5d] = psxBios__card_wait;
3639 //*******************C0 CALLS****************************
3640 biosC0[0x00] = psxBios_InitRCnt;
3641 biosC0[0x01] = psxBios_InitException;
3642 biosC0[0x02] = psxBios_SysEnqIntRP;
3643 biosC0[0x03] = psxBios_SysDeqIntRP;
3644 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3645 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3646 //biosC0[0x06] = psxBios_ExceptionHandler;
3647 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3648 biosC0[0x08] = psxBios_SysInitMemory;
3649 //biosC0[0x09] = psxBios_SysInitKMem;
3650 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3651 //biosC0[0x0b] = psxBios_SystemError;
3652 biosC0[0x0c] = psxBios_InitDefInt;
3653 //biosC0[0x0d] = psxBios_sys_c0_0d;
3654 //biosC0[0x0e] = psxBios_sys_c0_0e;
3655 //biosC0[0x0f] = psxBios_sys_c0_0f;
3656 //biosC0[0x10] = psxBios_sys_c0_10;
3657 //biosC0[0x11] = psxBios_sys_c0_11;
3658 //biosC0[0x12] = psxBios_InstallDevices;
3659 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3660 //biosC0[0x14] = psxBios_sys_c0_14;
3661 //biosC0[0x15] = psxBios__cdevinput;
3662 //biosC0[0x16] = psxBios__cdevscan;
3663 //biosC0[0x17] = psxBios__circgetc;
3664 //biosC0[0x18] = psxBios__circputc;
3665 //biosC0[0x19] = psxBios_ioabort;
3666 //biosC0[0x1a] = psxBios_sys_c0_1a
3667 //biosC0[0x1b] = psxBios_KernelRedirect;
3668 //biosC0[0x1c] = psxBios_PatchAOTable;
3669 //************** THE END ***************************************
3672 memset(FDesc, 0, sizeof(FDesc));
3673 memset(cdir, 0, sizeof(cdir));
3676 // somewhat pretend to be a SCPH1001 BIOS
3677 // some games look for these and take an exception if they're missing
3678 rom32 = (u32 *)psxR;
3679 rom32[0x100/4] = SWAP32(0x19951204);
3680 rom32[0x104/4] = SWAP32(3);
3681 romc = (char *)psxR;
3682 strcpy(romc + 0x108, "PCSX authors");
3683 strcpy(romc + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3684 strcpy(romc + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3685 strcpy(romc + 0x7ff54, "GPL-2.0-or-later");
3688 len = 0x80000 - 0x66000;
3689 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3690 len = 0x80000 - 0x69d68;
3691 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3693 // trap attempts to call bios directly
3694 rom32[0x00000/4] = HLEOP(hleop_dummy);
3695 rom32[0x00180/4] = HLEOP(hleop_dummy);
3696 rom32[0x3fffc/4] = HLEOP(hleop_dummy);
3697 rom32[0x65ffc/4] = HLEOP(hleop_dummy);
3698 rom32[0x7ff2c/4] = HLEOP(hleop_dummy);
3700 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3701 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3702 Here are some examples of games not working with this fix in place :
3703 R-type won't get past the Irem logo if not implemented.
3704 Crash Team Racing will softlock after the Sony logo.
3707 ram32 = (u32 *)psxM;
3708 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3709 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3710 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3711 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3713 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3714 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3716 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3717 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3718 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3719 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3721 ram32[0x00a0/4] = HLEOP(hleop_a0);
3722 ram32[0x00b0/4] = HLEOP(hleop_b0);
3723 ram32[0x00c0/4] = HLEOP(hleop_c0);
3725 setup_tt(4, 16, 0x801fff00);
3726 DeliverEvent(0xf0000003, 0x0010);
3728 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3729 strcpy((char *)&ram32[0xeff0/4], "bu");
3731 // default exception handler chains
3732 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3733 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3734 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3735 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3736 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3737 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3738 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3739 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3743 // fill the api jumptables with fake entries as some games patch them
3744 // (or rather the funcs listed there)
3745 ptr = (u32 *)&psxM[A_A0_TABLE];
3746 for (i = 0; i < 256; i++)
3747 ptr[i] = SWAP32(A_A0_DUMMY);
3749 ptr = (u32 *)&psxM[A_B0_TABLE];
3750 for (i = 0; i < 256; i++)
3751 ptr[i] = SWAP32(A_B0_DUMMY);
3752 // B(5b) is special because games patch (sometimes even jump to)
3753 // code at fixed offsets from it, nocash lists offsets:
3754 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3755 // call: +7a0=4b70, +884=4c54, +894=4c64
3756 ptr[0x5b] = SWAP32(A_B0_5B_DUMMY); // 0x43d0
3757 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3759 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3760 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3761 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3763 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3764 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3766 ptr = (u32 *)&psxM[A_C0_TABLE];
3767 for (i = 0; i < 256/2; i++)
3768 ptr[i] = SWAP32(A_C0_DUMMY);
3769 ptr[6] = SWAP32(A_EXCEPTION);
3772 ram32[A_A0_DUMMY/4] = HLEOP(hleop_dummy);
3773 ram32[A_B0_DUMMY/4] = HLEOP(hleop_dummy);
3774 ram32[A_C0_DUMMY/4] = HLEOP(hleop_dummy);
3775 ram32[A_B0_5B_DUMMY/4] = HLEOP(hleop_dummy);
3776 ram32[0x8000/4] = HLEOP(hleop_execret);
3778 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3779 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3780 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3781 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3782 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3783 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3784 ram32[A_RND_SEED/4] = SWAPu32(0x24040001); // was 0xac20cc00
3787 void psxBiosShutdown() {
3790 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 stack) {
3793 if (tcb_cnt != 4 || evcb_cnt != 16) {
3794 setup_tt(tcb_cnt, evcb_cnt, stack);
3795 DeliverEvent(0xf0000003, 0x0010);
3797 storeRam32(A_CONF_SP, stack);
3800 #define psxBios_PADpoll(pad) { \
3801 int i, more_data = 0; \
3802 PAD##pad##_startPoll(pad); \
3803 pad_buf##pad[1] = PAD##pad##_poll(0x42, &more_data); \
3804 pad_buf##pad[0] = more_data ? 0 : 0xff; \
3805 PAD##pad##_poll(0, &more_data); \
3807 while (more_data) { \
3808 pad_buf##pad[i++] = PAD##pad##_poll(0, &more_data); \
3812 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3816 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3817 psxBios_ReturnFromException();
3823 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3824 // so this is only partially implemented
3825 static void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3827 u32 cdrom_dma_ack_enable = 1; // a000b93c
3828 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3831 static void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3834 //PSXBIOS_LOG("%s\n", __func__);
3836 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3837 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3838 //if (--cdrom_irq_counter == 0) // 0xa0009180
3839 // DeliverEvent(0xf0000003, 0x10);
3843 mips_return_c(ret, 20);
3846 static void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3848 u32 cdrom_irq_ack_enable = 1; // a000b938
3849 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3852 static void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3855 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3856 PSXBIOS_LOG("%s TODO\n", __func__);
3859 mips_return_c(ret, 20);
3862 static void hleExc0_2_2_syscall() // not in any A/B/C table
3864 u32 tcbPtr = loadRam32(A_TT_PCB);
3865 TCB *tcb = loadRam32ptr(tcbPtr);
3866 u32 code = (SWAP32(tcb->cause) & 0x3c) >> 2;
3868 if (code != R3000E_Syscall) {
3870 DeliverEvent(0xf0000010, 0x1000);
3871 //psxBios_SystemErrorUnresolvedException();
3873 mips_return_c(0, 17);
3877 //printf("%s c=%d a0=%d\n", __func__, code, SWAP32(tcb->reg[4]));
3878 tcb->epc += SWAP32(4);
3879 switch (SWAP32(tcb->reg[4])) { // a0
3883 case 1: { // EnterCritical - disable irqs
3884 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3885 tcb->reg[2] = SWAP32(was_enabled);
3886 tcb->sr &= SWAP32(~0x404);
3889 case 2: // ExitCritical - enable irqs
3890 tcb->sr |= SWAP32(0x404);
3893 case 3: { // ChangeThreadSubFunction
3894 u32 tcbPtr = loadRam32(A_TT_PCB);
3895 storeRam32(tcbPtr, SWAP32(tcb->reg[5])); // a1
3899 DeliverEvent(0xf0000010, 0x4000);
3903 psxBios_ReturnFromException();
3906 static void hleExc1_0_1(void)
3908 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3909 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3912 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3915 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3916 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3919 mips_return_c(ret, 22);
3922 static void hleExc1_0_2(void)
3924 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3927 static void hleExc1_1_1(void)
3929 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3930 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3933 static void hleExc1_1_2(void)
3935 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3938 static void hleExc1_2_1(void)
3940 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3941 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3944 static void hleExc1_2_2(void)
3946 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3949 static void hleExc1_3_1(void)
3951 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3952 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3955 static void hleExc1_3_2(void)
3957 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3960 static void hleExc3_0_2_defint(void)
3962 static const struct {
3973 { 6, 6 }, // rcnt2 (bug)
3978 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3979 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3980 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3985 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3988 static void hleExcPadCard1(void)
3990 if (loadRam32(A_PAD_IRQR_ENA)) {
3991 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3992 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
3997 if (loadRam32(A_PAD_DR_DST))
4000 if (loadRam32(A_PAD_ACK_VBL))
4001 psxHwWrite16(0x1f801070, ~1);
4002 if (loadRam32(A_CARD_IRQR_ENA)) {
4006 mips_return_c(0, 18);
4009 static void hleExcPadCard2(void)
4011 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
4012 mips_return_c(ret, 15);
4015 void psxBiosException() {
4016 u32 tcbPtr = loadRam32(A_TT_PCB);
4017 u32 *chains = loadRam32ptr(A_TT_ExCB);
4018 TCB *tcb = loadRam32ptr(tcbPtr);
4024 // $at, $v0, $v1, $ra already saved by the mips code at A_EXCEPTION
4025 for (i = 4; i < 31; i++) {
4028 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
4030 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
4031 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
4032 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
4033 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
4034 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
4035 sp = fp = loadRam32(A_EXC_SP);
4039 // do the chains (always 4)
4040 for (c = lim = 0; c < 4; c++) {
4041 if (chains[c * 2] == 0)
4043 ptr = SWAP32(chains[c * 2]);
4044 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
4045 chain = castRam32ptr(ptr);
4050 softCallInException(SWAP32(chain[2]));
4051 if (returned_from_exception())
4054 if (v0 == 0 || chain[1] == 0)
4056 softCallInException(SWAP32(chain[1]));
4057 if (returned_from_exception())
4063 // return from exception (custom or default)
4065 ptr = loadRam32(A_EEXIT_PTR);
4066 if (ptr != A_EEXIT_DEF) {
4067 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
4068 longjmp_load(jmp_buf);
4073 psxBios_ReturnFromException();
4077 static void hleDummy() {
4078 log_unhandled("hleDummy called @%08x ra=%08x\n", psxRegs.pc - 4, ra);
4080 psxRegs.cycle += 1000;
4085 static void hleA0() {
4086 u32 call = t1 & 0xff;
4087 u32 entry = loadRam32(A_A0_TABLE + call * 4);
4089 if (call < 192 && entry != A_A0_DUMMY) {
4090 PSXBIOS_LOG("custom A%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4091 call, biosA0n[call], a0, entry, ra);
4094 PSXBIOS_LOG(" -> %08x\n", v0);
4096 else if (biosA0[call])
4099 //printf("A(%02x) -> %x\n", call, v0);
4103 static void hleB0() {
4104 u32 call = t1 & 0xff;
4105 u32 entry = loadRam32(A_B0_TABLE + call * 4);
4109 is_custom = entry != A_B0_5B_DUMMY;
4111 is_custom = entry != A_B0_DUMMY;
4113 PSXBIOS_LOG("custom B%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4114 call, biosB0n[call], a0, entry, ra);
4117 PSXBIOS_LOG(" -> %08x\n", v0);
4119 else if (biosB0[call])
4122 //printf("B(%02x) -> %x\n", call, v0);
4126 static void hleC0() {
4127 u32 call = t1 & 0xff;
4128 u32 entry = loadRam32(A_C0_TABLE + call * 4);
4130 if (call < 128 && entry != A_C0_DUMMY) {
4131 PSXBIOS_LOG("custom C%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4132 call, biosC0n[call], a0, entry, ra);
4135 PSXBIOS_LOG(" -> %08x\n", v0);
4137 else if (biosC0[call])
4140 //printf("C(%02x) -> %x\n", call, v0);
4144 // currently not used
4145 static void hleBootstrap() {
4150 static void hleExecRet() {
4151 const EXEC *header = (EXEC *)PSXM(s0);
4153 PSXBIOS_LOG("ExecRet %x: %x\n", s0, header->ret);
4155 ra = SWAP32(header->ret);
4156 sp = SWAP32(header->_sp);
4157 fp = SWAP32(header->_fp);
4158 gp = SWAP32(header->_gp);
4159 s0 = SWAP32(header->base);
4165 void (* const psxHLEt[24])() = {
4166 hleDummy, hleA0, hleB0, hleC0,
4167 hleBootstrap, hleExecRet, psxBiosException, hleDummy,
4168 hleExc0_0_1, hleExc0_0_2,
4169 hleExc0_1_1, hleExc0_1_2, hleExc0_2_2_syscall,
4170 hleExc1_0_1, hleExc1_0_2,
4171 hleExc1_1_1, hleExc1_1_2,
4172 hleExc1_2_1, hleExc1_2_2,
4173 hleExc1_3_1, hleExc1_3_2,
4175 hleExcPadCard1, hleExcPadCard2,
4178 void psxBiosCheckExe(u32 t_addr, u32 t_size)
4180 // lw $v0, 0x10($sp)
4183 // sw $v0, 0x10($sp)
4184 // lw $v0, 0x10($sp)
4186 // bne $v0, $v1, not_timeout
4189 static const u8 pattern[] = {
4190 0x10, 0x00, 0xA2, 0x8F, 0x00, 0x00, 0x00, 0x00,
4191 0xFF, 0xFF, 0x42, 0x24, 0x10, 0x00, 0xA2, 0xAF,
4192 0x10, 0x00, 0xA2, 0x8F, 0x00, 0x00, 0x00, 0x00,
4193 0x0C, 0x00, 0x43, 0x14, 0x00, 0x00, 0x00, 0x00,
4195 u32 start = t_addr & 0x1ffffc;
4196 u32 end = (start + t_size) & 0x1ffffc;
4197 u32 buf[sizeof(pattern) / sizeof(u32)];
4198 const u32 *r32 = (u32 *)(psxM + start);
4206 memcpy(buf, pattern, sizeof(buf));
4207 for (i = 0; i < t_size / 4; i += j + 1) {
4208 for (j = 0; j < sizeof(buf) / sizeof(buf[0]); j++)
4209 if (r32[i + j] != buf[j])
4211 if (j != sizeof(buf) / sizeof(buf[0]))
4214 if ((SWAP32(r32[i + j]) >> 16) != 0x3c04) // lui
4216 SysPrintf("HLE vsync @%08x\n", start + i * 4);
4217 psxRegs.biosBranchCheck = (t_addr & 0xa01ffffc) + i * 4;
4221 void psxBiosCheckBranch(void)
4225 static u32 cycles_prev, v0_prev;
4226 u32 cycles_passed, waste_cycles;
4227 u32 loops, v0_expect = v0_prev - 1;
4231 cycles_passed = psxRegs.cycle - cycles_prev;
4232 cycles_prev = psxRegs.cycle;
4234 if (cycles_passed < 10 || cycles_passed > 50 || v0 != v0_expect)
4237 waste_cycles = schedule_timeslice() - psxRegs.cycle;
4238 loops = waste_cycles / cycles_passed;
4242 psxRegs.cycle += loops * cycles_passed;
4243 //printf("c %4u %d\n", loops, cycles_passed);
4247 #define bfreeze(ptr, size) { \
4248 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
4249 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
4253 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
4254 #define bfreezel(ptr) bfreeze(ptr, sizeof(*(ptr)))
4256 void psxBiosFreeze(int Mode) {