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 "psxevents.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 assert(psxRegs.cpuInRecursion <= 1);
402 psxRegs.cpuInRecursion++;
403 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
405 while (pc0 != 0x80001000 && ++lim < 0x100000)
406 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
408 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
409 psxRegs.cpuInRecursion--;
412 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
414 psxRegs.CP0.n.SR |= ssr & 0x404;
417 static inline void softCallInException(u32 pc) {
422 assert(ra != 0x80001000);
423 if (ra == 0x80001000)
427 psxRegs.cpuInRecursion++;
428 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
430 while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 0x100000)
431 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
433 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
434 psxRegs.cpuInRecursion--;
437 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
438 if (pc0 == 0x80001000)
442 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
443 static u32 DeliverEvent(u32 class, u32 spec);
444 static u32 UnDeliverEvent(u32 class, u32 spec);
445 static void CloseEvent(u32 ev);
450 // System calls A0 */
453 #define buread(Ra1, mcd, length) { \
454 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); \
455 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
456 memcpy(Ra1, ptr, length); \
457 psxCpu->Clear(a1, (length + 3) / 4); \
458 if (FDesc[1 + mcd].mode & 0x8000) { \
459 DeliverEvent(0xf0000011, 0x0004); \
460 DeliverEvent(0xf4000001, 0x0004); \
463 FDesc[1 + mcd].offset += v0; \
466 #define buwrite(Ra1, mcd, length) { \
467 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
468 PSXBIOS_LOG("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
469 ptr = Mcd##mcd##Data + offset; \
470 memcpy(ptr, Ra1, length); \
471 FDesc[1 + mcd].offset += length; \
472 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
473 if (FDesc[1 + mcd].mode & 0x8000) { \
474 DeliverEvent(0xf0000011, 0x0004); \
475 DeliverEvent(0xf4000001, 0x0004); \
480 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
481 /* For some strange reason, the returned character is sign-expanded; */
482 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
483 /* TODO FIX ME : Properly implement this behaviour */
484 void psxBios_getc(void) // 0x03, 0x35
489 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
493 if (pa1 != INVALID_PTR) {
495 case 2: buread(pa1, 1, 1); break;
496 case 3: buread(pa1, 2, 1); break;
503 /* Copy of psxBios_write, except size is 1. */
504 void psxBios_putc(void) // 0x09, 0x3B
509 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
512 if (pa1 == INVALID_PTR) {
517 if (a0 == 1) { // stdout
518 char *ptr = (char *)pa1;
522 printf("%c", *ptr++); a2--;
528 case 2: buwrite(pa1, 1, 1); break;
529 case 3: buwrite(pa1, 2, 1); break;
535 void psxBios_todigit(void) // 0x0a
539 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
542 if (c >= 0x30 && c < 0x3A) {
545 else if (c > 0x60 && c < 0x7B) {
548 else if (c > 0x40 && c < 0x5B) {
551 else if (c >= 0x80) {
562 void psxBios_abs() { // 0x0e
563 if ((s32)a0 < 0) v0 = -(s32)a0;
568 void psxBios_labs() { // 0x0f
572 void psxBios_atoi() { // 0x10
574 char *p = (char *)Ra0;
576 if (p == INVALID_PTR) {
583 case ' ': case '\t': continue;
590 while (*p >= '0' && *p <= '9') {
591 n = n * 10 + *p++ - '0';
596 PSXBIOS_LOG("psxBios_%s %s (%x) -> 0x%x\n", biosA0n[0x10], Ra0, a0, v0);
599 void psxBios_atol() { // 0x11
609 static void psxBios_setjmp() { // 0x13
610 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
613 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
615 jmp_buf->ra_ = SWAP32(ra);
616 jmp_buf->sp_ = SWAP32(sp);
617 jmp_buf->fp_ = SWAP32(fp);
618 for (i = 0; i < 8; i++) // s0-s7
619 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
620 jmp_buf->gp_ = SWAP32(gp);
622 mips_return_c(0, 15);
625 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
629 ra = SWAP32(jmp_buf->ra_);
630 sp = SWAP32(jmp_buf->sp_);
631 fp = SWAP32(jmp_buf->fp_);
632 for (i = 0; i < 8; i++) // s0-s7
633 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
634 gp = SWAP32(jmp_buf->gp_);;
637 void psxBios_longjmp() { // 0x14
638 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
640 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
641 longjmp_load(jmp_buf);
642 mips_return_c(a1, 15);
645 void psxBios_strcat() { // 0x15
649 PSXBIOS_LOG("psxBios_%s %s (%x), %s (%x)\n", biosA0n[0x15], Ra0, a0, Ra1, a1);
650 if (a0 == 0 || a1 == 0 || p2 == INVALID_PTR)
655 while (loadRam8(p1)) {
659 for (; *p2; p1++, p2++)
663 mips_return_c(a0, 22);
666 void psxBios_strncat() { // 0x16
667 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
671 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
673 if (a0 == 0 || a1 == 0)
681 while ((*p1++ = *p2++) != '\0') {
691 void psxBios_strcmp() { // 0x17
692 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
694 if (a0 == 0 && a1 == 0)
700 else if (a0 == 0 && a1 != 0)
706 else if (a0 != 0 && a1 == 0)
713 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
716 while (*p1 == *p2++) {
735 void psxBios_strncmp() { // 0x18
736 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
738 if (a0 == 0 && a1 == 0)
744 else if (a0 == 0 && a1 != 0)
750 else if (a0 != 0 && a1 == 0)
757 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
760 while (--n >= 0 && *p1 == *p2++) {
764 v1 = a2 - ((a2-n) - 1);
772 v0 = (n < 0 ? 0 : *p1 - *--p2);
774 v1 = a2 - ((a2-n) - 1);
780 void psxBios_strcpy() { // 0x19
781 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
782 PSXBIOS_LOG("psxBios_%s %x, %s (%x)\n", biosA0n[0x19], a0, p2, a1);
783 if (a0 == 0 || a1 == 0)
789 while ((*p1++ = *p2++) != '\0');
794 void psxBios_strncpy() { // 0x1a
795 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
797 if (a0 == 0 || a1 == 0)
803 for (i = 0; i < n; i++) {
804 if ((*p1++ = *p2++) == '\0') {
816 void psxBios_strlen() { // 0x1b
817 char *p = (char *)Ra0;
828 void psxBios_index() { // 0x1c
829 char *p = (char *)Ra0;
839 v0 = a0 + (p - (char *)Ra0);
843 } while (*p++ != '\0');
848 void psxBios_rindex() { // 0x1d
849 char *p = (char *)Ra0;
859 v0 = a0 + (p - (char *)Ra0);
860 } while (*p++ != '\0');
865 void psxBios_strchr() { // 0x1e
869 void psxBios_strrchr() { // 0x1f
873 void psxBios_strpbrk() { // 0x20
874 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
876 while ((c = *p1++) != '\0') {
877 for (scanp = p2; (sc = *scanp++) != '\0';) {
879 v0 = a0 + (p1 - 1 - (char *)Ra0);
886 // BUG: return a0 instead of NULL if not found
890 void psxBios_strspn() { // 0x21
893 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
894 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
895 if (*p2 == '\0') break;
898 v0 = p1 - (char *)Ra0; pc0 = ra;
901 void psxBios_strcspn() { // 0x22
904 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
905 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
906 if (*p2 != '\0') break;
909 v0 = p1 - (char *)Ra0; pc0 = ra;
912 void psxBios_strtok() { // 0x23
913 char *pcA0 = (char *)Ra0;
914 char *pcRet = strtok(pcA0, (char *)Ra1);
916 v0 = a0 + pcRet - pcA0;
922 void psxBios_strstr() { // 0x24
923 char *p = (char *)Ra0, *p1, *p2;
924 PSXBIOS_LOG("psxBios_%s %s (%x), %s (%x)\n", biosA0n[0x24], p, a0, Ra1, a1);
930 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
935 v0 = a0 + (p - (char *)Ra0);
937 PSXBIOS_LOG(" -> %x\n", v0);
941 // bug: skips the whole matched substring + 1
948 void psxBios_toupper() { // 0x25
949 v0 = (s8)(a0 & 0xff);
950 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
954 void psxBios_tolower() { // 0x26
955 v0 = (s8)(a0 & 0xff);
956 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
960 static void do_memset(u32 dst, u32 v, s32 len)
966 if (db != INVALID_PTR)
970 psxCpu->Clear(dst, (len + 3) / 4);
973 static void do_memcpy(u32 dst, u32 src, s32 len)
975 u32 d = dst, s = src;
978 const u8 *sb = PSXM(s);
980 if (db != INVALID_PTR && sb != INVALID_PTR)
985 psxCpu->Clear(dst, (len + 3) / 4);
988 static void psxBios_memcpy();
990 static void psxBios_bcopy() { // 0x27 - memcpy with args swapped
991 //PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x27], a0, a1, a2);
992 u32 ret = a0, cycles = 0;
993 if (a0 == 0) // ...but it checks src this time
1000 do_memcpy(a1, a0, a2);
1006 mips_return_c(ret, cycles + 5);
1009 static void psxBios_bzero() { // 0x28
1010 /* Same as memset here (See memset below) */
1011 u32 ret = a0, cycles;
1012 if (a0 == 0 || (s32)a1 <= 0)
1014 mips_return_c(0, 6);
1017 do_memset(a0, 0, a1);
1021 // todo: many more cycles due to uncached bios mem
1022 mips_return_c(ret, cycles + 5);
1025 void psxBios_bcmp() { // 0x29
1026 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
1028 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
1030 while ((s32)a2-- > 0) {
1031 if (*p1++ != *p2++) {
1032 v0 = *p1 - *p2; // BUG: compare the NEXT byte
1041 static void psxBios_memcpy() { // 0x2a
1042 u32 ret = a0, cycles = 0;
1045 mips_return_c(0, 4);
1050 do_memcpy(a0, a1, a2);
1056 mips_return_c(ret, cycles + 5);
1059 static void psxBios_memset() { // 0x2b
1060 u32 ret = a0, cycles;
1061 if (a0 == 0 || (s32)a2 <= 0)
1063 mips_return_c(0, 6);
1066 do_memset(a0, a1, a2);
1070 // todo: many more cycles due to uncached bios mem
1071 mips_return_c(ret, cycles + 5);
1074 void psxBios_memmove() { // 0x2c
1075 u32 ret = a0, cycles = 0;
1078 mips_return_c(0, 4);
1082 if ((s32)a2 > 0 && a0 > a1 && a0 < a1 + a2) {
1083 u32 dst = a0, len = a2 + 1;
1086 while ((s32)a2 >= 0) { // BUG: copies one more byte here
1087 const u8 *sb = PSXM(a1);
1089 if (db != INVALID_PTR && sb != INVALID_PTR)
1095 psxCpu->Clear(dst, (len + 3) / 4);
1096 cycles = 10 + len * 8;
1097 } else if ((s32)a2 > 0) {
1098 do_memcpy(a0, a1, a2);
1104 mips_return_c(ret, cycles + 5);
1107 void psxBios_memcmp() { // 0x2d
1111 void psxBios_memchr() { // 0x2e
1112 char *p = (char *)Ra0;
1114 if (a0 == 0 || a2 > 0x7FFFFFFF)
1120 while ((s32)a2-- > 0) {
1121 if (*p++ != (s8)a1) continue;
1122 v0 = a0 + (p - (char *)Ra0 - 1);
1130 static void psxBios_rand() { // 0x2f
1131 u32 s = loadRam32(A_RND_SEED) * 1103515245 + 12345;
1132 storeRam32(A_RND_SEED, s);
1134 mips_return_c((s >> 16) & 0x7fff, 12+37);
1137 static void psxBios_srand() { // 0x30
1138 storeRam32(A_RND_SEED, a0);
1139 mips_return_void_c(3);
1142 static u32 qscmpfunc, qswidth;
1144 static inline int qscmp(char *a, char *b) {
1147 a0 = sa0 + (a - (char *)PSXM(sa0));
1148 a1 = sa0 + (b - (char *)PSXM(sa0));
1150 softCall(qscmpfunc);
1156 static inline void qexchange(char *i, char *j) {
1167 static inline void q3exchange(char *i, char *j, char *k) {
1179 static void qsort_main(char *a, char *l) {
1180 char *i, *j, *lp, *hp;
1185 if ((n = l - a) <= qswidth)
1187 n = qswidth * (n / (2 * qswidth));
1193 if ((c = qscmp(i, lp)) == 0) {
1194 qexchange(i, lp -= qswidth);
1205 if ((c = qscmp(hp, j)) == 0) {
1206 qexchange(hp += qswidth, j);
1211 q3exchange(i, hp += qswidth, j);
1225 if (lp - a >= l - hp) {
1226 qsort_main(hp + qswidth, l);
1235 q3exchange(j, lp -= qswidth, i);
1240 void psxBios_qsort() { // 0x31
1243 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1248 static int malloc_heap_grow(u32 size) {
1249 u32 heap_addr, heap_end, heap_addr_new;
1251 heap_addr = loadRam32(A_HEAP_BASE);
1252 heap_end = loadRam32(A_HEAP_END);
1253 heap_addr_new = heap_addr + 4 + size;
1254 if (heap_addr_new >= heap_end)
1256 storeRam32(A_HEAP_BASE, heap_addr_new);
1257 storeRam32(heap_addr - 4, size | 1);
1258 storeRam32(heap_addr + size, ~1); // terminator
1262 static void psxBios_malloc() { // 0x33
1263 u32 size = (a0 + 3) & ~3;
1264 u32 limit = 32*1024;
1268 PSXBIOS_LOG("psxBios_%s %d\n", biosA0n[0x33], a0);
1270 if (!loadRam32(A_HEAP_INIT_FLG)) {
1271 u32 heap_addr = loadRam32(A_HEAP_BASE);
1272 storeRam32(heap_addr, ~1);
1273 storeRam32(A_HEAP_FRSTCHNK, heap_addr);
1274 storeRam32(A_HEAP_CURCHNK, heap_addr);
1275 storeRam32(A_HEAP_BASE, heap_addr + 4);
1276 if (malloc_heap_grow(size)) {
1277 PSXBIOS_LOG("malloc: init OOM\n");
1278 mips_return_c(0, 20);
1281 storeRam32(A_HEAP_INIT_FLG, 1);
1284 for (i = 0; tries > 0 && i < limit; i++)
1286 u32 chunk = loadRam32(A_HEAP_CURCHNK);
1287 u32 chunk_hdr = loadRam32(chunk);
1288 u32 next_chunk = chunk + 4 + (chunk_hdr & ~3);
1289 u32 next_chunk_hdr = loadRam32(next_chunk);
1291 //printf(" c %08x %08x\n", chunk, chunk_hdr);
1292 if (chunk_hdr & 1) {
1294 if (chunk_hdr > (size | 1)) {
1296 u32 p2size = (chunk_hdr & ~3) - size - 4;
1297 storeRam32(chunk + 4 + size, p2size | 1);
1298 chunk_hdr = size | 1;
1300 if (chunk_hdr == (size | 1)) {
1301 storeRam32(chunk, size);
1305 if (next_chunk_hdr & 1) {
1307 u32 msize = (chunk_hdr & ~3) + 4 + (next_chunk_hdr & ~3);
1308 storeRam32(chunk, msize | 1);
1312 if (chunk_hdr == ~1) {
1315 storeRam32(A_HEAP_CURCHNK, loadRam32(A_HEAP_FRSTCHNK));
1319 // go to the next chunk
1320 storeRam32(A_HEAP_CURCHNK, next_chunk);
1326 else if (tries == 0 && malloc_heap_grow(size))
1329 u32 chunk = loadRam32(A_HEAP_CURCHNK);
1330 storeRam32(chunk, loadRam32(chunk) & ~3);
1334 PSXBIOS_LOG(" -> %08x\n", ret);
1335 mips_return_c(ret, 40);
1338 static void psxBios_free() { // 0x34
1339 PSXBIOS_LOG("psxBios_%s %x (%d bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1340 storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1341 mips_return_void_c(5);
1344 static void psxBios_calloc() { // 0x37
1346 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
1348 a0 = size = a0 * a1;
1352 a0 = ret; a1 = size;
1355 mips_return_c(ret, 21);
1358 void psxBios_realloc() { // 0x38
1362 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1366 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1371 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1376 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1377 /* Note that it is not quite implemented this way here. */
1387 /* InitHeap(void *block , int n) */
1388 static void psxBios_InitHeap() { // 0x39
1389 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
1391 storeRam32(A_HEAP_BASE, a0);
1392 storeRam32(A_HEAP_SIZE, a1);
1393 storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
1394 storeRam32(A_HEAP_INIT_FLG, 0);
1397 mips_return_void_c(14);
1400 void psxBios_getchar() { //0x3b
1401 v0 = getchar(); pc0 = ra;
1404 static void psxBios_printf_psxout() { // 0x3f
1407 u32 save[4] = { 0, };
1413 if (psp != INVALID_PTR) {
1414 memcpy(save, psp, 4 * 4);
1415 psxMu32ref(sp) = SWAP32((u32)a0);
1416 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1417 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1418 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1430 tmp2[j++] = Ra0[i]; goto _start;
1432 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1443 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1447 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1453 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1455 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1457 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1459 *ptmp++ = Ra0[i]; break;
1469 if (psp != INVALID_PTR)
1470 memcpy(psp, save, 4 * 4);
1473 SysPrintf("%s", tmp);
1476 void psxBios_printf() { // 0x3f
1477 psxBios_printf_psxout();
1481 static void psxBios_cd() { // 0x40
1482 const char *p, *dir = Ra0;
1483 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x40], a0, dir);
1484 if (dir != INVALID_PTR) {
1485 if ((p = strchr(dir, ':')))
1489 snprintf(cdir, sizeof(cdir), "%s", dir);
1491 mips_return_c(1, 100);
1494 static void psxBios_format() { // 0x41
1495 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x41], a0, Ra0);
1496 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1498 CreateMcd(Config.Mcd1);
1499 LoadMcd(1, Config.Mcd1);
1502 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1504 CreateMcd(Config.Mcd2);
1505 LoadMcd(2, Config.Mcd2);
1515 static void psxBios_SystemErrorUnresolvedException() {
1516 if (floodchk != 0x12340a40) { // prevent log flood
1517 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1518 floodchk = 0x12340a40;
1520 mips_return_void_c(1000);
1523 static void FlushCache() {
1524 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1525 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1527 // runs from uncached mem so tons of cycles
1532 * long Load(char *name, struct EXEC *header);
1535 void psxBios_Load() { // 0x42
1543 PSXBIOS_LOG("psxBios_%s %x(%s), %x\n", biosA0n[0x42], a0, pa0, a1);
1544 if (pa0 == INVALID_PTR || pa1 == INVALID_PTR) {
1548 if ((p = strchr(pa0, ':')))
1553 snprintf(path, sizeof(path), "%s\\%s", cdir, (char *)pa0);
1555 snprintf(path, sizeof(path), "%s", (char *)pa0);
1557 if (LoadCdromFile(path, &eheader) == 0) {
1558 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1559 psxCpu->Clear(a1, sizeof(EXEC) / 4);
1563 PSXBIOS_LOG(" -> %d\n", v0);
1569 * int Exec(struct EXEC *header , int argc , char **argv);
1572 void psxBios_Exec() { // 43
1573 EXEC *header = (EXEC *)castRam32ptr(a0);
1577 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1579 header->_sp = SWAP32(sp);
1580 header->_fp = SWAP32(fp);
1581 header->_sp = SWAP32(sp);
1582 header->_gp = SWAP32(gp);
1583 header->ret = SWAP32(ra);
1584 header->base = SWAP32(s0);
1586 ptr = SWAP32(header->b_addr);
1587 len = SWAP32(header->b_size);
1593 if (header->S_addr != 0)
1594 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1596 gp = SWAP32(header->gp0);
1604 pc0 = SWAP32(header->_pc0);
1607 static void psxBios_FlushCache() { // 44
1608 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1613 void psxBios_GPU_dw() { // 0x46
1618 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1621 GPU_writeData(0xa0000000);
1622 GPU_writeData((a1<<0x10)|(a0&0xffff));
1623 GPU_writeData((a3<<0x10)|(a2&0xffff));
1625 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1628 GPU_writeData(SWAPu32(*ptr++));
1634 void psxBios_mem2vram() { // 0x47
1636 gpuSyncPluginSR(); // flush
1637 GPU_writeData(0xa0000000);
1638 GPU_writeData((a1<<0x10)|(a0&0xffff));
1639 GPU_writeData((a3<<0x10)|(a2&0xffff));
1640 size = ((((a2 * a3) / 2) >> 4) << 16);
1641 GPU_writeStatus(0x04000002);
1642 psxHwWrite32(0x1f8010f4,0);
1643 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1644 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1645 psxHwWrite32(0x1f8010a4, size | 0x10);
1646 psxHwWrite32(0x1f8010a8,0x01000201);
1651 void psxBios_SendGPU() { // 0x48
1652 GPU_writeStatus(a0);
1657 void psxBios_GPU_cw() { // 0x49
1664 void psxBios_GPU_cwb() { // 0x4a
1665 u32 *ptr = (u32*)Ra0;
1670 GPU_writeData(SWAPu32(*ptr++));
1676 void psxBios_GPU_SendPackets() { //4b:
1678 GPU_writeStatus(0x04000002);
1679 psxHwWrite32(0x1f8010f4,0);
1680 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1681 psxHwWrite32(0x1f8010a0,a0);
1682 psxHwWrite32(0x1f8010a4,0);
1683 psxHwWrite32(0x1f8010a8,0x010000401);
1687 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1688 psxHwWrite32(0x1f8010a8,0x00000401);
1689 GPU_writeData(0x0400000);
1690 GPU_writeData(0x0200000);
1691 GPU_writeData(0x0100000);
1696 void psxBios_GPU_GetGPUStatus() { // 0x4d
1697 v0 = GPU_readStatus();
1703 void psxBios_LoadExec() { // 51
1704 EXEC *header = (EXEC*)PSXM(0xf000);
1708 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1710 s_addr = a1; s_size = a2;
1715 header->S_addr = s_addr;
1716 header->s_size = s_size;
1718 a0 = 0xf000; a1 = 0; a2 = 0;
1722 void psxBios__bu_init() { // 70
1724 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1727 DeliverEvent(0xf0000011, 0x0004);
1728 DeliverEvent(0xf4000001, 0x0004);
1733 void psxBios__96_init() { // 71
1735 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1741 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1742 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1743 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1745 static void psxBios_DequeueCdIntr_() {
1746 psxBios_SysDeqIntRP_(0, 0x91d0);
1747 psxBios_SysDeqIntRP_(0, 0x91e0);
1751 static void psxBios_DequeueCdIntr() { // a3
1752 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1753 psxBios_DequeueCdIntr_();
1756 static void psxBios_CdRemove() { // 56, 72
1757 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1759 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1760 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1761 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1762 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1763 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1764 psxBios_DequeueCdIntr_();
1766 // EnterCriticalSection - should be done at the beginning,
1767 // but this way is much easier to implement
1773 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack);
1775 static void psxBios_SetConf() { // 9c
1776 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9c], a0, a1, a2);
1777 setup_tt(a1, a0, a2);
1778 psxRegs.CP0.n.SR |= 0x401;
1779 mips_return_void_c(500);
1782 static void psxBios_GetConf() { // 9d
1783 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9d], a0, a1, a2);
1784 storeRam32(a0, loadRam32(A_CONF_EvCB));
1785 storeRam32(a1, loadRam32(A_CONF_TCB));
1786 storeRam32(a2, loadRam32(A_CONF_SP));
1787 mips_return_void_c(10);
1790 void psxBios_SetMem() { // 9f
1791 u32 new = psxHu32(0x1060);
1794 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1799 psxHu32ref(0x1060) = SWAP32(new);
1800 psxMu32ref(0x060) = a0;
1801 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1805 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1806 psxMu32ref(0x060) = a0;
1807 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1810 PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
1817 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1818 static void psxBios_get_cd_status() // a6
1820 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
1825 static void psxBios__card_info() { // ab
1826 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1828 storeRam32(A_CARD_CHAN1, a0);
1835 if (McdDisable[port & 1])
1839 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
1844 if (McdDisable[0] && McdDisable[1])
1847 DeliverEvent(0xf0000011, 0x0004);
1848 // DeliverEvent(0xf4000001, 0x0004);
1849 DeliverEvent(0xf4000001, ret);
1853 void psxBios__card_load() { // ac
1855 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1858 storeRam32(A_CARD_CHAN1, a0);
1860 // DeliverEvent(0xf0000011, 0x0004);
1861 DeliverEvent(0xf4000001, 0x0004);
1866 static void psxBios_GetSystemInfo() { // b4
1868 //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
1869 SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
1872 case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
1873 case 2: ret = 0xbfc0012c; break;
1874 case 5: ret = loadRam32(0x60) << 10; break;
1876 mips_return_c(ret, 20);
1879 /* System calls B0 */
1881 static u32 psxBios_SysMalloc_(u32 size);
1883 static void psxBios_SysMalloc() { // B 00
1884 u32 ret = psxBios_SysMalloc_(a0);
1886 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1887 mips_return_c(ret, 33);
1890 void psxBios_SetRCnt() { // 02
1892 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1899 psxRcntWtarget(a0, a1);
1900 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1901 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1902 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1903 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1904 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1906 psxRcntWmode(a0, mode);
1911 void psxBios_GetRCnt() { // 03
1913 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1918 case 0: v0 = psxRcntRcount0(); break;
1919 case 1: v0 = psxRcntRcount1(); break;
1920 case 2: v0 = psxRcntRcount2(); break;
1921 case 3: v0 = 0; break;
1926 void psxBios_StartRCnt() { // 04
1928 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1932 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1933 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1937 void psxBios_StopRCnt() { // 05
1939 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1943 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1944 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1948 void psxBios_ResetRCnt() { // 06
1950 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1955 psxRcntWmode(a0, 0);
1956 psxRcntWtarget(a0, 0);
1957 psxRcntWcount(a0, 0);
1962 static u32 DeliverEvent(u32 class, u32 spec) {
1963 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1964 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1965 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1966 u32 i, lim = evcb_len / 0x1c;
1968 //printf("%s %08x %x\n", __func__, class, spec);
1969 for (i = 0; i < lim; i++, ev++) {
1971 if (SWAP32(ev->status) != EvStACTIVE)
1974 if (SWAP32(ev->class) != class)
1977 if (SWAP32(ev->spec) != spec)
1980 ret = SWAP32(ev->mode);
1981 if (ret == EvMdMARK) {
1982 ev->status = SWAP32(EvStALREADY);
1986 if (ret == EvMdCALL) {
1987 ret = SWAP32(ev->fhandler);
2000 static u32 UnDeliverEvent(u32 class, u32 spec) {
2001 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
2002 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
2003 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
2004 u32 i, lim = evcb_len / 0x1c;
2006 for (i = 0; i < lim; i++, ev++) {
2008 if (SWAP32(ev->status) != EvStALREADY)
2011 if (SWAP32(ev->class) != class)
2014 if (SWAP32(ev->spec) != spec)
2017 if (SWAP32(ev->mode) == EvMdMARK)
2018 ev->status = SWAP32(EvStACTIVE);
2024 static void psxBios_DeliverEvent() { // 07
2026 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
2028 ret = DeliverEvent(a0, a1);
2032 static s32 get_free_EvCB_slot() {
2033 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
2034 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
2037 for (i = 0; i < lim; i++, ev++) {
2039 if (ev->status == SWAP32(EvStUNUSED))
2045 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
2046 u32 ret = get_free_EvCB_slot();
2047 if ((s32)ret >= 0) {
2048 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
2049 ev->class = SWAP32(class);
2050 ev->status = SWAP32(EvStDISABLED);
2051 ev->spec = SWAP32(spec);
2052 ev->mode = SWAP32(mode);
2053 ev->fhandler = SWAP32(func);
2059 static void psxBios_OpenEvent() { // 08
2060 u32 ret = OpenEvent(a0, a1, a2, a3);
2061 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
2062 biosB0n[0x08], a0, a1, a2, a3, ret);
2063 mips_return_c(ret, 36);
2066 static void CloseEvent(u32 ev)
2068 u32 base = loadRam32(A_TT_EvCB);
2069 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
2072 static void psxBios_CloseEvent() { // 09
2073 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
2074 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
2076 mips_return_c(1, 10);
2079 static void psxBios_WaitEvent() { // 0a
2080 u32 base = loadRam32(A_TT_EvCB);
2081 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2082 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
2085 if (status == EvStALREADY) {
2086 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2090 if (status != EvStACTIVE)
2092 mips_return_c(0, 2);
2096 // retrigger this hlecall after the next emulation event
2098 if ((s32)(next_interupt - psxRegs.cycle) > 0)
2099 psxRegs.cycle = next_interupt;
2103 static void psxBios_TestEvent() { // 0b
2104 u32 base = loadRam32(A_TT_EvCB);
2105 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2108 if (psxRegs.cycle - floodchk > 16*1024u) { // prevent log flood
2109 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
2110 floodchk = psxRegs.cycle;
2112 if (status == EvStALREADY) {
2113 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2117 mips_return_c(ret, 15);
2120 static void psxBios_EnableEvent() { // 0c
2121 u32 base = loadRam32(A_TT_EvCB);
2122 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2123 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
2124 if (status != EvStUNUSED)
2125 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2127 mips_return_c(1, 15);
2130 static void psxBios_DisableEvent() { // 0d
2131 u32 base = loadRam32(A_TT_EvCB);
2132 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2133 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2134 if (status != EvStUNUSED)
2135 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2137 mips_return_c(1, 15);
2141 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2144 void psxBios_OpenTh() { // 0e
2145 TCB *tcb = loadRam32ptr(A_TT_TCB);
2146 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2149 for (th = 1; th < limit; th++)
2151 if (tcb[th].status != SWAP32(0x4000)) break;
2155 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2156 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2158 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2160 mips_return_c(0xffffffff, 20);
2163 PSXBIOS_LOG("psxBios_%s -> %x\n", biosB0n[0x0e], 0xff000000 + th);
2165 tcb[th].status = SWAP32(0x4000);
2166 tcb[th].mode = SWAP32(0x1000);
2167 tcb[th].epc = SWAP32(a0);
2168 tcb[th].reg[30] = SWAP32(a1); // fp
2169 tcb[th].reg[29] = SWAP32(a1); // sp
2170 tcb[th].reg[28] = SWAP32(a2); // gp
2172 mips_return_c(0xff000000 + th, 34);
2176 * int CloseTh(long thread);
2179 static void psxBios_CloseTh() { // 0f
2180 u32 tcb = loadRam32(A_TT_TCB);
2181 u32 th = a0 & 0xffff;
2183 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x0f], a0);
2184 // in the usual bios fashion no checks, just write and return 1
2185 storeRam32(tcb + th * sizeof(TCB), 0x1000);
2187 mips_return_c(1, 11);
2191 * int ChangeTh(long thread);
2194 void psxBios_ChangeTh() { // 10
2195 u32 tcbBase = loadRam32(A_TT_TCB);
2196 u32 th = a0 & 0xffff;
2198 // this is quite spammy
2199 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2201 // without doing any argument checks, just issue a syscall
2202 // (like the real bios does)
2204 a1 = tcbBase + th * sizeof(TCB);
2209 void psxBios_InitPAD() { // 0x12
2210 u32 i, *ram32 = (u32 *)psxM;
2211 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2213 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2214 ram32[A_PAD_DR_DST/4] = 0;
2215 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2216 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2217 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2218 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2219 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2220 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2221 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2222 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2224 for (i = 0; i < a1; i++) {
2226 storeRam8(a0 + i, 0);
2228 for (i = 0; i < a3; i++) {
2230 storeRam8(a2 + i, 0);
2232 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2234 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2236 mips_return_c(1, 200);
2239 void psxBios_StartPAD() { // 13
2240 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2242 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2243 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2244 psxHwWrite16(0x1f801070, ~1);
2245 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2246 storeRam32(A_PAD_ACK_VBL, 1);
2247 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2248 psxRegs.CP0.n.SR |= 0x401;
2250 mips_return_c(1, 300);
2253 void psxBios_StopPAD() { // 14
2254 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2255 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2256 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2257 psxRegs.CP0.n.SR |= 0x401;
2258 mips_return_void_c(200);
2261 static void psxBios_PAD_init() { // 15
2263 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2264 if (a0 == 0x20000000 || a0 == 0x20000001)
2267 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2268 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2271 storeRam32(A_PAD_DR_DST, dst);
2274 mips_return_c(ret, 100);
2277 static u32 psxBios_PAD_dr_() {
2278 u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2279 u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2280 u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2281 dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2282 if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2284 dst[0] = buf1[3], dst[1] = buf1[2];
2285 if (buf1[1] == 0x23) {
2286 dst[0] |= 0xc7, dst[1] |= 7;
2287 if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2288 if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2291 if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2293 dst[2] = buf2[3], dst[3] = buf2[2];
2294 if (buf2[1] == 0x23) {
2295 dst[2] |= 0xc7, dst[3] |= 7;
2296 if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2297 if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2301 return SWAP32(*(u32 *)dst);
2304 static void psxBios_PAD_dr() { // 16
2305 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2306 u32 ret = psxBios_PAD_dr_();
2310 static void psxBios_ReturnFromException() { // 17
2311 u32 tcbPtr = loadRam32(A_TT_PCB);
2312 const TCB *tcb = loadRam32ptr(tcbPtr);
2316 for (i = 1; i < 32; i++)
2317 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2318 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2319 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2320 sr = SWAP32(tcb->sr);
2322 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2323 pc0 = k0 = SWAP32(tcb->epc);
2325 // the interpreter wants to know about sr changes, so do a MTC0
2326 sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2327 MTC0(&psxRegs, 12, sr);
2333 void psxBios_ResetEntryInt() { // 18
2334 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2336 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2337 mips_return_void_c(5);
2340 void psxBios_HookEntryInt() { // 19
2341 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2343 storeRam32(A_EEXIT_PTR, a0);
2344 mips_return_void_c(3);
2347 static void psxBios_UnDeliverEvent() { // 0x20
2349 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2351 ret = UnDeliverEvent(a0, a1);
2355 static void buopen(int mcd, char *ptr, char *cfg)
2358 char *mcd_data = ptr;
2360 strcpy(FDesc[1 + mcd].name, Ra0+5);
2361 FDesc[1 + mcd].offset = 0;
2362 FDesc[1 + mcd].mode = a1;
2364 for (i=1; i<16; i++) {
2365 const char *fptr = mcd_data + 128 * i;
2366 if ((*fptr & 0xF0) != 0x50) continue;
2367 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2368 FDesc[1 + mcd].mcfile = i;
2369 PSXBIOS_LOG("open %s\n", fptr+0xa);
2373 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2374 for (i=1; i<16; i++) {
2375 int j, xor, nblk = a1 >> 16;
2377 char *fptr = mcd_data + 128 * i;
2379 if ((*fptr & 0xF0) != 0xa0) continue;
2381 FDesc[1 + mcd].mcfile = i;
2384 fptr[5] = 0x20 * nblk;
2387 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2388 pptr = fptr2 = fptr;
2389 for(j=2; j<=nblk; j++) {
2391 for(i++; i<16; i++) {
2394 memset(fptr2, 0, 128);
2395 fptr2[0] = j < nblk ? 0x52 : 0x53;
2398 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2403 /* shouldn't this return ENOSPC if i == 16? */
2405 pptr[8] = pptr[9] = 0xff;
2406 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2408 PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2410 /* just go ahead and resave them all */
2411 SaveMcd(cfg, ptr, 128, 128 * 15);
2414 /* shouldn't this return ENOSPC if i == 16? */
2419 * int open(char *name , int mode);
2422 void psxBios_open() { // 0x32
2425 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x32], Ra0, a1);
2429 if (pa0 != INVALID_PTR) {
2430 if (!strncmp(pa0, "bu00", 4)) {
2431 buopen(1, Mcd1Data, Config.Mcd1);
2434 if (!strncmp(pa0, "bu10", 4)) {
2435 buopen(2, Mcd2Data, Config.Mcd2);
2443 * int lseek(int fd , int offset , int whence);
2446 void psxBios_lseek() { // 0x33
2448 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2453 FDesc[a0].offset = a1;
2455 // DeliverEvent(0xf0000011, 0x0004);
2456 // DeliverEvent(0xf4000001, 0x0004);
2460 FDesc[a0].offset+= a1;
2461 v0 = FDesc[a0].offset;
2470 * int read(int fd , void *buf , int nbytes);
2473 void psxBios_read() { // 0x34
2478 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2483 if (pa1 != INVALID_PTR) {
2485 case 2: buread(pa1, 1, a2); break;
2486 case 3: buread(pa1, 2, a2); break;
2494 * int write(int fd , void *buf , int nbytes);
2497 void psxBios_write() { // 0x35/0x03
2501 if (a0 != 1) // stdout
2502 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2505 if (pa1 == INVALID_PTR) {
2510 if (a0 == 1) { // stdout
2514 if (Config.PsxOut) while (a2 > 0) {
2515 SysPrintf("%c", *ptr++); a2--;
2521 case 2: buwrite(pa1, 1, a2); break;
2522 case 3: buwrite(pa1, 2, a2); break;
2528 static void psxBios_write_psxout() {
2529 if (a0 == 1) { // stdout
2530 const char *ptr = Ra1;
2533 if (ptr != INVALID_PTR)
2535 SysPrintf("%c", *ptr++);
2539 static void psxBios_putchar_psxout() { // 3d
2540 SysPrintf("%c", (char)a0);
2543 static void psxBios_puts_psxout() { // 3e/3f
2544 SysPrintf("%s", Ra0);
2548 * int close(int fd);
2551 void psxBios_close() { // 0x36
2553 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2560 void psxBios_putchar() { // 3d
2561 if (Config.PsxOut) SysPrintf("%c", (char)a0);
2565 void psxBios_puts() { // 3e/3f
2566 if (Config.PsxOut) SysPrintf("%s", Ra0);
2570 static void bufile(const u8 *mcd_data, u32 dir_) {
2571 struct DIRENTRY *dir = (struct DIRENTRY *)PSXM(dir_);
2572 const char *pfile = ffile + 5;
2573 const u8 *data = mcd_data;
2574 int i = 0, match = 0;
2579 if (dir == INVALID_PTR)
2582 for (; nfile <= 15 && !match; nfile++) {
2585 head = nfile * 0x40;
2586 data = mcd_data + 128 * nfile;
2587 name = (const char *)data + 0x0a;
2588 if ((data[0] & 0xF0) != 0x50) continue;
2589 /* Bug link files show up as free block. */
2590 if (!name[0]) continue;
2592 for (i = 0; i < 20; i++) {
2593 if (pfile[i] == name[i] || pfile[i] == '?')
2594 dir->name[i] = name[i];
2595 else if (pfile[i] == '*') {
2596 int len = strlen(name + i);
2599 memcpy(dir->name + i, name + i, len + 1);
2610 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n",
2611 nfile, dir->name, pfile, name, match);
2613 for (; nfile <= 15; nfile++, blocks++) {
2614 const u8 *data2 = mcd_data + 128 * nfile;
2615 const char *name = (const char *)data2 + 0x0a;
2616 if ((data2[0] & 0xF0) != 0x50 || name[0])
2620 // nul char of full lenth name seems to overwrite .attr
2621 dir->attr = SWAP32(i < 20 ? data[0] & 0xf0 : 0); // ?
2622 dir->size = 8192 * blocks;
2626 PSXBIOS_LOG(" -> %x '%s' %x %x %x %x\n", v0, v0 ? dir->name : "",
2627 dir->attr, dir->size, dir->next, dir->head);
2631 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2634 static void psxBios_firstfile() { // 42
2637 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x42], pa0, a1);
2640 if (pa0 != INVALID_PTR)
2642 snprintf(ffile, sizeof(ffile), "%s", pa0);
2644 strcpy(ffile + 5, "*"); // maybe?
2646 if (!strncmp(pa0, "bu00", 4)) {
2647 // firstfile() calls _card_read() internally, so deliver it's event
2648 DeliverEvent(0xf0000011, 0x0004);
2649 bufile((u8 *)Mcd1Data, a1);
2650 } else if (!strncmp(pa0, "bu10", 4)) {
2651 // firstfile() calls _card_read() internally, so deliver it's event
2652 DeliverEvent(0xf0000011, 0x0004);
2653 bufile((u8 *)Mcd2Data, a1);
2661 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2664 void psxBios_nextfile() { // 43
2665 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x43], a0);
2668 if (!strncmp(ffile, "bu00", 4))
2669 bufile((u8 *)Mcd1Data, a0);
2670 else if (!strncmp(ffile, "bu10", 4))
2671 bufile((u8 *)Mcd2Data, a0);
2676 #define burename(mcd) { \
2677 for (i=1; i<16; i++) { \
2678 int namelen, j, xor = 0; \
2679 ptr = Mcd##mcd##Data + 128 * i; \
2680 if ((*ptr & 0xF0) != 0x50) continue; \
2681 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2682 namelen = strlen(Ra1+5); \
2683 memcpy(ptr+0xa, Ra1+5, namelen); \
2684 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2685 for (j=0; j<127; j++) xor^= ptr[j]; \
2687 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2694 * int rename(char *old, char *new);
2697 void psxBios_rename() { // 44
2704 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2709 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2710 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2714 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2723 #define budelete(mcd) { \
2724 for (i=1; i<16; i++) { \
2725 ptr = Mcd##mcd##Data + 128 * i; \
2726 if ((*ptr & 0xF0) != 0x50) continue; \
2727 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2728 *ptr = (*ptr & 0xf) | 0xA0; \
2729 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2730 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2737 * int delete(char *name);
2740 void psxBios_delete() { // 45
2746 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2751 if (pa0 != INVALID_PTR) {
2752 if (!strncmp(pa0, "bu00", 4)) {
2756 if (!strncmp(pa0, "bu10", 4)) {
2764 void psxBios_InitCARD() { // 4a
2765 u32 *ram32 = (u32 *)psxM;
2766 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2767 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2768 // (maybe) todo: early_card_irq, etc
2770 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2772 psxBios_FlushCache();
2773 mips_return_c(0, 34+13+15+6);
2776 void psxBios_StartCARD() { // 4b
2777 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2778 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2779 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2781 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2782 storeRam32(A_PAD_ACK_VBL, 1);
2783 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2784 storeRam32(A_CARD_IRQR_ENA, 1);
2785 psxRegs.CP0.n.SR |= 0x401;
2787 mips_return_c(1, 200);
2790 void psxBios_StopCARD() { // 4c
2791 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2792 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2793 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2794 storeRam32(A_CARD_IRQR_ENA, 0);
2795 psxRegs.CP0.n.SR |= 0x401;
2796 mips_return_void_c(200);
2799 void psxBios__card_write() { // 0x4e
2804 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2807 Function also accepts sector 400h (a bug).
2808 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2812 /* Invalid sectors */
2816 storeRam32(A_CARD_CHAN1, a0);
2819 if (pa2 != INVALID_PTR) {
2821 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2822 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2824 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2825 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2829 DeliverEvent(0xf0000011, 0x0004);
2830 // DeliverEvent(0xf4000001, 0x0004);
2835 void psxBios__card_read() { // 0x4f
2840 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2843 Function also accepts sector 400h (a bug).
2844 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2848 /* Invalid sectors */
2852 storeRam32(A_CARD_CHAN1, a0);
2855 if (pa2 != INVALID_PTR) {
2857 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2859 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2863 DeliverEvent(0xf0000011, 0x0004);
2864 // DeliverEvent(0xf4000001, 0x0004);
2869 void psxBios__new_card() { // 0x50
2871 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2877 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2878 void psxBios__get_error(void) // 55
2880 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2885 void psxBios_Krom2RawAdd() { // 0x51
2888 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2889 const u32 table_8140[][2] = {
2890 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2891 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2892 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2893 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2894 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2895 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2896 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2897 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2898 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2902 const u32 table_889f[][2] = {
2903 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2904 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2905 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2906 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2907 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2908 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2909 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2910 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2914 if (a0 >= 0x8140 && a0 <= 0x84be) {
2915 while (table_8140[i][0] <= a0) i++;
2916 a0 -= table_8140[i - 1][0];
2917 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2918 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2919 while (table_889f[i][0] <= a0) i++;
2920 a0 -= table_889f[i - 1][0];
2921 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2929 void psxBios_GetC0Table() { // 56
2930 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2931 log_unhandled("GetC0Table @%08x\n", ra);
2933 mips_return_c(A_C0_TABLE, 3);
2936 void psxBios_GetB0Table() { // 57
2937 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2938 log_unhandled("GetB0Table @%08x\n", ra);
2940 mips_return_c(A_B0_TABLE, 3);
2943 static void psxBios__card_chan() { // 0x58
2945 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2947 // todo: should return active slot chan
2948 // (active - which was last processed by irq code)
2949 ret = loadRam32(A_CARD_CHAN1);
2950 mips_return_c(ret, 8);
2953 static void psxBios_ChangeClearPad() { // 5b
2955 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2956 ret = loadRam32(A_PAD_ACK_VBL);
2957 storeRam32(A_PAD_ACK_VBL, a0);
2959 mips_return_c(ret, 6);
2962 static void psxBios__card_status() { // 5c
2963 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
2969 static void psxBios__card_wait() { // 5d
2970 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
2976 /* System calls C0 */
2978 static void psxBios_InitRCnt() { // 00
2980 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2981 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2982 for (i = 0; i < 3; i++) {
2983 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2984 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2985 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2987 psxBios_SysEnqIntRP_(a0, 0x6d88);
2988 mips_return_c(0, 9);
2991 static void psxBios_InitException() { // 01
2992 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2993 psxBios_SysEnqIntRP_(a0, 0x6da8);
2994 mips_return_c(0, 9);
2998 * int SysEnqIntRP(int index , long *queue);
3001 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
3002 u32 old, base = loadRam32(A_TT_ExCB);
3004 old = loadRam32(base + (priority << 3));
3005 storeRam32(base + (priority << 3), chain_eptr);
3006 storeRam32(chain_eptr, old);
3007 mips_return_c(0, 9);
3010 static void psxBios_SysEnqIntRP() { // 02
3011 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
3012 psxBios_SysEnqIntRP_(a0, a1);
3016 * int SysDeqIntRP(int index , long *queue);
3019 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
3020 u32 ptr, next, base = loadRam32(A_TT_ExCB);
3021 u32 lim = 0, ret = 0;
3023 // as in original: no arg checks of any kind, bug if a1 == 0
3024 ptr = loadRam32(base + (priority << 3));
3026 next = loadRam32(ptr);
3027 if (ptr == chain_rm_eptr) {
3028 storeRam32(base + (priority << 3), next);
3033 while (next && next != chain_rm_eptr && lim++ < 100) {
3035 next = loadRam32(ptr);
3038 if (next == chain_rm_eptr) {
3039 next = loadRam32(next);
3040 storeRam32(ptr, next);
3047 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
3049 mips_return_c(ret, 12);
3052 static void psxBios_SysDeqIntRP() { // 03
3053 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
3054 psxBios_SysDeqIntRP_(a0, a1);
3057 static void psxBios_get_free_EvCB_slot() { // 04
3058 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
3059 s32 ret = get_free_EvCB_slot();
3060 mips_return_c(ret, 0);
3063 static void psxBios_SysInitMemory_(u32 base, u32 size) {
3064 storeRam32(base, 0);
3065 storeRam32(A_KMALLOC_PTR, base);
3066 storeRam32(A_KMALLOC_SIZE, size);
3067 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
3070 // this should be much more complicated, but maybe that'll be enough
3071 static u32 psxBios_SysMalloc_(u32 size) {
3072 u32 ptr = loadRam32(A_KMALLOC_PTR);
3074 size = (size + 3) & ~3;
3075 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
3076 storeRam32(ptr, size);
3080 static void psxBios_SysInitMemory() { // 08
3081 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
3083 psxBios_SysInitMemory_(a0, a1);
3084 mips_return_void_c(12);
3087 static void psxBios_ChangeClearRCnt() { // 0a
3090 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
3092 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
3093 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
3094 mips_return_c(ret, 8);
3097 static void psxBios_InitDefInt() { // 0c
3098 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3099 // should also clear the autoack table
3100 psxBios_SysEnqIntRP_(a0, 0x6d98);
3101 mips_return_c(0, 20 + 6*2);
3104 void psxBios_dummy() {
3105 u32 pc = (pc0 & 0x1fffff) - 4;
3106 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
3107 : pc == 0xc0 ? biosC0n : NULL;
3108 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
3109 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
3110 (void)pc; (void)ntab;
3111 mips_return_c(0, 100);
3114 void (*biosA0[256])();
3115 // C0 and B0 overlap (end of C0 is start of B0)
3116 void (*biosC0[256+128])();
3117 void (**biosB0)() = biosC0 + 128;
3119 static void setup_mips_code()
3122 ptr = (u32 *)&psxM[A_SYSCALL];
3123 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3124 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
3125 ptr[0x08/4] = SWAPu32(0x00000000); // nop
3127 ptr = (u32 *)&psxM[A_EXCEPTION];
3128 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
3129 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
3130 ptr[0x14/4] = SWAPu32(0x00000000); // nop
3131 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
3132 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3133 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
3134 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
3135 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
3136 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
3137 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
3139 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
3140 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
3141 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
3143 ptr[0xb0/4] = HLEOP(hleop_exception);
3146 static const struct {
3150 { 0xbfc050a4, hleop_exc0_0_1 },
3151 { 0xbfc04fbc, hleop_exc0_0_2 },
3152 { 0xbfc0506c, hleop_exc0_1_1 },
3153 { 0xbfc04dec, hleop_exc0_1_2 },
3154 { 0x1a00, hleop_exc0_2_2 },
3155 { 0x19c8, hleop_exc1_0_1 },
3156 { 0x18bc, hleop_exc1_0_2 },
3157 { 0x1990, hleop_exc1_1_1 },
3158 { 0x1858, hleop_exc1_1_2 },
3159 { 0x1958, hleop_exc1_2_1 },
3160 { 0x17f4, hleop_exc1_2_2 },
3161 { 0x1920, hleop_exc1_3_1 },
3162 { 0x1794, hleop_exc1_3_2 },
3163 { 0x2458, hleop_exc3_0_2 },
3164 { 0x49bc, hleop_exc_padcard1 },
3165 { 0x4a4c, hleop_exc_padcard2 },
3168 static int chain_hle_op(u32 handler)
3172 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3173 if (chainfns[i].addr == handler)
3174 return chainfns[i].op;
3178 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3180 d[0] = SWAPu32(next);
3181 d[1] = SWAPu32(handler1);
3182 d[2] = SWAPu32(handler2);
3184 // install the hle traps
3185 if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3186 if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3189 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack)
3191 u32 *ram32 = (u32 *)psxM;
3192 u32 s_excb = 0x20, s_evcb, s_pcb = 4, s_tcb;
3193 u32 p_excb, p_evcb, p_pcb, p_tcb;
3196 PSXBIOS_LOG("setup: tcb %u, evcb %u\n", tcb_cnt, evcb_cnt);
3198 // the real bios doesn't care, but we just don't
3199 // want to crash in case of garbage parameters
3200 if (tcb_cnt > 1024) tcb_cnt = 1024;
3201 if (evcb_cnt > 1024) evcb_cnt = 1024;
3202 s_evcb = 0x1c * evcb_cnt;
3203 s_tcb = 0xc0 * tcb_cnt;
3205 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3206 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3207 p_excb = psxBios_SysMalloc_(s_excb);
3208 p_evcb = psxBios_SysMalloc_(s_evcb);
3209 p_pcb = psxBios_SysMalloc_(s_pcb);
3210 p_tcb = psxBios_SysMalloc_(s_tcb);
3212 // "table of tables". Some games modify it
3213 assert(A_TT_ExCB == 0x0100);
3214 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3215 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3216 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3217 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3218 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3219 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3220 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3221 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3222 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3223 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3224 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3225 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3227 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3228 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3229 storeRam32(p_excb + 4*4, 0x0000); // chain2
3230 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3232 storeRam32(p_pcb, p_tcb);
3233 storeRam32(p_tcb, 0x4000); // first TCB
3234 for (i = 1; i < tcb_cnt; i++)
3235 storeRam32(p_tcb + sizeof(TCB) * i, 0x1000);
3238 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3239 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3240 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3241 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3242 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3244 storeRam32(A_CONF_EvCB, evcb_cnt);
3245 storeRam32(A_CONF_TCB, tcb_cnt);
3246 storeRam32(A_CONF_SP, stack);
3249 static const u32 gpu_ctl_def[] = {
3250 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3251 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3254 static const u32 gpu_data_def[] = {
3255 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3256 0xe5001000, 0xe6000000,
3257 0x02000000, 0x00000000, 0x01ff03ff
3261 static const u16 spu_config[] = {
3262 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3263 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3264 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3265 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3266 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3267 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3268 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3269 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3272 void psxBiosSetupBootState(void)
3274 boolean hle = Config.HLE;
3275 u32 *hw = (u32 *)psxH;
3278 // see also SetBootRegs()
3281 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3282 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3284 k0 = 0xbfc0d968; k1 = 0xf1c;
3285 ra = 0xf0001234; // just to easily detect attempts to return
3286 psxRegs.CP0.n.Cause = 0x20;
3287 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3289 hw[0x1000/4] = SWAP32(0x1f000000);
3290 hw[0x1004/4] = SWAP32(0x1f802000);
3291 hw[0x1008/4] = SWAP32(0x0013243f);
3292 hw[0x100c/4] = SWAP32(0x00003022);
3293 hw[0x1010/4] = SWAP32(0x0013243f);
3294 hw[0x1014/4] = SWAP32(0x200931e1);
3295 hw[0x1018/4] = SWAP32(0x00020943);
3296 hw[0x101c/4] = SWAP32(0x00070777);
3297 hw[0x1020/4] = SWAP32(0x0000132c);
3298 hw[0x1060/4] = SWAP32(0x00000b88);
3299 hw[0x1070/4] = SWAP32(0x00000001);
3300 hw[0x1074/4] = SWAP32(0x0000000c);
3301 hw[0x2040/4] = SWAP32(0x00000900);
3304 hw[0x10a0/4] = SWAP32(0x00ffffff);
3305 hw[0x10a8/4] = SWAP32(0x00000401);
3306 hw[0x10b0/4] = SWAP32(0x0008b000);
3307 hw[0x10b4/4] = SWAP32(0x00010200);
3308 hw[0x10e0/4] = SWAP32(0x000eccf4);
3309 hw[0x10e4/4] = SWAP32(0x00000400);
3310 hw[0x10e8/4] = SWAP32(0x00000002);
3311 hw[0x10f0/4] = SWAP32(0x00009099);
3312 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3321 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3322 GPU_writeStatus(gpu_ctl_def[i]);
3323 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3324 GPU_writeData(gpu_data_def[i]);
3327 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3328 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3331 static void hleExc0_0_1();
3332 static void hleExc0_0_2();
3333 static void hleExc0_1_1();
3334 static void hleExc0_1_2();
3336 #include "sjisfont.h"
3338 void psxBiosInit() {
3339 u32 *ptr, *ram32, *rom32;
3344 psxRegs.biosBranchCheck = ~0;
3346 memset(psxM, 0, 0x10000);
3347 for(i = 0; i < 256; i++) {
3352 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3353 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3354 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3355 biosA0[0x3f] = psxBios_printf_psxout;
3358 char verstr[0x24+1];
3359 rom32 = (u32 *)psxR;
3360 memcpy(verstr, psxR + 0x12c, 0x24);
3362 SysPrintf("BIOS: %08x, '%s', '%c'\n", SWAP32(rom32[0x100/4]),
3363 verstr, psxR[0x7ff52]);
3367 for(i = 0; i < 256; i++) {
3368 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3369 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3370 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3373 biosA0[0x00] = psxBios_open;
3374 biosA0[0x01] = psxBios_lseek;
3375 biosA0[0x02] = psxBios_read;
3376 biosA0[0x03] = psxBios_write;
3377 biosA0[0x04] = psxBios_close;
3378 //biosA0[0x05] = psxBios_ioctl;
3379 //biosA0[0x06] = psxBios_exit;
3380 //biosA0[0x07] = psxBios_sys_a0_07;
3381 biosA0[0x08] = psxBios_getc;
3382 biosA0[0x09] = psxBios_putc;
3383 biosA0[0x0a] = psxBios_todigit;
3384 //biosA0[0x0b] = psxBios_atof;
3385 //biosA0[0x0c] = psxBios_strtoul;
3386 //biosA0[0x0d] = psxBios_strtol;
3387 biosA0[0x0e] = psxBios_abs;
3388 biosA0[0x0f] = psxBios_labs;
3389 biosA0[0x10] = psxBios_atoi;
3390 biosA0[0x11] = psxBios_atol;
3391 //biosA0[0x12] = psxBios_atob;
3392 biosA0[0x13] = psxBios_setjmp;
3393 biosA0[0x14] = psxBios_longjmp;
3394 biosA0[0x15] = psxBios_strcat;
3395 biosA0[0x16] = psxBios_strncat;
3396 biosA0[0x17] = psxBios_strcmp;
3397 biosA0[0x18] = psxBios_strncmp;
3398 biosA0[0x19] = psxBios_strcpy;
3399 biosA0[0x1a] = psxBios_strncpy;
3400 biosA0[0x1b] = psxBios_strlen;
3401 biosA0[0x1c] = psxBios_index;
3402 biosA0[0x1d] = psxBios_rindex;
3403 biosA0[0x1e] = psxBios_strchr;
3404 biosA0[0x1f] = psxBios_strrchr;
3405 biosA0[0x20] = psxBios_strpbrk;
3406 biosA0[0x21] = psxBios_strspn;
3407 biosA0[0x22] = psxBios_strcspn;
3408 biosA0[0x23] = psxBios_strtok;
3409 biosA0[0x24] = psxBios_strstr;
3410 biosA0[0x25] = psxBios_toupper;
3411 biosA0[0x26] = psxBios_tolower;
3412 biosA0[0x27] = psxBios_bcopy;
3413 biosA0[0x28] = psxBios_bzero;
3414 biosA0[0x29] = psxBios_bcmp;
3415 biosA0[0x2a] = psxBios_memcpy;
3416 biosA0[0x2b] = psxBios_memset;
3417 biosA0[0x2c] = psxBios_memmove;
3418 biosA0[0x2d] = psxBios_memcmp;
3419 biosA0[0x2e] = psxBios_memchr;
3420 biosA0[0x2f] = psxBios_rand;
3421 biosA0[0x30] = psxBios_srand;
3422 biosA0[0x31] = psxBios_qsort;
3423 //biosA0[0x32] = psxBios_strtod;
3424 biosA0[0x33] = psxBios_malloc;
3425 biosA0[0x34] = psxBios_free;
3426 //biosA0[0x35] = psxBios_lsearch;
3427 //biosA0[0x36] = psxBios_bsearch;
3428 biosA0[0x37] = psxBios_calloc;
3429 biosA0[0x38] = psxBios_realloc;
3430 biosA0[0x39] = psxBios_InitHeap;
3431 //biosA0[0x3a] = psxBios__exit;
3432 biosA0[0x3b] = psxBios_getchar;
3433 biosA0[0x3c] = psxBios_putchar;
3434 //biosA0[0x3d] = psxBios_gets;
3435 biosA0[0x3e] = psxBios_puts;
3436 biosA0[0x3f] = psxBios_printf;
3437 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3438 //biosA0[0x41] = psxBios_LoadTest;
3439 biosA0[0x42] = psxBios_Load;
3440 biosA0[0x43] = psxBios_Exec;
3441 biosA0[0x44] = psxBios_FlushCache;
3442 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3443 biosA0[0x46] = psxBios_GPU_dw;
3444 biosA0[0x47] = psxBios_mem2vram;
3445 biosA0[0x48] = psxBios_SendGPU;
3446 biosA0[0x49] = psxBios_GPU_cw;
3447 biosA0[0x4a] = psxBios_GPU_cwb;
3448 biosA0[0x4b] = psxBios_GPU_SendPackets;
3449 biosA0[0x4c] = psxBios_sys_a0_4c;
3450 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3451 //biosA0[0x4e] = psxBios_GPU_sync;
3452 //biosA0[0x4f] = psxBios_sys_a0_4f;
3453 //biosA0[0x50] = psxBios_sys_a0_50;
3454 biosA0[0x51] = psxBios_LoadExec;
3455 //biosA0[0x52] = psxBios_GetSysSp;
3456 //biosA0[0x53] = psxBios_sys_a0_53;
3457 //biosA0[0x54] = psxBios__96_init_a54;
3458 //biosA0[0x55] = psxBios__bu_init_a55;
3459 biosA0[0x56] = psxBios_CdRemove;
3460 //biosA0[0x57] = psxBios_sys_a0_57;
3461 //biosA0[0x58] = psxBios_sys_a0_58;
3462 //biosA0[0x59] = psxBios_sys_a0_59;
3463 //biosA0[0x5a] = psxBios_sys_a0_5a;
3464 //biosA0[0x5b] = psxBios_dev_tty_init;
3465 //biosA0[0x5c] = psxBios_dev_tty_open;
3466 //biosA0[0x5d] = psxBios_sys_a0_5d;
3467 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3468 //biosA0[0x5f] = psxBios_dev_cd_open;
3469 //biosA0[0x60] = psxBios_dev_cd_read;
3470 //biosA0[0x61] = psxBios_dev_cd_close;
3471 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3472 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3473 //biosA0[0x64] = psxBios_dev_cd_chdir;
3474 //biosA0[0x65] = psxBios_dev_card_open;
3475 //biosA0[0x66] = psxBios_dev_card_read;
3476 //biosA0[0x67] = psxBios_dev_card_write;
3477 //biosA0[0x68] = psxBios_dev_card_close;
3478 //biosA0[0x69] = psxBios_dev_card_firstfile;
3479 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3480 //biosA0[0x6b] = psxBios_dev_card_erase;
3481 //biosA0[0x6c] = psxBios_dev_card_undelete;
3482 //biosA0[0x6d] = psxBios_dev_card_format;
3483 //biosA0[0x6e] = psxBios_dev_card_rename;
3484 //biosA0[0x6f] = psxBios_dev_card_6f;
3485 biosA0[0x70] = psxBios__bu_init;
3486 biosA0[0x71] = psxBios__96_init;
3487 biosA0[0x72] = psxBios_CdRemove;
3488 //biosA0[0x73] = psxBios_sys_a0_73;
3489 //biosA0[0x74] = psxBios_sys_a0_74;
3490 //biosA0[0x75] = psxBios_sys_a0_75;
3491 //biosA0[0x76] = psxBios_sys_a0_76;
3492 //biosA0[0x77] = psxBios_sys_a0_77;
3493 //biosA0[0x78] = psxBios__96_CdSeekL;
3494 //biosA0[0x79] = psxBios_sys_a0_79;
3495 //biosA0[0x7a] = psxBios_sys_a0_7a;
3496 //biosA0[0x7b] = psxBios_sys_a0_7b;
3497 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3498 //biosA0[0x7d] = psxBios_sys_a0_7d;
3499 //biosA0[0x7e] = psxBios__96_CdRead;
3500 //biosA0[0x7f] = psxBios_sys_a0_7f;
3501 //biosA0[0x80] = psxBios_sys_a0_80;
3502 //biosA0[0x81] = psxBios_sys_a0_81;
3503 //biosA0[0x82] = psxBios_sys_a0_82;
3504 //biosA0[0x83] = psxBios_sys_a0_83;
3505 //biosA0[0x84] = psxBios_sys_a0_84;
3506 //biosA0[0x85] = psxBios__96_CdStop;
3507 //biosA0[0x86] = psxBios_sys_a0_86;
3508 //biosA0[0x87] = psxBios_sys_a0_87;
3509 //biosA0[0x88] = psxBios_sys_a0_88;
3510 //biosA0[0x89] = psxBios_sys_a0_89;
3511 //biosA0[0x8a] = psxBios_sys_a0_8a;
3512 //biosA0[0x8b] = psxBios_sys_a0_8b;
3513 //biosA0[0x8c] = psxBios_sys_a0_8c;
3514 //biosA0[0x8d] = psxBios_sys_a0_8d;
3515 //biosA0[0x8e] = psxBios_sys_a0_8e;
3516 //biosA0[0x8f] = psxBios_sys_a0_8f;
3517 biosA0[0x90] = hleExc0_1_2;
3518 biosA0[0x91] = hleExc0_0_2;
3519 biosA0[0x92] = hleExc0_1_1;
3520 biosA0[0x93] = hleExc0_0_1;
3521 //biosA0[0x94] = psxBios_sys_a0_94;
3522 //biosA0[0x95] = psxBios_sys_a0_95;
3523 //biosA0[0x96] = psxBios_AddCDROMDevice;
3524 //biosA0[0x97] = psxBios_AddMemCardDevide;
3525 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3526 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3527 //biosA0[0x9a] = psxBios_sys_a0_9a;
3528 //biosA0[0x9b] = psxBios_sys_a0_9b;
3529 biosA0[0x9c] = psxBios_SetConf;
3530 biosA0[0x9d] = psxBios_GetConf;
3531 //biosA0[0x9e] = psxBios_sys_a0_9e;
3532 biosA0[0x9f] = psxBios_SetMem;
3533 //biosA0[0xa0] = psxBios__boot;
3534 //biosA0[0xa1] = psxBios_SystemError;
3535 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3536 biosA0[0xa3] = psxBios_DequeueCdIntr;
3537 //biosA0[0xa4] = psxBios_sys_a0_a4;
3538 //biosA0[0xa5] = psxBios_ReadSector;
3539 biosA0[0xa6] = psxBios_get_cd_status;
3540 //biosA0[0xa7] = psxBios_bufs_cb_0;
3541 //biosA0[0xa8] = psxBios_bufs_cb_1;
3542 //biosA0[0xa9] = psxBios_bufs_cb_2;
3543 //biosA0[0xaa] = psxBios_bufs_cb_3;
3544 biosA0[0xab] = psxBios__card_info;
3545 biosA0[0xac] = psxBios__card_load;
3546 //biosA0[0axd] = psxBios__card_auto;
3547 //biosA0[0xae] = psxBios_bufs_cd_4;
3548 //biosA0[0xaf] = psxBios_sys_a0_af;
3549 //biosA0[0xb0] = psxBios_sys_a0_b0;
3550 //biosA0[0xb1] = psxBios_sys_a0_b1;
3551 //biosA0[0xb2] = psxBios_do_a_long_jmp
3552 //biosA0[0xb3] = psxBios_sys_a0_b3;
3553 biosA0[0xb4] = psxBios_GetSystemInfo;
3554 //*******************B0 CALLS****************************
3555 biosB0[0x00] = psxBios_SysMalloc;
3556 //biosB0[0x01] = psxBios_sys_b0_01;
3557 biosB0[0x02] = psxBios_SetRCnt;
3558 biosB0[0x03] = psxBios_GetRCnt;
3559 biosB0[0x04] = psxBios_StartRCnt;
3560 biosB0[0x05] = psxBios_StopRCnt;
3561 biosB0[0x06] = psxBios_ResetRCnt;
3562 biosB0[0x07] = psxBios_DeliverEvent;
3563 biosB0[0x08] = psxBios_OpenEvent;
3564 biosB0[0x09] = psxBios_CloseEvent;
3565 biosB0[0x0a] = psxBios_WaitEvent;
3566 biosB0[0x0b] = psxBios_TestEvent;
3567 biosB0[0x0c] = psxBios_EnableEvent;
3568 biosB0[0x0d] = psxBios_DisableEvent;
3569 biosB0[0x0e] = psxBios_OpenTh;
3570 biosB0[0x0f] = psxBios_CloseTh;
3571 biosB0[0x10] = psxBios_ChangeTh;
3572 //biosB0[0x11] = psxBios_psxBios_b0_11;
3573 biosB0[0x12] = psxBios_InitPAD;
3574 biosB0[0x13] = psxBios_StartPAD;
3575 biosB0[0x14] = psxBios_StopPAD;
3576 biosB0[0x15] = psxBios_PAD_init;
3577 biosB0[0x16] = psxBios_PAD_dr;
3578 biosB0[0x17] = psxBios_ReturnFromException;
3579 biosB0[0x18] = psxBios_ResetEntryInt;
3580 biosB0[0x19] = psxBios_HookEntryInt;
3581 //biosB0[0x1a] = psxBios_sys_b0_1a;
3582 //biosB0[0x1b] = psxBios_sys_b0_1b;
3583 //biosB0[0x1c] = psxBios_sys_b0_1c;
3584 //biosB0[0x1d] = psxBios_sys_b0_1d;
3585 //biosB0[0x1e] = psxBios_sys_b0_1e;
3586 //biosB0[0x1f] = psxBios_sys_b0_1f;
3587 biosB0[0x20] = psxBios_UnDeliverEvent;
3588 //biosB0[0x21] = psxBios_sys_b0_21;
3589 //biosB0[0x22] = psxBios_sys_b0_22;
3590 //biosB0[0x23] = psxBios_sys_b0_23;
3591 //biosB0[0x24] = psxBios_sys_b0_24;
3592 //biosB0[0x25] = psxBios_sys_b0_25;
3593 //biosB0[0x26] = psxBios_sys_b0_26;
3594 //biosB0[0x27] = psxBios_sys_b0_27;
3595 //biosB0[0x28] = psxBios_sys_b0_28;
3596 //biosB0[0x29] = psxBios_sys_b0_29;
3597 //biosB0[0x2a] = psxBios_sys_b0_2a;
3598 //biosB0[0x2b] = psxBios_sys_b0_2b;
3599 //biosB0[0x2c] = psxBios_sys_b0_2c;
3600 //biosB0[0x2d] = psxBios_sys_b0_2d;
3601 //biosB0[0x2e] = psxBios_sys_b0_2e;
3602 //biosB0[0x2f] = psxBios_sys_b0_2f;
3603 //biosB0[0x30] = psxBios_sys_b0_30;
3604 //biosB0[0x31] = psxBios_sys_b0_31;
3605 biosB0[0x32] = psxBios_open;
3606 biosB0[0x33] = psxBios_lseek;
3607 biosB0[0x34] = psxBios_read;
3608 biosB0[0x35] = psxBios_write;
3609 biosB0[0x36] = psxBios_close;
3610 //biosB0[0x37] = psxBios_ioctl;
3611 //biosB0[0x38] = psxBios_exit;
3612 //biosB0[0x39] = psxBios_sys_b0_39;
3613 //biosB0[0x3a] = psxBios_getc;
3614 //biosB0[0x3b] = psxBios_putc;
3615 biosB0[0x3c] = psxBios_getchar;
3616 biosB0[0x3d] = psxBios_putchar;
3617 //biosB0[0x3e] = psxBios_gets;
3618 biosB0[0x3f] = psxBios_puts;
3619 biosB0[0x40] = psxBios_cd;
3620 biosB0[0x41] = psxBios_format;
3621 biosB0[0x42] = psxBios_firstfile;
3622 biosB0[0x43] = psxBios_nextfile;
3623 biosB0[0x44] = psxBios_rename;
3624 biosB0[0x45] = psxBios_delete;
3625 //biosB0[0x46] = psxBios_undelete;
3626 //biosB0[0x47] = psxBios_AddDevice;
3627 //biosB0[0x48] = psxBios_RemoteDevice;
3628 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3629 biosB0[0x4a] = psxBios_InitCARD;
3630 biosB0[0x4b] = psxBios_StartCARD;
3631 biosB0[0x4c] = psxBios_StopCARD;
3632 //biosB0[0x4d] = psxBios_sys_b0_4d;
3633 biosB0[0x4e] = psxBios__card_write;
3634 biosB0[0x4f] = psxBios__card_read;
3635 biosB0[0x50] = psxBios__new_card;
3636 biosB0[0x51] = psxBios_Krom2RawAdd;
3637 //biosB0[0x52] = psxBios_sys_b0_52;
3638 //biosB0[0x53] = psxBios_sys_b0_53;
3639 //biosB0[0x54] = psxBios__get_errno;
3640 biosB0[0x55] = psxBios__get_error;
3641 biosB0[0x56] = psxBios_GetC0Table;
3642 biosB0[0x57] = psxBios_GetB0Table;
3643 biosB0[0x58] = psxBios__card_chan;
3644 //biosB0[0x59] = psxBios_sys_b0_59;
3645 //biosB0[0x5a] = psxBios_sys_b0_5a;
3646 biosB0[0x5b] = psxBios_ChangeClearPad;
3647 biosB0[0x5c] = psxBios__card_status;
3648 biosB0[0x5d] = psxBios__card_wait;
3649 //*******************C0 CALLS****************************
3650 biosC0[0x00] = psxBios_InitRCnt;
3651 biosC0[0x01] = psxBios_InitException;
3652 biosC0[0x02] = psxBios_SysEnqIntRP;
3653 biosC0[0x03] = psxBios_SysDeqIntRP;
3654 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3655 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3656 //biosC0[0x06] = psxBios_ExceptionHandler;
3657 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3658 biosC0[0x08] = psxBios_SysInitMemory;
3659 //biosC0[0x09] = psxBios_SysInitKMem;
3660 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3661 //biosC0[0x0b] = psxBios_SystemError;
3662 biosC0[0x0c] = psxBios_InitDefInt;
3663 //biosC0[0x0d] = psxBios_sys_c0_0d;
3664 //biosC0[0x0e] = psxBios_sys_c0_0e;
3665 //biosC0[0x0f] = psxBios_sys_c0_0f;
3666 //biosC0[0x10] = psxBios_sys_c0_10;
3667 //biosC0[0x11] = psxBios_sys_c0_11;
3668 //biosC0[0x12] = psxBios_InstallDevices;
3669 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3670 //biosC0[0x14] = psxBios_sys_c0_14;
3671 //biosC0[0x15] = psxBios__cdevinput;
3672 //biosC0[0x16] = psxBios__cdevscan;
3673 //biosC0[0x17] = psxBios__circgetc;
3674 //biosC0[0x18] = psxBios__circputc;
3675 //biosC0[0x19] = psxBios_ioabort;
3676 //biosC0[0x1a] = psxBios_sys_c0_1a
3677 //biosC0[0x1b] = psxBios_KernelRedirect;
3678 //biosC0[0x1c] = psxBios_PatchAOTable;
3679 //************** THE END ***************************************
3682 memset(FDesc, 0, sizeof(FDesc));
3683 memset(cdir, 0, sizeof(cdir));
3686 // somewhat pretend to be a SCPH1001 BIOS
3687 // some games look for these and take an exception if they're missing
3688 rom32 = (u32 *)psxR;
3689 rom32[0x100/4] = SWAP32(0x19951204);
3690 rom32[0x104/4] = SWAP32(3);
3691 romc = (char *)psxR;
3692 strcpy(romc + 0x108, "PCSX authors");
3693 strcpy(romc + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3694 strcpy(romc + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3695 strcpy(romc + 0x7ff54, "GPL-2.0-or-later");
3698 len = 0x80000 - 0x66000;
3699 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3700 len = 0x80000 - 0x69d68;
3701 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3703 // trap attempts to call bios directly
3704 rom32[0x00000/4] = HLEOP(hleop_dummy);
3705 rom32[0x00180/4] = HLEOP(hleop_dummy);
3706 rom32[0x3fffc/4] = HLEOP(hleop_dummy);
3707 rom32[0x65ffc/4] = HLEOP(hleop_dummy);
3708 rom32[0x7ff2c/4] = HLEOP(hleop_dummy);
3710 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3711 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3712 Here are some examples of games not working with this fix in place :
3713 R-type won't get past the Irem logo if not implemented.
3714 Crash Team Racing will softlock after the Sony logo.
3717 ram32 = (u32 *)psxM;
3718 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3719 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3720 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3721 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3723 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3724 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3726 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3727 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3728 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3729 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3731 ram32[0x00a0/4] = HLEOP(hleop_a0);
3732 ram32[0x00b0/4] = HLEOP(hleop_b0);
3733 ram32[0x00c0/4] = HLEOP(hleop_c0);
3735 setup_tt(4, 16, 0x801fff00);
3736 DeliverEvent(0xf0000003, 0x0010);
3738 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3739 strcpy((char *)&ram32[0xeff0/4], "bu");
3741 // default exception handler chains
3742 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3743 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3744 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3745 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3746 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3747 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3748 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3749 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3753 // fill the api jumptables with fake entries as some games patch them
3754 // (or rather the funcs listed there)
3755 ptr = (u32 *)&psxM[A_A0_TABLE];
3756 for (i = 0; i < 256; i++)
3757 ptr[i] = SWAP32(A_A0_DUMMY);
3759 ptr = (u32 *)&psxM[A_B0_TABLE];
3760 for (i = 0; i < 256; i++)
3761 ptr[i] = SWAP32(A_B0_DUMMY);
3762 // B(5b) is special because games patch (sometimes even jump to)
3763 // code at fixed offsets from it, nocash lists offsets:
3764 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3765 // call: +7a0=4b70, +884=4c54, +894=4c64
3766 ptr[0x5b] = SWAP32(A_B0_5B_DUMMY); // 0x43d0
3767 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3769 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3770 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3771 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3773 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3774 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3776 ptr = (u32 *)&psxM[A_C0_TABLE];
3777 for (i = 0; i < 256/2; i++)
3778 ptr[i] = SWAP32(A_C0_DUMMY);
3779 ptr[6] = SWAP32(A_EXCEPTION);
3782 ram32[A_A0_DUMMY/4] = HLEOP(hleop_dummy);
3783 ram32[A_B0_DUMMY/4] = HLEOP(hleop_dummy);
3784 ram32[A_C0_DUMMY/4] = HLEOP(hleop_dummy);
3785 ram32[A_B0_5B_DUMMY/4] = HLEOP(hleop_dummy);
3786 ram32[0x8000/4] = HLEOP(hleop_execret);
3788 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3789 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3790 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3791 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3792 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3793 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3794 ram32[A_RND_SEED/4] = SWAPu32(0x24040001); // was 0xac20cc00
3797 void psxBiosShutdown() {
3800 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 stack) {
3803 if (tcb_cnt != 4 || evcb_cnt != 16) {
3804 setup_tt(tcb_cnt, evcb_cnt, stack);
3805 DeliverEvent(0xf0000003, 0x0010);
3807 storeRam32(A_CONF_SP, stack);
3810 #define psxBios_PADpoll(pad) { \
3811 int i, more_data = 0; \
3812 PAD##pad##_startPoll(pad); \
3813 pad_buf##pad[1] = PAD##pad##_poll(0x42, &more_data); \
3814 pad_buf##pad[0] = more_data ? 0 : 0xff; \
3815 PAD##pad##_poll(0, &more_data); \
3817 while (more_data) { \
3818 pad_buf##pad[i++] = PAD##pad##_poll(0, &more_data); \
3822 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3826 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3827 psxBios_ReturnFromException();
3833 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3834 // so this is only partially implemented
3835 static void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3837 u32 cdrom_dma_ack_enable = 1; // a000b93c
3838 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3841 static void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3844 //PSXBIOS_LOG("%s\n", __func__);
3846 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3847 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3848 //if (--cdrom_irq_counter == 0) // 0xa0009180
3849 // DeliverEvent(0xf0000003, 0x10);
3853 mips_return_c(ret, 20);
3856 static void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3858 u32 cdrom_irq_ack_enable = 1; // a000b938
3859 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3862 static void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3865 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3866 PSXBIOS_LOG("%s TODO\n", __func__);
3869 mips_return_c(ret, 20);
3872 static void hleExc0_2_2_syscall() // not in any A/B/C table
3874 u32 tcbPtr = loadRam32(A_TT_PCB);
3875 TCB *tcb = loadRam32ptr(tcbPtr);
3876 u32 code = (SWAP32(tcb->cause) & 0x3c) >> 2;
3878 if (code != R3000E_Syscall) {
3880 DeliverEvent(0xf0000010, 0x1000);
3881 //psxBios_SystemErrorUnresolvedException();
3883 mips_return_c(0, 17);
3887 //printf("%s c=%d a0=%d\n", __func__, code, SWAP32(tcb->reg[4]));
3888 tcb->epc += SWAP32(4);
3889 switch (SWAP32(tcb->reg[4])) { // a0
3893 case 1: { // EnterCritical - disable irqs
3894 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3895 tcb->reg[2] = SWAP32(was_enabled);
3896 tcb->sr &= SWAP32(~0x404);
3899 case 2: // ExitCritical - enable irqs
3900 tcb->sr |= SWAP32(0x404);
3903 case 3: { // ChangeThreadSubFunction
3904 u32 tcbPtr = loadRam32(A_TT_PCB);
3905 storeRam32(tcbPtr, SWAP32(tcb->reg[5])); // a1
3909 DeliverEvent(0xf0000010, 0x4000);
3913 psxBios_ReturnFromException();
3916 static void hleExc1_0_1(void)
3918 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3919 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3922 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3925 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3926 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3929 mips_return_c(ret, 22);
3932 static void hleExc1_0_2(void)
3934 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3937 static void hleExc1_1_1(void)
3939 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3940 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3943 static void hleExc1_1_2(void)
3945 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3948 static void hleExc1_2_1(void)
3950 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3951 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3954 static void hleExc1_2_2(void)
3956 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3959 static void hleExc1_3_1(void)
3961 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3962 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3965 static void hleExc1_3_2(void)
3967 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3970 static void hleExc3_0_2_defint(void)
3972 static const struct {
3983 { 6, 6 }, // rcnt2 (bug)
3988 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3989 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3990 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3995 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3998 static void hleExcPadCard1(void)
4000 if (loadRam32(A_PAD_IRQR_ENA)) {
4001 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
4002 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
4007 if (loadRam32(A_PAD_DR_DST))
4010 if (loadRam32(A_PAD_ACK_VBL))
4011 psxHwWrite16(0x1f801070, ~1);
4012 if (loadRam32(A_CARD_IRQR_ENA)) {
4016 mips_return_c(0, 18);
4019 static void hleExcPadCard2(void)
4021 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
4022 mips_return_c(ret, 15);
4025 void psxBiosException() {
4026 u32 tcbPtr = loadRam32(A_TT_PCB);
4027 u32 *chains = loadRam32ptr(A_TT_ExCB);
4028 TCB *tcb = loadRam32ptr(tcbPtr);
4034 // $at, $v0, $v1, $ra already saved by the mips code at A_EXCEPTION
4035 for (i = 4; i < 31; i++) {
4038 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
4040 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
4041 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
4042 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
4043 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
4044 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
4045 sp = fp = loadRam32(A_EXC_SP);
4048 assert(!psxRegs.cpuInRecursion);
4050 // do the chains (always 4)
4051 for (c = lim = 0; c < 4; c++) {
4052 if (chains[c * 2] == 0)
4054 ptr = SWAP32(chains[c * 2]);
4055 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
4056 chain = castRam32ptr(ptr);
4061 softCallInException(SWAP32(chain[2]));
4062 if (returned_from_exception())
4065 if (v0 == 0 || chain[1] == 0)
4067 softCallInException(SWAP32(chain[1]));
4068 if (returned_from_exception())
4074 // return from exception (custom or default)
4076 ptr = loadRam32(A_EEXIT_PTR);
4077 if (ptr != A_EEXIT_DEF) {
4078 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
4079 longjmp_load(jmp_buf);
4084 psxBios_ReturnFromException();
4088 static void hleDummy() {
4089 log_unhandled("hleDummy called @%08x ra=%08x\n", psxRegs.pc - 4, ra);
4091 psxRegs.cycle += 1000;
4096 static void hleA0() {
4097 u32 call = t1 & 0xff;
4098 u32 entry = loadRam32(A_A0_TABLE + call * 4);
4100 if (call < 192 && entry != A_A0_DUMMY) {
4101 PSXBIOS_LOG("custom A%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4102 call, biosA0n[call], a0, entry, ra);
4105 PSXBIOS_LOG(" -> %08x\n", v0);
4107 else if (biosA0[call])
4110 //printf("A(%02x) -> %x\n", call, v0);
4114 static void hleB0() {
4115 u32 call = t1 & 0xff;
4116 u32 entry = loadRam32(A_B0_TABLE + call * 4);
4120 is_custom = entry != A_B0_5B_DUMMY;
4122 is_custom = entry != A_B0_DUMMY;
4124 PSXBIOS_LOG("custom B%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4125 call, biosB0n[call], a0, entry, ra);
4128 PSXBIOS_LOG(" -> %08x\n", v0);
4130 else if (biosB0[call])
4133 //printf("B(%02x) -> %x\n", call, v0);
4137 static void hleC0() {
4138 u32 call = t1 & 0xff;
4139 u32 entry = loadRam32(A_C0_TABLE + call * 4);
4141 if (call < 128 && entry != A_C0_DUMMY) {
4142 PSXBIOS_LOG("custom C%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4143 call, biosC0n[call], a0, entry, ra);
4146 PSXBIOS_LOG(" -> %08x\n", v0);
4148 else if (biosC0[call])
4151 //printf("C(%02x) -> %x\n", call, v0);
4155 // currently not used
4156 static void hleBootstrap() {
4161 static void hleExecRet() {
4162 const EXEC *header = (EXEC *)PSXM(s0);
4164 PSXBIOS_LOG("ExecRet %x: %x\n", s0, header->ret);
4166 ra = SWAP32(header->ret);
4167 sp = SWAP32(header->_sp);
4168 fp = SWAP32(header->_fp);
4169 gp = SWAP32(header->_gp);
4170 s0 = SWAP32(header->base);
4176 void (* const psxHLEt[24])() = {
4177 hleDummy, hleA0, hleB0, hleC0,
4178 hleBootstrap, hleExecRet, psxBiosException, hleDummy,
4179 hleExc0_0_1, hleExc0_0_2,
4180 hleExc0_1_1, hleExc0_1_2, hleExc0_2_2_syscall,
4181 hleExc1_0_1, hleExc1_0_2,
4182 hleExc1_1_1, hleExc1_1_2,
4183 hleExc1_2_1, hleExc1_2_2,
4184 hleExc1_3_1, hleExc1_3_2,
4186 hleExcPadCard1, hleExcPadCard2,
4189 void psxBiosCheckExe(u32 t_addr, u32 t_size, int loading_state)
4191 // lw $v0, 0x10($sp)
4194 // sw $v0, 0x10($sp)
4195 // lw $v0, 0x10($sp)
4197 // bne $v0, $v1, not_timeout
4200 static const u8 pattern[] = {
4201 0x10, 0x00, 0xA2, 0x8F, 0x00, 0x00, 0x00, 0x00,
4202 0xFF, 0xFF, 0x42, 0x24, 0x10, 0x00, 0xA2, 0xAF,
4203 0x10, 0x00, 0xA2, 0x8F, 0x00, 0x00, 0x00, 0x00,
4204 0x0C, 0x00, 0x43, 0x14, 0x00, 0x00, 0x00, 0x00,
4206 u32 start = t_addr & 0x1ffffc;
4207 u32 end = (start + t_size) & 0x1ffffc;
4208 u32 buf[sizeof(pattern) / sizeof(u32)];
4209 const u32 *r32 = (u32 *)(psxM + start);
4217 memcpy(buf, pattern, sizeof(buf));
4218 for (i = 0; i < t_size / 4; i += j + 1) {
4219 for (j = 0; j < sizeof(buf) / sizeof(buf[0]); j++)
4220 if (r32[i + j] != buf[j])
4222 if (j != sizeof(buf) / sizeof(buf[0]))
4225 if ((SWAP32(r32[i + j]) >> 16) != 0x3c04) // lui
4228 SysPrintf("HLE vsync @%08x\n", start + i * 4);
4229 psxRegs.biosBranchCheck = (t_addr & 0xa01ffffc) + i * 4;
4233 void psxBiosCheckBranch(void)
4237 static u32 cycles_prev, v0_prev;
4238 u32 cycles_passed, waste_cycles;
4239 u32 loops, v0_expect = v0_prev - 1;
4243 cycles_passed = psxRegs.cycle - cycles_prev;
4244 cycles_prev = psxRegs.cycle;
4246 if (cycles_passed < 10 || cycles_passed > 50 || v0 != v0_expect)
4249 waste_cycles = schedule_timeslice() - psxRegs.cycle;
4250 loops = waste_cycles / cycles_passed;
4254 psxRegs.cycle += loops * cycles_passed;
4255 //printf("c %4u %d\n", loops, cycles_passed);
4259 #define bfreeze(ptr, size) { \
4260 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
4261 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
4265 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
4266 #define bfreezel(ptr) bfreeze(ptr, sizeof(*(ptr)))
4268 void psxBiosFreeze(int Mode) {