1 /***************************************************************************
2 * Copyright (C) 2019 Ryan Schultz, PCSX-df Team, PCSX team, gameblabla, *
3 * dmitrysmagin, senquack *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
19 ***************************************************************************/
21 /* Gameblabla 2018-2019 :
22 * Numerous changes to bios calls as well as improvements in order to conform to nocash's findings
23 * for the PSX bios calls. Thanks senquack for helping out with some of the changes
24 * and helping to spot issues and refine my patches.
28 * Internal simulated HLE BIOS.
31 // TODO: implement all system calls, count the exact CPU cycles of system calls.
38 #include "psxinterpreter.h"
39 #include "new_dynarec/events.h"
43 //#define PSXBIOS_LOG printf
44 #define PSXBIOS_LOG(...)
47 #define PTR_1 (void *)(size_t)1
49 char *biosA0n[256] = {
51 "open", "lseek", "read", "write",
52 "close", "ioctl", "exit", "sys_a0_07",
53 "getc", "putc", "todigit", "atof",
54 "strtoul", "strtol", "abs", "labs",
56 "atoi", "atol", "atob", "setjmp",
57 "longjmp", "strcat", "strncat", "strcmp",
58 "strncmp", "strcpy", "strncpy", "strlen",
59 "index", "rindex", "strchr", "strrchr",
61 "strpbrk", "strspn", "strcspn", "strtok",
62 "strstr", "toupper", "tolower", "bcopy",
63 "bzero", "bcmp", "memcpy", "memset",
64 "memmove", "memcmp", "memchr", "rand",
66 "srand", "qsort", "strtod", "malloc",
67 "free", "lsearch", "bsearch", "calloc",
68 "realloc", "InitHeap", "_exit", "getchar",
69 "putchar", "gets", "puts", "printf",
71 "SystemErrorUnresolvedException", "LoadTest", "Load", "Exec",
72 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
73 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
74 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
76 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
77 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
78 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
79 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
81 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
82 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
83 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
84 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
86 "_bu_init", "_96_init", "CdRemove", "sys_a0_73",
87 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
88 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
89 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
91 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
92 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
93 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
94 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
96 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
97 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
98 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
99 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
101 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
102 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
103 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
104 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
106 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
110 char *biosB0n[256] = {
112 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
113 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
114 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
115 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
117 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
118 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
119 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
120 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
122 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
123 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
124 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
125 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
127 "sys_b0_30", "sys_b0_31", "open", "lseek",
128 "read", "write", "close", "ioctl",
129 "exit", "sys_b0_39", "getc", "putc",
130 "getchar", "putchar", "gets", "puts",
132 "cd", "format", "firstfile", "nextfile",
133 "rename", "delete", "undelete", "AddDevice",
134 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
135 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
137 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
138 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
139 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
140 "_card_status", "_card_wait",
143 char *biosC0n[256] = {
145 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
146 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
147 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
148 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
150 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
151 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
152 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
156 //#define r0 (psxRegs.GPR.n.r0)
157 #define at (psxRegs.GPR.n.at)
158 #define v0 (psxRegs.GPR.n.v0)
159 #define v1 (psxRegs.GPR.n.v1)
160 #define a0 (psxRegs.GPR.n.a0)
161 #define a1 (psxRegs.GPR.n.a1)
162 #define a2 (psxRegs.GPR.n.a2)
163 #define a3 (psxRegs.GPR.n.a3)
164 #define t0 (psxRegs.GPR.n.t0)
165 #define t1 (psxRegs.GPR.n.t1)
166 #define t2 (psxRegs.GPR.n.t2)
167 #define t3 (psxRegs.GPR.n.t3)
168 #define t4 (psxRegs.GPR.n.t4)
169 #define t5 (psxRegs.GPR.n.t5)
170 #define t6 (psxRegs.GPR.n.t6)
171 #define t7 (psxRegs.GPR.n.t7)
172 #define t8 (psxRegs.GPR.n.t8)
173 #define t9 (psxRegs.GPR.n.t9)
174 #define s0 (psxRegs.GPR.n.s0)
175 #define s1 (psxRegs.GPR.n.s1)
176 #define s2 (psxRegs.GPR.n.s2)
177 #define s3 (psxRegs.GPR.n.s3)
178 #define s4 (psxRegs.GPR.n.s4)
179 #define s5 (psxRegs.GPR.n.s5)
180 #define s6 (psxRegs.GPR.n.s6)
181 #define s7 (psxRegs.GPR.n.s7)
182 #define k0 (psxRegs.GPR.n.k0)
183 #define k1 (psxRegs.GPR.n.k1)
184 #define gp (psxRegs.GPR.n.gp)
185 #define sp (psxRegs.GPR.n.sp)
186 #define fp (psxRegs.GPR.n.fp)
187 #define ra (psxRegs.GPR.n.ra)
188 #define pc0 (psxRegs.pc)
190 #define Ra0 ((char *)PSXM(a0))
191 #define Ra1 ((char *)PSXM(a1))
192 #define Ra2 ((char *)PSXM(a2))
193 #define Ra3 ((char *)PSXM(a3))
194 #define Rv0 ((char *)PSXM(v0))
195 #define Rsp ((char *)PSXM(sp))
206 #define EvStUNUSED 0x0000
207 #define EvStDISABLED 0x1000
208 #define EvStACTIVE 0x2000
209 #define EvStALREADY 0x4000
211 #define EvMdCALL 0x1000
212 #define EvMdMARK 0x2000
235 u32 _sp, _fp, _gp, ret, base;
255 // todo: FileDesc layout is wrong
256 // todo: get rid of these globals
257 static FileDesc FDesc[32];
258 static char ffile[64];
260 static char cdir[8*8+8];
263 // fixed RAM offsets, SCPH1001 compatible
264 #define A_TT_ExCB 0x0100
265 #define A_TT_PCB 0x0108
266 #define A_TT_TCB 0x0110
267 #define A_TT_EvCB 0x0120
268 #define A_A0_TABLE 0x0200
269 #define A_B0_TABLE 0x0874
270 #define A_C0_TABLE 0x0674
271 #define A_SYSCALL 0x0650
272 #define A_EXCEPTION 0x0c80
273 #define A_EXC_SP 0x6cf0
274 #define A_EEXIT_DEF 0x6cf4
275 #define A_KMALLOC_PTR 0x7460
276 #define A_KMALLOC_SIZE 0x7464
277 #define A_KMALLOC_END 0x7468
278 #define A_PADCRD_CHN_E 0x74a8 // pad/card irq chain entry, see hleExcPadCard1()
279 #define A_PAD_IRQR_ENA 0x74b8 // pad read on vint irq (nocash 'pad_enable_flag')
280 #define A_CARD_IRQR_ENA 0x74bc // same for card
281 #define A_PAD_INBUF 0x74c8 // 2x buffers for rx pad data
282 #define A_PAD_OUTBUF 0x74d0 // 2x buffers for tx pad data
283 #define A_PAD_IN_LEN 0x74d8
284 #define A_PAD_OUT_LEN 0x74e0
285 #define A_PAD_DR_DST 0x74c4
286 #define A_CARD_CHAN1 0x7500
287 #define A_PAD_DR_BUF1 0x7570
288 #define A_PAD_DR_BUF2 0x7598
289 #define A_EEXIT_PTR 0x75d0
290 #define A_EXC_STACK 0x85d8 // exception stack top
291 #define A_RCNT_VBL_ACK 0x8600
292 #define A_PAD_ACK_VBL 0x8914 // enable vint ack by pad reading code
293 #define A_HEAP_BASE 0x9000
294 #define A_HEAP_SIZE 0x9004
295 #define A_HEAP_END 0x9008
296 #define A_HEAP_INIT_FLG 0x900c
297 #define A_RND_SEED 0x9010
298 #define A_HEAP_FRSTCHNK 0xb060
299 #define A_HEAP_CURCHNK 0xb064
300 #define A_CONF_TCB 0xb940
301 #define A_CONF_EvCB 0xb944
302 #define A_CONF_SP 0xb948
303 #define A_CD_EVENTS 0xb9b8
304 #define A_EXC_GP 0xf450
306 #define A_A0_DUMMY 0x1010
307 #define A_B0_DUMMY 0x2010
308 #define A_C0_DUMMY 0x3010
309 #define A_B0_5B_DUMMY 0x43d0
311 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
313 static u8 loadRam8(u32 addr)
315 assert(!(addr & 0x5f800000));
316 return psxM[addr & 0x1fffff];
319 static u32 loadRam32(u32 addr)
321 assert(!(addr & 0x5f800000));
322 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
325 static void *castRam8ptr(u32 addr)
327 assert(!(addr & 0x5f800000));
328 return psxM + (addr & 0x1fffff);
331 static void *castRam32ptr(u32 addr)
333 assert(!(addr & 0x5f800003));
334 return psxM + (addr & 0x1ffffc);
337 static void *loadRam8ptr(u32 addr)
339 return castRam8ptr(loadRam32(addr));
342 static void *loadRam32ptr(u32 addr)
344 return castRam32ptr(loadRam32(addr));
347 static void storeRam8(u32 addr, u8 d)
349 assert(!(addr & 0x5f800000));
350 *((u8 *)psxM + (addr & 0x1fffff)) = d;
353 static void storeRam32(u32 addr, u32 d)
355 assert(!(addr & 0x5f800000));
356 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
359 static void mips_return(u32 val)
365 static void mips_return_void(void)
370 static void use_cycles(u32 cycle)
372 psxRegs.cycle += cycle * 2;
375 static void mips_return_c(u32 val, u32 cycle)
381 static void mips_return_void_c(u32 cycle)
387 static int returned_from_exception(void)
389 // 0x80000080 means it took another exception just after return
390 return pc0 == k0 || pc0 == 0x80000080;
393 static inline void softCall(u32 pc) {
395 u32 ssr = psxRegs.CP0.n.SR;
399 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
401 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 = castRam8ptr(a0);
1483 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x40], a0, dir);
1484 if ((p = strchr(dir, ':')))
1488 snprintf(cdir, sizeof(cdir), "%s", dir);
1489 mips_return_c(1, 100);
1492 static void psxBios_format() { // 0x41
1493 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x41], a0, Ra0);
1494 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1496 CreateMcd(Config.Mcd1);
1497 LoadMcd(1, Config.Mcd1);
1500 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1502 CreateMcd(Config.Mcd2);
1503 LoadMcd(2, Config.Mcd2);
1513 static void psxBios_SystemErrorUnresolvedException() {
1514 if (floodchk != 0x12340a40) { // prevent log flood
1515 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1516 floodchk = 0x12340a40;
1518 mips_return_void_c(1000);
1521 static void FlushCache() {
1522 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1523 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1525 // runs from uncached mem so tons of cycles
1530 * long Load(char *name, struct EXEC *header);
1533 void psxBios_Load() { // 0x42
1541 PSXBIOS_LOG("psxBios_%s %x(%s), %x\n", biosA0n[0x42], a0, pa0, a1);
1542 if (pa0 == INVALID_PTR || pa1 == INVALID_PTR) {
1546 if ((p = strchr(pa0, ':')))
1551 snprintf(path, sizeof(path), "%s\\%s", cdir, (char *)pa0);
1553 snprintf(path, sizeof(path), "%s", (char *)pa0);
1555 if (LoadCdromFile(path, &eheader) == 0) {
1556 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1557 psxCpu->Clear(a1, sizeof(EXEC) / 4);
1561 PSXBIOS_LOG(" -> %d\n", v0);
1567 * int Exec(struct EXEC *header , int argc , char **argv);
1570 void psxBios_Exec() { // 43
1571 EXEC *header = (EXEC *)castRam32ptr(a0);
1575 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1577 header->_sp = SWAP32(sp);
1578 header->_fp = SWAP32(fp);
1579 header->_sp = SWAP32(sp);
1580 header->_gp = SWAP32(gp);
1581 header->ret = SWAP32(ra);
1582 header->base = SWAP32(s0);
1584 ptr = SWAP32(header->b_addr);
1585 len = SWAP32(header->b_size);
1591 if (header->S_addr != 0)
1592 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1594 gp = SWAP32(header->gp0);
1602 pc0 = SWAP32(header->_pc0);
1605 static void psxBios_FlushCache() { // 44
1606 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1611 void psxBios_GPU_dw() { // 0x46
1616 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1619 GPU_writeData(0xa0000000);
1620 GPU_writeData((a1<<0x10)|(a0&0xffff));
1621 GPU_writeData((a3<<0x10)|(a2&0xffff));
1623 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1626 GPU_writeData(SWAPu32(*ptr++));
1632 void psxBios_mem2vram() { // 0x47
1634 gpuSyncPluginSR(); // flush
1635 GPU_writeData(0xa0000000);
1636 GPU_writeData((a1<<0x10)|(a0&0xffff));
1637 GPU_writeData((a3<<0x10)|(a2&0xffff));
1638 size = ((((a2 * a3) / 2) >> 4) << 16);
1639 GPU_writeStatus(0x04000002);
1640 psxHwWrite32(0x1f8010f4,0);
1641 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1642 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1643 psxHwWrite32(0x1f8010a4, size | 0x10);
1644 psxHwWrite32(0x1f8010a8,0x01000201);
1649 void psxBios_SendGPU() { // 0x48
1650 GPU_writeStatus(a0);
1655 void psxBios_GPU_cw() { // 0x49
1662 void psxBios_GPU_cwb() { // 0x4a
1663 u32 *ptr = (u32*)Ra0;
1668 GPU_writeData(SWAPu32(*ptr++));
1674 void psxBios_GPU_SendPackets() { //4b:
1676 GPU_writeStatus(0x04000002);
1677 psxHwWrite32(0x1f8010f4,0);
1678 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1679 psxHwWrite32(0x1f8010a0,a0);
1680 psxHwWrite32(0x1f8010a4,0);
1681 psxHwWrite32(0x1f8010a8,0x010000401);
1685 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1686 psxHwWrite32(0x1f8010a8,0x00000401);
1687 GPU_writeData(0x0400000);
1688 GPU_writeData(0x0200000);
1689 GPU_writeData(0x0100000);
1694 void psxBios_GPU_GetGPUStatus() { // 0x4d
1695 v0 = GPU_readStatus();
1701 void psxBios_LoadExec() { // 51
1702 EXEC *header = (EXEC*)PSXM(0xf000);
1706 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1708 s_addr = a1; s_size = a2;
1713 header->S_addr = s_addr;
1714 header->s_size = s_size;
1716 a0 = 0xf000; a1 = 0; a2 = 0;
1720 void psxBios__bu_init() { // 70
1722 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1725 DeliverEvent(0xf0000011, 0x0004);
1726 DeliverEvent(0xf4000001, 0x0004);
1731 void psxBios__96_init() { // 71
1733 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1739 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1740 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1741 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1743 static void psxBios_DequeueCdIntr_() {
1744 psxBios_SysDeqIntRP_(0, 0x91d0);
1745 psxBios_SysDeqIntRP_(0, 0x91e0);
1749 static void psxBios_DequeueCdIntr() { // a3
1750 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1751 psxBios_DequeueCdIntr_();
1754 static void psxBios_CdRemove() { // 56, 72
1755 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1757 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1758 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1759 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1760 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1761 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1762 psxBios_DequeueCdIntr_();
1764 // EnterCriticalSection - should be done at the beginning,
1765 // but this way is much easier to implement
1771 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack);
1773 static void psxBios_SetConf() { // 9c
1774 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9c], a0, a1, a2);
1775 setup_tt(a1, a0, a2);
1776 psxRegs.CP0.n.SR |= 0x401;
1777 mips_return_void_c(500);
1780 static void psxBios_GetConf() { // 9d
1781 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9d], a0, a1, a2);
1782 storeRam32(a0, loadRam32(A_CONF_EvCB));
1783 storeRam32(a1, loadRam32(A_CONF_TCB));
1784 storeRam32(a2, loadRam32(A_CONF_SP));
1785 mips_return_void_c(10);
1788 void psxBios_SetMem() { // 9f
1789 u32 new = psxHu32(0x1060);
1792 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1797 psxHu32ref(0x1060) = SWAP32(new);
1798 psxMu32ref(0x060) = a0;
1799 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1803 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1804 psxMu32ref(0x060) = a0;
1805 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1808 PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
1815 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1816 static void psxBios_get_cd_status() // a6
1818 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
1823 static void psxBios__card_info() { // ab
1824 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1826 storeRam32(A_CARD_CHAN1, a0);
1833 if (McdDisable[port & 1])
1837 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
1842 if (McdDisable[0] && McdDisable[1])
1845 DeliverEvent(0xf0000011, 0x0004);
1846 // DeliverEvent(0xf4000001, 0x0004);
1847 DeliverEvent(0xf4000001, ret);
1851 void psxBios__card_load() { // ac
1853 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1856 storeRam32(A_CARD_CHAN1, a0);
1858 // DeliverEvent(0xf0000011, 0x0004);
1859 DeliverEvent(0xf4000001, 0x0004);
1864 static void psxBios_GetSystemInfo() { // b4
1866 //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
1867 SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
1870 case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
1871 case 2: ret = 0xbfc0012c; break;
1872 case 5: ret = loadRam32(0x60) << 10; break;
1874 mips_return_c(ret, 20);
1877 /* System calls B0 */
1879 static u32 psxBios_SysMalloc_(u32 size);
1881 static void psxBios_SysMalloc() { // B 00
1882 u32 ret = psxBios_SysMalloc_(a0);
1884 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1885 mips_return_c(ret, 33);
1888 void psxBios_SetRCnt() { // 02
1890 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1897 psxRcntWtarget(a0, a1);
1898 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1899 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1900 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1901 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1902 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1904 psxRcntWmode(a0, mode);
1909 void psxBios_GetRCnt() { // 03
1911 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1916 case 0: v0 = psxRcntRcount0(); break;
1917 case 1: v0 = psxRcntRcount1(); break;
1918 case 2: v0 = psxRcntRcount2(); break;
1919 case 3: v0 = 0; break;
1924 void psxBios_StartRCnt() { // 04
1926 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1930 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1931 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1935 void psxBios_StopRCnt() { // 05
1937 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1941 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1942 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1946 void psxBios_ResetRCnt() { // 06
1948 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1953 psxRcntWmode(a0, 0);
1954 psxRcntWtarget(a0, 0);
1955 psxRcntWcount(a0, 0);
1960 static u32 DeliverEvent(u32 class, u32 spec) {
1961 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1962 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1963 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1964 u32 i, lim = evcb_len / 0x1c;
1966 //printf("%s %08x %x\n", __func__, class, spec);
1967 for (i = 0; i < lim; i++, ev++) {
1969 if (SWAP32(ev->status) != EvStACTIVE)
1972 if (SWAP32(ev->class) != class)
1975 if (SWAP32(ev->spec) != spec)
1978 ret = SWAP32(ev->mode);
1979 if (ret == EvMdMARK) {
1980 ev->status = SWAP32(EvStALREADY);
1984 if (ret == EvMdCALL) {
1985 ret = SWAP32(ev->fhandler);
1998 static u32 UnDeliverEvent(u32 class, u32 spec) {
1999 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
2000 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
2001 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
2002 u32 i, lim = evcb_len / 0x1c;
2004 for (i = 0; i < lim; i++, ev++) {
2006 if (SWAP32(ev->status) != EvStALREADY)
2009 if (SWAP32(ev->class) != class)
2012 if (SWAP32(ev->spec) != spec)
2015 if (SWAP32(ev->mode) == EvMdMARK)
2016 ev->status = SWAP32(EvStACTIVE);
2022 static void psxBios_DeliverEvent() { // 07
2024 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
2026 ret = DeliverEvent(a0, a1);
2030 static s32 get_free_EvCB_slot() {
2031 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
2032 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
2035 for (i = 0; i < lim; i++, ev++) {
2037 if (ev->status == SWAP32(EvStUNUSED))
2043 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
2044 u32 ret = get_free_EvCB_slot();
2045 if ((s32)ret >= 0) {
2046 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
2047 ev->class = SWAP32(class);
2048 ev->status = SWAP32(EvStDISABLED);
2049 ev->spec = SWAP32(spec);
2050 ev->mode = SWAP32(mode);
2051 ev->fhandler = SWAP32(func);
2057 static void psxBios_OpenEvent() { // 08
2058 u32 ret = OpenEvent(a0, a1, a2, a3);
2059 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
2060 biosB0n[0x08], a0, a1, a2, a3, ret);
2061 mips_return_c(ret, 36);
2064 static void CloseEvent(u32 ev)
2066 u32 base = loadRam32(A_TT_EvCB);
2067 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
2070 static void psxBios_CloseEvent() { // 09
2071 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
2072 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
2074 mips_return_c(1, 10);
2077 static void psxBios_WaitEvent() { // 0a
2078 u32 base = loadRam32(A_TT_EvCB);
2079 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2080 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
2083 if (status == EvStALREADY) {
2084 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2088 if (status != EvStACTIVE)
2090 mips_return_c(0, 2);
2094 // retrigger this hlecall after the next emulation event
2096 if ((s32)(next_interupt - psxRegs.cycle) > 0)
2097 psxRegs.cycle = next_interupt;
2101 static void psxBios_TestEvent() { // 0b
2102 u32 base = loadRam32(A_TT_EvCB);
2103 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2106 if (psxRegs.cycle - floodchk > 16*1024u) { // prevent log flood
2107 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
2108 floodchk = psxRegs.cycle;
2110 if (status == EvStALREADY) {
2111 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2115 mips_return_c(ret, 15);
2118 static void psxBios_EnableEvent() { // 0c
2119 u32 base = loadRam32(A_TT_EvCB);
2120 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2121 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
2122 if (status != EvStUNUSED)
2123 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2125 mips_return_c(1, 15);
2128 static void psxBios_DisableEvent() { // 0d
2129 u32 base = loadRam32(A_TT_EvCB);
2130 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2131 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2132 if (status != EvStUNUSED)
2133 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2135 mips_return_c(1, 15);
2139 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2142 void psxBios_OpenTh() { // 0e
2143 TCB *tcb = loadRam32ptr(A_TT_TCB);
2144 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2147 for (th = 1; th < limit; th++)
2149 if (tcb[th].status != SWAP32(0x4000)) break;
2153 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2154 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2156 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2158 mips_return_c(0xffffffff, 20);
2161 PSXBIOS_LOG("psxBios_%s -> %x\n", biosB0n[0x0e], 0xff000000 + th);
2163 tcb[th].status = SWAP32(0x4000);
2164 tcb[th].mode = SWAP32(0x1000);
2165 tcb[th].epc = SWAP32(a0);
2166 tcb[th].reg[30] = SWAP32(a1); // fp
2167 tcb[th].reg[29] = SWAP32(a1); // sp
2168 tcb[th].reg[28] = SWAP32(a2); // gp
2170 mips_return_c(0xff000000 + th, 34);
2174 * int CloseTh(long thread);
2177 static void psxBios_CloseTh() { // 0f
2178 u32 tcb = loadRam32(A_TT_TCB);
2179 u32 th = a0 & 0xffff;
2181 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x0f], a0);
2182 // in the usual bios fashion no checks, just write and return 1
2183 storeRam32(tcb + th * sizeof(TCB), 0x1000);
2185 mips_return_c(1, 11);
2189 * int ChangeTh(long thread);
2192 void psxBios_ChangeTh() { // 10
2193 u32 tcbBase = loadRam32(A_TT_TCB);
2194 u32 th = a0 & 0xffff;
2196 // this is quite spammy
2197 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2199 // without doing any argument checks, just issue a syscall
2200 // (like the real bios does)
2202 a1 = tcbBase + th * sizeof(TCB);
2207 void psxBios_InitPAD() { // 0x12
2208 u32 i, *ram32 = (u32 *)psxM;
2209 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2211 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2212 ram32[A_PAD_DR_DST/4] = 0;
2213 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2214 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2215 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2216 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2217 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2218 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2219 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2220 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2222 for (i = 0; i < a1; i++) {
2224 storeRam8(a0 + i, 0);
2226 for (i = 0; i < a3; i++) {
2228 storeRam8(a2 + i, 0);
2230 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2232 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2234 mips_return_c(1, 200);
2237 void psxBios_StartPAD() { // 13
2238 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2240 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2241 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2242 psxHwWrite16(0x1f801070, ~1);
2243 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2244 storeRam32(A_PAD_ACK_VBL, 1);
2245 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2246 psxRegs.CP0.n.SR |= 0x401;
2248 mips_return_c(1, 300);
2251 void psxBios_StopPAD() { // 14
2252 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2253 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2254 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2255 psxRegs.CP0.n.SR |= 0x401;
2256 mips_return_void_c(200);
2259 static void psxBios_PAD_init() { // 15
2261 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2262 if (a0 == 0x20000000 || a0 == 0x20000001)
2265 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2266 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2269 storeRam32(A_PAD_DR_DST, dst);
2272 mips_return_c(ret, 100);
2275 static u32 psxBios_PAD_dr_() {
2276 u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2277 u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2278 u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2279 dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2280 if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2282 dst[0] = buf1[3], dst[1] = buf1[2];
2283 if (buf1[1] == 0x23) {
2284 dst[0] |= 0xc7, dst[1] |= 7;
2285 if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2286 if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2289 if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2291 dst[2] = buf2[3], dst[3] = buf2[2];
2292 if (buf2[1] == 0x23) {
2293 dst[2] |= 0xc7, dst[3] |= 7;
2294 if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2295 if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2299 return SWAP32(*(u32 *)dst);
2302 static void psxBios_PAD_dr() { // 16
2303 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2304 u32 ret = psxBios_PAD_dr_();
2308 static void psxBios_ReturnFromException() { // 17
2309 u32 tcbPtr = loadRam32(A_TT_PCB);
2310 const TCB *tcb = loadRam32ptr(tcbPtr);
2314 for (i = 1; i < 32; i++)
2315 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2316 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2317 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2318 sr = SWAP32(tcb->sr);
2320 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2321 pc0 = k0 = SWAP32(tcb->epc);
2323 // the interpreter wants to know about sr changes, so do a MTC0
2324 sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2325 MTC0(&psxRegs, 12, sr);
2331 void psxBios_ResetEntryInt() { // 18
2332 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2334 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2335 mips_return_void_c(5);
2338 void psxBios_HookEntryInt() { // 19
2339 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2341 storeRam32(A_EEXIT_PTR, a0);
2342 mips_return_void_c(3);
2345 static void psxBios_UnDeliverEvent() { // 0x20
2347 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2349 ret = UnDeliverEvent(a0, a1);
2353 static void buopen(int mcd, char *ptr, char *cfg)
2356 char *mcd_data = ptr;
2358 strcpy(FDesc[1 + mcd].name, Ra0+5);
2359 FDesc[1 + mcd].offset = 0;
2360 FDesc[1 + mcd].mode = a1;
2362 for (i=1; i<16; i++) {
2363 const char *fptr = mcd_data + 128 * i;
2364 if ((*fptr & 0xF0) != 0x50) continue;
2365 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2366 FDesc[1 + mcd].mcfile = i;
2367 PSXBIOS_LOG("open %s\n", fptr+0xa);
2371 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2372 for (i=1; i<16; i++) {
2373 int j, xor, nblk = a1 >> 16;
2375 char *fptr = mcd_data + 128 * i;
2377 if ((*fptr & 0xF0) != 0xa0) continue;
2379 FDesc[1 + mcd].mcfile = i;
2382 fptr[5] = 0x20 * nblk;
2385 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2386 pptr = fptr2 = fptr;
2387 for(j=2; j<=nblk; j++) {
2389 for(i++; i<16; i++) {
2392 memset(fptr2, 0, 128);
2393 fptr2[0] = j < nblk ? 0x52 : 0x53;
2396 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2401 /* shouldn't this return ENOSPC if i == 16? */
2403 pptr[8] = pptr[9] = 0xff;
2404 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2406 PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2408 /* just go ahead and resave them all */
2409 SaveMcd(cfg, ptr, 128, 128 * 15);
2412 /* shouldn't this return ENOSPC if i == 16? */
2417 * int open(char *name , int mode);
2420 void psxBios_open() { // 0x32
2423 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x32], Ra0, a1);
2427 if (pa0 != INVALID_PTR) {
2428 if (!strncmp(pa0, "bu00", 4)) {
2429 buopen(1, Mcd1Data, Config.Mcd1);
2432 if (!strncmp(pa0, "bu10", 4)) {
2433 buopen(2, Mcd2Data, Config.Mcd2);
2441 * int lseek(int fd , int offset , int whence);
2444 void psxBios_lseek() { // 0x33
2446 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2451 FDesc[a0].offset = a1;
2453 // DeliverEvent(0xf0000011, 0x0004);
2454 // DeliverEvent(0xf4000001, 0x0004);
2458 FDesc[a0].offset+= a1;
2459 v0 = FDesc[a0].offset;
2468 * int read(int fd , void *buf , int nbytes);
2471 void psxBios_read() { // 0x34
2476 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2481 if (pa1 != INVALID_PTR) {
2483 case 2: buread(pa1, 1, a2); break;
2484 case 3: buread(pa1, 2, a2); break;
2492 * int write(int fd , void *buf , int nbytes);
2495 void psxBios_write() { // 0x35/0x03
2499 if (a0 != 1) // stdout
2500 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2503 if (pa1 == INVALID_PTR) {
2508 if (a0 == 1) { // stdout
2512 if (Config.PsxOut) while (a2 > 0) {
2513 SysPrintf("%c", *ptr++); a2--;
2519 case 2: buwrite(pa1, 1, a2); break;
2520 case 3: buwrite(pa1, 2, a2); break;
2526 static void psxBios_write_psxout() {
2527 if (a0 == 1) { // stdout
2528 const char *ptr = Ra1;
2531 if (ptr != INVALID_PTR)
2533 SysPrintf("%c", *ptr++);
2537 static void psxBios_putchar_psxout() { // 3d
2538 SysPrintf("%c", (char)a0);
2541 static void psxBios_puts_psxout() { // 3e/3f
2542 SysPrintf("%s", Ra0);
2546 * int close(int fd);
2549 void psxBios_close() { // 0x36
2551 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2558 void psxBios_putchar() { // 3d
2559 if (Config.PsxOut) SysPrintf("%c", (char)a0);
2563 void psxBios_puts() { // 3e/3f
2564 if (Config.PsxOut) SysPrintf("%s", Ra0);
2568 static void bufile(const u8 *mcd_data, u32 dir_) {
2569 struct DIRENTRY *dir = (struct DIRENTRY *)castRam8ptr(dir_);
2570 const char *pfile = ffile + 5;
2571 const u8 *data = mcd_data;
2572 int i = 0, match = 0;
2577 for (; nfile <= 15 && !match; nfile++) {
2580 head = nfile * 0x40;
2581 data = mcd_data + 128 * nfile;
2582 name = (const char *)data + 0x0a;
2583 if ((data[0] & 0xF0) != 0x50) continue;
2584 /* Bug link files show up as free block. */
2585 if (!name[0]) continue;
2587 for (i = 0; i < 20; i++) {
2588 if (pfile[i] == name[i] || pfile[i] == '?')
2589 dir->name[i] = name[i];
2590 else if (pfile[i] == '*') {
2591 int len = strlen(name + i);
2594 memcpy(dir->name + i, name + i, len + 1);
2605 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n",
2606 nfile, dir->name, pfile, name, match);
2608 for (; nfile <= 15; nfile++, blocks++) {
2609 const u8 *data2 = mcd_data + 128 * nfile;
2610 const char *name = (const char *)data2 + 0x0a;
2611 if ((data2[0] & 0xF0) != 0x50 || name[0])
2615 // nul char of full lenth name seems to overwrite .attr
2616 dir->attr = SWAP32(i < 20 ? data[0] & 0xf0 : 0); // ?
2617 dir->size = 8192 * blocks;
2621 PSXBIOS_LOG(" -> %x '%s' %x %x %x %x\n", v0, v0 ? dir->name : "",
2622 dir->attr, dir->size, dir->next, dir->head);
2626 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2629 static void psxBios_firstfile() { // 42
2630 char *pa0 = castRam8ptr(a0);
2632 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x42], pa0, a1);
2636 snprintf(ffile, sizeof(ffile), "%s", pa0);
2638 strcpy(ffile + 5, "*"); // maybe?
2640 if (!strncmp(pa0, "bu00", 4)) {
2641 // firstfile() calls _card_read() internally, so deliver it's event
2642 DeliverEvent(0xf0000011, 0x0004);
2643 bufile((u8 *)Mcd1Data, a1);
2644 } else if (!strncmp(pa0, "bu10", 4)) {
2645 // firstfile() calls _card_read() internally, so deliver it's event
2646 DeliverEvent(0xf0000011, 0x0004);
2647 bufile((u8 *)Mcd2Data, a1);
2655 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2658 void psxBios_nextfile() { // 43
2659 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x43], a0);
2662 if (!strncmp(ffile, "bu00", 4))
2663 bufile((u8 *)Mcd1Data, a0);
2664 else if (!strncmp(ffile, "bu10", 4))
2665 bufile((u8 *)Mcd2Data, a0);
2670 #define burename(mcd) { \
2671 for (i=1; i<16; i++) { \
2672 int namelen, j, xor = 0; \
2673 ptr = Mcd##mcd##Data + 128 * i; \
2674 if ((*ptr & 0xF0) != 0x50) continue; \
2675 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2676 namelen = strlen(Ra1+5); \
2677 memcpy(ptr+0xa, Ra1+5, namelen); \
2678 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2679 for (j=0; j<127; j++) xor^= ptr[j]; \
2681 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2688 * int rename(char *old, char *new);
2691 void psxBios_rename() { // 44
2698 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2703 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2704 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2708 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2717 #define budelete(mcd) { \
2718 for (i=1; i<16; i++) { \
2719 ptr = Mcd##mcd##Data + 128 * i; \
2720 if ((*ptr & 0xF0) != 0x50) continue; \
2721 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2722 *ptr = (*ptr & 0xf) | 0xA0; \
2723 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2724 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2731 * int delete(char *name);
2734 void psxBios_delete() { // 45
2740 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2745 if (pa0 != INVALID_PTR) {
2746 if (!strncmp(pa0, "bu00", 4)) {
2750 if (!strncmp(pa0, "bu10", 4)) {
2758 void psxBios_InitCARD() { // 4a
2759 u32 *ram32 = (u32 *)psxM;
2760 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2761 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2762 // (maybe) todo: early_card_irq, etc
2764 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2766 psxBios_FlushCache();
2767 mips_return_c(0, 34+13+15+6);
2770 void psxBios_StartCARD() { // 4b
2771 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2772 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2773 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2775 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2776 storeRam32(A_PAD_ACK_VBL, 1);
2777 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2778 storeRam32(A_CARD_IRQR_ENA, 1);
2779 psxRegs.CP0.n.SR |= 0x401;
2781 mips_return_c(1, 200);
2784 void psxBios_StopCARD() { // 4c
2785 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2786 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2787 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2788 storeRam32(A_CARD_IRQR_ENA, 0);
2789 psxRegs.CP0.n.SR |= 0x401;
2790 mips_return_void_c(200);
2793 void psxBios__card_write() { // 0x4e
2798 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2801 Function also accepts sector 400h (a bug).
2802 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2806 /* Invalid sectors */
2810 storeRam32(A_CARD_CHAN1, a0);
2813 if (pa2 != INVALID_PTR) {
2815 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2816 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2818 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2819 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2823 DeliverEvent(0xf0000011, 0x0004);
2824 // DeliverEvent(0xf4000001, 0x0004);
2829 void psxBios__card_read() { // 0x4f
2834 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2837 Function also accepts sector 400h (a bug).
2838 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2842 /* Invalid sectors */
2846 storeRam32(A_CARD_CHAN1, a0);
2849 if (pa2 != INVALID_PTR) {
2851 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2853 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2857 DeliverEvent(0xf0000011, 0x0004);
2858 // DeliverEvent(0xf4000001, 0x0004);
2863 void psxBios__new_card() { // 0x50
2865 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2871 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2872 void psxBios__get_error(void) // 55
2874 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2879 void psxBios_Krom2RawAdd() { // 0x51
2882 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2883 const u32 table_8140[][2] = {
2884 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2885 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2886 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2887 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2888 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2889 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2890 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2891 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2892 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2896 const u32 table_889f[][2] = {
2897 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2898 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2899 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2900 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2901 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2902 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2903 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2904 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2908 if (a0 >= 0x8140 && a0 <= 0x84be) {
2909 while (table_8140[i][0] <= a0) i++;
2910 a0 -= table_8140[i - 1][0];
2911 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2912 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2913 while (table_889f[i][0] <= a0) i++;
2914 a0 -= table_889f[i - 1][0];
2915 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2923 void psxBios_GetC0Table() { // 56
2924 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2925 log_unhandled("GetC0Table @%08x\n", ra);
2927 mips_return_c(A_C0_TABLE, 3);
2930 void psxBios_GetB0Table() { // 57
2931 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2932 log_unhandled("GetB0Table @%08x\n", ra);
2934 mips_return_c(A_B0_TABLE, 3);
2937 static void psxBios__card_chan() { // 0x58
2939 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2941 // todo: should return active slot chan
2942 // (active - which was last processed by irq code)
2943 ret = loadRam32(A_CARD_CHAN1);
2944 mips_return_c(ret, 8);
2947 static void psxBios_ChangeClearPad() { // 5b
2949 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2950 ret = loadRam32(A_PAD_ACK_VBL);
2951 storeRam32(A_PAD_ACK_VBL, a0);
2953 mips_return_c(ret, 6);
2956 static void psxBios__card_status() { // 5c
2957 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
2963 static void psxBios__card_wait() { // 5d
2964 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
2970 /* System calls C0 */
2972 static void psxBios_InitRCnt() { // 00
2974 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2975 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2976 for (i = 0; i < 3; i++) {
2977 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2978 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2979 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2981 psxBios_SysEnqIntRP_(a0, 0x6d88);
2982 mips_return_c(0, 9);
2985 static void psxBios_InitException() { // 01
2986 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2987 psxBios_SysEnqIntRP_(a0, 0x6da8);
2988 mips_return_c(0, 9);
2992 * int SysEnqIntRP(int index , long *queue);
2995 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2996 u32 old, base = loadRam32(A_TT_ExCB);
2998 old = loadRam32(base + (priority << 3));
2999 storeRam32(base + (priority << 3), chain_eptr);
3000 storeRam32(chain_eptr, old);
3001 mips_return_c(0, 9);
3004 static void psxBios_SysEnqIntRP() { // 02
3005 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
3006 psxBios_SysEnqIntRP_(a0, a1);
3010 * int SysDeqIntRP(int index , long *queue);
3013 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
3014 u32 ptr, next, base = loadRam32(A_TT_ExCB);
3015 u32 lim = 0, ret = 0;
3017 // as in original: no arg checks of any kind, bug if a1 == 0
3018 ptr = loadRam32(base + (priority << 3));
3020 next = loadRam32(ptr);
3021 if (ptr == chain_rm_eptr) {
3022 storeRam32(base + (priority << 3), next);
3027 while (next && next != chain_rm_eptr && lim++ < 100) {
3029 next = loadRam32(ptr);
3032 if (next == chain_rm_eptr) {
3033 next = loadRam32(next);
3034 storeRam32(ptr, next);
3041 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
3043 mips_return_c(ret, 12);
3046 static void psxBios_SysDeqIntRP() { // 03
3047 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
3048 psxBios_SysDeqIntRP_(a0, a1);
3051 static void psxBios_get_free_EvCB_slot() { // 04
3052 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
3053 s32 ret = get_free_EvCB_slot();
3054 mips_return_c(ret, 0);
3057 static void psxBios_SysInitMemory_(u32 base, u32 size) {
3058 storeRam32(base, 0);
3059 storeRam32(A_KMALLOC_PTR, base);
3060 storeRam32(A_KMALLOC_SIZE, size);
3061 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
3064 // this should be much more complicated, but maybe that'll be enough
3065 static u32 psxBios_SysMalloc_(u32 size) {
3066 u32 ptr = loadRam32(A_KMALLOC_PTR);
3068 size = (size + 3) & ~3;
3069 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
3070 storeRam32(ptr, size);
3074 static void psxBios_SysInitMemory() { // 08
3075 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
3077 psxBios_SysInitMemory_(a0, a1);
3078 mips_return_void_c(12);
3081 static void psxBios_ChangeClearRCnt() { // 0a
3084 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
3086 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
3087 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
3088 mips_return_c(ret, 8);
3091 static void psxBios_InitDefInt() { // 0c
3092 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3093 // should also clear the autoack table
3094 psxBios_SysEnqIntRP_(a0, 0x6d98);
3095 mips_return_c(0, 20 + 6*2);
3098 void psxBios_dummy() {
3099 u32 pc = (pc0 & 0x1fffff) - 4;
3100 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
3101 : pc == 0xc0 ? biosC0n : NULL;
3102 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
3103 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
3104 (void)pc; (void)ntab;
3105 mips_return_c(0, 100);
3108 void (*biosA0[256])();
3109 // C0 and B0 overlap (end of C0 is start of B0)
3110 void (*biosC0[256+128])();
3111 void (**biosB0)() = biosC0 + 128;
3113 static void setup_mips_code()
3116 ptr = (u32 *)&psxM[A_SYSCALL];
3117 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3118 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
3119 ptr[0x08/4] = SWAPu32(0x00000000); // nop
3121 ptr = (u32 *)&psxM[A_EXCEPTION];
3122 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
3123 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
3124 ptr[0x14/4] = SWAPu32(0x00000000); // nop
3125 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
3126 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3127 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
3128 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
3129 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
3130 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
3131 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
3133 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
3134 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
3135 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
3137 ptr[0xb0/4] = HLEOP(hleop_exception);
3140 static const struct {
3144 { 0xbfc050a4, hleop_exc0_0_1 },
3145 { 0xbfc04fbc, hleop_exc0_0_2 },
3146 { 0xbfc0506c, hleop_exc0_1_1 },
3147 { 0xbfc04dec, hleop_exc0_1_2 },
3148 { 0x1a00, hleop_exc0_2_2 },
3149 { 0x19c8, hleop_exc1_0_1 },
3150 { 0x18bc, hleop_exc1_0_2 },
3151 { 0x1990, hleop_exc1_1_1 },
3152 { 0x1858, hleop_exc1_1_2 },
3153 { 0x1958, hleop_exc1_2_1 },
3154 { 0x17f4, hleop_exc1_2_2 },
3155 { 0x1920, hleop_exc1_3_1 },
3156 { 0x1794, hleop_exc1_3_2 },
3157 { 0x2458, hleop_exc3_0_2 },
3158 { 0x49bc, hleop_exc_padcard1 },
3159 { 0x4a4c, hleop_exc_padcard2 },
3162 static int chain_hle_op(u32 handler)
3166 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3167 if (chainfns[i].addr == handler)
3168 return chainfns[i].op;
3172 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3174 d[0] = SWAPu32(next);
3175 d[1] = SWAPu32(handler1);
3176 d[2] = SWAPu32(handler2);
3178 // install the hle traps
3179 if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3180 if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3183 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack)
3185 u32 *ram32 = (u32 *)psxM;
3186 u32 s_excb = 0x20, s_evcb, s_pcb = 4, s_tcb;
3187 u32 p_excb, p_evcb, p_pcb, p_tcb;
3190 PSXBIOS_LOG("setup: tcb %u, evcb %u\n", tcb_cnt, evcb_cnt);
3192 // the real bios doesn't care, but we just don't
3193 // want to crash in case of garbage parameters
3194 if (tcb_cnt > 1024) tcb_cnt = 1024;
3195 if (evcb_cnt > 1024) evcb_cnt = 1024;
3196 s_evcb = 0x1c * evcb_cnt;
3197 s_tcb = 0xc0 * tcb_cnt;
3199 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3200 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3201 p_excb = psxBios_SysMalloc_(s_excb);
3202 p_evcb = psxBios_SysMalloc_(s_evcb);
3203 p_pcb = psxBios_SysMalloc_(s_pcb);
3204 p_tcb = psxBios_SysMalloc_(s_tcb);
3206 // "table of tables". Some games modify it
3207 assert(A_TT_ExCB == 0x0100);
3208 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3209 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3210 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3211 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3212 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3213 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3214 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3215 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3216 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3217 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3218 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3219 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3221 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3222 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3223 storeRam32(p_excb + 4*4, 0x0000); // chain2
3224 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3226 storeRam32(p_pcb, p_tcb);
3227 storeRam32(p_tcb, 0x4000); // first TCB
3228 for (i = 1; i < tcb_cnt; i++)
3229 storeRam32(p_tcb + sizeof(TCB) * i, 0x1000);
3232 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3233 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3234 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3235 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3236 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3238 storeRam32(A_CONF_EvCB, evcb_cnt);
3239 storeRam32(A_CONF_TCB, tcb_cnt);
3240 storeRam32(A_CONF_SP, stack);
3243 static const u32 gpu_ctl_def[] = {
3244 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3245 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3248 static const u32 gpu_data_def[] = {
3249 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3250 0xe5001000, 0xe6000000,
3251 0x02000000, 0x00000000, 0x01ff03ff
3255 static const u16 spu_config[] = {
3256 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3257 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3258 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3259 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3260 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3261 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3262 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3263 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3266 void psxBiosSetupBootState(void)
3268 boolean hle = Config.HLE;
3269 u32 *hw = (u32 *)psxH;
3272 // see also SetBootRegs()
3275 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3276 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3278 k0 = 0xbfc0d968; k1 = 0xf1c;
3279 ra = 0xf0001234; // just to easily detect attempts to return
3280 psxRegs.CP0.n.Cause = 0x20;
3281 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3283 hw[0x1000/4] = SWAP32(0x1f000000);
3284 hw[0x1004/4] = SWAP32(0x1f802000);
3285 hw[0x1008/4] = SWAP32(0x0013243f);
3286 hw[0x100c/4] = SWAP32(0x00003022);
3287 hw[0x1010/4] = SWAP32(0x0013243f);
3288 hw[0x1014/4] = SWAP32(0x200931e1);
3289 hw[0x1018/4] = SWAP32(0x00020943);
3290 hw[0x101c/4] = SWAP32(0x00070777);
3291 hw[0x1020/4] = SWAP32(0x0000132c);
3292 hw[0x1060/4] = SWAP32(0x00000b88);
3293 hw[0x1070/4] = SWAP32(0x00000001);
3294 hw[0x1074/4] = SWAP32(0x0000000c);
3295 hw[0x2040/4] = SWAP32(0x00000900);
3298 hw[0x10a0/4] = SWAP32(0x00ffffff);
3299 hw[0x10a8/4] = SWAP32(0x00000401);
3300 hw[0x10b0/4] = SWAP32(0x0008b000);
3301 hw[0x10b4/4] = SWAP32(0x00010200);
3302 hw[0x10e0/4] = SWAP32(0x000eccf4);
3303 hw[0x10e4/4] = SWAP32(0x00000400);
3304 hw[0x10e8/4] = SWAP32(0x00000002);
3305 hw[0x10f0/4] = SWAP32(0x00009099);
3306 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3315 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3316 GPU_writeStatus(gpu_ctl_def[i]);
3317 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3318 GPU_writeData(gpu_data_def[i]);
3319 HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
3322 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3323 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3326 static void hleExc0_0_1();
3327 static void hleExc0_0_2();
3328 static void hleExc0_1_1();
3329 static void hleExc0_1_2();
3331 #include "sjisfont.h"
3333 void psxBiosInit() {
3334 u32 *ptr, *ram32, *rom32;
3339 psxRegs.biosBranchCheck = ~0;
3341 memset(psxM, 0, 0x10000);
3342 for(i = 0; i < 256; i++) {
3347 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3348 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3349 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3350 biosA0[0x3f] = psxBios_printf_psxout;
3353 char verstr[0x24+1];
3354 rom32 = (u32 *)psxR;
3355 memcpy(verstr, psxR + 0x12c, 0x24);
3357 SysPrintf("BIOS: %08x, '%s', '%c'\n", SWAP32(rom32[0x100/4]),
3358 verstr, psxR[0x7ff52]);
3362 for(i = 0; i < 256; i++) {
3363 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3364 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3365 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3368 biosA0[0x00] = psxBios_open;
3369 biosA0[0x01] = psxBios_lseek;
3370 biosA0[0x02] = psxBios_read;
3371 biosA0[0x03] = psxBios_write;
3372 biosA0[0x04] = psxBios_close;
3373 //biosA0[0x05] = psxBios_ioctl;
3374 //biosA0[0x06] = psxBios_exit;
3375 //biosA0[0x07] = psxBios_sys_a0_07;
3376 biosA0[0x08] = psxBios_getc;
3377 biosA0[0x09] = psxBios_putc;
3378 biosA0[0x0a] = psxBios_todigit;
3379 //biosA0[0x0b] = psxBios_atof;
3380 //biosA0[0x0c] = psxBios_strtoul;
3381 //biosA0[0x0d] = psxBios_strtol;
3382 biosA0[0x0e] = psxBios_abs;
3383 biosA0[0x0f] = psxBios_labs;
3384 biosA0[0x10] = psxBios_atoi;
3385 biosA0[0x11] = psxBios_atol;
3386 //biosA0[0x12] = psxBios_atob;
3387 biosA0[0x13] = psxBios_setjmp;
3388 biosA0[0x14] = psxBios_longjmp;
3389 biosA0[0x15] = psxBios_strcat;
3390 biosA0[0x16] = psxBios_strncat;
3391 biosA0[0x17] = psxBios_strcmp;
3392 biosA0[0x18] = psxBios_strncmp;
3393 biosA0[0x19] = psxBios_strcpy;
3394 biosA0[0x1a] = psxBios_strncpy;
3395 biosA0[0x1b] = psxBios_strlen;
3396 biosA0[0x1c] = psxBios_index;
3397 biosA0[0x1d] = psxBios_rindex;
3398 biosA0[0x1e] = psxBios_strchr;
3399 biosA0[0x1f] = psxBios_strrchr;
3400 biosA0[0x20] = psxBios_strpbrk;
3401 biosA0[0x21] = psxBios_strspn;
3402 biosA0[0x22] = psxBios_strcspn;
3403 biosA0[0x23] = psxBios_strtok;
3404 biosA0[0x24] = psxBios_strstr;
3405 biosA0[0x25] = psxBios_toupper;
3406 biosA0[0x26] = psxBios_tolower;
3407 biosA0[0x27] = psxBios_bcopy;
3408 biosA0[0x28] = psxBios_bzero;
3409 biosA0[0x29] = psxBios_bcmp;
3410 biosA0[0x2a] = psxBios_memcpy;
3411 biosA0[0x2b] = psxBios_memset;
3412 biosA0[0x2c] = psxBios_memmove;
3413 biosA0[0x2d] = psxBios_memcmp;
3414 biosA0[0x2e] = psxBios_memchr;
3415 biosA0[0x2f] = psxBios_rand;
3416 biosA0[0x30] = psxBios_srand;
3417 biosA0[0x31] = psxBios_qsort;
3418 //biosA0[0x32] = psxBios_strtod;
3419 biosA0[0x33] = psxBios_malloc;
3420 biosA0[0x34] = psxBios_free;
3421 //biosA0[0x35] = psxBios_lsearch;
3422 //biosA0[0x36] = psxBios_bsearch;
3423 biosA0[0x37] = psxBios_calloc;
3424 biosA0[0x38] = psxBios_realloc;
3425 biosA0[0x39] = psxBios_InitHeap;
3426 //biosA0[0x3a] = psxBios__exit;
3427 biosA0[0x3b] = psxBios_getchar;
3428 biosA0[0x3c] = psxBios_putchar;
3429 //biosA0[0x3d] = psxBios_gets;
3430 biosA0[0x3e] = psxBios_puts;
3431 biosA0[0x3f] = psxBios_printf;
3432 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3433 //biosA0[0x41] = psxBios_LoadTest;
3434 biosA0[0x42] = psxBios_Load;
3435 biosA0[0x43] = psxBios_Exec;
3436 biosA0[0x44] = psxBios_FlushCache;
3437 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3438 biosA0[0x46] = psxBios_GPU_dw;
3439 biosA0[0x47] = psxBios_mem2vram;
3440 biosA0[0x48] = psxBios_SendGPU;
3441 biosA0[0x49] = psxBios_GPU_cw;
3442 biosA0[0x4a] = psxBios_GPU_cwb;
3443 biosA0[0x4b] = psxBios_GPU_SendPackets;
3444 biosA0[0x4c] = psxBios_sys_a0_4c;
3445 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3446 //biosA0[0x4e] = psxBios_GPU_sync;
3447 //biosA0[0x4f] = psxBios_sys_a0_4f;
3448 //biosA0[0x50] = psxBios_sys_a0_50;
3449 biosA0[0x51] = psxBios_LoadExec;
3450 //biosA0[0x52] = psxBios_GetSysSp;
3451 //biosA0[0x53] = psxBios_sys_a0_53;
3452 //biosA0[0x54] = psxBios__96_init_a54;
3453 //biosA0[0x55] = psxBios__bu_init_a55;
3454 biosA0[0x56] = psxBios_CdRemove;
3455 //biosA0[0x57] = psxBios_sys_a0_57;
3456 //biosA0[0x58] = psxBios_sys_a0_58;
3457 //biosA0[0x59] = psxBios_sys_a0_59;
3458 //biosA0[0x5a] = psxBios_sys_a0_5a;
3459 //biosA0[0x5b] = psxBios_dev_tty_init;
3460 //biosA0[0x5c] = psxBios_dev_tty_open;
3461 //biosA0[0x5d] = psxBios_sys_a0_5d;
3462 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3463 //biosA0[0x5f] = psxBios_dev_cd_open;
3464 //biosA0[0x60] = psxBios_dev_cd_read;
3465 //biosA0[0x61] = psxBios_dev_cd_close;
3466 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3467 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3468 //biosA0[0x64] = psxBios_dev_cd_chdir;
3469 //biosA0[0x65] = psxBios_dev_card_open;
3470 //biosA0[0x66] = psxBios_dev_card_read;
3471 //biosA0[0x67] = psxBios_dev_card_write;
3472 //biosA0[0x68] = psxBios_dev_card_close;
3473 //biosA0[0x69] = psxBios_dev_card_firstfile;
3474 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3475 //biosA0[0x6b] = psxBios_dev_card_erase;
3476 //biosA0[0x6c] = psxBios_dev_card_undelete;
3477 //biosA0[0x6d] = psxBios_dev_card_format;
3478 //biosA0[0x6e] = psxBios_dev_card_rename;
3479 //biosA0[0x6f] = psxBios_dev_card_6f;
3480 biosA0[0x70] = psxBios__bu_init;
3481 biosA0[0x71] = psxBios__96_init;
3482 biosA0[0x72] = psxBios_CdRemove;
3483 //biosA0[0x73] = psxBios_sys_a0_73;
3484 //biosA0[0x74] = psxBios_sys_a0_74;
3485 //biosA0[0x75] = psxBios_sys_a0_75;
3486 //biosA0[0x76] = psxBios_sys_a0_76;
3487 //biosA0[0x77] = psxBios_sys_a0_77;
3488 //biosA0[0x78] = psxBios__96_CdSeekL;
3489 //biosA0[0x79] = psxBios_sys_a0_79;
3490 //biosA0[0x7a] = psxBios_sys_a0_7a;
3491 //biosA0[0x7b] = psxBios_sys_a0_7b;
3492 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3493 //biosA0[0x7d] = psxBios_sys_a0_7d;
3494 //biosA0[0x7e] = psxBios__96_CdRead;
3495 //biosA0[0x7f] = psxBios_sys_a0_7f;
3496 //biosA0[0x80] = psxBios_sys_a0_80;
3497 //biosA0[0x81] = psxBios_sys_a0_81;
3498 //biosA0[0x82] = psxBios_sys_a0_82;
3499 //biosA0[0x83] = psxBios_sys_a0_83;
3500 //biosA0[0x84] = psxBios_sys_a0_84;
3501 //biosA0[0x85] = psxBios__96_CdStop;
3502 //biosA0[0x86] = psxBios_sys_a0_86;
3503 //biosA0[0x87] = psxBios_sys_a0_87;
3504 //biosA0[0x88] = psxBios_sys_a0_88;
3505 //biosA0[0x89] = psxBios_sys_a0_89;
3506 //biosA0[0x8a] = psxBios_sys_a0_8a;
3507 //biosA0[0x8b] = psxBios_sys_a0_8b;
3508 //biosA0[0x8c] = psxBios_sys_a0_8c;
3509 //biosA0[0x8d] = psxBios_sys_a0_8d;
3510 //biosA0[0x8e] = psxBios_sys_a0_8e;
3511 //biosA0[0x8f] = psxBios_sys_a0_8f;
3512 biosA0[0x90] = hleExc0_1_2;
3513 biosA0[0x91] = hleExc0_0_2;
3514 biosA0[0x92] = hleExc0_1_1;
3515 biosA0[0x93] = hleExc0_0_1;
3516 //biosA0[0x94] = psxBios_sys_a0_94;
3517 //biosA0[0x95] = psxBios_sys_a0_95;
3518 //biosA0[0x96] = psxBios_AddCDROMDevice;
3519 //biosA0[0x97] = psxBios_AddMemCardDevide;
3520 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3521 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3522 //biosA0[0x9a] = psxBios_sys_a0_9a;
3523 //biosA0[0x9b] = psxBios_sys_a0_9b;
3524 biosA0[0x9c] = psxBios_SetConf;
3525 biosA0[0x9d] = psxBios_GetConf;
3526 //biosA0[0x9e] = psxBios_sys_a0_9e;
3527 biosA0[0x9f] = psxBios_SetMem;
3528 //biosA0[0xa0] = psxBios__boot;
3529 //biosA0[0xa1] = psxBios_SystemError;
3530 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3531 biosA0[0xa3] = psxBios_DequeueCdIntr;
3532 //biosA0[0xa4] = psxBios_sys_a0_a4;
3533 //biosA0[0xa5] = psxBios_ReadSector;
3534 biosA0[0xa6] = psxBios_get_cd_status;
3535 //biosA0[0xa7] = psxBios_bufs_cb_0;
3536 //biosA0[0xa8] = psxBios_bufs_cb_1;
3537 //biosA0[0xa9] = psxBios_bufs_cb_2;
3538 //biosA0[0xaa] = psxBios_bufs_cb_3;
3539 biosA0[0xab] = psxBios__card_info;
3540 biosA0[0xac] = psxBios__card_load;
3541 //biosA0[0axd] = psxBios__card_auto;
3542 //biosA0[0xae] = psxBios_bufs_cd_4;
3543 //biosA0[0xaf] = psxBios_sys_a0_af;
3544 //biosA0[0xb0] = psxBios_sys_a0_b0;
3545 //biosA0[0xb1] = psxBios_sys_a0_b1;
3546 //biosA0[0xb2] = psxBios_do_a_long_jmp
3547 //biosA0[0xb3] = psxBios_sys_a0_b3;
3548 biosA0[0xb4] = psxBios_GetSystemInfo;
3549 //*******************B0 CALLS****************************
3550 biosB0[0x00] = psxBios_SysMalloc;
3551 //biosB0[0x01] = psxBios_sys_b0_01;
3552 biosB0[0x02] = psxBios_SetRCnt;
3553 biosB0[0x03] = psxBios_GetRCnt;
3554 biosB0[0x04] = psxBios_StartRCnt;
3555 biosB0[0x05] = psxBios_StopRCnt;
3556 biosB0[0x06] = psxBios_ResetRCnt;
3557 biosB0[0x07] = psxBios_DeliverEvent;
3558 biosB0[0x08] = psxBios_OpenEvent;
3559 biosB0[0x09] = psxBios_CloseEvent;
3560 biosB0[0x0a] = psxBios_WaitEvent;
3561 biosB0[0x0b] = psxBios_TestEvent;
3562 biosB0[0x0c] = psxBios_EnableEvent;
3563 biosB0[0x0d] = psxBios_DisableEvent;
3564 biosB0[0x0e] = psxBios_OpenTh;
3565 biosB0[0x0f] = psxBios_CloseTh;
3566 biosB0[0x10] = psxBios_ChangeTh;
3567 //biosB0[0x11] = psxBios_psxBios_b0_11;
3568 biosB0[0x12] = psxBios_InitPAD;
3569 biosB0[0x13] = psxBios_StartPAD;
3570 biosB0[0x14] = psxBios_StopPAD;
3571 biosB0[0x15] = psxBios_PAD_init;
3572 biosB0[0x16] = psxBios_PAD_dr;
3573 biosB0[0x17] = psxBios_ReturnFromException;
3574 biosB0[0x18] = psxBios_ResetEntryInt;
3575 biosB0[0x19] = psxBios_HookEntryInt;
3576 //biosB0[0x1a] = psxBios_sys_b0_1a;
3577 //biosB0[0x1b] = psxBios_sys_b0_1b;
3578 //biosB0[0x1c] = psxBios_sys_b0_1c;
3579 //biosB0[0x1d] = psxBios_sys_b0_1d;
3580 //biosB0[0x1e] = psxBios_sys_b0_1e;
3581 //biosB0[0x1f] = psxBios_sys_b0_1f;
3582 biosB0[0x20] = psxBios_UnDeliverEvent;
3583 //biosB0[0x21] = psxBios_sys_b0_21;
3584 //biosB0[0x22] = psxBios_sys_b0_22;
3585 //biosB0[0x23] = psxBios_sys_b0_23;
3586 //biosB0[0x24] = psxBios_sys_b0_24;
3587 //biosB0[0x25] = psxBios_sys_b0_25;
3588 //biosB0[0x26] = psxBios_sys_b0_26;
3589 //biosB0[0x27] = psxBios_sys_b0_27;
3590 //biosB0[0x28] = psxBios_sys_b0_28;
3591 //biosB0[0x29] = psxBios_sys_b0_29;
3592 //biosB0[0x2a] = psxBios_sys_b0_2a;
3593 //biosB0[0x2b] = psxBios_sys_b0_2b;
3594 //biosB0[0x2c] = psxBios_sys_b0_2c;
3595 //biosB0[0x2d] = psxBios_sys_b0_2d;
3596 //biosB0[0x2e] = psxBios_sys_b0_2e;
3597 //biosB0[0x2f] = psxBios_sys_b0_2f;
3598 //biosB0[0x30] = psxBios_sys_b0_30;
3599 //biosB0[0x31] = psxBios_sys_b0_31;
3600 biosB0[0x32] = psxBios_open;
3601 biosB0[0x33] = psxBios_lseek;
3602 biosB0[0x34] = psxBios_read;
3603 biosB0[0x35] = psxBios_write;
3604 biosB0[0x36] = psxBios_close;
3605 //biosB0[0x37] = psxBios_ioctl;
3606 //biosB0[0x38] = psxBios_exit;
3607 //biosB0[0x39] = psxBios_sys_b0_39;
3608 //biosB0[0x3a] = psxBios_getc;
3609 //biosB0[0x3b] = psxBios_putc;
3610 biosB0[0x3c] = psxBios_getchar;
3611 biosB0[0x3d] = psxBios_putchar;
3612 //biosB0[0x3e] = psxBios_gets;
3613 biosB0[0x3f] = psxBios_puts;
3614 biosB0[0x40] = psxBios_cd;
3615 biosB0[0x41] = psxBios_format;
3616 biosB0[0x42] = psxBios_firstfile;
3617 biosB0[0x43] = psxBios_nextfile;
3618 biosB0[0x44] = psxBios_rename;
3619 biosB0[0x45] = psxBios_delete;
3620 //biosB0[0x46] = psxBios_undelete;
3621 //biosB0[0x47] = psxBios_AddDevice;
3622 //biosB0[0x48] = psxBios_RemoteDevice;
3623 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3624 biosB0[0x4a] = psxBios_InitCARD;
3625 biosB0[0x4b] = psxBios_StartCARD;
3626 biosB0[0x4c] = psxBios_StopCARD;
3627 //biosB0[0x4d] = psxBios_sys_b0_4d;
3628 biosB0[0x4e] = psxBios__card_write;
3629 biosB0[0x4f] = psxBios__card_read;
3630 biosB0[0x50] = psxBios__new_card;
3631 biosB0[0x51] = psxBios_Krom2RawAdd;
3632 //biosB0[0x52] = psxBios_sys_b0_52;
3633 //biosB0[0x53] = psxBios_sys_b0_53;
3634 //biosB0[0x54] = psxBios__get_errno;
3635 biosB0[0x55] = psxBios__get_error;
3636 biosB0[0x56] = psxBios_GetC0Table;
3637 biosB0[0x57] = psxBios_GetB0Table;
3638 biosB0[0x58] = psxBios__card_chan;
3639 //biosB0[0x59] = psxBios_sys_b0_59;
3640 //biosB0[0x5a] = psxBios_sys_b0_5a;
3641 biosB0[0x5b] = psxBios_ChangeClearPad;
3642 biosB0[0x5c] = psxBios__card_status;
3643 biosB0[0x5d] = psxBios__card_wait;
3644 //*******************C0 CALLS****************************
3645 biosC0[0x00] = psxBios_InitRCnt;
3646 biosC0[0x01] = psxBios_InitException;
3647 biosC0[0x02] = psxBios_SysEnqIntRP;
3648 biosC0[0x03] = psxBios_SysDeqIntRP;
3649 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3650 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3651 //biosC0[0x06] = psxBios_ExceptionHandler;
3652 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3653 biosC0[0x08] = psxBios_SysInitMemory;
3654 //biosC0[0x09] = psxBios_SysInitKMem;
3655 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3656 //biosC0[0x0b] = psxBios_SystemError;
3657 biosC0[0x0c] = psxBios_InitDefInt;
3658 //biosC0[0x0d] = psxBios_sys_c0_0d;
3659 //biosC0[0x0e] = psxBios_sys_c0_0e;
3660 //biosC0[0x0f] = psxBios_sys_c0_0f;
3661 //biosC0[0x10] = psxBios_sys_c0_10;
3662 //biosC0[0x11] = psxBios_sys_c0_11;
3663 //biosC0[0x12] = psxBios_InstallDevices;
3664 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3665 //biosC0[0x14] = psxBios_sys_c0_14;
3666 //biosC0[0x15] = psxBios__cdevinput;
3667 //biosC0[0x16] = psxBios__cdevscan;
3668 //biosC0[0x17] = psxBios__circgetc;
3669 //biosC0[0x18] = psxBios__circputc;
3670 //biosC0[0x19] = psxBios_ioabort;
3671 //biosC0[0x1a] = psxBios_sys_c0_1a
3672 //biosC0[0x1b] = psxBios_KernelRedirect;
3673 //biosC0[0x1c] = psxBios_PatchAOTable;
3674 //************** THE END ***************************************
3677 memset(FDesc, 0, sizeof(FDesc));
3678 memset(cdir, 0, sizeof(cdir));
3681 // somewhat pretend to be a SCPH1001 BIOS
3682 // some games look for these and take an exception if they're missing
3683 rom32 = (u32 *)psxR;
3684 rom32[0x100/4] = SWAP32(0x19951204);
3685 rom32[0x104/4] = SWAP32(3);
3686 romc = (char *)psxR;
3687 strcpy(romc + 0x108, "PCSX authors");
3688 strcpy(romc + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3689 strcpy(romc + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3690 strcpy(romc + 0x7ff54, "GPL-2.0-or-later");
3693 len = 0x80000 - 0x66000;
3694 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3695 len = 0x80000 - 0x69d68;
3696 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3698 // trap attempts to call bios directly
3699 rom32[0x00000/4] = HLEOP(hleop_dummy);
3700 rom32[0x00180/4] = HLEOP(hleop_dummy);
3701 rom32[0x3fffc/4] = HLEOP(hleop_dummy);
3702 rom32[0x65ffc/4] = HLEOP(hleop_dummy);
3703 rom32[0x7ff2c/4] = HLEOP(hleop_dummy);
3705 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3706 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3707 Here are some examples of games not working with this fix in place :
3708 R-type won't get past the Irem logo if not implemented.
3709 Crash Team Racing will softlock after the Sony logo.
3712 ram32 = (u32 *)psxM;
3713 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3714 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3715 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3716 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3718 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3719 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3721 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3722 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3723 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3724 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3726 ram32[0x00a0/4] = HLEOP(hleop_a0);
3727 ram32[0x00b0/4] = HLEOP(hleop_b0);
3728 ram32[0x00c0/4] = HLEOP(hleop_c0);
3730 setup_tt(4, 16, 0x801fff00);
3731 DeliverEvent(0xf0000003, 0x0010);
3733 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3734 strcpy((char *)&ram32[0xeff0/4], "bu");
3736 // default exception handler chains
3737 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3738 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3739 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3740 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3741 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3742 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3743 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3744 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3748 // fill the api jumptables with fake entries as some games patch them
3749 // (or rather the funcs listed there)
3750 ptr = (u32 *)&psxM[A_A0_TABLE];
3751 for (i = 0; i < 256; i++)
3752 ptr[i] = SWAP32(A_A0_DUMMY);
3754 ptr = (u32 *)&psxM[A_B0_TABLE];
3755 for (i = 0; i < 256; i++)
3756 ptr[i] = SWAP32(A_B0_DUMMY);
3757 // B(5b) is special because games patch (sometimes even jump to)
3758 // code at fixed offsets from it, nocash lists offsets:
3759 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3760 // call: +7a0=4b70, +884=4c54, +894=4c64
3761 ptr[0x5b] = SWAP32(A_B0_5B_DUMMY); // 0x43d0
3762 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3764 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3765 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3766 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3768 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3769 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3771 ptr = (u32 *)&psxM[A_C0_TABLE];
3772 for (i = 0; i < 256/2; i++)
3773 ptr[i] = SWAP32(A_C0_DUMMY);
3774 ptr[6] = SWAP32(A_EXCEPTION);
3777 ram32[A_A0_DUMMY/4] = HLEOP(hleop_dummy);
3778 ram32[A_B0_DUMMY/4] = HLEOP(hleop_dummy);
3779 ram32[A_C0_DUMMY/4] = HLEOP(hleop_dummy);
3780 ram32[A_B0_5B_DUMMY/4] = HLEOP(hleop_dummy);
3781 ram32[0x8000/4] = HLEOP(hleop_execret);
3783 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3784 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3785 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3786 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3787 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3788 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3789 ram32[A_RND_SEED/4] = SWAPu32(0x24040001); // was 0xac20cc00
3792 void psxBiosShutdown() {
3795 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 stack) {
3798 if (tcb_cnt != 4 || evcb_cnt != 16) {
3799 setup_tt(tcb_cnt, evcb_cnt, stack);
3800 DeliverEvent(0xf0000003, 0x0010);
3802 storeRam32(A_CONF_SP, stack);
3805 #define psxBios_PADpoll(pad) { \
3806 int i, more_data = 0; \
3807 PAD##pad##_startPoll(pad); \
3808 pad_buf##pad[1] = PAD##pad##_poll(0x42, &more_data); \
3809 pad_buf##pad[0] = more_data ? 0 : 0xff; \
3810 PAD##pad##_poll(0, &more_data); \
3812 while (more_data) { \
3813 pad_buf##pad[i++] = PAD##pad##_poll(0, &more_data); \
3817 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3821 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3822 psxBios_ReturnFromException();
3828 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3829 // so this is only partially implemented
3830 static void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3832 u32 cdrom_dma_ack_enable = 1; // a000b93c
3833 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3836 static void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3839 //PSXBIOS_LOG("%s\n", __func__);
3841 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3842 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3843 //if (--cdrom_irq_counter == 0) // 0xa0009180
3844 // DeliverEvent(0xf0000003, 0x10);
3848 mips_return_c(ret, 20);
3851 static void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3853 u32 cdrom_irq_ack_enable = 1; // a000b938
3854 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3857 static void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3860 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3861 PSXBIOS_LOG("%s TODO\n", __func__);
3864 mips_return_c(ret, 20);
3867 static void hleExc0_2_2_syscall() // not in any A/B/C table
3869 u32 tcbPtr = loadRam32(A_TT_PCB);
3870 TCB *tcb = loadRam32ptr(tcbPtr);
3871 u32 code = (SWAP32(tcb->cause) & 0x3c) >> 2;
3873 if (code != R3000E_Syscall) {
3875 DeliverEvent(0xf0000010, 0x1000);
3876 //psxBios_SystemErrorUnresolvedException();
3878 mips_return_c(0, 17);
3882 //printf("%s c=%d a0=%d\n", __func__, code, SWAP32(tcb->reg[4]));
3883 tcb->epc += SWAP32(4);
3884 switch (SWAP32(tcb->reg[4])) { // a0
3888 case 1: { // EnterCritical - disable irqs
3889 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3890 tcb->reg[2] = SWAP32(was_enabled);
3891 tcb->sr &= SWAP32(~0x404);
3894 case 2: // ExitCritical - enable irqs
3895 tcb->sr |= SWAP32(0x404);
3898 case 3: { // ChangeThreadSubFunction
3899 u32 tcbPtr = loadRam32(A_TT_PCB);
3900 storeRam32(tcbPtr, SWAP32(tcb->reg[5])); // a1
3904 DeliverEvent(0xf0000010, 0x4000);
3908 psxBios_ReturnFromException();
3911 static void hleExc1_0_1(void)
3913 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3914 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3917 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3920 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3921 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3924 mips_return_c(ret, 22);
3927 static void hleExc1_0_2(void)
3929 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3932 static void hleExc1_1_1(void)
3934 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3935 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3938 static void hleExc1_1_2(void)
3940 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3943 static void hleExc1_2_1(void)
3945 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3946 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3949 static void hleExc1_2_2(void)
3951 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3954 static void hleExc1_3_1(void)
3956 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3957 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3960 static void hleExc1_3_2(void)
3962 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3965 static void hleExc3_0_2_defint(void)
3967 static const struct {
3978 { 6, 6 }, // rcnt2 (bug)
3983 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3984 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3985 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3990 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3993 static void hleExcPadCard1(void)
3995 if (loadRam32(A_PAD_IRQR_ENA)) {
3996 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3997 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
4002 if (loadRam32(A_PAD_DR_DST))
4005 if (loadRam32(A_PAD_ACK_VBL))
4006 psxHwWrite16(0x1f801070, ~1);
4007 if (loadRam32(A_CARD_IRQR_ENA)) {
4011 mips_return_c(0, 18);
4014 static void hleExcPadCard2(void)
4016 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
4017 mips_return_c(ret, 15);
4020 void psxBiosException() {
4021 u32 tcbPtr = loadRam32(A_TT_PCB);
4022 u32 *chains = loadRam32ptr(A_TT_ExCB);
4023 TCB *tcb = loadRam32ptr(tcbPtr);
4029 // $at, $v0, $v1, $ra already saved by the mips code at A_EXCEPTION
4030 for (i = 4; i < 31; i++) {
4033 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
4035 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
4036 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
4037 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
4038 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
4039 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
4040 sp = fp = loadRam32(A_EXC_SP);
4043 assert(!psxRegs.cpuInRecursion);
4045 // do the chains (always 4)
4046 for (c = lim = 0; c < 4; c++) {
4047 if (chains[c * 2] == 0)
4049 ptr = SWAP32(chains[c * 2]);
4050 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
4051 chain = castRam32ptr(ptr);
4056 softCallInException(SWAP32(chain[2]));
4057 if (returned_from_exception())
4060 if (v0 == 0 || chain[1] == 0)
4062 softCallInException(SWAP32(chain[1]));
4063 if (returned_from_exception())
4069 // return from exception (custom or default)
4071 ptr = loadRam32(A_EEXIT_PTR);
4072 if (ptr != A_EEXIT_DEF) {
4073 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
4074 longjmp_load(jmp_buf);
4079 psxBios_ReturnFromException();
4083 static void hleDummy() {
4084 log_unhandled("hleDummy called @%08x ra=%08x\n", psxRegs.pc - 4, ra);
4086 psxRegs.cycle += 1000;
4091 static void hleA0() {
4092 u32 call = t1 & 0xff;
4093 u32 entry = loadRam32(A_A0_TABLE + call * 4);
4095 if (call < 192 && entry != A_A0_DUMMY) {
4096 PSXBIOS_LOG("custom A%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4097 call, biosA0n[call], a0, entry, ra);
4100 PSXBIOS_LOG(" -> %08x\n", v0);
4102 else if (biosA0[call])
4105 //printf("A(%02x) -> %x\n", call, v0);
4109 static void hleB0() {
4110 u32 call = t1 & 0xff;
4111 u32 entry = loadRam32(A_B0_TABLE + call * 4);
4115 is_custom = entry != A_B0_5B_DUMMY;
4117 is_custom = entry != A_B0_DUMMY;
4119 PSXBIOS_LOG("custom B%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4120 call, biosB0n[call], a0, entry, ra);
4123 PSXBIOS_LOG(" -> %08x\n", v0);
4125 else if (biosB0[call])
4128 //printf("B(%02x) -> %x\n", call, v0);
4132 static void hleC0() {
4133 u32 call = t1 & 0xff;
4134 u32 entry = loadRam32(A_C0_TABLE + call * 4);
4136 if (call < 128 && entry != A_C0_DUMMY) {
4137 PSXBIOS_LOG("custom C%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4138 call, biosC0n[call], a0, entry, ra);
4141 PSXBIOS_LOG(" -> %08x\n", v0);
4143 else if (biosC0[call])
4146 //printf("C(%02x) -> %x\n", call, v0);
4150 // currently not used
4151 static void hleBootstrap() {
4156 static void hleExecRet() {
4157 const EXEC *header = (EXEC *)PSXM(s0);
4159 PSXBIOS_LOG("ExecRet %x: %x\n", s0, header->ret);
4161 ra = SWAP32(header->ret);
4162 sp = SWAP32(header->_sp);
4163 fp = SWAP32(header->_fp);
4164 gp = SWAP32(header->_gp);
4165 s0 = SWAP32(header->base);
4171 void (* const psxHLEt[24])() = {
4172 hleDummy, hleA0, hleB0, hleC0,
4173 hleBootstrap, hleExecRet, psxBiosException, hleDummy,
4174 hleExc0_0_1, hleExc0_0_2,
4175 hleExc0_1_1, hleExc0_1_2, hleExc0_2_2_syscall,
4176 hleExc1_0_1, hleExc1_0_2,
4177 hleExc1_1_1, hleExc1_1_2,
4178 hleExc1_2_1, hleExc1_2_2,
4179 hleExc1_3_1, hleExc1_3_2,
4181 hleExcPadCard1, hleExcPadCard2,
4184 void psxBiosCheckExe(u32 t_addr, u32 t_size, int loading_state)
4186 // lw $v0, 0x10($sp)
4189 // sw $v0, 0x10($sp)
4190 // lw $v0, 0x10($sp)
4192 // bne $v0, $v1, not_timeout
4195 static const u8 pattern[] = {
4196 0x10, 0x00, 0xA2, 0x8F, 0x00, 0x00, 0x00, 0x00,
4197 0xFF, 0xFF, 0x42, 0x24, 0x10, 0x00, 0xA2, 0xAF,
4198 0x10, 0x00, 0xA2, 0x8F, 0x00, 0x00, 0x00, 0x00,
4199 0x0C, 0x00, 0x43, 0x14, 0x00, 0x00, 0x00, 0x00,
4201 u32 start = t_addr & 0x1ffffc;
4202 u32 end = (start + t_size) & 0x1ffffc;
4203 u32 buf[sizeof(pattern) / sizeof(u32)];
4204 const u32 *r32 = (u32 *)(psxM + start);
4212 memcpy(buf, pattern, sizeof(buf));
4213 for (i = 0; i < t_size / 4; i += j + 1) {
4214 for (j = 0; j < sizeof(buf) / sizeof(buf[0]); j++)
4215 if (r32[i + j] != buf[j])
4217 if (j != sizeof(buf) / sizeof(buf[0]))
4220 if ((SWAP32(r32[i + j]) >> 16) != 0x3c04) // lui
4223 SysPrintf("HLE vsync @%08x\n", start + i * 4);
4224 psxRegs.biosBranchCheck = (t_addr & 0xa01ffffc) + i * 4;
4228 void psxBiosCheckBranch(void)
4232 static u32 cycles_prev, v0_prev;
4233 u32 cycles_passed, waste_cycles;
4234 u32 loops, v0_expect = v0_prev - 1;
4238 cycles_passed = psxRegs.cycle - cycles_prev;
4239 cycles_prev = psxRegs.cycle;
4241 if (cycles_passed < 10 || cycles_passed > 50 || v0 != v0_expect)
4244 waste_cycles = schedule_timeslice() - psxRegs.cycle;
4245 loops = waste_cycles / cycles_passed;
4249 psxRegs.cycle += loops * cycles_passed;
4250 //printf("c %4u %d\n", loops, cycles_passed);
4254 #define bfreeze(ptr, size) { \
4255 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
4256 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
4260 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
4261 #define bfreezel(ptr) bfreeze(ptr, sizeof(*(ptr)))
4263 void psxBiosFreeze(int Mode) {