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"
42 //#define PSXBIOS_LOG printf
43 #define PSXBIOS_LOG(...)
46 #define PTR_1 (void *)(size_t)1
48 char *biosA0n[256] = {
50 "open", "lseek", "read", "write",
51 "close", "ioctl", "exit", "sys_a0_07",
52 "getc", "putc", "todigit", "atof",
53 "strtoul", "strtol", "abs", "labs",
55 "atoi", "atol", "atob", "setjmp",
56 "longjmp", "strcat", "strncat", "strcmp",
57 "strncmp", "strcpy", "strncpy", "strlen",
58 "index", "rindex", "strchr", "strrchr",
60 "strpbrk", "strspn", "strcspn", "strtok",
61 "strstr", "toupper", "tolower", "bcopy",
62 "bzero", "bcmp", "memcpy", "memset",
63 "memmove", "memcmp", "memchr", "rand",
65 "srand", "qsort", "strtod", "malloc",
66 "free", "lsearch", "bsearch", "calloc",
67 "realloc", "InitHeap", "_exit", "getchar",
68 "putchar", "gets", "puts", "printf",
70 "SystemErrorUnresolvedException", "LoadTest", "Load", "Exec",
71 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
72 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
73 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
75 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
76 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
77 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
78 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
80 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
81 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
82 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
83 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
85 "_bu_init", "_96_init", "CdRemove", "sys_a0_73",
86 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
87 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
88 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
90 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
91 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
92 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
93 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
95 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
96 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
97 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
98 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
100 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
101 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
102 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
103 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
105 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
109 char *biosB0n[256] = {
111 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
112 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
113 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
114 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
116 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
117 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
118 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
119 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
121 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
122 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
123 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
124 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
126 "sys_b0_30", "sys_b0_31", "open", "lseek",
127 "read", "write", "close", "ioctl",
128 "exit", "sys_b0_39", "getc", "putc",
129 "getchar", "putchar", "gets", "puts",
131 "cd", "format", "firstfile", "nextfile",
132 "rename", "delete", "undelete", "AddDevice",
133 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
134 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
136 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
137 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
138 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
139 "_card_status", "_card_wait",
142 char *biosC0n[256] = {
144 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
145 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
146 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
147 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
149 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
150 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
151 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
155 //#define r0 (psxRegs.GPR.n.r0)
156 #define at (psxRegs.GPR.n.at)
157 #define v0 (psxRegs.GPR.n.v0)
158 #define v1 (psxRegs.GPR.n.v1)
159 #define a0 (psxRegs.GPR.n.a0)
160 #define a1 (psxRegs.GPR.n.a1)
161 #define a2 (psxRegs.GPR.n.a2)
162 #define a3 (psxRegs.GPR.n.a3)
163 #define t0 (psxRegs.GPR.n.t0)
164 #define t1 (psxRegs.GPR.n.t1)
165 #define t2 (psxRegs.GPR.n.t2)
166 #define t3 (psxRegs.GPR.n.t3)
167 #define t4 (psxRegs.GPR.n.t4)
168 #define t5 (psxRegs.GPR.n.t5)
169 #define t6 (psxRegs.GPR.n.t6)
170 #define t7 (psxRegs.GPR.n.t7)
171 #define t8 (psxRegs.GPR.n.t8)
172 #define t9 (psxRegs.GPR.n.t9)
173 #define s0 (psxRegs.GPR.n.s0)
174 #define s1 (psxRegs.GPR.n.s1)
175 #define s2 (psxRegs.GPR.n.s2)
176 #define s3 (psxRegs.GPR.n.s3)
177 #define s4 (psxRegs.GPR.n.s4)
178 #define s5 (psxRegs.GPR.n.s5)
179 #define s6 (psxRegs.GPR.n.s6)
180 #define s7 (psxRegs.GPR.n.s7)
181 #define k0 (psxRegs.GPR.n.k0)
182 #define k1 (psxRegs.GPR.n.k1)
183 #define gp (psxRegs.GPR.n.gp)
184 #define sp (psxRegs.GPR.n.sp)
185 #define fp (psxRegs.GPR.n.fp)
186 #define ra (psxRegs.GPR.n.ra)
187 #define pc0 (psxRegs.pc)
189 #define Ra0 ((char *)PSXM(a0))
190 #define Ra1 ((char *)PSXM(a1))
191 #define Ra2 ((char *)PSXM(a2))
192 #define Ra3 ((char *)PSXM(a3))
193 #define Rv0 ((char *)PSXM(v0))
194 #define Rsp ((char *)PSXM(sp))
205 #define EvStUNUSED 0x0000
206 #define EvStDISABLED 0x1000
207 #define EvStACTIVE 0x2000
208 #define EvStALREADY 0x4000
210 #define EvMdCALL 0x1000
211 #define EvMdMARK 0x2000
234 u32 _sp, _fp, _gp, ret, base;
254 // todo: FileDesc layout is wrong
255 // todo: get rid of these globals
256 static FileDesc FDesc[32];
257 static char ffile[64];
259 static char cdir[8*8+8];
262 // fixed RAM offsets, SCPH1001 compatible
263 #define A_TT_ExCB 0x0100
264 #define A_TT_PCB 0x0108
265 #define A_TT_TCB 0x0110
266 #define A_TT_EvCB 0x0120
267 #define A_A0_TABLE 0x0200
268 #define A_B0_TABLE 0x0874
269 #define A_C0_TABLE 0x0674
270 #define A_SYSCALL 0x0650
271 #define A_EXCEPTION 0x0c80
272 #define A_EXC_SP 0x6cf0
273 #define A_EEXIT_DEF 0x6cf4
274 #define A_KMALLOC_PTR 0x7460
275 #define A_KMALLOC_SIZE 0x7464
276 #define A_KMALLOC_END 0x7468
277 #define A_PADCRD_CHN_E 0x74a8 // pad/card irq chain entry, see hleExcPadCard1()
278 #define A_PAD_IRQR_ENA 0x74b8 // pad read on vint irq (nocash 'pad_enable_flag')
279 #define A_CARD_IRQR_ENA 0x74bc // same for card
280 #define A_PAD_INBUF 0x74c8 // 2x buffers for rx pad data
281 #define A_PAD_OUTBUF 0x74d0 // 2x buffers for tx pad data
282 #define A_PAD_IN_LEN 0x74d8
283 #define A_PAD_OUT_LEN 0x74e0
284 #define A_PAD_DR_DST 0x74c4
285 #define A_CARD_CHAN1 0x7500
286 #define A_PAD_DR_BUF1 0x7570
287 #define A_PAD_DR_BUF2 0x7598
288 #define A_EEXIT_PTR 0x75d0
289 #define A_EXC_STACK 0x85d8 // exception stack top
290 #define A_RCNT_VBL_ACK 0x8600
291 #define A_PAD_ACK_VBL 0x8914 // enable vint ack by pad reading code
292 #define A_HEAP_BASE 0x9000
293 #define A_HEAP_SIZE 0x9004
294 #define A_HEAP_END 0x9008
295 #define A_HEAP_INIT_FLG 0x900c
296 #define A_RND_SEED 0x9010
297 #define A_HEAP_FRSTCHNK 0xb060
298 #define A_HEAP_CURCHNK 0xb064
299 #define A_CONF_TCB 0xb940
300 #define A_CONF_EvCB 0xb944
301 #define A_CONF_SP 0xb948
302 #define A_CD_EVENTS 0xb9b8
303 #define A_EXC_GP 0xf450
305 #define A_A0_DUMMY 0x1010
306 #define A_B0_DUMMY 0x2010
307 #define A_C0_DUMMY 0x3010
308 #define A_B0_5B_DUMMY 0x43d0
310 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
312 static u8 loadRam8(u32 addr)
314 assert(!(addr & 0x5f800000));
315 return psxM[addr & 0x1fffff];
318 static u32 loadRam32(u32 addr)
320 assert(!(addr & 0x5f800000));
321 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
324 static void *castRam8ptr(u32 addr)
326 assert(!(addr & 0x5f800000));
327 return psxM + (addr & 0x1fffff);
330 static void *castRam32ptr(u32 addr)
332 assert(!(addr & 0x5f800003));
333 return psxM + (addr & 0x1ffffc);
336 static void *loadRam8ptr(u32 addr)
338 return castRam8ptr(loadRam32(addr));
341 static void *loadRam32ptr(u32 addr)
343 return castRam32ptr(loadRam32(addr));
346 static void storeRam8(u32 addr, u8 d)
348 assert(!(addr & 0x5f800000));
349 *((u8 *)psxM + (addr & 0x1fffff)) = d;
352 static void storeRam32(u32 addr, u32 d)
354 assert(!(addr & 0x5f800000));
355 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
358 static void mips_return(u32 val)
364 static void mips_return_void(void)
369 static void use_cycles(u32 cycle)
371 psxRegs.cycle += cycle * 2;
374 static void mips_return_c(u32 val, u32 cycle)
380 static void mips_return_void_c(u32 cycle)
386 static int returned_from_exception(void)
388 // 0x80000080 means it took another exception just after return
389 return pc0 == k0 || pc0 == 0x80000080;
392 static inline void softCall(u32 pc) {
394 u32 ssr = psxRegs.CP0.n.SR;
398 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
400 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
402 while (pc0 != 0x80001000 && ++lim < 1000000)
403 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
405 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
408 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
410 psxRegs.CP0.n.SR |= ssr & 0x404;
413 static inline void softCallInException(u32 pc) {
418 assert(ra != 0x80001000);
419 if (ra == 0x80001000)
423 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
425 while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 1000000)
426 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
428 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
431 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
432 if (pc0 == 0x80001000)
436 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
437 static u32 DeliverEvent(u32 class, u32 spec);
438 static u32 UnDeliverEvent(u32 class, u32 spec);
439 static void CloseEvent(u32 ev);
444 // System calls A0 */
447 #define buread(Ra1, mcd, length) { \
448 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); \
449 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
450 memcpy(Ra1, ptr, length); \
451 psxCpu->Clear(a1, (length + 3) / 4); \
452 if (FDesc[1 + mcd].mode & 0x8000) { \
453 DeliverEvent(0xf0000011, 0x0004); \
454 DeliverEvent(0xf4000001, 0x0004); \
457 FDesc[1 + mcd].offset += v0; \
460 #define buwrite(Ra1, mcd, length) { \
461 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
462 PSXBIOS_LOG("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
463 ptr = Mcd##mcd##Data + offset; \
464 memcpy(ptr, Ra1, length); \
465 FDesc[1 + mcd].offset += length; \
466 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
467 if (FDesc[1 + mcd].mode & 0x8000) { \
468 DeliverEvent(0xf0000011, 0x0004); \
469 DeliverEvent(0xf4000001, 0x0004); \
474 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
475 /* For some strange reason, the returned character is sign-expanded; */
476 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
477 /* TODO FIX ME : Properly implement this behaviour */
478 void psxBios_getc(void) // 0x03, 0x35
483 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
487 if (pa1 != INVALID_PTR) {
489 case 2: buread(pa1, 1, 1); break;
490 case 3: buread(pa1, 2, 1); break;
497 /* Copy of psxBios_write, except size is 1. */
498 void psxBios_putc(void) // 0x09, 0x3B
503 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
506 if (pa1 == INVALID_PTR) {
511 if (a0 == 1) { // stdout
512 char *ptr = (char *)pa1;
516 printf("%c", *ptr++); a2--;
522 case 2: buwrite(pa1, 1, 1); break;
523 case 3: buwrite(pa1, 2, 1); break;
529 void psxBios_todigit(void) // 0x0a
533 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
536 if (c >= 0x30 && c < 0x3A) {
539 else if (c > 0x60 && c < 0x7B) {
542 else if (c > 0x40 && c < 0x5B) {
545 else if (c >= 0x80) {
556 void psxBios_abs() { // 0x0e
557 if ((s32)a0 < 0) v0 = -(s32)a0;
562 void psxBios_labs() { // 0x0f
566 void psxBios_atoi() { // 0x10
568 char *p = (char *)Ra0;
570 if (p == INVALID_PTR) {
577 case ' ': case '\t': continue;
584 while (*p >= '0' && *p <= '9') {
585 n = n * 10 + *p++ - '0';
590 PSXBIOS_LOG("psxBios_%s %s (%x) -> 0x%x\n", biosA0n[0x10], Ra0, a0, v0);
593 void psxBios_atol() { // 0x11
603 static void psxBios_setjmp() { // 0x13
604 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
607 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
609 jmp_buf->ra_ = SWAP32(ra);
610 jmp_buf->sp_ = SWAP32(sp);
611 jmp_buf->fp_ = SWAP32(fp);
612 for (i = 0; i < 8; i++) // s0-s7
613 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
614 jmp_buf->gp_ = SWAP32(gp);
616 mips_return_c(0, 15);
619 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
623 ra = SWAP32(jmp_buf->ra_);
624 sp = SWAP32(jmp_buf->sp_);
625 fp = SWAP32(jmp_buf->fp_);
626 for (i = 0; i < 8; i++) // s0-s7
627 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
628 gp = SWAP32(jmp_buf->gp_);;
631 void psxBios_longjmp() { // 0x14
632 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
634 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
635 longjmp_load(jmp_buf);
636 mips_return_c(a1, 15);
639 void psxBios_strcat() { // 0x15
643 PSXBIOS_LOG("psxBios_%s %s (%x), %s (%x)\n", biosA0n[0x15], Ra0, a0, Ra1, a1);
644 if (a0 == 0 || a1 == 0 || p2 == INVALID_PTR)
649 while (loadRam8(p1)) {
653 for (; *p2; p1++, p2++)
657 mips_return_c(a0, 22);
660 void psxBios_strncat() { // 0x16
661 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
665 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
667 if (a0 == 0 || a1 == 0)
675 while ((*p1++ = *p2++) != '\0') {
685 void psxBios_strcmp() { // 0x17
686 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
688 if (a0 == 0 && a1 == 0)
694 else if (a0 == 0 && a1 != 0)
700 else if (a0 != 0 && a1 == 0)
707 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
710 while (*p1 == *p2++) {
729 void psxBios_strncmp() { // 0x18
730 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
732 if (a0 == 0 && a1 == 0)
738 else if (a0 == 0 && a1 != 0)
744 else if (a0 != 0 && a1 == 0)
751 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
754 while (--n >= 0 && *p1 == *p2++) {
758 v1 = a2 - ((a2-n) - 1);
766 v0 = (n < 0 ? 0 : *p1 - *--p2);
768 v1 = a2 - ((a2-n) - 1);
774 void psxBios_strcpy() { // 0x19
775 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
776 PSXBIOS_LOG("psxBios_%s %x, %s (%x)\n", biosA0n[0x19], a0, p2, a1);
777 if (a0 == 0 || a1 == 0)
783 while ((*p1++ = *p2++) != '\0');
788 void psxBios_strncpy() { // 0x1a
789 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
791 if (a0 == 0 || a1 == 0)
797 for (i = 0; i < n; i++) {
798 if ((*p1++ = *p2++) == '\0') {
810 void psxBios_strlen() { // 0x1b
811 char *p = (char *)Ra0;
822 void psxBios_index() { // 0x1c
823 char *p = (char *)Ra0;
833 v0 = a0 + (p - (char *)Ra0);
837 } while (*p++ != '\0');
842 void psxBios_rindex() { // 0x1d
843 char *p = (char *)Ra0;
853 v0 = a0 + (p - (char *)Ra0);
854 } while (*p++ != '\0');
859 void psxBios_strchr() { // 0x1e
863 void psxBios_strrchr() { // 0x1f
867 void psxBios_strpbrk() { // 0x20
868 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
870 while ((c = *p1++) != '\0') {
871 for (scanp = p2; (sc = *scanp++) != '\0';) {
873 v0 = a0 + (p1 - 1 - (char *)Ra0);
880 // BUG: return a0 instead of NULL if not found
884 void psxBios_strspn() { // 0x21
887 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
888 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
889 if (*p2 == '\0') break;
892 v0 = p1 - (char *)Ra0; pc0 = ra;
895 void psxBios_strcspn() { // 0x22
898 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
899 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
900 if (*p2 != '\0') break;
903 v0 = p1 - (char *)Ra0; pc0 = ra;
906 void psxBios_strtok() { // 0x23
907 char *pcA0 = (char *)Ra0;
908 char *pcRet = strtok(pcA0, (char *)Ra1);
910 v0 = a0 + pcRet - pcA0;
916 void psxBios_strstr() { // 0x24
917 char *p = (char *)Ra0, *p1, *p2;
918 PSXBIOS_LOG("psxBios_%s %s (%x), %s (%x)\n", biosA0n[0x24], p, a0, Ra1, a1);
924 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
929 v0 = a0 + (p - (char *)Ra0);
931 PSXBIOS_LOG(" -> %x\n", v0);
935 // bug: skips the whole matched substring + 1
942 void psxBios_toupper() { // 0x25
943 v0 = (s8)(a0 & 0xff);
944 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
948 void psxBios_tolower() { // 0x26
949 v0 = (s8)(a0 & 0xff);
950 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
954 static void do_memset(u32 dst, u32 v, s32 len)
960 if (db != INVALID_PTR)
964 psxCpu->Clear(dst, (len + 3) / 4);
967 static void do_memcpy(u32 dst, u32 src, s32 len)
969 u32 d = dst, s = src;
972 const u8 *sb = PSXM(s);
974 if (db != INVALID_PTR && sb != INVALID_PTR)
979 psxCpu->Clear(dst, (len + 3) / 4);
982 static void psxBios_memcpy();
984 static void psxBios_bcopy() { // 0x27 - memcpy with args swapped
985 //PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x27], a0, a1, a2);
986 u32 ret = a0, cycles = 0;
987 if (a0 == 0) // ...but it checks src this time
994 do_memcpy(a1, a0, a2);
1000 mips_return_c(ret, cycles + 5);
1003 static void psxBios_bzero() { // 0x28
1004 /* Same as memset here (See memset below) */
1005 u32 ret = a0, cycles;
1006 if (a0 == 0 || (s32)a1 <= 0)
1008 mips_return_c(0, 6);
1011 do_memset(a0, 0, a1);
1015 // todo: many more cycles due to uncached bios mem
1016 mips_return_c(ret, cycles + 5);
1019 void psxBios_bcmp() { // 0x29
1020 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
1022 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
1024 while ((s32)a2-- > 0) {
1025 if (*p1++ != *p2++) {
1026 v0 = *p1 - *p2; // BUG: compare the NEXT byte
1035 static void psxBios_memcpy() { // 0x2a
1036 u32 ret = a0, cycles = 0;
1039 mips_return_c(0, 4);
1044 do_memcpy(a0, a1, a2);
1050 mips_return_c(ret, cycles + 5);
1053 static void psxBios_memset() { // 0x2b
1054 u32 ret = a0, cycles;
1055 if (a0 == 0 || (s32)a2 <= 0)
1057 mips_return_c(0, 6);
1060 do_memset(a0, a1, a2);
1064 // todo: many more cycles due to uncached bios mem
1065 mips_return_c(ret, cycles + 5);
1068 void psxBios_memmove() { // 0x2c
1069 u32 ret = a0, cycles = 0;
1072 mips_return_c(0, 4);
1076 if ((s32)a2 > 0 && a0 > a1 && a0 < a1 + a2) {
1077 u32 dst = a0, len = a2 + 1;
1080 while ((s32)a2 >= 0) { // BUG: copies one more byte here
1081 const u8 *sb = PSXM(a1);
1083 if (db != INVALID_PTR && sb != INVALID_PTR)
1089 psxCpu->Clear(dst, (len + 3) / 4);
1090 cycles = 10 + len * 8;
1091 } else if ((s32)a2 > 0) {
1092 do_memcpy(a0, a1, a2);
1098 mips_return_c(ret, cycles + 5);
1101 void psxBios_memcmp() { // 0x2d
1105 void psxBios_memchr() { // 0x2e
1106 char *p = (char *)Ra0;
1108 if (a0 == 0 || a2 > 0x7FFFFFFF)
1114 while ((s32)a2-- > 0) {
1115 if (*p++ != (s8)a1) continue;
1116 v0 = a0 + (p - (char *)Ra0 - 1);
1124 static void psxBios_rand() { // 0x2f
1125 u32 s = loadRam32(A_RND_SEED) * 1103515245 + 12345;
1126 storeRam32(A_RND_SEED, s);
1128 mips_return_c((s >> 16) & 0x7fff, 12+37);
1131 static void psxBios_srand() { // 0x30
1132 storeRam32(A_RND_SEED, a0);
1133 mips_return_void_c(3);
1136 static u32 qscmpfunc, qswidth;
1138 static inline int qscmp(char *a, char *b) {
1141 a0 = sa0 + (a - (char *)PSXM(sa0));
1142 a1 = sa0 + (b - (char *)PSXM(sa0));
1144 softCall(qscmpfunc);
1150 static inline void qexchange(char *i, char *j) {
1161 static inline void q3exchange(char *i, char *j, char *k) {
1173 static void qsort_main(char *a, char *l) {
1174 char *i, *j, *lp, *hp;
1179 if ((n = l - a) <= qswidth)
1181 n = qswidth * (n / (2 * qswidth));
1187 if ((c = qscmp(i, lp)) == 0) {
1188 qexchange(i, lp -= qswidth);
1199 if ((c = qscmp(hp, j)) == 0) {
1200 qexchange(hp += qswidth, j);
1205 q3exchange(i, hp += qswidth, j);
1219 if (lp - a >= l - hp) {
1220 qsort_main(hp + qswidth, l);
1229 q3exchange(j, lp -= qswidth, i);
1234 void psxBios_qsort() { // 0x31
1237 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1242 static int malloc_heap_grow(u32 size) {
1243 u32 heap_addr, heap_end, heap_addr_new;
1245 heap_addr = loadRam32(A_HEAP_BASE);
1246 heap_end = loadRam32(A_HEAP_END);
1247 heap_addr_new = heap_addr + 4 + size;
1248 if (heap_addr_new >= heap_end)
1250 storeRam32(A_HEAP_BASE, heap_addr_new);
1251 storeRam32(heap_addr - 4, size | 1);
1252 storeRam32(heap_addr + size, ~1); // terminator
1256 static void psxBios_malloc() { // 0x33
1257 u32 size = (a0 + 3) & ~3;
1258 u32 limit = 32*1024;
1262 PSXBIOS_LOG("psxBios_%s %d\n", biosA0n[0x33], a0);
1264 if (!loadRam32(A_HEAP_INIT_FLG)) {
1265 u32 heap_addr = loadRam32(A_HEAP_BASE);
1266 storeRam32(heap_addr, ~1);
1267 storeRam32(A_HEAP_FRSTCHNK, heap_addr);
1268 storeRam32(A_HEAP_CURCHNK, heap_addr);
1269 storeRam32(A_HEAP_BASE, heap_addr + 4);
1270 if (malloc_heap_grow(size)) {
1271 PSXBIOS_LOG("malloc: init OOM\n");
1272 mips_return_c(0, 20);
1275 storeRam32(A_HEAP_INIT_FLG, 1);
1278 for (i = 0; tries > 0 && i < limit; i++)
1280 u32 chunk = loadRam32(A_HEAP_CURCHNK);
1281 u32 chunk_hdr = loadRam32(chunk);
1282 u32 next_chunk = chunk + 4 + (chunk_hdr & ~3);
1283 u32 next_chunk_hdr = loadRam32(next_chunk);
1285 //printf(" c %08x %08x\n", chunk, chunk_hdr);
1286 if (chunk_hdr & 1) {
1288 if (chunk_hdr > (size | 1)) {
1290 u32 p2size = (chunk_hdr & ~3) - size - 4;
1291 storeRam32(chunk + 4 + size, p2size | 1);
1292 chunk_hdr = size | 1;
1294 if (chunk_hdr == (size | 1)) {
1295 storeRam32(chunk, size);
1299 if (next_chunk_hdr & 1) {
1301 u32 msize = (chunk_hdr & ~3) + 4 + (next_chunk_hdr & ~3);
1302 storeRam32(chunk, msize | 1);
1306 if (chunk_hdr == ~1) {
1309 storeRam32(A_HEAP_CURCHNK, loadRam32(A_HEAP_FRSTCHNK));
1313 // go to the next chunk
1314 storeRam32(A_HEAP_CURCHNK, next_chunk);
1320 else if (tries == 0 && malloc_heap_grow(size))
1323 u32 chunk = loadRam32(A_HEAP_CURCHNK);
1324 storeRam32(chunk, loadRam32(chunk) & ~3);
1328 PSXBIOS_LOG(" -> %08x\n", ret);
1329 mips_return_c(ret, 40);
1332 static void psxBios_free() { // 0x34
1333 PSXBIOS_LOG("psxBios_%s %x (%d bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1334 storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1335 mips_return_void_c(5);
1338 static void psxBios_calloc() { // 0x37
1340 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
1342 a0 = size = a0 * a1;
1346 a0 = ret; a1 = size;
1349 mips_return_c(ret, 21);
1352 void psxBios_realloc() { // 0x38
1356 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1360 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1365 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1370 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1371 /* Note that it is not quite implemented this way here. */
1381 /* InitHeap(void *block , int n) */
1382 static void psxBios_InitHeap() { // 0x39
1383 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
1385 storeRam32(A_HEAP_BASE, a0);
1386 storeRam32(A_HEAP_SIZE, a1);
1387 storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
1388 storeRam32(A_HEAP_INIT_FLG, 0);
1391 mips_return_void_c(14);
1394 void psxBios_getchar() { //0x3b
1395 v0 = getchar(); pc0 = ra;
1398 static void psxBios_printf_psxout() { // 0x3f
1401 u32 save[4] = { 0, };
1407 if (psp != INVALID_PTR) {
1408 memcpy(save, psp, 4 * 4);
1409 psxMu32ref(sp) = SWAP32((u32)a0);
1410 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1411 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1412 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1424 tmp2[j++] = Ra0[i]; goto _start;
1426 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1437 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1441 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1447 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1449 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1451 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1453 *ptmp++ = Ra0[i]; break;
1463 if (psp != INVALID_PTR)
1464 memcpy(psp, save, 4 * 4);
1467 SysPrintf("%s", tmp);
1470 void psxBios_printf() { // 0x3f
1471 psxBios_printf_psxout();
1475 static void psxBios_cd() { // 0x40
1476 const char *p, *dir = castRam8ptr(a0);
1477 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x40], a0, dir);
1478 if ((p = strchr(dir, ':')))
1482 snprintf(cdir, sizeof(cdir), "%s", dir);
1483 mips_return_c(1, 100);
1486 static void psxBios_format() { // 0x41
1487 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x41], a0, Ra0);
1488 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1490 CreateMcd(Config.Mcd1);
1491 LoadMcd(1, Config.Mcd1);
1494 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1496 CreateMcd(Config.Mcd2);
1497 LoadMcd(2, Config.Mcd2);
1507 static void psxBios_SystemErrorUnresolvedException() {
1508 if (floodchk != 0x12340a40) { // prevent log flood
1509 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1510 floodchk = 0x12340a40;
1512 mips_return_void_c(1000);
1515 static void FlushCache() {
1516 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1517 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1519 // runs from uncached mem so tons of cycles
1524 * long Load(char *name, struct EXEC *header);
1527 void psxBios_Load() { // 0x42
1535 PSXBIOS_LOG("psxBios_%s %x(%s), %x\n", biosA0n[0x42], a0, pa0, a1);
1536 if (pa0 == INVALID_PTR || pa1 == INVALID_PTR) {
1540 if ((p = strchr(pa0, ':')))
1545 snprintf(path, sizeof(path), "%s\\%s", cdir, (char *)pa0);
1547 snprintf(path, sizeof(path), "%s", (char *)pa0);
1549 if (LoadCdromFile(path, &eheader) == 0) {
1550 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1551 psxCpu->Clear(a1, sizeof(EXEC) / 4);
1555 PSXBIOS_LOG(" -> %d\n", v0);
1561 * int Exec(struct EXEC *header , int argc , char **argv);
1564 void psxBios_Exec() { // 43
1565 EXEC *header = (EXEC *)castRam32ptr(a0);
1569 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1571 header->_sp = SWAP32(sp);
1572 header->_fp = SWAP32(fp);
1573 header->_sp = SWAP32(sp);
1574 header->_gp = SWAP32(gp);
1575 header->ret = SWAP32(ra);
1576 header->base = SWAP32(s0);
1578 ptr = SWAP32(header->b_addr);
1579 len = SWAP32(header->b_size);
1585 if (header->S_addr != 0)
1586 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1588 gp = SWAP32(header->gp0);
1596 pc0 = SWAP32(header->_pc0);
1599 static void psxBios_FlushCache() { // 44
1600 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1605 void psxBios_GPU_dw() { // 0x46
1610 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1613 GPU_writeData(0xa0000000);
1614 GPU_writeData((a1<<0x10)|(a0&0xffff));
1615 GPU_writeData((a3<<0x10)|(a2&0xffff));
1617 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1620 GPU_writeData(SWAPu32(*ptr++));
1626 void psxBios_mem2vram() { // 0x47
1628 gpuSyncPluginSR(); // flush
1629 GPU_writeData(0xa0000000);
1630 GPU_writeData((a1<<0x10)|(a0&0xffff));
1631 GPU_writeData((a3<<0x10)|(a2&0xffff));
1632 size = ((((a2 * a3) / 2) >> 4) << 16);
1633 GPU_writeStatus(0x04000002);
1634 psxHwWrite32(0x1f8010f4,0);
1635 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1636 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1637 psxHwWrite32(0x1f8010a4, size | 0x10);
1638 psxHwWrite32(0x1f8010a8,0x01000201);
1643 void psxBios_SendGPU() { // 0x48
1644 GPU_writeStatus(a0);
1649 void psxBios_GPU_cw() { // 0x49
1656 void psxBios_GPU_cwb() { // 0x4a
1657 u32 *ptr = (u32*)Ra0;
1662 GPU_writeData(SWAPu32(*ptr++));
1668 void psxBios_GPU_SendPackets() { //4b:
1670 GPU_writeStatus(0x04000002);
1671 psxHwWrite32(0x1f8010f4,0);
1672 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1673 psxHwWrite32(0x1f8010a0,a0);
1674 psxHwWrite32(0x1f8010a4,0);
1675 psxHwWrite32(0x1f8010a8,0x010000401);
1679 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1680 psxHwWrite32(0x1f8010a8,0x00000401);
1681 GPU_writeData(0x0400000);
1682 GPU_writeData(0x0200000);
1683 GPU_writeData(0x0100000);
1688 void psxBios_GPU_GetGPUStatus() { // 0x4d
1689 v0 = GPU_readStatus();
1695 void psxBios_LoadExec() { // 51
1696 EXEC *header = (EXEC*)PSXM(0xf000);
1700 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1702 s_addr = a1; s_size = a2;
1707 header->S_addr = s_addr;
1708 header->s_size = s_size;
1710 a0 = 0xf000; a1 = 0; a2 = 0;
1714 void psxBios__bu_init() { // 70
1716 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1719 DeliverEvent(0xf0000011, 0x0004);
1720 DeliverEvent(0xf4000001, 0x0004);
1725 void psxBios__96_init() { // 71
1727 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1733 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1734 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1735 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1737 static void psxBios_DequeueCdIntr_() {
1738 psxBios_SysDeqIntRP_(0, 0x91d0);
1739 psxBios_SysDeqIntRP_(0, 0x91e0);
1743 static void psxBios_DequeueCdIntr() { // a3
1744 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1745 psxBios_DequeueCdIntr_();
1748 static void psxBios_CdRemove() { // 56, 72
1749 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1751 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1752 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1753 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1754 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1755 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1756 psxBios_DequeueCdIntr_();
1758 // EnterCriticalSection - should be done at the beginning,
1759 // but this way is much easier to implement
1765 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack);
1767 static void psxBios_SetConf() { // 9c
1768 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9c], a0, a1, a2);
1769 setup_tt(a1, a0, a2);
1770 psxRegs.CP0.n.SR |= 0x401;
1771 mips_return_void_c(500);
1774 static void psxBios_GetConf() { // 9d
1775 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9d], a0, a1, a2);
1776 storeRam32(a0, loadRam32(A_CONF_EvCB));
1777 storeRam32(a1, loadRam32(A_CONF_TCB));
1778 storeRam32(a2, loadRam32(A_CONF_SP));
1779 mips_return_void_c(10);
1782 void psxBios_SetMem() { // 9f
1783 u32 new = psxHu32(0x1060);
1786 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1791 psxHu32ref(0x1060) = SWAP32(new);
1792 psxMu32ref(0x060) = a0;
1793 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1797 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1798 psxMu32ref(0x060) = a0;
1799 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1802 PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
1809 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1810 static void psxBios_get_cd_status() // a6
1812 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
1817 static void psxBios__card_info() { // ab
1818 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1820 storeRam32(A_CARD_CHAN1, a0);
1827 if (McdDisable[port & 1])
1831 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
1836 if (McdDisable[0] && McdDisable[1])
1839 DeliverEvent(0xf0000011, 0x0004);
1840 // DeliverEvent(0xf4000001, 0x0004);
1841 DeliverEvent(0xf4000001, ret);
1845 void psxBios__card_load() { // ac
1847 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1850 storeRam32(A_CARD_CHAN1, a0);
1852 // DeliverEvent(0xf0000011, 0x0004);
1853 DeliverEvent(0xf4000001, 0x0004);
1858 static void psxBios_GetSystemInfo() { // b4
1860 //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
1861 SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
1864 case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
1865 case 2: ret = 0xbfc0012c; break;
1866 case 5: ret = loadRam32(0x60) << 10; break;
1868 mips_return_c(ret, 20);
1871 /* System calls B0 */
1873 static u32 psxBios_SysMalloc_(u32 size);
1875 static void psxBios_SysMalloc() { // B 00
1876 u32 ret = psxBios_SysMalloc_(a0);
1878 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1879 mips_return_c(ret, 33);
1882 void psxBios_SetRCnt() { // 02
1884 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1891 psxRcntWtarget(a0, a1);
1892 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1893 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1894 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1895 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1896 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1898 psxRcntWmode(a0, mode);
1903 void psxBios_GetRCnt() { // 03
1905 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1910 case 0: v0 = psxRcntRcount0(); break;
1911 case 1: v0 = psxRcntRcount1(); break;
1912 case 2: v0 = psxRcntRcount2(); break;
1913 case 3: v0 = 0; break;
1918 void psxBios_StartRCnt() { // 04
1920 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1924 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1925 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1929 void psxBios_StopRCnt() { // 05
1931 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1935 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1936 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1940 void psxBios_ResetRCnt() { // 06
1942 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1947 psxRcntWmode(a0, 0);
1948 psxRcntWtarget(a0, 0);
1949 psxRcntWcount(a0, 0);
1954 static u32 DeliverEvent(u32 class, u32 spec) {
1955 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1956 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1957 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1958 u32 i, lim = evcb_len / 0x1c;
1960 //printf("%s %08x %x\n", __func__, class, spec);
1961 for (i = 0; i < lim; i++, ev++) {
1963 if (SWAP32(ev->status) != EvStACTIVE)
1966 if (SWAP32(ev->class) != class)
1969 if (SWAP32(ev->spec) != spec)
1972 ret = SWAP32(ev->mode);
1973 if (ret == EvMdMARK) {
1974 ev->status = SWAP32(EvStALREADY);
1978 if (ret == EvMdCALL) {
1979 ret = SWAP32(ev->fhandler);
1992 static u32 UnDeliverEvent(u32 class, u32 spec) {
1993 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1994 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1995 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1996 u32 i, lim = evcb_len / 0x1c;
1998 for (i = 0; i < lim; i++, ev++) {
2000 if (SWAP32(ev->status) != EvStALREADY)
2003 if (SWAP32(ev->class) != class)
2006 if (SWAP32(ev->spec) != spec)
2009 if (SWAP32(ev->mode) == EvMdMARK)
2010 ev->status = SWAP32(EvStACTIVE);
2016 static void psxBios_DeliverEvent() { // 07
2018 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
2020 ret = DeliverEvent(a0, a1);
2024 static s32 get_free_EvCB_slot() {
2025 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
2026 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
2029 for (i = 0; i < lim; i++, ev++) {
2031 if (ev->status == SWAP32(EvStUNUSED))
2037 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
2038 u32 ret = get_free_EvCB_slot();
2039 if ((s32)ret >= 0) {
2040 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
2041 ev->class = SWAP32(class);
2042 ev->status = SWAP32(EvStDISABLED);
2043 ev->spec = SWAP32(spec);
2044 ev->mode = SWAP32(mode);
2045 ev->fhandler = SWAP32(func);
2051 static void psxBios_OpenEvent() { // 08
2052 u32 ret = OpenEvent(a0, a1, a2, a3);
2053 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
2054 biosB0n[0x08], a0, a1, a2, a3, ret);
2055 mips_return_c(ret, 36);
2058 static void CloseEvent(u32 ev)
2060 u32 base = loadRam32(A_TT_EvCB);
2061 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
2064 static void psxBios_CloseEvent() { // 09
2065 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
2066 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
2068 mips_return_c(1, 10);
2071 static void psxBios_WaitEvent() { // 0a
2072 u32 base = loadRam32(A_TT_EvCB);
2073 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2074 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
2077 if (status == EvStALREADY) {
2078 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2082 if (status != EvStACTIVE)
2084 mips_return_c(0, 2);
2088 // retrigger this hlecall after the next emulation event
2090 if ((s32)(next_interupt - psxRegs.cycle) > 0)
2091 psxRegs.cycle = next_interupt;
2095 static void psxBios_TestEvent() { // 0b
2096 u32 base = loadRam32(A_TT_EvCB);
2097 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2100 if (psxRegs.cycle - floodchk > 16*1024u) { // prevent log flood
2101 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
2102 floodchk = psxRegs.cycle;
2104 if (status == EvStALREADY) {
2105 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2109 mips_return_c(ret, 15);
2112 static void psxBios_EnableEvent() { // 0c
2113 u32 base = loadRam32(A_TT_EvCB);
2114 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2115 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
2116 if (status != EvStUNUSED)
2117 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2119 mips_return_c(1, 15);
2122 static void psxBios_DisableEvent() { // 0d
2123 u32 base = loadRam32(A_TT_EvCB);
2124 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2125 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2126 if (status != EvStUNUSED)
2127 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2129 mips_return_c(1, 15);
2133 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2136 void psxBios_OpenTh() { // 0e
2137 TCB *tcb = loadRam32ptr(A_TT_TCB);
2138 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2141 for (th = 1; th < limit; th++)
2143 if (tcb[th].status != SWAP32(0x4000)) break;
2147 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2148 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2150 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2152 mips_return_c(0xffffffff, 20);
2155 PSXBIOS_LOG("psxBios_%s -> %x\n", biosB0n[0x0e], 0xff000000 + th);
2157 tcb[th].status = SWAP32(0x4000);
2158 tcb[th].mode = SWAP32(0x1000);
2159 tcb[th].epc = SWAP32(a0);
2160 tcb[th].reg[30] = SWAP32(a1); // fp
2161 tcb[th].reg[29] = SWAP32(a1); // sp
2162 tcb[th].reg[28] = SWAP32(a2); // gp
2164 mips_return_c(0xff000000 + th, 34);
2168 * int CloseTh(long thread);
2171 static void psxBios_CloseTh() { // 0f
2172 u32 tcb = loadRam32(A_TT_TCB);
2173 u32 th = a0 & 0xffff;
2175 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x0f], a0);
2176 // in the usual bios fashion no checks, just write and return 1
2177 storeRam32(tcb + th * sizeof(TCB), 0x1000);
2179 mips_return_c(1, 11);
2183 * int ChangeTh(long thread);
2186 void psxBios_ChangeTh() { // 10
2187 u32 tcbBase = loadRam32(A_TT_TCB);
2188 u32 th = a0 & 0xffff;
2190 // this is quite spammy
2191 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2193 // without doing any argument checks, just issue a syscall
2194 // (like the real bios does)
2196 a1 = tcbBase + th * sizeof(TCB);
2201 void psxBios_InitPAD() { // 0x12
2202 u32 i, *ram32 = (u32 *)psxM;
2203 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2205 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2206 ram32[A_PAD_DR_DST/4] = 0;
2207 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2208 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2209 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2210 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2211 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2212 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2213 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2214 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2216 for (i = 0; i < a1; i++) {
2218 storeRam8(a0 + i, 0);
2220 for (i = 0; i < a3; i++) {
2222 storeRam8(a2 + i, 0);
2224 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2226 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2228 mips_return_c(1, 200);
2231 void psxBios_StartPAD() { // 13
2232 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2234 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2235 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2236 psxHwWrite16(0x1f801070, ~1);
2237 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2238 storeRam32(A_PAD_ACK_VBL, 1);
2239 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2240 psxRegs.CP0.n.SR |= 0x401;
2242 mips_return_c(1, 300);
2245 void psxBios_StopPAD() { // 14
2246 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2247 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2248 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2249 psxRegs.CP0.n.SR |= 0x401;
2250 mips_return_void_c(200);
2253 static void psxBios_PAD_init() { // 15
2255 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2256 if (a0 == 0x20000000 || a0 == 0x20000001)
2259 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2260 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2263 storeRam32(A_PAD_DR_DST, dst);
2266 mips_return_c(ret, 100);
2269 static u32 psxBios_PAD_dr_() {
2270 u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2271 u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2272 u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2273 dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2274 if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2276 dst[0] = buf1[3], dst[1] = buf1[2];
2277 if (buf1[1] == 0x23) {
2278 dst[0] |= 0xc7, dst[1] |= 7;
2279 if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2280 if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2283 if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2285 dst[2] = buf2[3], dst[3] = buf2[2];
2286 if (buf2[1] == 0x23) {
2287 dst[2] |= 0xc7, dst[3] |= 7;
2288 if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2289 if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2293 return SWAP32(*(u32 *)dst);
2296 static void psxBios_PAD_dr() { // 16
2297 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2298 u32 ret = psxBios_PAD_dr_();
2302 static void psxBios_ReturnFromException() { // 17
2303 u32 tcbPtr = loadRam32(A_TT_PCB);
2304 const TCB *tcb = loadRam32ptr(tcbPtr);
2308 for (i = 1; i < 32; i++)
2309 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2310 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2311 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2312 sr = SWAP32(tcb->sr);
2314 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2315 pc0 = k0 = SWAP32(tcb->epc);
2317 // the interpreter wants to know about sr changes, so do a MTC0
2318 sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2319 MTC0(&psxRegs, 12, sr);
2325 void psxBios_ResetEntryInt() { // 18
2326 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2328 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2329 mips_return_void_c(5);
2332 void psxBios_HookEntryInt() { // 19
2333 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2335 storeRam32(A_EEXIT_PTR, a0);
2336 mips_return_void_c(3);
2339 static void psxBios_UnDeliverEvent() { // 0x20
2341 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2343 ret = UnDeliverEvent(a0, a1);
2347 static void buopen(int mcd, char *ptr, char *cfg)
2350 char *mcd_data = ptr;
2352 strcpy(FDesc[1 + mcd].name, Ra0+5);
2353 FDesc[1 + mcd].offset = 0;
2354 FDesc[1 + mcd].mode = a1;
2356 for (i=1; i<16; i++) {
2357 const char *fptr = mcd_data + 128 * i;
2358 if ((*fptr & 0xF0) != 0x50) continue;
2359 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2360 FDesc[1 + mcd].mcfile = i;
2361 PSXBIOS_LOG("open %s\n", fptr+0xa);
2365 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2366 for (i=1; i<16; i++) {
2367 int j, xor, nblk = a1 >> 16;
2369 char *fptr = mcd_data + 128 * i;
2371 if ((*fptr & 0xF0) != 0xa0) continue;
2373 FDesc[1 + mcd].mcfile = i;
2376 fptr[5] = 0x20 * nblk;
2379 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2380 pptr = fptr2 = fptr;
2381 for(j=2; j<=nblk; j++) {
2383 for(i++; i<16; i++) {
2386 memset(fptr2, 0, 128);
2387 fptr2[0] = j < nblk ? 0x52 : 0x53;
2390 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2395 /* shouldn't this return ENOSPC if i == 16? */
2397 pptr[8] = pptr[9] = 0xff;
2398 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2400 PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2402 /* just go ahead and resave them all */
2403 SaveMcd(cfg, ptr, 128, 128 * 15);
2406 /* shouldn't this return ENOSPC if i == 16? */
2411 * int open(char *name , int mode);
2414 void psxBios_open() { // 0x32
2417 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x32], Ra0, a1);
2421 if (pa0 != INVALID_PTR) {
2422 if (!strncmp(pa0, "bu00", 4)) {
2423 buopen(1, Mcd1Data, Config.Mcd1);
2426 if (!strncmp(pa0, "bu10", 4)) {
2427 buopen(2, Mcd2Data, Config.Mcd2);
2435 * int lseek(int fd , int offset , int whence);
2438 void psxBios_lseek() { // 0x33
2440 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2445 FDesc[a0].offset = a1;
2447 // DeliverEvent(0xf0000011, 0x0004);
2448 // DeliverEvent(0xf4000001, 0x0004);
2452 FDesc[a0].offset+= a1;
2453 v0 = FDesc[a0].offset;
2462 * int read(int fd , void *buf , int nbytes);
2465 void psxBios_read() { // 0x34
2470 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2475 if (pa1 != INVALID_PTR) {
2477 case 2: buread(pa1, 1, a2); break;
2478 case 3: buread(pa1, 2, a2); break;
2486 * int write(int fd , void *buf , int nbytes);
2489 void psxBios_write() { // 0x35/0x03
2493 if (a0 != 1) // stdout
2494 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2497 if (pa1 == INVALID_PTR) {
2502 if (a0 == 1) { // stdout
2506 if (Config.PsxOut) while (a2 > 0) {
2507 SysPrintf("%c", *ptr++); a2--;
2513 case 2: buwrite(pa1, 1, a2); break;
2514 case 3: buwrite(pa1, 2, a2); break;
2520 static void psxBios_write_psxout() {
2521 if (a0 == 1) { // stdout
2522 const char *ptr = Ra1;
2525 if (ptr != INVALID_PTR)
2527 SysPrintf("%c", *ptr++);
2531 static void psxBios_putchar_psxout() { // 3d
2532 SysPrintf("%c", (char)a0);
2535 static void psxBios_puts_psxout() { // 3e/3f
2536 SysPrintf("%s", Ra0);
2540 * int close(int fd);
2543 void psxBios_close() { // 0x36
2545 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2552 void psxBios_putchar() { // 3d
2553 if (Config.PsxOut) SysPrintf("%c", (char)a0);
2557 void psxBios_puts() { // 3e/3f
2558 if (Config.PsxOut) SysPrintf("%s", Ra0);
2562 static void bufile(const u8 *mcd_data, u32 dir_) {
2563 struct DIRENTRY *dir = (struct DIRENTRY *)castRam8ptr(dir_);
2564 const char *pfile = ffile + 5;
2565 const u8 *data = mcd_data;
2566 int i = 0, match = 0;
2571 for (; nfile <= 15 && !match; nfile++) {
2574 head = nfile * 0x40;
2575 data = mcd_data + 128 * nfile;
2576 name = (const char *)data + 0x0a;
2577 if ((data[0] & 0xF0) != 0x50) continue;
2578 /* Bug link files show up as free block. */
2579 if (!name[0]) continue;
2581 for (i = 0; i < 20; i++) {
2582 if (pfile[i] == name[i] || pfile[i] == '?')
2583 dir->name[i] = name[i];
2584 else if (pfile[i] == '*') {
2585 int len = strlen(name + i);
2588 memcpy(dir->name + i, name + i, len + 1);
2599 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n",
2600 nfile, dir->name, pfile, name, match);
2602 for (; nfile <= 15; nfile++, blocks++) {
2603 const u8 *data2 = mcd_data + 128 * nfile;
2604 const char *name = (const char *)data2 + 0x0a;
2605 if ((data2[0] & 0xF0) != 0x50 || name[0])
2609 // nul char of full lenth name seems to overwrite .attr
2610 dir->attr = SWAP32(i < 20 ? data[0] & 0xf0 : 0); // ?
2611 dir->size = 8192 * blocks;
2615 PSXBIOS_LOG(" -> %x '%s' %x %x %x %x\n", v0, v0 ? dir->name : "",
2616 dir->attr, dir->size, dir->next, dir->head);
2620 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2623 static void psxBios_firstfile() { // 42
2624 char *pa0 = castRam8ptr(a0);
2626 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x42], pa0, a1);
2630 snprintf(ffile, sizeof(ffile), "%s", pa0);
2632 strcpy(ffile + 5, "*"); // maybe?
2634 if (!strncmp(pa0, "bu00", 4)) {
2635 // firstfile() calls _card_read() internally, so deliver it's event
2636 DeliverEvent(0xf0000011, 0x0004);
2637 bufile((u8 *)Mcd1Data, a1);
2638 } else if (!strncmp(pa0, "bu10", 4)) {
2639 // firstfile() calls _card_read() internally, so deliver it's event
2640 DeliverEvent(0xf0000011, 0x0004);
2641 bufile((u8 *)Mcd2Data, a1);
2649 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2652 void psxBios_nextfile() { // 43
2653 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x43], a0);
2656 if (!strncmp(ffile, "bu00", 4))
2657 bufile((u8 *)Mcd1Data, a0);
2658 else if (!strncmp(ffile, "bu10", 4))
2659 bufile((u8 *)Mcd2Data, a0);
2664 #define burename(mcd) { \
2665 for (i=1; i<16; i++) { \
2666 int namelen, j, xor = 0; \
2667 ptr = Mcd##mcd##Data + 128 * i; \
2668 if ((*ptr & 0xF0) != 0x50) continue; \
2669 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2670 namelen = strlen(Ra1+5); \
2671 memcpy(ptr+0xa, Ra1+5, namelen); \
2672 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2673 for (j=0; j<127; j++) xor^= ptr[j]; \
2675 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2682 * int rename(char *old, char *new);
2685 void psxBios_rename() { // 44
2692 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2697 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2698 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2702 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2711 #define budelete(mcd) { \
2712 for (i=1; i<16; i++) { \
2713 ptr = Mcd##mcd##Data + 128 * i; \
2714 if ((*ptr & 0xF0) != 0x50) continue; \
2715 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2716 *ptr = (*ptr & 0xf) | 0xA0; \
2717 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2718 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2725 * int delete(char *name);
2728 void psxBios_delete() { // 45
2734 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2739 if (pa0 != INVALID_PTR) {
2740 if (!strncmp(pa0, "bu00", 4)) {
2744 if (!strncmp(pa0, "bu10", 4)) {
2752 void psxBios_InitCARD() { // 4a
2753 u32 *ram32 = (u32 *)psxM;
2754 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2755 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2756 // (maybe) todo: early_card_irq, etc
2758 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2760 psxBios_FlushCache();
2761 mips_return_c(0, 34+13+15+6);
2764 void psxBios_StartCARD() { // 4b
2765 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2766 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2767 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2769 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2770 storeRam32(A_PAD_ACK_VBL, 1);
2771 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2772 storeRam32(A_CARD_IRQR_ENA, 1);
2773 psxRegs.CP0.n.SR |= 0x401;
2775 mips_return_c(1, 200);
2778 void psxBios_StopCARD() { // 4c
2779 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2780 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2781 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2782 storeRam32(A_CARD_IRQR_ENA, 0);
2783 psxRegs.CP0.n.SR |= 0x401;
2784 mips_return_void_c(200);
2787 void psxBios__card_write() { // 0x4e
2792 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2795 Function also accepts sector 400h (a bug).
2796 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2800 /* Invalid sectors */
2804 storeRam32(A_CARD_CHAN1, a0);
2807 if (pa2 != INVALID_PTR) {
2809 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2810 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2812 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2813 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2817 DeliverEvent(0xf0000011, 0x0004);
2818 // DeliverEvent(0xf4000001, 0x0004);
2823 void psxBios__card_read() { // 0x4f
2828 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2831 Function also accepts sector 400h (a bug).
2832 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2836 /* Invalid sectors */
2840 storeRam32(A_CARD_CHAN1, a0);
2843 if (pa2 != INVALID_PTR) {
2845 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2847 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2851 DeliverEvent(0xf0000011, 0x0004);
2852 // DeliverEvent(0xf4000001, 0x0004);
2857 void psxBios__new_card() { // 0x50
2859 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2865 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2866 void psxBios__get_error(void) // 55
2868 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2873 void psxBios_Krom2RawAdd() { // 0x51
2876 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2877 const u32 table_8140[][2] = {
2878 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2879 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2880 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2881 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2882 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2883 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2884 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2885 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2886 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2890 const u32 table_889f[][2] = {
2891 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2892 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2893 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2894 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2895 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2896 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2897 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2898 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2902 if (a0 >= 0x8140 && a0 <= 0x84be) {
2903 while (table_8140[i][0] <= a0) i++;
2904 a0 -= table_8140[i - 1][0];
2905 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2906 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2907 while (table_889f[i][0] <= a0) i++;
2908 a0 -= table_889f[i - 1][0];
2909 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2917 void psxBios_GetC0Table() { // 56
2918 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2919 log_unhandled("GetC0Table @%08x\n", ra);
2921 mips_return_c(A_C0_TABLE, 3);
2924 void psxBios_GetB0Table() { // 57
2925 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2926 log_unhandled("GetB0Table @%08x\n", ra);
2928 mips_return_c(A_B0_TABLE, 3);
2931 static void psxBios__card_chan() { // 0x58
2933 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2935 // todo: should return active slot chan
2936 // (active - which was last processed by irq code)
2937 ret = loadRam32(A_CARD_CHAN1);
2938 mips_return_c(ret, 8);
2941 static void psxBios_ChangeClearPad() { // 5b
2943 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2944 ret = loadRam32(A_PAD_ACK_VBL);
2945 storeRam32(A_PAD_ACK_VBL, a0);
2947 mips_return_c(ret, 6);
2950 static void psxBios__card_status() { // 5c
2951 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
2957 static void psxBios__card_wait() { // 5d
2958 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
2964 /* System calls C0 */
2966 static void psxBios_InitRCnt() { // 00
2968 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2969 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2970 for (i = 0; i < 3; i++) {
2971 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2972 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2973 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2975 psxBios_SysEnqIntRP_(a0, 0x6d88);
2976 mips_return_c(0, 9);
2979 static void psxBios_InitException() { // 01
2980 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2981 psxBios_SysEnqIntRP_(a0, 0x6da8);
2982 mips_return_c(0, 9);
2986 * int SysEnqIntRP(int index , long *queue);
2989 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2990 u32 old, base = loadRam32(A_TT_ExCB);
2992 old = loadRam32(base + (priority << 3));
2993 storeRam32(base + (priority << 3), chain_eptr);
2994 storeRam32(chain_eptr, old);
2995 mips_return_c(0, 9);
2998 static void psxBios_SysEnqIntRP() { // 02
2999 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
3000 psxBios_SysEnqIntRP_(a0, a1);
3004 * int SysDeqIntRP(int index , long *queue);
3007 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
3008 u32 ptr, next, base = loadRam32(A_TT_ExCB);
3009 u32 lim = 0, ret = 0;
3011 // as in original: no arg checks of any kind, bug if a1 == 0
3012 ptr = loadRam32(base + (priority << 3));
3014 next = loadRam32(ptr);
3015 if (ptr == chain_rm_eptr) {
3016 storeRam32(base + (priority << 3), next);
3021 while (next && next != chain_rm_eptr && lim++ < 100) {
3023 next = loadRam32(ptr);
3026 if (next == chain_rm_eptr) {
3027 next = loadRam32(next);
3028 storeRam32(ptr, next);
3035 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
3037 mips_return_c(ret, 12);
3040 static void psxBios_SysDeqIntRP() { // 03
3041 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
3042 psxBios_SysDeqIntRP_(a0, a1);
3045 static void psxBios_get_free_EvCB_slot() { // 04
3046 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
3047 s32 ret = get_free_EvCB_slot();
3048 mips_return_c(ret, 0);
3051 static void psxBios_SysInitMemory_(u32 base, u32 size) {
3052 storeRam32(base, 0);
3053 storeRam32(A_KMALLOC_PTR, base);
3054 storeRam32(A_KMALLOC_SIZE, size);
3055 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
3058 // this should be much more complicated, but maybe that'll be enough
3059 static u32 psxBios_SysMalloc_(u32 size) {
3060 u32 ptr = loadRam32(A_KMALLOC_PTR);
3062 size = (size + 3) & ~3;
3063 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
3064 storeRam32(ptr, size);
3068 static void psxBios_SysInitMemory() { // 08
3069 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
3071 psxBios_SysInitMemory_(a0, a1);
3072 mips_return_void_c(12);
3075 static void psxBios_ChangeClearRCnt() { // 0a
3078 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
3080 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
3081 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
3082 mips_return_c(ret, 8);
3085 static void psxBios_InitDefInt() { // 0c
3086 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3087 // should also clear the autoack table
3088 psxBios_SysEnqIntRP_(a0, 0x6d98);
3089 mips_return_c(0, 20 + 6*2);
3092 void psxBios_dummy() {
3093 u32 pc = (pc0 & 0x1fffff) - 4;
3094 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
3095 : pc == 0xc0 ? biosC0n : NULL;
3096 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
3097 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
3098 (void)pc; (void)ntab;
3099 mips_return_c(0, 100);
3102 void (*biosA0[256])();
3103 // C0 and B0 overlap (end of C0 is start of B0)
3104 void (*biosC0[256+128])();
3105 void (**biosB0)() = biosC0 + 128;
3107 static void setup_mips_code()
3110 ptr = (u32 *)&psxM[A_SYSCALL];
3111 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3112 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
3113 ptr[0x08/4] = SWAPu32(0x00000000); // nop
3115 ptr = (u32 *)&psxM[A_EXCEPTION];
3116 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
3117 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
3118 ptr[0x14/4] = SWAPu32(0x00000000); // nop
3119 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
3120 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3121 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
3122 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
3123 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
3124 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
3125 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
3127 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
3128 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
3129 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
3131 ptr[0xb0/4] = HLEOP(hleop_exception);
3134 static const struct {
3138 { 0xbfc050a4, hleop_exc0_0_1 },
3139 { 0xbfc04fbc, hleop_exc0_0_2 },
3140 { 0xbfc0506c, hleop_exc0_1_1 },
3141 { 0xbfc04dec, hleop_exc0_1_2 },
3142 { 0x1a00, hleop_exc0_2_2 },
3143 { 0x19c8, hleop_exc1_0_1 },
3144 { 0x18bc, hleop_exc1_0_2 },
3145 { 0x1990, hleop_exc1_1_1 },
3146 { 0x1858, hleop_exc1_1_2 },
3147 { 0x1958, hleop_exc1_2_1 },
3148 { 0x17f4, hleop_exc1_2_2 },
3149 { 0x1920, hleop_exc1_3_1 },
3150 { 0x1794, hleop_exc1_3_2 },
3151 { 0x2458, hleop_exc3_0_2 },
3152 { 0x49bc, hleop_exc_padcard1 },
3153 { 0x4a4c, hleop_exc_padcard2 },
3156 static int chain_hle_op(u32 handler)
3160 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3161 if (chainfns[i].addr == handler)
3162 return chainfns[i].op;
3166 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3168 d[0] = SWAPu32(next);
3169 d[1] = SWAPu32(handler1);
3170 d[2] = SWAPu32(handler2);
3172 // install the hle traps
3173 if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3174 if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3177 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack)
3179 u32 *ram32 = (u32 *)psxM;
3180 u32 s_excb = 0x20, s_evcb, s_pcb = 4, s_tcb;
3181 u32 p_excb, p_evcb, p_pcb, p_tcb;
3184 PSXBIOS_LOG("setup: tcb %u, evcb %u\n", tcb_cnt, evcb_cnt);
3186 // the real bios doesn't care, but we just don't
3187 // want to crash in case of garbage parameters
3188 if (tcb_cnt > 1024) tcb_cnt = 1024;
3189 if (evcb_cnt > 1024) evcb_cnt = 1024;
3190 s_evcb = 0x1c * evcb_cnt;
3191 s_tcb = 0xc0 * tcb_cnt;
3193 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3194 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3195 p_excb = psxBios_SysMalloc_(s_excb);
3196 p_evcb = psxBios_SysMalloc_(s_evcb);
3197 p_pcb = psxBios_SysMalloc_(s_pcb);
3198 p_tcb = psxBios_SysMalloc_(s_tcb);
3200 // "table of tables". Some games modify it
3201 assert(A_TT_ExCB == 0x0100);
3202 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3203 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3204 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3205 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3206 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3207 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3208 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3209 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3210 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3211 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3212 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3213 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3215 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3216 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3217 storeRam32(p_excb + 4*4, 0x0000); // chain2
3218 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3220 storeRam32(p_pcb, p_tcb);
3221 storeRam32(p_tcb, 0x4000); // first TCB
3222 for (i = 1; i < tcb_cnt; i++)
3223 storeRam32(p_tcb + sizeof(TCB) * i, 0x1000);
3226 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3227 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3228 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3229 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3230 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3232 storeRam32(A_CONF_EvCB, evcb_cnt);
3233 storeRam32(A_CONF_TCB, tcb_cnt);
3234 storeRam32(A_CONF_SP, stack);
3237 static const u32 gpu_ctl_def[] = {
3238 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3239 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3242 static const u32 gpu_data_def[] = {
3243 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3244 0xe5001000, 0xe6000000,
3245 0x02000000, 0x00000000, 0x01ff03ff
3249 static const u16 spu_config[] = {
3250 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3251 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3252 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3253 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3254 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3255 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3256 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3257 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3260 void psxBiosSetupBootState(void)
3262 boolean hle = Config.HLE;
3263 u32 *hw = (u32 *)psxH;
3266 // see also SetBootRegs()
3269 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3270 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3272 k0 = 0xbfc0d968; k1 = 0xf1c;
3273 ra = 0xf0001234; // just to easily detect attempts to return
3274 psxRegs.CP0.n.Cause = 0x20;
3275 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3277 hw[0x1000/4] = SWAP32(0x1f000000);
3278 hw[0x1004/4] = SWAP32(0x1f802000);
3279 hw[0x1008/4] = SWAP32(0x0013243f);
3280 hw[0x100c/4] = SWAP32(0x00003022);
3281 hw[0x1010/4] = SWAP32(0x0013243f);
3282 hw[0x1014/4] = SWAP32(0x200931e1);
3283 hw[0x1018/4] = SWAP32(0x00020943);
3284 hw[0x101c/4] = SWAP32(0x00070777);
3285 hw[0x1020/4] = SWAP32(0x0000132c);
3286 hw[0x1060/4] = SWAP32(0x00000b88);
3287 hw[0x1070/4] = SWAP32(0x00000001);
3288 hw[0x1074/4] = SWAP32(0x0000000c);
3289 hw[0x2040/4] = SWAP32(0x00000900);
3292 hw[0x10a0/4] = SWAP32(0x00ffffff);
3293 hw[0x10a8/4] = SWAP32(0x00000401);
3294 hw[0x10b0/4] = SWAP32(0x0008b000);
3295 hw[0x10b4/4] = SWAP32(0x00010200);
3296 hw[0x10e0/4] = SWAP32(0x000eccf4);
3297 hw[0x10e4/4] = SWAP32(0x00000400);
3298 hw[0x10e8/4] = SWAP32(0x00000002);
3299 hw[0x10f0/4] = SWAP32(0x00009099);
3300 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3309 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3310 GPU_writeStatus(gpu_ctl_def[i]);
3311 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3312 GPU_writeData(gpu_data_def[i]);
3313 HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
3316 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3317 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3320 static void hleExc0_0_1();
3321 static void hleExc0_0_2();
3322 static void hleExc0_1_1();
3323 static void hleExc0_1_2();
3325 #include "sjisfont.h"
3327 void psxBiosInit() {
3328 u32 *ptr, *ram32, *rom32;
3333 memset(psxM, 0, 0x10000);
3334 for(i = 0; i < 256; i++) {
3339 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3340 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3341 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3342 biosA0[0x3f] = psxBios_printf_psxout;
3345 char verstr[0x24+1];
3346 rom32 = (u32 *)psxR;
3347 memcpy(verstr, psxR + 0x12c, 0x24);
3349 SysPrintf("BIOS: %08x, '%s', '%c'\n", SWAP32(rom32[0x100/4]),
3350 verstr, psxR[0x7ff52]);
3354 for(i = 0; i < 256; i++) {
3355 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3356 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3357 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3360 biosA0[0x00] = psxBios_open;
3361 biosA0[0x01] = psxBios_lseek;
3362 biosA0[0x02] = psxBios_read;
3363 biosA0[0x03] = psxBios_write;
3364 biosA0[0x04] = psxBios_close;
3365 //biosA0[0x05] = psxBios_ioctl;
3366 //biosA0[0x06] = psxBios_exit;
3367 //biosA0[0x07] = psxBios_sys_a0_07;
3368 biosA0[0x08] = psxBios_getc;
3369 biosA0[0x09] = psxBios_putc;
3370 biosA0[0x0a] = psxBios_todigit;
3371 //biosA0[0x0b] = psxBios_atof;
3372 //biosA0[0x0c] = psxBios_strtoul;
3373 //biosA0[0x0d] = psxBios_strtol;
3374 biosA0[0x0e] = psxBios_abs;
3375 biosA0[0x0f] = psxBios_labs;
3376 biosA0[0x10] = psxBios_atoi;
3377 biosA0[0x11] = psxBios_atol;
3378 //biosA0[0x12] = psxBios_atob;
3379 biosA0[0x13] = psxBios_setjmp;
3380 biosA0[0x14] = psxBios_longjmp;
3381 biosA0[0x15] = psxBios_strcat;
3382 biosA0[0x16] = psxBios_strncat;
3383 biosA0[0x17] = psxBios_strcmp;
3384 biosA0[0x18] = psxBios_strncmp;
3385 biosA0[0x19] = psxBios_strcpy;
3386 biosA0[0x1a] = psxBios_strncpy;
3387 biosA0[0x1b] = psxBios_strlen;
3388 biosA0[0x1c] = psxBios_index;
3389 biosA0[0x1d] = psxBios_rindex;
3390 biosA0[0x1e] = psxBios_strchr;
3391 biosA0[0x1f] = psxBios_strrchr;
3392 biosA0[0x20] = psxBios_strpbrk;
3393 biosA0[0x21] = psxBios_strspn;
3394 biosA0[0x22] = psxBios_strcspn;
3395 biosA0[0x23] = psxBios_strtok;
3396 biosA0[0x24] = psxBios_strstr;
3397 biosA0[0x25] = psxBios_toupper;
3398 biosA0[0x26] = psxBios_tolower;
3399 biosA0[0x27] = psxBios_bcopy;
3400 biosA0[0x28] = psxBios_bzero;
3401 biosA0[0x29] = psxBios_bcmp;
3402 biosA0[0x2a] = psxBios_memcpy;
3403 biosA0[0x2b] = psxBios_memset;
3404 biosA0[0x2c] = psxBios_memmove;
3405 biosA0[0x2d] = psxBios_memcmp;
3406 biosA0[0x2e] = psxBios_memchr;
3407 biosA0[0x2f] = psxBios_rand;
3408 biosA0[0x30] = psxBios_srand;
3409 biosA0[0x31] = psxBios_qsort;
3410 //biosA0[0x32] = psxBios_strtod;
3411 biosA0[0x33] = psxBios_malloc;
3412 biosA0[0x34] = psxBios_free;
3413 //biosA0[0x35] = psxBios_lsearch;
3414 //biosA0[0x36] = psxBios_bsearch;
3415 biosA0[0x37] = psxBios_calloc;
3416 biosA0[0x38] = psxBios_realloc;
3417 biosA0[0x39] = psxBios_InitHeap;
3418 //biosA0[0x3a] = psxBios__exit;
3419 biosA0[0x3b] = psxBios_getchar;
3420 biosA0[0x3c] = psxBios_putchar;
3421 //biosA0[0x3d] = psxBios_gets;
3422 biosA0[0x3e] = psxBios_puts;
3423 biosA0[0x3f] = psxBios_printf;
3424 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3425 //biosA0[0x41] = psxBios_LoadTest;
3426 biosA0[0x42] = psxBios_Load;
3427 biosA0[0x43] = psxBios_Exec;
3428 biosA0[0x44] = psxBios_FlushCache;
3429 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3430 biosA0[0x46] = psxBios_GPU_dw;
3431 biosA0[0x47] = psxBios_mem2vram;
3432 biosA0[0x48] = psxBios_SendGPU;
3433 biosA0[0x49] = psxBios_GPU_cw;
3434 biosA0[0x4a] = psxBios_GPU_cwb;
3435 biosA0[0x4b] = psxBios_GPU_SendPackets;
3436 biosA0[0x4c] = psxBios_sys_a0_4c;
3437 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3438 //biosA0[0x4e] = psxBios_GPU_sync;
3439 //biosA0[0x4f] = psxBios_sys_a0_4f;
3440 //biosA0[0x50] = psxBios_sys_a0_50;
3441 biosA0[0x51] = psxBios_LoadExec;
3442 //biosA0[0x52] = psxBios_GetSysSp;
3443 //biosA0[0x53] = psxBios_sys_a0_53;
3444 //biosA0[0x54] = psxBios__96_init_a54;
3445 //biosA0[0x55] = psxBios__bu_init_a55;
3446 biosA0[0x56] = psxBios_CdRemove;
3447 //biosA0[0x57] = psxBios_sys_a0_57;
3448 //biosA0[0x58] = psxBios_sys_a0_58;
3449 //biosA0[0x59] = psxBios_sys_a0_59;
3450 //biosA0[0x5a] = psxBios_sys_a0_5a;
3451 //biosA0[0x5b] = psxBios_dev_tty_init;
3452 //biosA0[0x5c] = psxBios_dev_tty_open;
3453 //biosA0[0x5d] = psxBios_sys_a0_5d;
3454 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3455 //biosA0[0x5f] = psxBios_dev_cd_open;
3456 //biosA0[0x60] = psxBios_dev_cd_read;
3457 //biosA0[0x61] = psxBios_dev_cd_close;
3458 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3459 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3460 //biosA0[0x64] = psxBios_dev_cd_chdir;
3461 //biosA0[0x65] = psxBios_dev_card_open;
3462 //biosA0[0x66] = psxBios_dev_card_read;
3463 //biosA0[0x67] = psxBios_dev_card_write;
3464 //biosA0[0x68] = psxBios_dev_card_close;
3465 //biosA0[0x69] = psxBios_dev_card_firstfile;
3466 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3467 //biosA0[0x6b] = psxBios_dev_card_erase;
3468 //biosA0[0x6c] = psxBios_dev_card_undelete;
3469 //biosA0[0x6d] = psxBios_dev_card_format;
3470 //biosA0[0x6e] = psxBios_dev_card_rename;
3471 //biosA0[0x6f] = psxBios_dev_card_6f;
3472 biosA0[0x70] = psxBios__bu_init;
3473 biosA0[0x71] = psxBios__96_init;
3474 biosA0[0x72] = psxBios_CdRemove;
3475 //biosA0[0x73] = psxBios_sys_a0_73;
3476 //biosA0[0x74] = psxBios_sys_a0_74;
3477 //biosA0[0x75] = psxBios_sys_a0_75;
3478 //biosA0[0x76] = psxBios_sys_a0_76;
3479 //biosA0[0x77] = psxBios_sys_a0_77;
3480 //biosA0[0x78] = psxBios__96_CdSeekL;
3481 //biosA0[0x79] = psxBios_sys_a0_79;
3482 //biosA0[0x7a] = psxBios_sys_a0_7a;
3483 //biosA0[0x7b] = psxBios_sys_a0_7b;
3484 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3485 //biosA0[0x7d] = psxBios_sys_a0_7d;
3486 //biosA0[0x7e] = psxBios__96_CdRead;
3487 //biosA0[0x7f] = psxBios_sys_a0_7f;
3488 //biosA0[0x80] = psxBios_sys_a0_80;
3489 //biosA0[0x81] = psxBios_sys_a0_81;
3490 //biosA0[0x82] = psxBios_sys_a0_82;
3491 //biosA0[0x83] = psxBios_sys_a0_83;
3492 //biosA0[0x84] = psxBios_sys_a0_84;
3493 //biosA0[0x85] = psxBios__96_CdStop;
3494 //biosA0[0x86] = psxBios_sys_a0_86;
3495 //biosA0[0x87] = psxBios_sys_a0_87;
3496 //biosA0[0x88] = psxBios_sys_a0_88;
3497 //biosA0[0x89] = psxBios_sys_a0_89;
3498 //biosA0[0x8a] = psxBios_sys_a0_8a;
3499 //biosA0[0x8b] = psxBios_sys_a0_8b;
3500 //biosA0[0x8c] = psxBios_sys_a0_8c;
3501 //biosA0[0x8d] = psxBios_sys_a0_8d;
3502 //biosA0[0x8e] = psxBios_sys_a0_8e;
3503 //biosA0[0x8f] = psxBios_sys_a0_8f;
3504 biosA0[0x90] = hleExc0_1_2;
3505 biosA0[0x91] = hleExc0_0_2;
3506 biosA0[0x92] = hleExc0_1_1;
3507 biosA0[0x93] = hleExc0_0_1;
3508 //biosA0[0x94] = psxBios_sys_a0_94;
3509 //biosA0[0x95] = psxBios_sys_a0_95;
3510 //biosA0[0x96] = psxBios_AddCDROMDevice;
3511 //biosA0[0x97] = psxBios_AddMemCardDevide;
3512 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3513 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3514 //biosA0[0x9a] = psxBios_sys_a0_9a;
3515 //biosA0[0x9b] = psxBios_sys_a0_9b;
3516 biosA0[0x9c] = psxBios_SetConf;
3517 biosA0[0x9d] = psxBios_GetConf;
3518 //biosA0[0x9e] = psxBios_sys_a0_9e;
3519 biosA0[0x9f] = psxBios_SetMem;
3520 //biosA0[0xa0] = psxBios__boot;
3521 //biosA0[0xa1] = psxBios_SystemError;
3522 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3523 biosA0[0xa3] = psxBios_DequeueCdIntr;
3524 //biosA0[0xa4] = psxBios_sys_a0_a4;
3525 //biosA0[0xa5] = psxBios_ReadSector;
3526 biosA0[0xa6] = psxBios_get_cd_status;
3527 //biosA0[0xa7] = psxBios_bufs_cb_0;
3528 //biosA0[0xa8] = psxBios_bufs_cb_1;
3529 //biosA0[0xa9] = psxBios_bufs_cb_2;
3530 //biosA0[0xaa] = psxBios_bufs_cb_3;
3531 biosA0[0xab] = psxBios__card_info;
3532 biosA0[0xac] = psxBios__card_load;
3533 //biosA0[0axd] = psxBios__card_auto;
3534 //biosA0[0xae] = psxBios_bufs_cd_4;
3535 //biosA0[0xaf] = psxBios_sys_a0_af;
3536 //biosA0[0xb0] = psxBios_sys_a0_b0;
3537 //biosA0[0xb1] = psxBios_sys_a0_b1;
3538 //biosA0[0xb2] = psxBios_do_a_long_jmp
3539 //biosA0[0xb3] = psxBios_sys_a0_b3;
3540 biosA0[0xb4] = psxBios_GetSystemInfo;
3541 //*******************B0 CALLS****************************
3542 biosB0[0x00] = psxBios_SysMalloc;
3543 //biosB0[0x01] = psxBios_sys_b0_01;
3544 biosB0[0x02] = psxBios_SetRCnt;
3545 biosB0[0x03] = psxBios_GetRCnt;
3546 biosB0[0x04] = psxBios_StartRCnt;
3547 biosB0[0x05] = psxBios_StopRCnt;
3548 biosB0[0x06] = psxBios_ResetRCnt;
3549 biosB0[0x07] = psxBios_DeliverEvent;
3550 biosB0[0x08] = psxBios_OpenEvent;
3551 biosB0[0x09] = psxBios_CloseEvent;
3552 biosB0[0x0a] = psxBios_WaitEvent;
3553 biosB0[0x0b] = psxBios_TestEvent;
3554 biosB0[0x0c] = psxBios_EnableEvent;
3555 biosB0[0x0d] = psxBios_DisableEvent;
3556 biosB0[0x0e] = psxBios_OpenTh;
3557 biosB0[0x0f] = psxBios_CloseTh;
3558 biosB0[0x10] = psxBios_ChangeTh;
3559 //biosB0[0x11] = psxBios_psxBios_b0_11;
3560 biosB0[0x12] = psxBios_InitPAD;
3561 biosB0[0x13] = psxBios_StartPAD;
3562 biosB0[0x14] = psxBios_StopPAD;
3563 biosB0[0x15] = psxBios_PAD_init;
3564 biosB0[0x16] = psxBios_PAD_dr;
3565 biosB0[0x17] = psxBios_ReturnFromException;
3566 biosB0[0x18] = psxBios_ResetEntryInt;
3567 biosB0[0x19] = psxBios_HookEntryInt;
3568 //biosB0[0x1a] = psxBios_sys_b0_1a;
3569 //biosB0[0x1b] = psxBios_sys_b0_1b;
3570 //biosB0[0x1c] = psxBios_sys_b0_1c;
3571 //biosB0[0x1d] = psxBios_sys_b0_1d;
3572 //biosB0[0x1e] = psxBios_sys_b0_1e;
3573 //biosB0[0x1f] = psxBios_sys_b0_1f;
3574 biosB0[0x20] = psxBios_UnDeliverEvent;
3575 //biosB0[0x21] = psxBios_sys_b0_21;
3576 //biosB0[0x22] = psxBios_sys_b0_22;
3577 //biosB0[0x23] = psxBios_sys_b0_23;
3578 //biosB0[0x24] = psxBios_sys_b0_24;
3579 //biosB0[0x25] = psxBios_sys_b0_25;
3580 //biosB0[0x26] = psxBios_sys_b0_26;
3581 //biosB0[0x27] = psxBios_sys_b0_27;
3582 //biosB0[0x28] = psxBios_sys_b0_28;
3583 //biosB0[0x29] = psxBios_sys_b0_29;
3584 //biosB0[0x2a] = psxBios_sys_b0_2a;
3585 //biosB0[0x2b] = psxBios_sys_b0_2b;
3586 //biosB0[0x2c] = psxBios_sys_b0_2c;
3587 //biosB0[0x2d] = psxBios_sys_b0_2d;
3588 //biosB0[0x2e] = psxBios_sys_b0_2e;
3589 //biosB0[0x2f] = psxBios_sys_b0_2f;
3590 //biosB0[0x30] = psxBios_sys_b0_30;
3591 //biosB0[0x31] = psxBios_sys_b0_31;
3592 biosB0[0x32] = psxBios_open;
3593 biosB0[0x33] = psxBios_lseek;
3594 biosB0[0x34] = psxBios_read;
3595 biosB0[0x35] = psxBios_write;
3596 biosB0[0x36] = psxBios_close;
3597 //biosB0[0x37] = psxBios_ioctl;
3598 //biosB0[0x38] = psxBios_exit;
3599 //biosB0[0x39] = psxBios_sys_b0_39;
3600 //biosB0[0x3a] = psxBios_getc;
3601 //biosB0[0x3b] = psxBios_putc;
3602 biosB0[0x3c] = psxBios_getchar;
3603 biosB0[0x3d] = psxBios_putchar;
3604 //biosB0[0x3e] = psxBios_gets;
3605 biosB0[0x3f] = psxBios_puts;
3606 biosB0[0x40] = psxBios_cd;
3607 biosB0[0x41] = psxBios_format;
3608 biosB0[0x42] = psxBios_firstfile;
3609 biosB0[0x43] = psxBios_nextfile;
3610 biosB0[0x44] = psxBios_rename;
3611 biosB0[0x45] = psxBios_delete;
3612 //biosB0[0x46] = psxBios_undelete;
3613 //biosB0[0x47] = psxBios_AddDevice;
3614 //biosB0[0x48] = psxBios_RemoteDevice;
3615 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3616 biosB0[0x4a] = psxBios_InitCARD;
3617 biosB0[0x4b] = psxBios_StartCARD;
3618 biosB0[0x4c] = psxBios_StopCARD;
3619 //biosB0[0x4d] = psxBios_sys_b0_4d;
3620 biosB0[0x4e] = psxBios__card_write;
3621 biosB0[0x4f] = psxBios__card_read;
3622 biosB0[0x50] = psxBios__new_card;
3623 biosB0[0x51] = psxBios_Krom2RawAdd;
3624 //biosB0[0x52] = psxBios_sys_b0_52;
3625 //biosB0[0x53] = psxBios_sys_b0_53;
3626 //biosB0[0x54] = psxBios__get_errno;
3627 biosB0[0x55] = psxBios__get_error;
3628 biosB0[0x56] = psxBios_GetC0Table;
3629 biosB0[0x57] = psxBios_GetB0Table;
3630 biosB0[0x58] = psxBios__card_chan;
3631 //biosB0[0x59] = psxBios_sys_b0_59;
3632 //biosB0[0x5a] = psxBios_sys_b0_5a;
3633 biosB0[0x5b] = psxBios_ChangeClearPad;
3634 biosB0[0x5c] = psxBios__card_status;
3635 biosB0[0x5d] = psxBios__card_wait;
3636 //*******************C0 CALLS****************************
3637 biosC0[0x00] = psxBios_InitRCnt;
3638 biosC0[0x01] = psxBios_InitException;
3639 biosC0[0x02] = psxBios_SysEnqIntRP;
3640 biosC0[0x03] = psxBios_SysDeqIntRP;
3641 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3642 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3643 //biosC0[0x06] = psxBios_ExceptionHandler;
3644 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3645 biosC0[0x08] = psxBios_SysInitMemory;
3646 //biosC0[0x09] = psxBios_SysInitKMem;
3647 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3648 //biosC0[0x0b] = psxBios_SystemError;
3649 biosC0[0x0c] = psxBios_InitDefInt;
3650 //biosC0[0x0d] = psxBios_sys_c0_0d;
3651 //biosC0[0x0e] = psxBios_sys_c0_0e;
3652 //biosC0[0x0f] = psxBios_sys_c0_0f;
3653 //biosC0[0x10] = psxBios_sys_c0_10;
3654 //biosC0[0x11] = psxBios_sys_c0_11;
3655 //biosC0[0x12] = psxBios_InstallDevices;
3656 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3657 //biosC0[0x14] = psxBios_sys_c0_14;
3658 //biosC0[0x15] = psxBios__cdevinput;
3659 //biosC0[0x16] = psxBios__cdevscan;
3660 //biosC0[0x17] = psxBios__circgetc;
3661 //biosC0[0x18] = psxBios__circputc;
3662 //biosC0[0x19] = psxBios_ioabort;
3663 //biosC0[0x1a] = psxBios_sys_c0_1a
3664 //biosC0[0x1b] = psxBios_KernelRedirect;
3665 //biosC0[0x1c] = psxBios_PatchAOTable;
3666 //************** THE END ***************************************
3669 memset(FDesc, 0, sizeof(FDesc));
3670 memset(cdir, 0, sizeof(cdir));
3673 // somewhat pretend to be a SCPH1001 BIOS
3674 // some games look for these and take an exception if they're missing
3675 rom32 = (u32 *)psxR;
3676 rom32[0x100/4] = SWAP32(0x19951204);
3677 rom32[0x104/4] = SWAP32(3);
3678 romc = (char *)psxR;
3679 strcpy(romc + 0x108, "PCSX authors");
3680 strcpy(romc + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3681 strcpy(romc + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3682 strcpy(romc + 0x7ff54, "GPL-2.0-or-later");
3685 len = 0x80000 - 0x66000;
3686 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3687 len = 0x80000 - 0x69d68;
3688 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3690 // trap attempts to call bios directly
3691 rom32[0x00000/4] = HLEOP(hleop_dummy);
3692 rom32[0x00180/4] = HLEOP(hleop_dummy);
3693 rom32[0x3fffc/4] = HLEOP(hleop_dummy);
3694 rom32[0x65ffc/4] = HLEOP(hleop_dummy);
3695 rom32[0x7ff2c/4] = HLEOP(hleop_dummy);
3697 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3698 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3699 Here are some examples of games not working with this fix in place :
3700 R-type won't get past the Irem logo if not implemented.
3701 Crash Team Racing will softlock after the Sony logo.
3704 ram32 = (u32 *)psxM;
3705 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3706 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3707 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3708 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3710 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3711 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3713 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3714 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3715 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3716 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3718 ram32[0x00a0/4] = HLEOP(hleop_a0);
3719 ram32[0x00b0/4] = HLEOP(hleop_b0);
3720 ram32[0x00c0/4] = HLEOP(hleop_c0);
3722 setup_tt(4, 16, 0x801fff00);
3723 DeliverEvent(0xf0000003, 0x0010);
3725 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3726 strcpy((char *)&ram32[0xeff0/4], "bu");
3728 // default exception handler chains
3729 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3730 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3731 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3732 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3733 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3734 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3735 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3736 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3740 // fill the api jumptables with fake entries as some games patch them
3741 // (or rather the funcs listed there)
3742 ptr = (u32 *)&psxM[A_A0_TABLE];
3743 for (i = 0; i < 256; i++)
3744 ptr[i] = SWAP32(A_A0_DUMMY);
3746 ptr = (u32 *)&psxM[A_B0_TABLE];
3747 for (i = 0; i < 256; i++)
3748 ptr[i] = SWAP32(A_B0_DUMMY);
3749 // B(5b) is special because games patch (sometimes even jump to)
3750 // code at fixed offsets from it, nocash lists offsets:
3751 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3752 // call: +7a0=4b70, +884=4c54, +894=4c64
3753 ptr[0x5b] = SWAP32(A_B0_5B_DUMMY); // 0x43d0
3754 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3756 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3757 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3758 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3760 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3761 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3763 ptr = (u32 *)&psxM[A_C0_TABLE];
3764 for (i = 0; i < 256/2; i++)
3765 ptr[i] = SWAP32(A_C0_DUMMY);
3766 ptr[6] = SWAP32(A_EXCEPTION);
3769 ram32[A_A0_DUMMY/4] = HLEOP(hleop_dummy);
3770 ram32[A_B0_DUMMY/4] = HLEOP(hleop_dummy);
3771 ram32[A_C0_DUMMY/4] = HLEOP(hleop_dummy);
3772 ram32[A_B0_5B_DUMMY/4] = HLEOP(hleop_dummy);
3773 ram32[0x8000/4] = HLEOP(hleop_execret);
3775 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3776 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3777 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3778 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3779 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3780 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3781 ram32[A_RND_SEED/4] = SWAPu32(0x24040001); // was 0xac20cc00
3784 void psxBiosShutdown() {
3787 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 stack) {
3790 if (tcb_cnt != 4 || evcb_cnt != 16) {
3791 setup_tt(tcb_cnt, evcb_cnt, stack);
3792 DeliverEvent(0xf0000003, 0x0010);
3794 storeRam32(A_CONF_SP, stack);
3797 #define psxBios_PADpoll(pad) { \
3798 int i, more_data = 0; \
3799 PAD##pad##_startPoll(pad); \
3800 pad_buf##pad[1] = PAD##pad##_poll(0x42, &more_data); \
3801 pad_buf##pad[0] = more_data ? 0 : 0xff; \
3802 PAD##pad##_poll(0, &more_data); \
3804 while (more_data) { \
3805 pad_buf##pad[i++] = PAD##pad##_poll(0, &more_data); \
3809 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3813 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3814 psxBios_ReturnFromException();
3820 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3821 // so this is only partially implemented
3822 static void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3824 u32 cdrom_dma_ack_enable = 1; // a000b93c
3825 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3828 static void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3831 //PSXBIOS_LOG("%s\n", __func__);
3833 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3834 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3835 //if (--cdrom_irq_counter == 0) // 0xa0009180
3836 // DeliverEvent(0xf0000003, 0x10);
3840 mips_return_c(ret, 20);
3843 static void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3845 u32 cdrom_irq_ack_enable = 1; // a000b938
3846 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3849 static void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3852 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3853 PSXBIOS_LOG("%s TODO\n", __func__);
3856 mips_return_c(ret, 20);
3859 static void hleExc0_2_2_syscall() // not in any A/B/C table
3861 u32 tcbPtr = loadRam32(A_TT_PCB);
3862 TCB *tcb = loadRam32ptr(tcbPtr);
3863 u32 code = (SWAP32(tcb->cause) & 0x3c) >> 2;
3865 if (code != R3000E_Syscall) {
3867 DeliverEvent(0xf0000010, 0x1000);
3868 //psxBios_SystemErrorUnresolvedException();
3870 mips_return_c(0, 17);
3874 //printf("%s c=%d a0=%d\n", __func__, code, SWAP32(tcb->reg[4]));
3875 tcb->epc += SWAP32(4);
3876 switch (SWAP32(tcb->reg[4])) { // a0
3880 case 1: { // EnterCritical - disable irqs
3881 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3882 tcb->reg[2] = SWAP32(was_enabled);
3883 tcb->sr &= SWAP32(~0x404);
3886 case 2: // ExitCritical - enable irqs
3887 tcb->sr |= SWAP32(0x404);
3890 case 3: { // ChangeThreadSubFunction
3891 u32 tcbPtr = loadRam32(A_TT_PCB);
3892 storeRam32(tcbPtr, SWAP32(tcb->reg[5])); // a1
3896 DeliverEvent(0xf0000010, 0x4000);
3900 psxBios_ReturnFromException();
3903 static void hleExc1_0_1(void)
3905 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3906 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3909 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3912 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3913 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3916 mips_return_c(ret, 22);
3919 static void hleExc1_0_2(void)
3921 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3924 static void hleExc1_1_1(void)
3926 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3927 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3930 static void hleExc1_1_2(void)
3932 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3935 static void hleExc1_2_1(void)
3937 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3938 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3941 static void hleExc1_2_2(void)
3943 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3946 static void hleExc1_3_1(void)
3948 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3949 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3952 static void hleExc1_3_2(void)
3954 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3957 static void hleExc3_0_2_defint(void)
3959 static const struct {
3970 { 6, 6 }, // rcnt2 (bug)
3975 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3976 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3977 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3982 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3985 static void hleExcPadCard1(void)
3987 if (loadRam32(A_PAD_IRQR_ENA)) {
3988 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3989 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
3994 if (loadRam32(A_PAD_DR_DST))
3997 if (loadRam32(A_PAD_ACK_VBL))
3998 psxHwWrite16(0x1f801070, ~1);
3999 if (loadRam32(A_CARD_IRQR_ENA)) {
4003 mips_return_c(0, 18);
4006 static void hleExcPadCard2(void)
4008 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
4009 mips_return_c(ret, 15);
4012 void psxBiosException() {
4013 u32 tcbPtr = loadRam32(A_TT_PCB);
4014 u32 *chains = loadRam32ptr(A_TT_ExCB);
4015 TCB *tcb = loadRam32ptr(tcbPtr);
4021 // $at, $v0, $v1, $ra already saved by the mips code at A_EXCEPTION
4022 for (i = 4; i < 31; i++) {
4025 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
4027 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
4028 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
4029 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
4030 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
4031 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
4032 sp = fp = loadRam32(A_EXC_SP);
4036 // do the chains (always 4)
4037 for (c = lim = 0; c < 4; c++) {
4038 if (chains[c * 2] == 0)
4040 ptr = SWAP32(chains[c * 2]);
4041 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
4042 chain = castRam32ptr(ptr);
4047 softCallInException(SWAP32(chain[2]));
4048 if (returned_from_exception())
4051 if (v0 == 0 || chain[1] == 0)
4053 softCallInException(SWAP32(chain[1]));
4054 if (returned_from_exception())
4060 // return from exception (custom or default)
4062 ptr = loadRam32(A_EEXIT_PTR);
4063 if (ptr != A_EEXIT_DEF) {
4064 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
4065 longjmp_load(jmp_buf);
4070 psxBios_ReturnFromException();
4074 static void hleDummy() {
4075 log_unhandled("hleDummy called @%08x ra=%08x\n", psxRegs.pc - 4, ra);
4077 psxRegs.cycle += 1000;
4082 static void hleA0() {
4083 u32 call = t1 & 0xff;
4084 u32 entry = loadRam32(A_A0_TABLE + call * 4);
4086 if (call < 192 && entry != A_A0_DUMMY) {
4087 PSXBIOS_LOG("custom A%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4088 call, biosA0n[call], a0, entry, ra);
4091 PSXBIOS_LOG(" -> %08x\n", v0);
4093 else if (biosA0[call])
4096 //printf("A(%02x) -> %x\n", call, v0);
4100 static void hleB0() {
4101 u32 call = t1 & 0xff;
4102 u32 entry = loadRam32(A_B0_TABLE + call * 4);
4106 is_custom = entry != A_B0_5B_DUMMY;
4108 is_custom = entry != A_B0_DUMMY;
4110 PSXBIOS_LOG("custom B%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4111 call, biosB0n[call], a0, entry, ra);
4114 PSXBIOS_LOG(" -> %08x\n", v0);
4116 else if (biosB0[call])
4119 //printf("B(%02x) -> %x\n", call, v0);
4123 static void hleC0() {
4124 u32 call = t1 & 0xff;
4125 u32 entry = loadRam32(A_C0_TABLE + call * 4);
4127 if (call < 128 && entry != A_C0_DUMMY) {
4128 PSXBIOS_LOG("custom C%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4129 call, biosC0n[call], a0, entry, ra);
4132 PSXBIOS_LOG(" -> %08x\n", v0);
4134 else if (biosC0[call])
4137 //printf("C(%02x) -> %x\n", call, v0);
4141 // currently not used
4142 static void hleBootstrap() {
4147 static void hleExecRet() {
4148 const EXEC *header = (EXEC *)PSXM(s0);
4150 PSXBIOS_LOG("ExecRet %x: %x\n", s0, header->ret);
4152 ra = SWAP32(header->ret);
4153 sp = SWAP32(header->_sp);
4154 fp = SWAP32(header->_fp);
4155 gp = SWAP32(header->_gp);
4156 s0 = SWAP32(header->base);
4162 void (* const psxHLEt[24])() = {
4163 hleDummy, hleA0, hleB0, hleC0,
4164 hleBootstrap, hleExecRet, psxBiosException, hleDummy,
4165 hleExc0_0_1, hleExc0_0_2,
4166 hleExc0_1_1, hleExc0_1_2, hleExc0_2_2_syscall,
4167 hleExc1_0_1, hleExc1_0_2,
4168 hleExc1_1_1, hleExc1_1_2,
4169 hleExc1_2_1, hleExc1_2_2,
4170 hleExc1_3_1, hleExc1_3_2,
4172 hleExcPadCard1, hleExcPadCard2,
4176 #define bfreeze(ptr, size) { \
4177 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
4178 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
4182 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
4183 #define bfreezel(ptr) bfreeze(ptr, sizeof(*(ptr)))
4185 void psxBiosFreeze(int Mode) {