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"
41 #if (defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)
42 #pragma GCC diagnostic ignored "-Wpointer-sign"
46 //#define PSXBIOS_LOG printf
47 #define PSXBIOS_LOG(...)
50 #define PTR_1 (void *)(size_t)1
52 char *biosA0n[256] = {
54 "open", "lseek", "read", "write",
55 "close", "ioctl", "exit", "sys_a0_07",
56 "getc", "putc", "todigit", "atof",
57 "strtoul", "strtol", "abs", "labs",
59 "atoi", "atol", "atob", "setjmp",
60 "longjmp", "strcat", "strncat", "strcmp",
61 "strncmp", "strcpy", "strncpy", "strlen",
62 "index", "rindex", "strchr", "strrchr",
64 "strpbrk", "strspn", "strcspn", "strtok",
65 "strstr", "toupper", "tolower", "bcopy",
66 "bzero", "bcmp", "memcpy", "memset",
67 "memmove", "memcmp", "memchr", "rand",
69 "srand", "qsort", "strtod", "malloc",
70 "free", "lsearch", "bsearch", "calloc",
71 "realloc", "InitHeap", "_exit", "getchar",
72 "putchar", "gets", "puts", "printf",
74 "SystemErrorUnresolvedException", "LoadTest", "Load", "Exec",
75 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
76 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
77 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
79 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
80 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
81 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
82 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
84 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
85 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
86 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
87 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
89 "_bu_init", "_96_init", "CdRemove", "sys_a0_73",
90 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
91 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
92 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
94 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
95 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
96 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
97 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
99 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
100 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
101 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
102 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
104 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
105 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
106 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
107 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
109 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
113 char *biosB0n[256] = {
115 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
116 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
117 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
118 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
120 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
121 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
122 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
123 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
125 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
126 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
127 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
128 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
130 "sys_b0_30", "sys_b0_31", "open", "lseek",
131 "read", "write", "close", "ioctl",
132 "exit", "sys_b0_39", "getc", "putc",
133 "getchar", "putchar", "gets", "puts",
135 "cd", "format", "firstfile", "nextfile",
136 "rename", "delete", "undelete", "AddDevice",
137 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
138 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
140 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
141 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
142 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
143 "_card_status", "_card_wait",
146 char *biosC0n[256] = {
148 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
149 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
150 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
151 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
153 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
154 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
155 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
159 //#define r0 (psxRegs.GPR.n.r0)
160 #define at (psxRegs.GPR.n.at)
161 #define v0 (psxRegs.GPR.n.v0)
162 #define v1 (psxRegs.GPR.n.v1)
163 #define a0 (psxRegs.GPR.n.a0)
164 #define a1 (psxRegs.GPR.n.a1)
165 #define a2 (psxRegs.GPR.n.a2)
166 #define a3 (psxRegs.GPR.n.a3)
167 #define t0 (psxRegs.GPR.n.t0)
168 #define t1 (psxRegs.GPR.n.t1)
169 #define t2 (psxRegs.GPR.n.t2)
170 #define t3 (psxRegs.GPR.n.t3)
171 #define t4 (psxRegs.GPR.n.t4)
172 #define t5 (psxRegs.GPR.n.t5)
173 #define t6 (psxRegs.GPR.n.t6)
174 #define t7 (psxRegs.GPR.n.t7)
175 #define t8 (psxRegs.GPR.n.t8)
176 #define t9 (psxRegs.GPR.n.t9)
177 #define s0 (psxRegs.GPR.n.s0)
178 #define s1 (psxRegs.GPR.n.s1)
179 #define s2 (psxRegs.GPR.n.s2)
180 #define s3 (psxRegs.GPR.n.s3)
181 #define s4 (psxRegs.GPR.n.s4)
182 #define s5 (psxRegs.GPR.n.s5)
183 #define s6 (psxRegs.GPR.n.s6)
184 #define s7 (psxRegs.GPR.n.s7)
185 #define k0 (psxRegs.GPR.n.k0)
186 #define k1 (psxRegs.GPR.n.k1)
187 #define gp (psxRegs.GPR.n.gp)
188 #define sp (psxRegs.GPR.n.sp)
189 #define fp (psxRegs.GPR.n.fp)
190 #define ra (psxRegs.GPR.n.ra)
191 #define pc0 (psxRegs.pc)
193 #define Ra0 ((char *)PSXM(a0))
194 #define Ra1 ((char *)PSXM(a1))
195 #define Ra2 ((char *)PSXM(a2))
196 #define Ra3 ((char *)PSXM(a3))
197 #define Rv0 ((char *)PSXM(v0))
198 #define Rsp ((char *)PSXM(sp))
209 #define EvStUNUSED 0x0000
210 #define EvStDISABLED 0x1000
211 #define EvStACTIVE 0x2000
212 #define EvStALREADY 0x4000
214 #define EvMdCALL 0x1000
215 #define EvMdMARK 0x2000
238 u32 _sp, _fp, _gp, ret, base;
258 // todo: FileDesc layout is wrong
259 // todo: get rid of these globals
260 static FileDesc FDesc[32];
261 static char ffile[64];
263 static char cdir[8*8+8];
266 // fixed RAM offsets, SCPH1001 compatible
267 #define A_TT_ExCB 0x0100
268 #define A_TT_PCB 0x0108
269 #define A_TT_TCB 0x0110
270 #define A_TT_EvCB 0x0120
271 #define A_A0_TABLE 0x0200
272 #define A_B0_TABLE 0x0874
273 #define A_C0_TABLE 0x0674
274 #define A_SYSCALL 0x0650
275 #define A_EXCEPTION 0x0c80
276 #define A_EXC_SP 0x6cf0
277 #define A_EEXIT_DEF 0x6cf4
278 #define A_KMALLOC_PTR 0x7460
279 #define A_KMALLOC_SIZE 0x7464
280 #define A_KMALLOC_END 0x7468
281 #define A_PADCRD_CHN_E 0x74a8 // pad/card irq chain entry, see hleExcPadCard1()
282 #define A_PAD_IRQR_ENA 0x74b8 // pad read on vint irq (nocash 'pad_enable_flag')
283 #define A_CARD_IRQR_ENA 0x74bc // same for card
284 #define A_PAD_INBUF 0x74c8 // 2x buffers for rx pad data
285 #define A_PAD_OUTBUF 0x74d0 // 2x buffers for tx pad data
286 #define A_PAD_IN_LEN 0x74d8
287 #define A_PAD_OUT_LEN 0x74e0
288 #define A_PAD_DR_DST 0x74c4
289 #define A_CARD_CHAN1 0x7500
290 #define A_PAD_DR_BUF1 0x7570
291 #define A_PAD_DR_BUF2 0x7598
292 #define A_EEXIT_PTR 0x75d0
293 #define A_EXC_STACK 0x85d8 // exception stack top
294 #define A_RCNT_VBL_ACK 0x8600
295 #define A_PAD_ACK_VBL 0x8914 // enable vint ack by pad reading code
296 #define A_HEAP_BASE 0x9000
297 #define A_HEAP_SIZE 0x9004
298 #define A_HEAP_END 0x9008
299 #define A_HEAP_FLAG 0x900c
300 #define A_RND_SEED 0x9010
301 #define A_CONF_TCB 0xb940
302 #define A_CONF_EvCB 0xb944
303 #define A_CONF_SP 0xb948
304 #define A_CD_EVENTS 0xb9b8
305 #define A_EXC_GP 0xf450
307 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
309 static u32 loadRam32(u32 addr)
311 assert(!(addr & 0x5f800000));
312 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
315 static void *castRam8ptr(u32 addr)
317 assert(!(addr & 0x5f800000));
318 return psxM + (addr & 0x1fffff);
321 static void *castRam32ptr(u32 addr)
323 assert(!(addr & 0x5f800003));
324 return psxM + (addr & 0x1ffffc);
327 static void *loadRam8ptr(u32 addr)
329 return castRam8ptr(loadRam32(addr));
332 static void *loadRam32ptr(u32 addr)
334 return castRam32ptr(loadRam32(addr));
337 static void storeRam8(u32 addr, u8 d)
339 assert(!(addr & 0x5f800000));
340 *((u8 *)psxM + (addr & 0x1fffff)) = d;
343 static void storeRam32(u32 addr, u32 d)
345 assert(!(addr & 0x5f800000));
346 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
349 static void mips_return(u32 val)
355 static void mips_return_void(void)
360 static void use_cycles(u32 cycle)
362 psxRegs.cycle += cycle * 2;
365 static void mips_return_c(u32 val, u32 cycle)
371 static void mips_return_void_c(u32 cycle)
377 static int returned_from_exception(void)
379 // 0x80000080 means it took another exception just after return
380 return pc0 == k0 || pc0 == 0x80000080;
383 static inline void softCall(u32 pc) {
385 u32 ssr = psxRegs.CP0.n.SR;
389 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
391 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
393 while (pc0 != 0x80001000 && ++lim < 1000000)
394 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
396 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
399 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
401 psxRegs.CP0.n.SR |= ssr & 0x404;
404 static inline void softCallInException(u32 pc) {
409 assert(ra != 0x80001000);
410 if (ra == 0x80001000)
414 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
416 while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 1000000)
417 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
419 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
422 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
423 if (pc0 == 0x80001000)
427 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
428 static u32 DeliverEvent(u32 class, u32 spec);
429 static u32 UnDeliverEvent(u32 class, u32 spec);
430 static void CloseEvent(u32 ev);
435 // System calls A0 */
438 #define buread(Ra1, mcd, length) { \
439 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); \
440 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
441 memcpy(Ra1, ptr, length); \
442 psxCpu->Clear(a1, (length + 3) / 4); \
443 if (FDesc[1 + mcd].mode & 0x8000) { \
444 DeliverEvent(0xf0000011, 0x0004); \
445 DeliverEvent(0xf4000001, 0x0004); \
448 FDesc[1 + mcd].offset += v0; \
451 #define buwrite(Ra1, mcd, length) { \
452 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
453 PSXBIOS_LOG("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
454 ptr = Mcd##mcd##Data + offset; \
455 memcpy(ptr, Ra1, length); \
456 FDesc[1 + mcd].offset += length; \
457 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
458 if (FDesc[1 + mcd].mode & 0x8000) { \
459 DeliverEvent(0xf0000011, 0x0004); \
460 DeliverEvent(0xf4000001, 0x0004); \
465 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
466 /* For some strange reason, the returned character is sign-expanded; */
467 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
468 /* TODO FIX ME : Properly implement this behaviour */
469 void psxBios_getc(void) // 0x03, 0x35
474 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
478 if (pa1 != INVALID_PTR) {
480 case 2: buread(pa1, 1, 1); break;
481 case 3: buread(pa1, 2, 1); break;
488 /* Copy of psxBios_write, except size is 1. */
489 void psxBios_putc(void) // 0x09, 0x3B
494 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
497 if (pa1 == INVALID_PTR) {
502 if (a0 == 1) { // stdout
503 char *ptr = (char *)pa1;
507 printf("%c", *ptr++); a2--;
513 case 2: buwrite(pa1, 1, 1); break;
514 case 3: buwrite(pa1, 2, 1); break;
520 void psxBios_todigit(void) // 0x0a
524 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
527 if (c >= 0x30 && c < 0x3A) {
530 else if (c > 0x60 && c < 0x7B) {
533 else if (c > 0x40 && c < 0x5B) {
536 else if (c >= 0x80) {
547 void psxBios_abs() { // 0x0e
548 if ((s32)a0 < 0) v0 = -(s32)a0;
553 void psxBios_labs() { // 0x0f
557 void psxBios_atoi() { // 0x10
559 char *p = (char *)Ra0;
563 case ' ': case '\t': continue;
570 while (*p >= '0' && *p <= '9') {
571 n = n * 10 + *p++ - '0';
578 void psxBios_atol() { // 0x11
588 static void psxBios_setjmp() { // 0x13
589 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
592 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
594 jmp_buf->ra_ = SWAP32(ra);
595 jmp_buf->sp_ = SWAP32(sp);
596 jmp_buf->fp_ = SWAP32(fp);
597 for (i = 0; i < 8; i++) // s0-s7
598 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
599 jmp_buf->gp_ = SWAP32(gp);
601 mips_return_c(0, 15);
604 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
608 ra = SWAP32(jmp_buf->ra_);
609 sp = SWAP32(jmp_buf->sp_);
610 fp = SWAP32(jmp_buf->fp_);
611 for (i = 0; i < 8; i++) // s0-s7
612 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
613 gp = SWAP32(jmp_buf->gp_);;
616 void psxBios_longjmp() { // 0x14
617 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
619 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
620 longjmp_load(jmp_buf);
621 mips_return_c(a1, 15);
624 void psxBios_strcat() { // 0x15
625 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
628 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
630 if (a0 == 0 || a1 == 0)
638 while ((*p1++ = *p2++) != '\0');
643 void psxBios_strncat() { // 0x16
644 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
648 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
650 if (a0 == 0 || a1 == 0)
658 while ((*p1++ = *p2++) != '\0') {
668 void psxBios_strcmp() { // 0x17
669 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
671 if (a0 == 0 && a1 == 0)
677 else if (a0 == 0 && a1 != 0)
683 else if (a0 != 0 && a1 == 0)
690 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
693 while (*p1 == *p2++) {
712 void psxBios_strncmp() { // 0x18
713 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
715 if (a0 == 0 && a1 == 0)
721 else if (a0 == 0 && a1 != 0)
727 else if (a0 != 0 && a1 == 0)
734 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
737 while (--n >= 0 && *p1 == *p2++) {
741 v1 = a2 - ((a2-n) - 1);
749 v0 = (n < 0 ? 0 : *p1 - *--p2);
751 v1 = a2 - ((a2-n) - 1);
757 void psxBios_strcpy() { // 0x19
758 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
759 if (a0 == 0 || a1 == 0)
765 while ((*p1++ = *p2++) != '\0');
770 void psxBios_strncpy() { // 0x1a
771 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
773 if (a0 == 0 || a1 == 0)
779 for (i = 0; i < n; i++) {
780 if ((*p1++ = *p2++) == '\0') {
792 void psxBios_strlen() { // 0x1b
793 char *p = (char *)Ra0;
804 void psxBios_index() { // 0x1c
805 char *p = (char *)Ra0;
815 v0 = a0 + (p - (char *)Ra0);
819 } while (*p++ != '\0');
824 void psxBios_rindex() { // 0x1d
825 char *p = (char *)Ra0;
835 v0 = a0 + (p - (char *)Ra0);
836 } while (*p++ != '\0');
841 void psxBios_strchr() { // 0x1e
845 void psxBios_strrchr() { // 0x1f
849 void psxBios_strpbrk() { // 0x20
850 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
852 while ((c = *p1++) != '\0') {
853 for (scanp = p2; (sc = *scanp++) != '\0';) {
855 v0 = a0 + (p1 - 1 - (char *)Ra0);
862 // BUG: return a0 instead of NULL if not found
866 void psxBios_strspn() { // 0x21
869 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
870 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
871 if (*p2 == '\0') break;
874 v0 = p1 - (char *)Ra0; pc0 = ra;
877 void psxBios_strcspn() { // 0x22
880 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
881 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
882 if (*p2 != '\0') break;
885 v0 = p1 - (char *)Ra0; pc0 = ra;
888 void psxBios_strtok() { // 0x23
889 char *pcA0 = (char *)Ra0;
890 char *pcRet = strtok(pcA0, (char *)Ra1);
892 v0 = a0 + pcRet - pcA0;
898 void psxBios_strstr() { // 0x24
899 char *p = (char *)Ra0, *p1, *p2;
905 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
910 v0 = a0 + (p - (char *)Ra0);
921 void psxBios_toupper() { // 0x25
922 v0 = (s8)(a0 & 0xff);
923 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
927 void psxBios_tolower() { // 0x26
928 v0 = (s8)(a0 & 0xff);
929 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
933 static void do_memset(u32 dst, u32 v, s32 len)
939 if (db != INVALID_PTR)
943 psxCpu->Clear(dst, (len + 3) / 4);
946 static void do_memcpy(u32 dst, u32 src, s32 len)
948 u32 d = dst, s = src;
951 const u8 *sb = PSXM(s);
953 if (db != INVALID_PTR && sb != INVALID_PTR)
958 psxCpu->Clear(dst, (len + 3) / 4);
961 static void psxBios_memcpy();
963 static void psxBios_bcopy() { // 0x27 - memcpy with args swapped
964 //PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x27], a0, a1, a2);
965 u32 ret = a0, cycles = 0;
966 if (a0 == 0) // ...but it checks src this time
973 do_memcpy(a1, a0, a2);
979 mips_return_c(ret, cycles + 5);
982 static void psxBios_bzero() { // 0x28
983 /* Same as memset here (See memset below) */
984 u32 ret = a0, cycles;
985 if (a0 == 0 || (s32)a1 <= 0)
990 do_memset(a0, 0, a1);
994 // todo: many more cycles due to uncached bios mem
995 mips_return_c(ret, cycles + 5);
998 void psxBios_bcmp() { // 0x29
999 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
1001 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
1003 while ((s32)a2-- > 0) {
1004 if (*p1++ != *p2++) {
1005 v0 = *p1 - *p2; // BUG: compare the NEXT byte
1014 static void psxBios_memcpy() { // 0x2a
1015 u32 ret = a0, cycles = 0;
1018 mips_return_c(0, 4);
1023 do_memcpy(a0, a1, a2);
1029 mips_return_c(ret, cycles + 5);
1032 static void psxBios_memset() { // 0x2b
1033 u32 ret = a0, cycles;
1034 if (a0 == 0 || (s32)a2 <= 0)
1036 mips_return_c(0, 6);
1039 do_memset(a0, a1, a2);
1043 // todo: many more cycles due to uncached bios mem
1044 mips_return_c(ret, cycles + 5);
1047 void psxBios_memmove() { // 0x2c
1048 u32 ret = a0, cycles = 0;
1051 mips_return_c(0, 4);
1055 if ((s32)a2 > 0 && a0 > a1 && a0 < a1 + a2) {
1056 u32 dst = a0, len = a2 + 1;
1059 while ((s32)a2 >= 0) { // BUG: copies one more byte here
1060 const u8 *sb = PSXM(a1);
1062 if (db != INVALID_PTR && sb != INVALID_PTR)
1068 psxCpu->Clear(dst, (len + 3) / 4);
1069 cycles = 10 + len * 8;
1070 } else if ((s32)a2 > 0) {
1071 do_memcpy(a0, a1, a2);
1077 mips_return_c(ret, cycles + 5);
1080 void psxBios_memcmp() { // 0x2d
1084 void psxBios_memchr() { // 0x2e
1085 char *p = (char *)Ra0;
1087 if (a0 == 0 || a2 > 0x7FFFFFFF)
1093 while ((s32)a2-- > 0) {
1094 if (*p++ != (s8)a1) continue;
1095 v0 = a0 + (p - (char *)Ra0 - 1);
1103 static void psxBios_rand() { // 0x2f
1104 u32 s = loadRam32(A_RND_SEED) * 1103515245 + 12345;
1105 storeRam32(A_RND_SEED, s);
1107 mips_return_c((s >> 16) & 0x7fff, 12+37);
1110 static void psxBios_srand() { // 0x30
1111 storeRam32(A_RND_SEED, a0);
1112 mips_return_void_c(3);
1115 static u32 qscmpfunc, qswidth;
1117 static inline int qscmp(char *a, char *b) {
1120 a0 = sa0 + (a - (char *)PSXM(sa0));
1121 a1 = sa0 + (b - (char *)PSXM(sa0));
1123 softCall(qscmpfunc);
1129 static inline void qexchange(char *i, char *j) {
1140 static inline void q3exchange(char *i, char *j, char *k) {
1152 static void qsort_main(char *a, char *l) {
1153 char *i, *j, *lp, *hp;
1158 if ((n = l - a) <= qswidth)
1160 n = qswidth * (n / (2 * qswidth));
1166 if ((c = qscmp(i, lp)) == 0) {
1167 qexchange(i, lp -= qswidth);
1178 if ((c = qscmp(hp, j)) == 0) {
1179 qexchange(hp += qswidth, j);
1184 q3exchange(i, hp += qswidth, j);
1198 if (lp - a >= l - hp) {
1199 qsort_main(hp + qswidth, l);
1208 q3exchange(j, lp -= qswidth, i);
1213 void psxBios_qsort() { // 0x31
1216 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1221 // this isn't how the real bios works, but maybe good enough
1222 static void psxBios_malloc() { // 0x33
1223 u32 *heap_addr, *heap_end;
1224 u32 *chunk, *newchunk = NULL;
1225 unsigned int dsize = 0, csize, cstat;
1227 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x33], a0);
1228 heap_addr = loadRam32ptr(A_HEAP_BASE);
1229 heap_end = loadRam32ptr(A_HEAP_END);
1230 if (heap_addr >= heap_end) {
1236 // scan through heap and combine free chunks of space
1239 while(chunk < heap_end) {
1240 // get size and status of actual chunk
1241 csize = ((u32)*chunk) & 0xfffffffc;
1242 cstat = ((u32)*chunk) & 1;
1244 // most probably broken heap descriptor
1245 // this fixes Burning Road
1248 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1253 // it's a free chunk
1258 colflag = 1; // let's begin a new collection of free memory
1260 else dsize += (csize+4); // add the new size including header
1262 // not a free chunk: did we start a collection ?
1264 if(colflag == 1) { // collection is over
1266 *newchunk = SWAP32(dsize | 1);
1271 chunk = (u32*)((uptr)chunk + csize + 4);
1273 // if neccessary free memory on end of heap
1275 *newchunk = SWAP32(dsize | 1);
1278 csize = ((u32)*chunk) & 0xfffffffc;
1279 cstat = ((u32)*chunk) & 1;
1280 dsize = (a0 + 3) & 0xfffffffc;
1282 // exit on uninitialized heap
1283 if (chunk == NULL) {
1284 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1290 // search an unused chunk that is big enough until the end of the heap
1291 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1292 chunk = (u32*)((uptr)chunk + csize + 4);
1294 // catch out of memory
1295 if(chunk >= heap_end) {
1296 printf("malloc %x,%x: Out of memory error!\n",
1302 csize = ((u32)*chunk) & 0xfffffffc;
1303 cstat = ((u32)*chunk) & 1;
1307 if(dsize == csize) {
1308 // chunk has same size
1309 *chunk &= 0xfffffffc;
1310 } else if (dsize > csize) {
1315 *chunk = SWAP32(dsize);
1316 newchunk = (u32*)((uptr)chunk + dsize + 4);
1317 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1320 // return pointer to allocated memory
1321 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1323 //printf ("malloc %x,%x\n", v0, a0);
1327 static void psxBios_free() { // 0x34
1328 PSXBIOS_LOG("psxBios_%s %x (%x bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1329 storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1330 mips_return_void_c(5);
1333 static void psxBios_calloc() { // 0x37
1335 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
1337 a0 = size = a0 * a1;
1341 a0 = ret; a1 = size;
1344 mips_return_c(ret, 21);
1347 void psxBios_realloc() { // 0x38
1351 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1355 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1360 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1365 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1366 /* Note that it is not quite implemented this way here. */
1376 /* InitHeap(void *block , int n) */
1377 static void psxBios_InitHeap() { // 0x39
1378 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
1380 storeRam32(A_HEAP_BASE, a0);
1381 storeRam32(A_HEAP_SIZE, a1);
1382 storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
1383 storeRam32(A_HEAP_FLAG, 0);
1386 mips_return_void_c(14);
1389 void psxBios_getchar() { //0x3b
1390 v0 = getchar(); pc0 = ra;
1393 static void psxBios_printf_psxout() { // 0x3f
1402 if (psp != INVALID_PTR) {
1403 memcpy(save, psp, 4 * 4);
1404 psxMu32ref(sp) = SWAP32((u32)a0);
1405 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1406 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1407 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1419 tmp2[j++] = Ra0[i]; goto _start;
1421 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1432 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1436 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1442 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1444 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1446 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1448 *ptmp++ = Ra0[i]; break;
1458 if (psp != INVALID_PTR)
1459 memcpy(psp, save, 4 * 4);
1462 SysPrintf("%s", tmp);
1465 void psxBios_printf() { // 0x3f
1466 psxBios_printf_psxout();
1470 static void psxBios_cd() { // 0x40
1471 const char *p, *dir = castRam8ptr(a0);
1472 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x40], a0, dir);
1473 if ((p = strchr(dir, ':')))
1477 snprintf(cdir, sizeof(cdir), "%s", dir);
1478 mips_return_c(1, 100);
1481 static void psxBios_format() { // 0x41
1482 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x41], a0, Ra0);
1483 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1485 CreateMcd(Config.Mcd1);
1486 LoadMcd(1, Config.Mcd1);
1489 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1491 CreateMcd(Config.Mcd2);
1492 LoadMcd(2, Config.Mcd2);
1502 static void psxBios_SystemErrorUnresolvedException() {
1503 if (floodchk != 0x12340a40) { // prevent log flood
1504 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1505 floodchk = 0x12340a40;
1507 mips_return_void_c(1000);
1510 static void FlushCache() {
1511 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1512 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1514 // runs from uncached mem so tons of cycles
1519 * long Load(char *name, struct EXEC *header);
1522 void psxBios_Load() { // 0x42
1530 PSXBIOS_LOG("psxBios_%s %x(%s), %x\n", biosA0n[0x42], a0, pa0, a1);
1531 if (pa0 == INVALID_PTR || pa1 == INVALID_PTR) {
1535 if ((p = strchr(pa0, ':')))
1540 snprintf(path, sizeof(path), "%s\\%s", cdir, (char *)pa0);
1542 snprintf(path, sizeof(path), "%s", (char *)pa0);
1544 if (LoadCdromFile(path, &eheader) == 0) {
1545 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1546 psxCpu->Clear(a1, sizeof(EXEC) / 4);
1550 PSXBIOS_LOG(" -> %d\n", v0);
1556 * int Exec(struct EXEC *header , int argc , char **argv);
1559 void psxBios_Exec() { // 43
1560 EXEC *header = (EXEC *)castRam32ptr(a0);
1564 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1566 header->_sp = SWAP32(sp);
1567 header->_fp = SWAP32(fp);
1568 header->_sp = SWAP32(sp);
1569 header->_gp = SWAP32(gp);
1570 header->ret = SWAP32(ra);
1571 header->base = SWAP32(s0);
1573 ptr = SWAP32(header->b_addr);
1574 len = SWAP32(header->b_size);
1580 if (header->S_addr != 0)
1581 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1583 gp = SWAP32(header->gp0);
1591 pc0 = SWAP32(header->_pc0);
1594 static void psxBios_FlushCache() { // 44
1595 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1600 void psxBios_GPU_dw() { // 0x46
1605 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1608 GPU_writeData(0xa0000000);
1609 GPU_writeData((a1<<0x10)|(a0&0xffff));
1610 GPU_writeData((a3<<0x10)|(a2&0xffff));
1612 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1615 GPU_writeData(SWAPu32(*ptr++));
1621 void psxBios_mem2vram() { // 0x47
1623 gpuSyncPluginSR(); // flush
1624 GPU_writeData(0xa0000000);
1625 GPU_writeData((a1<<0x10)|(a0&0xffff));
1626 GPU_writeData((a3<<0x10)|(a2&0xffff));
1627 size = ((((a2 * a3) / 2) >> 4) << 16);
1628 GPU_writeStatus(0x04000002);
1629 psxHwWrite32(0x1f8010f4,0);
1630 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1631 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1632 psxHwWrite32(0x1f8010a4, size | 0x10);
1633 psxHwWrite32(0x1f8010a8,0x01000201);
1638 void psxBios_SendGPU() { // 0x48
1639 GPU_writeStatus(a0);
1644 void psxBios_GPU_cw() { // 0x49
1651 void psxBios_GPU_cwb() { // 0x4a
1652 u32 *ptr = (u32*)Ra0;
1657 GPU_writeData(SWAPu32(*ptr++));
1663 void psxBios_GPU_SendPackets() { //4b:
1665 GPU_writeStatus(0x04000002);
1666 psxHwWrite32(0x1f8010f4,0);
1667 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1668 psxHwWrite32(0x1f8010a0,a0);
1669 psxHwWrite32(0x1f8010a4,0);
1670 psxHwWrite32(0x1f8010a8,0x010000401);
1674 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1675 psxHwWrite32(0x1f8010a8,0x00000401);
1676 GPU_writeData(0x0400000);
1677 GPU_writeData(0x0200000);
1678 GPU_writeData(0x0100000);
1683 void psxBios_GPU_GetGPUStatus() { // 0x4d
1684 v0 = GPU_readStatus();
1690 void psxBios_LoadExec() { // 51
1691 EXEC *header = (EXEC*)PSXM(0xf000);
1695 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1697 s_addr = a1; s_size = a2;
1702 header->S_addr = s_addr;
1703 header->s_size = s_size;
1705 a0 = 0xf000; a1 = 0; a2 = 0;
1709 void psxBios__bu_init() { // 70
1711 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1714 DeliverEvent(0xf0000011, 0x0004);
1715 DeliverEvent(0xf4000001, 0x0004);
1720 void psxBios__96_init() { // 71
1722 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1728 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1729 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1730 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1732 static void psxBios_DequeueCdIntr_() {
1733 psxBios_SysDeqIntRP_(0, 0x91d0);
1734 psxBios_SysDeqIntRP_(0, 0x91e0);
1738 static void psxBios_DequeueCdIntr() { // a3
1739 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1740 psxBios_DequeueCdIntr_();
1743 static void psxBios_CdRemove() { // 56, 72
1744 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1746 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1747 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1748 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1749 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1750 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1751 psxBios_DequeueCdIntr_();
1753 // EnterCriticalSection - should be done at the beginning,
1754 // but this way is much easier to implement
1760 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack);
1762 static void psxBios_SetConf() { // 9c
1763 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9c], a0, a1, a2);
1764 setup_tt(a1, a0, a2);
1765 psxRegs.CP0.n.SR |= 0x401;
1766 mips_return_void_c(500);
1769 static void psxBios_GetConf() { // 9d
1770 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9d], a0, a1, a2);
1771 storeRam32(a0, loadRam32(A_CONF_EvCB));
1772 storeRam32(a1, loadRam32(A_CONF_TCB));
1773 storeRam32(a2, loadRam32(A_CONF_SP));
1774 mips_return_void_c(10);
1777 void psxBios_SetMem() { // 9f
1778 u32 new = psxHu32(0x1060);
1781 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1786 psxHu32ref(0x1060) = SWAP32(new);
1787 psxMu32ref(0x060) = a0;
1788 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1792 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1793 psxMu32ref(0x060) = a0;
1794 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1797 PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
1804 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1805 static void psxBios_get_cd_status() // a6
1807 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
1812 static void psxBios__card_info() { // ab
1813 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1815 storeRam32(A_CARD_CHAN1, a0);
1822 if (McdDisable[port & 1])
1826 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
1831 if (McdDisable[0] && McdDisable[1])
1834 DeliverEvent(0xf0000011, 0x0004);
1835 // DeliverEvent(0xf4000001, 0x0004);
1836 DeliverEvent(0xf4000001, ret);
1840 void psxBios__card_load() { // ac
1842 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1845 storeRam32(A_CARD_CHAN1, a0);
1847 // DeliverEvent(0xf0000011, 0x0004);
1848 DeliverEvent(0xf4000001, 0x0004);
1853 static void psxBios_GetSystemInfo() { // b4
1855 //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
1856 SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
1859 case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
1860 case 2: ret = 0xbfc0012c; break;
1861 case 5: ret = loadRam32(0x60) << 10; break;
1863 mips_return_c(ret, 20);
1866 /* System calls B0 */
1868 static u32 psxBios_SysMalloc_(u32 size);
1870 static void psxBios_SysMalloc() { // B 00
1871 u32 ret = psxBios_SysMalloc_(a0);
1873 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1874 mips_return_c(ret, 33);
1877 void psxBios_SetRCnt() { // 02
1879 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1886 psxRcntWtarget(a0, a1);
1887 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1888 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1889 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1890 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1891 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1893 psxRcntWmode(a0, mode);
1898 void psxBios_GetRCnt() { // 03
1900 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1905 case 0: v0 = psxRcntRcount0(); break;
1906 case 1: v0 = psxRcntRcount1(); break;
1907 case 2: v0 = psxRcntRcount2(); break;
1908 case 3: v0 = 0; break;
1913 void psxBios_StartRCnt() { // 04
1915 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1919 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1920 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1924 void psxBios_StopRCnt() { // 05
1926 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1930 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1931 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1935 void psxBios_ResetRCnt() { // 06
1937 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1942 psxRcntWmode(a0, 0);
1943 psxRcntWtarget(a0, 0);
1944 psxRcntWcount(a0, 0);
1949 static u32 DeliverEvent(u32 class, u32 spec) {
1950 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1951 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1952 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1953 u32 i, lim = evcb_len / 0x1c;
1955 //printf("%s %08x %x\n", __func__, class, spec);
1956 for (i = 0; i < lim; i++, ev++) {
1958 if (SWAP32(ev->status) != EvStACTIVE)
1961 if (SWAP32(ev->class) != class)
1964 if (SWAP32(ev->spec) != spec)
1967 ret = SWAP32(ev->mode);
1968 if (ret == EvMdMARK) {
1969 ev->status = SWAP32(EvStALREADY);
1973 if (ret == EvMdCALL) {
1974 ret = SWAP32(ev->fhandler);
1987 static u32 UnDeliverEvent(u32 class, u32 spec) {
1988 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1989 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1990 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1991 u32 i, lim = evcb_len / 0x1c;
1993 for (i = 0; i < lim; i++, ev++) {
1995 if (SWAP32(ev->status) != EvStALREADY)
1998 if (SWAP32(ev->class) != class)
2001 if (SWAP32(ev->spec) != spec)
2004 if (SWAP32(ev->mode) == EvMdMARK)
2005 ev->status = SWAP32(EvStACTIVE);
2011 static void psxBios_DeliverEvent() { // 07
2013 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
2015 ret = DeliverEvent(a0, a1);
2019 static s32 get_free_EvCB_slot() {
2020 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
2021 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
2024 for (i = 0; i < lim; i++, ev++) {
2026 if (ev->status == SWAP32(EvStUNUSED))
2032 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
2033 u32 ret = get_free_EvCB_slot();
2034 if ((s32)ret >= 0) {
2035 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
2036 ev->class = SWAP32(class);
2037 ev->status = SWAP32(EvStDISABLED);
2038 ev->spec = SWAP32(spec);
2039 ev->mode = SWAP32(mode);
2040 ev->fhandler = SWAP32(func);
2046 static void psxBios_OpenEvent() { // 08
2047 u32 ret = OpenEvent(a0, a1, a2, a3);
2048 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
2049 biosB0n[0x08], a0, a1, a2, a3, ret);
2050 mips_return_c(ret, 36);
2053 static void CloseEvent(u32 ev)
2055 u32 base = loadRam32(A_TT_EvCB);
2056 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
2059 static void psxBios_CloseEvent() { // 09
2060 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
2061 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
2063 mips_return_c(1, 10);
2066 static void psxBios_WaitEvent() { // 0a
2067 u32 base = loadRam32(A_TT_EvCB);
2068 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2069 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
2072 if (status == EvStALREADY) {
2073 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2077 if (status != EvStACTIVE)
2079 mips_return_c(0, 2);
2083 // retrigger this hlecall after the next emulation event
2085 if ((s32)(next_interupt - psxRegs.cycle) > 0)
2086 psxRegs.cycle = next_interupt;
2090 static void psxBios_TestEvent() { // 0b
2091 u32 base = loadRam32(A_TT_EvCB);
2092 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2095 if (psxRegs.cycle - floodchk > 16*1024u) { // prevent log flood
2096 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
2097 floodchk = psxRegs.cycle;
2099 if (status == EvStALREADY) {
2100 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2104 mips_return_c(ret, 15);
2107 static void psxBios_EnableEvent() { // 0c
2108 u32 base = loadRam32(A_TT_EvCB);
2109 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2110 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
2111 if (status != EvStUNUSED)
2112 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2114 mips_return_c(1, 15);
2117 static void psxBios_DisableEvent() { // 0d
2118 u32 base = loadRam32(A_TT_EvCB);
2119 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2120 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2121 if (status != EvStUNUSED)
2122 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2124 mips_return_c(1, 15);
2128 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2131 void psxBios_OpenTh() { // 0e
2132 TCB *tcb = loadRam32ptr(A_TT_TCB);
2133 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2136 for (th = 1; th < limit; th++)
2138 if (tcb[th].status != SWAP32(0x4000)) break;
2142 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2143 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2145 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2147 mips_return_c(0xffffffff, 20);
2150 PSXBIOS_LOG("psxBios_%s -> %x\n", biosB0n[0x0e], 0xff000000 + th);
2152 tcb[th].status = SWAP32(0x4000);
2153 tcb[th].mode = SWAP32(0x1000);
2154 tcb[th].epc = SWAP32(a0);
2155 tcb[th].reg[30] = SWAP32(a1); // fp
2156 tcb[th].reg[29] = SWAP32(a1); // sp
2157 tcb[th].reg[28] = SWAP32(a2); // gp
2159 mips_return_c(0xff000000 + th, 34);
2163 * int CloseTh(long thread);
2166 static void psxBios_CloseTh() { // 0f
2167 u32 tcb = loadRam32(A_TT_TCB);
2168 u32 th = a0 & 0xffff;
2170 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x0f], a0);
2171 // in the usual bios fashion no checks, just write and return 1
2172 storeRam32(tcb + th * sizeof(TCB), 0x1000);
2174 mips_return_c(1, 11);
2178 * int ChangeTh(long thread);
2181 void psxBios_ChangeTh() { // 10
2182 u32 tcbBase = loadRam32(A_TT_TCB);
2183 u32 th = a0 & 0xffff;
2185 // this is quite spammy
2186 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2188 // without doing any argument checks, just issue a syscall
2189 // (like the real bios does)
2191 a1 = tcbBase + th * sizeof(TCB);
2196 void psxBios_InitPAD() { // 0x12
2197 u32 i, *ram32 = (u32 *)psxM;
2198 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2200 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2201 ram32[A_PAD_DR_DST/4] = 0;
2202 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2203 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2204 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2205 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2206 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2207 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2208 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2209 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2211 for (i = 0; i < a1; i++) {
2213 storeRam8(a0 + i, 0);
2215 for (i = 0; i < a3; i++) {
2217 storeRam8(a2 + i, 0);
2219 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2221 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2223 mips_return_c(1, 200);
2226 void psxBios_StartPAD() { // 13
2227 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2229 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2230 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2231 psxHwWrite16(0x1f801070, ~1);
2232 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2233 storeRam32(A_PAD_ACK_VBL, 1);
2234 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2235 psxRegs.CP0.n.SR |= 0x401;
2237 mips_return_c(1, 300);
2240 void psxBios_StopPAD() { // 14
2241 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2242 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2243 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2244 psxRegs.CP0.n.SR |= 0x401;
2245 mips_return_void_c(200);
2248 static void psxBios_PAD_init() { // 15
2250 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2251 if (a0 == 0x20000000 || a0 == 0x20000001)
2254 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2255 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2258 storeRam32(A_PAD_DR_DST, dst);
2261 mips_return_c(ret, 100);
2264 static u32 psxBios_PAD_dr_() {
2265 u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2266 u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2267 u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2268 dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2269 if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2271 dst[0] = buf1[3], dst[1] = buf1[2];
2272 if (buf1[1] == 0x23) {
2273 dst[0] |= 0xc7, dst[1] |= 7;
2274 if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2275 if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2278 if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2280 dst[2] = buf2[3], dst[3] = buf2[2];
2281 if (buf2[1] == 0x23) {
2282 dst[2] |= 0xc7, dst[3] |= 7;
2283 if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2284 if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2288 return SWAP32(*(u32 *)dst);
2291 static void psxBios_PAD_dr() { // 16
2292 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2293 u32 ret = psxBios_PAD_dr_();
2297 static void psxBios_ReturnFromException() { // 17
2298 u32 tcbPtr = loadRam32(A_TT_PCB);
2299 const TCB *tcb = loadRam32ptr(tcbPtr);
2303 for (i = 1; i < 32; i++)
2304 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2305 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2306 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2307 sr = SWAP32(tcb->sr);
2309 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2310 pc0 = k0 = SWAP32(tcb->epc);
2312 // the interpreter wants to know about sr changes, so do a MTC0
2313 sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2314 MTC0(&psxRegs, 12, sr);
2320 void psxBios_ResetEntryInt() { // 18
2321 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2323 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2324 mips_return_void_c(5);
2327 void psxBios_HookEntryInt() { // 19
2328 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2330 storeRam32(A_EEXIT_PTR, a0);
2331 mips_return_void_c(3);
2334 static void psxBios_UnDeliverEvent() { // 0x20
2336 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2338 ret = UnDeliverEvent(a0, a1);
2342 static void buopen(int mcd, char *ptr, char *cfg)
2345 char *mcd_data = ptr;
2347 strcpy(FDesc[1 + mcd].name, Ra0+5);
2348 FDesc[1 + mcd].offset = 0;
2349 FDesc[1 + mcd].mode = a1;
2351 for (i=1; i<16; i++) {
2352 const char *fptr = mcd_data + 128 * i;
2353 if ((*fptr & 0xF0) != 0x50) continue;
2354 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2355 FDesc[1 + mcd].mcfile = i;
2356 PSXBIOS_LOG("open %s\n", fptr+0xa);
2360 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2361 for (i=1; i<16; i++) {
2362 int j, xor, nblk = a1 >> 16;
2364 char *fptr = mcd_data + 128 * i;
2366 if ((*fptr & 0xF0) != 0xa0) continue;
2368 FDesc[1 + mcd].mcfile = i;
2371 fptr[5] = 0x20 * nblk;
2374 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2375 pptr = fptr2 = fptr;
2376 for(j=2; j<=nblk; j++) {
2378 for(i++; i<16; i++) {
2381 memset(fptr2, 0, 128);
2382 fptr2[0] = j < nblk ? 0x52 : 0x53;
2385 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2390 /* shouldn't this return ENOSPC if i == 16? */
2392 pptr[8] = pptr[9] = 0xff;
2393 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2395 PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2397 /* just go ahead and resave them all */
2398 SaveMcd(cfg, ptr, 128, 128 * 15);
2401 /* shouldn't this return ENOSPC if i == 16? */
2406 * int open(char *name , int mode);
2409 void psxBios_open() { // 0x32
2412 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x32], Ra0, a1);
2416 if (pa0 != INVALID_PTR) {
2417 if (!strncmp(pa0, "bu00", 4)) {
2418 buopen(1, Mcd1Data, Config.Mcd1);
2421 if (!strncmp(pa0, "bu10", 4)) {
2422 buopen(2, Mcd2Data, Config.Mcd2);
2430 * int lseek(int fd , int offset , int whence);
2433 void psxBios_lseek() { // 0x33
2435 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2440 FDesc[a0].offset = a1;
2442 // DeliverEvent(0xf0000011, 0x0004);
2443 // DeliverEvent(0xf4000001, 0x0004);
2447 FDesc[a0].offset+= a1;
2448 v0 = FDesc[a0].offset;
2457 * int read(int fd , void *buf , int nbytes);
2460 void psxBios_read() { // 0x34
2465 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2470 if (pa1 != INVALID_PTR) {
2472 case 2: buread(pa1, 1, a2); break;
2473 case 3: buread(pa1, 2, a2); break;
2481 * int write(int fd , void *buf , int nbytes);
2484 void psxBios_write() { // 0x35/0x03
2488 if (a0 != 1) // stdout
2489 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2492 if (pa1 == INVALID_PTR) {
2497 if (a0 == 1) { // stdout
2501 if (Config.PsxOut) while (a2 > 0) {
2502 SysPrintf("%c", *ptr++); a2--;
2508 case 2: buwrite(pa1, 1, a2); break;
2509 case 3: buwrite(pa1, 2, a2); break;
2515 static void psxBios_write_psxout() {
2516 if (a0 == 1) { // stdout
2517 const char *ptr = Ra1;
2520 if (ptr != INVALID_PTR)
2522 SysPrintf("%c", *ptr++);
2526 static void psxBios_putchar_psxout() { // 3d
2527 SysPrintf("%c", (char)a0);
2530 static void psxBios_puts_psxout() { // 3e/3f
2531 SysPrintf("%s", Ra0);
2535 * int close(int fd);
2538 void psxBios_close() { // 0x36
2540 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2547 void psxBios_putchar() { // 3d
2548 if (Config.PsxOut) SysPrintf("%c", (char)a0);
2552 void psxBios_puts() { // 3e/3f
2553 if (Config.PsxOut) SysPrintf("%s", Ra0);
2557 static void bufile(const u8 *mcd_data, u32 dir_) {
2558 struct DIRENTRY *dir = (struct DIRENTRY *)castRam8ptr(dir_);
2559 const char *pfile = ffile + 5;
2560 const u8 *data = mcd_data;
2561 int i = 0, match = 0;
2566 for (; nfile <= 15 && !match; nfile++) {
2569 head = nfile * 0x40;
2570 data = mcd_data + 128 * nfile;
2571 name = (const char *)data + 0x0a;
2572 if ((data[0] & 0xF0) != 0x50) continue;
2573 /* Bug link files show up as free block. */
2574 if (!name[0]) continue;
2576 for (i = 0; i < 20; i++) {
2577 if (pfile[i] == name[i] || pfile[i] == '?')
2578 dir->name[i] = name[i];
2579 else if (pfile[i] == '*') {
2580 int len = strlen(name + i);
2583 memcpy(dir->name + i, name + i, len + 1);
2594 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n",
2595 nfile, dir->name, pfile, name, match);
2597 for (; nfile <= 15; nfile++, blocks++) {
2598 const u8 *data2 = mcd_data + 128 * nfile;
2599 const char *name = data2 + 0x0a;
2600 if ((data2[0] & 0xF0) != 0x50 || name[0])
2604 // nul char of full lenth name seems to overwrite .attr
2605 dir->attr = SWAP32(i < 20 ? data[0] & 0xf0 : 0); // ?
2606 dir->size = 8192 * blocks;
2610 PSXBIOS_LOG(" -> %x '%s' %x %x %x %x\n", v0, v0 ? dir->name : "",
2611 dir->attr, dir->size, dir->next, dir->head);
2615 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2618 static void psxBios_firstfile() { // 42
2619 char *pa0 = castRam8ptr(a0);
2621 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x42], pa0, a1);
2625 snprintf(ffile, sizeof(ffile), "%s", pa0);
2627 strcpy(ffile + 5, "*"); // maybe?
2629 if (!strncmp(pa0, "bu00", 4)) {
2630 // firstfile() calls _card_read() internally, so deliver it's event
2631 DeliverEvent(0xf0000011, 0x0004);
2632 bufile(Mcd1Data, a1);
2633 } else if (!strncmp(pa0, "bu10", 4)) {
2634 // firstfile() calls _card_read() internally, so deliver it's event
2635 DeliverEvent(0xf0000011, 0x0004);
2636 bufile(Mcd2Data, a1);
2644 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2647 void psxBios_nextfile() { // 43
2648 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x43], a0);
2651 if (!strncmp(ffile, "bu00", 4))
2652 bufile(Mcd1Data, a0);
2653 else if (!strncmp(ffile, "bu10", 4))
2654 bufile(Mcd2Data, a0);
2659 #define burename(mcd) { \
2660 for (i=1; i<16; i++) { \
2661 int namelen, j, xor = 0; \
2662 ptr = Mcd##mcd##Data + 128 * i; \
2663 if ((*ptr & 0xF0) != 0x50) continue; \
2664 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2665 namelen = strlen(Ra1+5); \
2666 memcpy(ptr+0xa, Ra1+5, namelen); \
2667 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2668 for (j=0; j<127; j++) xor^= ptr[j]; \
2670 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2677 * int rename(char *old, char *new);
2680 void psxBios_rename() { // 44
2687 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2692 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2693 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2697 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2706 #define budelete(mcd) { \
2707 for (i=1; i<16; i++) { \
2708 ptr = Mcd##mcd##Data + 128 * i; \
2709 if ((*ptr & 0xF0) != 0x50) continue; \
2710 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2711 *ptr = (*ptr & 0xf) | 0xA0; \
2712 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2713 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2720 * int delete(char *name);
2723 void psxBios_delete() { // 45
2729 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2734 if (pa0 != INVALID_PTR) {
2735 if (!strncmp(pa0, "bu00", 4)) {
2739 if (!strncmp(pa0, "bu10", 4)) {
2747 void psxBios_InitCARD() { // 4a
2748 u32 *ram32 = (u32 *)psxM;
2749 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2750 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2751 // (maybe) todo: early_card_irq, etc
2753 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2755 psxBios_FlushCache();
2756 mips_return_c(0, 34+13+15+6);
2759 void psxBios_StartCARD() { // 4b
2760 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2761 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2762 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2764 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2765 storeRam32(A_PAD_ACK_VBL, 1);
2766 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2767 storeRam32(A_CARD_IRQR_ENA, 1);
2768 psxRegs.CP0.n.SR |= 0x401;
2770 mips_return_c(1, 200);
2773 void psxBios_StopCARD() { // 4c
2774 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2775 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2776 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2777 storeRam32(A_CARD_IRQR_ENA, 0);
2778 psxRegs.CP0.n.SR |= 0x401;
2779 mips_return_void_c(200);
2782 void psxBios__card_write() { // 0x4e
2787 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2790 Function also accepts sector 400h (a bug).
2791 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2795 /* Invalid sectors */
2799 storeRam32(A_CARD_CHAN1, a0);
2802 if (pa2 != INVALID_PTR) {
2804 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2805 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2807 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2808 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2812 DeliverEvent(0xf0000011, 0x0004);
2813 // DeliverEvent(0xf4000001, 0x0004);
2818 void psxBios__card_read() { // 0x4f
2823 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2826 Function also accepts sector 400h (a bug).
2827 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2831 /* Invalid sectors */
2835 storeRam32(A_CARD_CHAN1, a0);
2838 if (pa2 != INVALID_PTR) {
2840 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2842 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2846 DeliverEvent(0xf0000011, 0x0004);
2847 // DeliverEvent(0xf4000001, 0x0004);
2852 void psxBios__new_card() { // 0x50
2854 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2860 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2861 void psxBios__get_error(void) // 55
2863 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2868 void psxBios_Krom2RawAdd() { // 0x51
2871 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2872 const u32 table_8140[][2] = {
2873 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2874 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2875 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2876 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2877 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2878 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2879 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2880 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2881 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2885 const u32 table_889f[][2] = {
2886 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2887 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2888 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2889 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2890 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2891 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2892 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2893 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2897 if (a0 >= 0x8140 && a0 <= 0x84be) {
2898 while (table_8140[i][0] <= a0) i++;
2899 a0 -= table_8140[i - 1][0];
2900 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2901 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2902 while (table_889f[i][0] <= a0) i++;
2903 a0 -= table_889f[i - 1][0];
2904 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2912 void psxBios_GetC0Table() { // 56
2913 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2914 log_unhandled("GetC0Table @%08x\n", ra);
2916 mips_return_c(A_C0_TABLE, 3);
2919 void psxBios_GetB0Table() { // 57
2920 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2921 log_unhandled("GetB0Table @%08x\n", ra);
2923 mips_return_c(A_B0_TABLE, 3);
2926 static void psxBios__card_chan() { // 0x58
2928 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2930 // todo: should return active slot chan
2931 // (active - which was last processed by irq code)
2932 ret = loadRam32(A_CARD_CHAN1);
2933 mips_return_c(ret, 8);
2936 static void psxBios_ChangeClearPad() { // 5b
2938 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2939 ret = loadRam32(A_PAD_ACK_VBL);
2940 storeRam32(A_PAD_ACK_VBL, a0);
2942 mips_return_c(ret, 6);
2945 static void psxBios__card_status() { // 5c
2946 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
2952 static void psxBios__card_wait() { // 5d
2953 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
2959 /* System calls C0 */
2961 static void psxBios_InitRCnt() { // 00
2963 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2964 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2965 for (i = 0; i < 3; i++) {
2966 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2967 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2968 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2970 psxBios_SysEnqIntRP_(a0, 0x6d88);
2971 mips_return_c(0, 9);
2974 static void psxBios_InitException() { // 01
2975 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2976 psxBios_SysEnqIntRP_(a0, 0x6da8);
2977 mips_return_c(0, 9);
2981 * int SysEnqIntRP(int index , long *queue);
2984 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2985 u32 old, base = loadRam32(A_TT_ExCB);
2987 old = loadRam32(base + (priority << 3));
2988 storeRam32(base + (priority << 3), chain_eptr);
2989 storeRam32(chain_eptr, old);
2990 mips_return_c(0, 9);
2993 static void psxBios_SysEnqIntRP() { // 02
2994 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2995 psxBios_SysEnqIntRP_(a0, a1);
2999 * int SysDeqIntRP(int index , long *queue);
3002 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
3003 u32 ptr, next, base = loadRam32(A_TT_ExCB);
3004 u32 lim = 0, ret = 0;
3006 // as in original: no arg checks of any kind, bug if a1 == 0
3007 ptr = loadRam32(base + (priority << 3));
3009 next = loadRam32(ptr);
3010 if (ptr == chain_rm_eptr) {
3011 storeRam32(base + (priority << 3), next);
3016 while (next && next != chain_rm_eptr && lim++ < 100) {
3018 next = loadRam32(ptr);
3021 if (next == chain_rm_eptr) {
3022 next = loadRam32(next);
3023 storeRam32(ptr, next);
3030 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
3032 mips_return_c(ret, 12);
3035 static void psxBios_SysDeqIntRP() { // 03
3036 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
3037 psxBios_SysDeqIntRP_(a0, a1);
3040 static void psxBios_get_free_EvCB_slot() { // 04
3041 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
3042 s32 ret = get_free_EvCB_slot();
3043 mips_return_c(ret, 0);
3046 static void psxBios_SysInitMemory_(u32 base, u32 size) {
3047 storeRam32(base, 0);
3048 storeRam32(A_KMALLOC_PTR, base);
3049 storeRam32(A_KMALLOC_SIZE, size);
3050 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
3053 // this should be much more complicated, but maybe that'll be enough
3054 static u32 psxBios_SysMalloc_(u32 size) {
3055 u32 ptr = loadRam32(A_KMALLOC_PTR);
3057 size = (size + 3) & ~3;
3058 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
3059 storeRam32(ptr, size);
3063 static void psxBios_SysInitMemory() { // 08
3064 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
3066 psxBios_SysInitMemory_(a0, a1);
3067 mips_return_void_c(12);
3070 static void psxBios_ChangeClearRCnt() { // 0a
3073 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
3075 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
3076 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
3077 mips_return_c(ret, 8);
3080 static void psxBios_InitDefInt() { // 0c
3081 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3082 // should also clear the autoack table
3083 psxBios_SysEnqIntRP_(a0, 0x6d98);
3084 mips_return_c(0, 20 + 6*2);
3087 void psxBios_dummy() {
3088 u32 pc = (pc0 & 0x1fffff) - 4;
3089 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
3090 : pc == 0xc0 ? biosC0n : NULL;
3091 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
3092 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
3093 (void)pc; (void)ntab;
3094 mips_return_c(0, 100);
3097 void (*biosA0[256])();
3098 // C0 and B0 overlap (end of C0 is start of B0)
3099 void (*biosC0[256+128])();
3100 void (**biosB0)() = biosC0 + 128;
3102 static void setup_mips_code()
3105 ptr = (u32 *)&psxM[A_SYSCALL];
3106 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3107 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
3108 ptr[0x08/4] = SWAPu32(0x00000000); // nop
3110 ptr = (u32 *)&psxM[A_EXCEPTION];
3111 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
3112 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
3113 ptr[0x14/4] = SWAPu32(0x00000000); // nop
3114 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
3115 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3116 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
3117 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
3118 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
3119 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
3120 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
3122 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
3123 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
3124 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
3126 ptr[0xb0/4] = HLEOP(hleop_exception);
3129 static const struct {
3133 { 0xbfc050a4, hleop_exc0_0_1 },
3134 { 0xbfc04fbc, hleop_exc0_0_2 },
3135 { 0xbfc0506c, hleop_exc0_1_1 },
3136 { 0xbfc04dec, hleop_exc0_1_2 },
3137 { 0x1a00, hleop_exc0_2_2 },
3138 { 0x19c8, hleop_exc1_0_1 },
3139 { 0x18bc, hleop_exc1_0_2 },
3140 { 0x1990, hleop_exc1_1_1 },
3141 { 0x1858, hleop_exc1_1_2 },
3142 { 0x1958, hleop_exc1_2_1 },
3143 { 0x17f4, hleop_exc1_2_2 },
3144 { 0x1920, hleop_exc1_3_1 },
3145 { 0x1794, hleop_exc1_3_2 },
3146 { 0x2458, hleop_exc3_0_2 },
3147 { 0x49bc, hleop_exc_padcard1 },
3148 { 0x4a4c, hleop_exc_padcard2 },
3151 static int chain_hle_op(u32 handler)
3155 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3156 if (chainfns[i].addr == handler)
3157 return chainfns[i].op;
3161 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3163 d[0] = SWAPu32(next);
3164 d[1] = SWAPu32(handler1);
3165 d[2] = SWAPu32(handler2);
3167 // install the hle traps
3168 if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3169 if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3172 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack)
3174 u32 *ram32 = (u32 *)psxM;
3175 u32 s_excb = 0x20, s_evcb, s_pcb = 4, s_tcb;
3176 u32 p_excb, p_evcb, p_pcb, p_tcb;
3179 PSXBIOS_LOG("setup: tcb %u, evcb %u\n", tcb_cnt, evcb_cnt);
3181 // the real bios doesn't care, but we just don't
3182 // want to crash in case of garbage parameters
3183 if (tcb_cnt > 1024) tcb_cnt = 1024;
3184 if (evcb_cnt > 1024) evcb_cnt = 1024;
3185 s_evcb = 0x1c * evcb_cnt;
3186 s_tcb = 0xc0 * tcb_cnt;
3188 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3189 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3190 p_excb = psxBios_SysMalloc_(s_excb);
3191 p_evcb = psxBios_SysMalloc_(s_evcb);
3192 p_pcb = psxBios_SysMalloc_(s_pcb);
3193 p_tcb = psxBios_SysMalloc_(s_tcb);
3195 // "table of tables". Some games modify it
3196 assert(A_TT_ExCB == 0x0100);
3197 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3198 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3199 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3200 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3201 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3202 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3203 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3204 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3205 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3206 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3207 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3208 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3210 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3211 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3212 storeRam32(p_excb + 4*4, 0x0000); // chain2
3213 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3215 storeRam32(p_pcb, p_tcb);
3216 storeRam32(p_tcb, 0x4000); // first TCB
3217 for (i = 1; i < tcb_cnt; i++)
3218 storeRam32(p_tcb + sizeof(TCB) * i, 0x1000);
3221 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3222 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3223 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3224 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3225 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3227 storeRam32(A_CONF_EvCB, evcb_cnt);
3228 storeRam32(A_CONF_TCB, tcb_cnt);
3229 storeRam32(A_CONF_SP, stack);
3232 static const u32 gpu_ctl_def[] = {
3233 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3234 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3237 static const u32 gpu_data_def[] = {
3238 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3239 0xe5001000, 0xe6000000,
3240 0x02000000, 0x00000000, 0x01ff03ff
3244 static const u16 spu_config[] = {
3245 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3246 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3247 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3248 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3249 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3250 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3251 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3252 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3255 void psxBiosSetupBootState(void)
3257 boolean hle = Config.HLE;
3258 u32 *hw = (u32 *)psxH;
3261 // see also SetBootRegs()
3264 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3265 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3267 k0 = 0xbfc0d968; k1 = 0xf1c;
3268 ra = 0xf0001234; // just to easily detect attempts to return
3269 psxRegs.CP0.n.Cause = 0x20;
3270 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3272 hw[0x1000/4] = SWAP32(0x1f000000);
3273 hw[0x1004/4] = SWAP32(0x1f802000);
3274 hw[0x1008/4] = SWAP32(0x0013243f);
3275 hw[0x100c/4] = SWAP32(0x00003022);
3276 hw[0x1010/4] = SWAP32(0x0013243f);
3277 hw[0x1014/4] = SWAP32(0x200931e1);
3278 hw[0x1018/4] = SWAP32(0x00020943);
3279 hw[0x101c/4] = SWAP32(0x00070777);
3280 hw[0x1020/4] = SWAP32(0x0000132c);
3281 hw[0x1060/4] = SWAP32(0x00000b88);
3282 hw[0x1070/4] = SWAP32(0x00000001);
3283 hw[0x1074/4] = SWAP32(0x0000000c);
3284 hw[0x2040/4] = SWAP32(0x00000900);
3287 hw[0x10a0/4] = SWAP32(0x00ffffff);
3288 hw[0x10a8/4] = SWAP32(0x00000401);
3289 hw[0x10b0/4] = SWAP32(0x0008b000);
3290 hw[0x10b4/4] = SWAP32(0x00010200);
3291 hw[0x10e0/4] = SWAP32(0x000eccf4);
3292 hw[0x10e4/4] = SWAP32(0x00000400);
3293 hw[0x10e8/4] = SWAP32(0x00000002);
3294 hw[0x10f0/4] = SWAP32(0x00009099);
3295 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3304 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3305 GPU_writeStatus(gpu_ctl_def[i]);
3306 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3307 GPU_writeData(gpu_data_def[i]);
3308 HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
3311 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3312 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3315 #include "sjisfont.h"
3317 void psxBiosInit() {
3318 u32 *ptr, *ram32, *rom32;
3322 memset(psxM, 0, 0x10000);
3323 for(i = 0; i < 256; i++) {
3328 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3329 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3330 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3331 biosA0[0x3f] = psxBios_printf_psxout;
3333 if (!Config.HLE) return;
3335 for(i = 0; i < 256; i++) {
3336 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3337 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3338 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3341 biosA0[0x00] = psxBios_open;
3342 biosA0[0x01] = psxBios_lseek;
3343 biosA0[0x02] = psxBios_read;
3344 biosA0[0x03] = psxBios_write;
3345 biosA0[0x04] = psxBios_close;
3346 //biosA0[0x05] = psxBios_ioctl;
3347 //biosA0[0x06] = psxBios_exit;
3348 //biosA0[0x07] = psxBios_sys_a0_07;
3349 biosA0[0x08] = psxBios_getc;
3350 biosA0[0x09] = psxBios_putc;
3351 biosA0[0x0a] = psxBios_todigit;
3352 //biosA0[0x0b] = psxBios_atof;
3353 //biosA0[0x0c] = psxBios_strtoul;
3354 //biosA0[0x0d] = psxBios_strtol;
3355 biosA0[0x0e] = psxBios_abs;
3356 biosA0[0x0f] = psxBios_labs;
3357 biosA0[0x10] = psxBios_atoi;
3358 biosA0[0x11] = psxBios_atol;
3359 //biosA0[0x12] = psxBios_atob;
3360 biosA0[0x13] = psxBios_setjmp;
3361 biosA0[0x14] = psxBios_longjmp;
3362 biosA0[0x15] = psxBios_strcat;
3363 biosA0[0x16] = psxBios_strncat;
3364 biosA0[0x17] = psxBios_strcmp;
3365 biosA0[0x18] = psxBios_strncmp;
3366 biosA0[0x19] = psxBios_strcpy;
3367 biosA0[0x1a] = psxBios_strncpy;
3368 biosA0[0x1b] = psxBios_strlen;
3369 biosA0[0x1c] = psxBios_index;
3370 biosA0[0x1d] = psxBios_rindex;
3371 biosA0[0x1e] = psxBios_strchr;
3372 biosA0[0x1f] = psxBios_strrchr;
3373 biosA0[0x20] = psxBios_strpbrk;
3374 biosA0[0x21] = psxBios_strspn;
3375 biosA0[0x22] = psxBios_strcspn;
3376 biosA0[0x23] = psxBios_strtok;
3377 biosA0[0x24] = psxBios_strstr;
3378 biosA0[0x25] = psxBios_toupper;
3379 biosA0[0x26] = psxBios_tolower;
3380 biosA0[0x27] = psxBios_bcopy;
3381 biosA0[0x28] = psxBios_bzero;
3382 biosA0[0x29] = psxBios_bcmp;
3383 biosA0[0x2a] = psxBios_memcpy;
3384 biosA0[0x2b] = psxBios_memset;
3385 biosA0[0x2c] = psxBios_memmove;
3386 biosA0[0x2d] = psxBios_memcmp;
3387 biosA0[0x2e] = psxBios_memchr;
3388 biosA0[0x2f] = psxBios_rand;
3389 biosA0[0x30] = psxBios_srand;
3390 biosA0[0x31] = psxBios_qsort;
3391 //biosA0[0x32] = psxBios_strtod;
3392 biosA0[0x33] = psxBios_malloc;
3393 biosA0[0x34] = psxBios_free;
3394 //biosA0[0x35] = psxBios_lsearch;
3395 //biosA0[0x36] = psxBios_bsearch;
3396 biosA0[0x37] = psxBios_calloc;
3397 biosA0[0x38] = psxBios_realloc;
3398 biosA0[0x39] = psxBios_InitHeap;
3399 //biosA0[0x3a] = psxBios__exit;
3400 biosA0[0x3b] = psxBios_getchar;
3401 biosA0[0x3c] = psxBios_putchar;
3402 //biosA0[0x3d] = psxBios_gets;
3403 biosA0[0x3e] = psxBios_puts;
3404 biosA0[0x3f] = psxBios_printf;
3405 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3406 //biosA0[0x41] = psxBios_LoadTest;
3407 biosA0[0x42] = psxBios_Load;
3408 biosA0[0x43] = psxBios_Exec;
3409 biosA0[0x44] = psxBios_FlushCache;
3410 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3411 biosA0[0x46] = psxBios_GPU_dw;
3412 biosA0[0x47] = psxBios_mem2vram;
3413 biosA0[0x48] = psxBios_SendGPU;
3414 biosA0[0x49] = psxBios_GPU_cw;
3415 biosA0[0x4a] = psxBios_GPU_cwb;
3416 biosA0[0x4b] = psxBios_GPU_SendPackets;
3417 biosA0[0x4c] = psxBios_sys_a0_4c;
3418 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3419 //biosA0[0x4e] = psxBios_GPU_sync;
3420 //biosA0[0x4f] = psxBios_sys_a0_4f;
3421 //biosA0[0x50] = psxBios_sys_a0_50;
3422 biosA0[0x51] = psxBios_LoadExec;
3423 //biosA0[0x52] = psxBios_GetSysSp;
3424 //biosA0[0x53] = psxBios_sys_a0_53;
3425 //biosA0[0x54] = psxBios__96_init_a54;
3426 //biosA0[0x55] = psxBios__bu_init_a55;
3427 biosA0[0x56] = psxBios_CdRemove;
3428 //biosA0[0x57] = psxBios_sys_a0_57;
3429 //biosA0[0x58] = psxBios_sys_a0_58;
3430 //biosA0[0x59] = psxBios_sys_a0_59;
3431 //biosA0[0x5a] = psxBios_sys_a0_5a;
3432 //biosA0[0x5b] = psxBios_dev_tty_init;
3433 //biosA0[0x5c] = psxBios_dev_tty_open;
3434 //biosA0[0x5d] = psxBios_sys_a0_5d;
3435 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3436 //biosA0[0x5f] = psxBios_dev_cd_open;
3437 //biosA0[0x60] = psxBios_dev_cd_read;
3438 //biosA0[0x61] = psxBios_dev_cd_close;
3439 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3440 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3441 //biosA0[0x64] = psxBios_dev_cd_chdir;
3442 //biosA0[0x65] = psxBios_dev_card_open;
3443 //biosA0[0x66] = psxBios_dev_card_read;
3444 //biosA0[0x67] = psxBios_dev_card_write;
3445 //biosA0[0x68] = psxBios_dev_card_close;
3446 //biosA0[0x69] = psxBios_dev_card_firstfile;
3447 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3448 //biosA0[0x6b] = psxBios_dev_card_erase;
3449 //biosA0[0x6c] = psxBios_dev_card_undelete;
3450 //biosA0[0x6d] = psxBios_dev_card_format;
3451 //biosA0[0x6e] = psxBios_dev_card_rename;
3452 //biosA0[0x6f] = psxBios_dev_card_6f;
3453 biosA0[0x70] = psxBios__bu_init;
3454 biosA0[0x71] = psxBios__96_init;
3455 biosA0[0x72] = psxBios_CdRemove;
3456 //biosA0[0x73] = psxBios_sys_a0_73;
3457 //biosA0[0x74] = psxBios_sys_a0_74;
3458 //biosA0[0x75] = psxBios_sys_a0_75;
3459 //biosA0[0x76] = psxBios_sys_a0_76;
3460 //biosA0[0x77] = psxBios_sys_a0_77;
3461 //biosA0[0x78] = psxBios__96_CdSeekL;
3462 //biosA0[0x79] = psxBios_sys_a0_79;
3463 //biosA0[0x7a] = psxBios_sys_a0_7a;
3464 //biosA0[0x7b] = psxBios_sys_a0_7b;
3465 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3466 //biosA0[0x7d] = psxBios_sys_a0_7d;
3467 //biosA0[0x7e] = psxBios__96_CdRead;
3468 //biosA0[0x7f] = psxBios_sys_a0_7f;
3469 //biosA0[0x80] = psxBios_sys_a0_80;
3470 //biosA0[0x81] = psxBios_sys_a0_81;
3471 //biosA0[0x82] = psxBios_sys_a0_82;
3472 //biosA0[0x83] = psxBios_sys_a0_83;
3473 //biosA0[0x84] = psxBios_sys_a0_84;
3474 //biosA0[0x85] = psxBios__96_CdStop;
3475 //biosA0[0x86] = psxBios_sys_a0_86;
3476 //biosA0[0x87] = psxBios_sys_a0_87;
3477 //biosA0[0x88] = psxBios_sys_a0_88;
3478 //biosA0[0x89] = psxBios_sys_a0_89;
3479 //biosA0[0x8a] = psxBios_sys_a0_8a;
3480 //biosA0[0x8b] = psxBios_sys_a0_8b;
3481 //biosA0[0x8c] = psxBios_sys_a0_8c;
3482 //biosA0[0x8d] = psxBios_sys_a0_8d;
3483 //biosA0[0x8e] = psxBios_sys_a0_8e;
3484 //biosA0[0x8f] = psxBios_sys_a0_8f;
3485 biosA0[0x90] = hleExc0_1_2;
3486 biosA0[0x91] = hleExc0_0_2;
3487 biosA0[0x92] = hleExc0_1_1;
3488 biosA0[0x93] = hleExc0_0_1;
3489 //biosA0[0x94] = psxBios_sys_a0_94;
3490 //biosA0[0x95] = psxBios_sys_a0_95;
3491 //biosA0[0x96] = psxBios_AddCDROMDevice;
3492 //biosA0[0x97] = psxBios_AddMemCardDevide;
3493 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3494 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3495 //biosA0[0x9a] = psxBios_sys_a0_9a;
3496 //biosA0[0x9b] = psxBios_sys_a0_9b;
3497 biosA0[0x9c] = psxBios_SetConf;
3498 biosA0[0x9d] = psxBios_GetConf;
3499 //biosA0[0x9e] = psxBios_sys_a0_9e;
3500 biosA0[0x9f] = psxBios_SetMem;
3501 //biosA0[0xa0] = psxBios__boot;
3502 //biosA0[0xa1] = psxBios_SystemError;
3503 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3504 biosA0[0xa3] = psxBios_DequeueCdIntr;
3505 //biosA0[0xa4] = psxBios_sys_a0_a4;
3506 //biosA0[0xa5] = psxBios_ReadSector;
3507 biosA0[0xa6] = psxBios_get_cd_status;
3508 //biosA0[0xa7] = psxBios_bufs_cb_0;
3509 //biosA0[0xa8] = psxBios_bufs_cb_1;
3510 //biosA0[0xa9] = psxBios_bufs_cb_2;
3511 //biosA0[0xaa] = psxBios_bufs_cb_3;
3512 biosA0[0xab] = psxBios__card_info;
3513 biosA0[0xac] = psxBios__card_load;
3514 //biosA0[0axd] = psxBios__card_auto;
3515 //biosA0[0xae] = psxBios_bufs_cd_4;
3516 //biosA0[0xaf] = psxBios_sys_a0_af;
3517 //biosA0[0xb0] = psxBios_sys_a0_b0;
3518 //biosA0[0xb1] = psxBios_sys_a0_b1;
3519 //biosA0[0xb2] = psxBios_do_a_long_jmp
3520 //biosA0[0xb3] = psxBios_sys_a0_b3;
3521 biosA0[0xb4] = psxBios_GetSystemInfo;
3522 //*******************B0 CALLS****************************
3523 biosB0[0x00] = psxBios_SysMalloc;
3524 //biosB0[0x01] = psxBios_sys_b0_01;
3525 biosB0[0x02] = psxBios_SetRCnt;
3526 biosB0[0x03] = psxBios_GetRCnt;
3527 biosB0[0x04] = psxBios_StartRCnt;
3528 biosB0[0x05] = psxBios_StopRCnt;
3529 biosB0[0x06] = psxBios_ResetRCnt;
3530 biosB0[0x07] = psxBios_DeliverEvent;
3531 biosB0[0x08] = psxBios_OpenEvent;
3532 biosB0[0x09] = psxBios_CloseEvent;
3533 biosB0[0x0a] = psxBios_WaitEvent;
3534 biosB0[0x0b] = psxBios_TestEvent;
3535 biosB0[0x0c] = psxBios_EnableEvent;
3536 biosB0[0x0d] = psxBios_DisableEvent;
3537 biosB0[0x0e] = psxBios_OpenTh;
3538 biosB0[0x0f] = psxBios_CloseTh;
3539 biosB0[0x10] = psxBios_ChangeTh;
3540 //biosB0[0x11] = psxBios_psxBios_b0_11;
3541 biosB0[0x12] = psxBios_InitPAD;
3542 biosB0[0x13] = psxBios_StartPAD;
3543 biosB0[0x14] = psxBios_StopPAD;
3544 biosB0[0x15] = psxBios_PAD_init;
3545 biosB0[0x16] = psxBios_PAD_dr;
3546 biosB0[0x17] = psxBios_ReturnFromException;
3547 biosB0[0x18] = psxBios_ResetEntryInt;
3548 biosB0[0x19] = psxBios_HookEntryInt;
3549 //biosB0[0x1a] = psxBios_sys_b0_1a;
3550 //biosB0[0x1b] = psxBios_sys_b0_1b;
3551 //biosB0[0x1c] = psxBios_sys_b0_1c;
3552 //biosB0[0x1d] = psxBios_sys_b0_1d;
3553 //biosB0[0x1e] = psxBios_sys_b0_1e;
3554 //biosB0[0x1f] = psxBios_sys_b0_1f;
3555 biosB0[0x20] = psxBios_UnDeliverEvent;
3556 //biosB0[0x21] = psxBios_sys_b0_21;
3557 //biosB0[0x22] = psxBios_sys_b0_22;
3558 //biosB0[0x23] = psxBios_sys_b0_23;
3559 //biosB0[0x24] = psxBios_sys_b0_24;
3560 //biosB0[0x25] = psxBios_sys_b0_25;
3561 //biosB0[0x26] = psxBios_sys_b0_26;
3562 //biosB0[0x27] = psxBios_sys_b0_27;
3563 //biosB0[0x28] = psxBios_sys_b0_28;
3564 //biosB0[0x29] = psxBios_sys_b0_29;
3565 //biosB0[0x2a] = psxBios_sys_b0_2a;
3566 //biosB0[0x2b] = psxBios_sys_b0_2b;
3567 //biosB0[0x2c] = psxBios_sys_b0_2c;
3568 //biosB0[0x2d] = psxBios_sys_b0_2d;
3569 //biosB0[0x2e] = psxBios_sys_b0_2e;
3570 //biosB0[0x2f] = psxBios_sys_b0_2f;
3571 //biosB0[0x30] = psxBios_sys_b0_30;
3572 //biosB0[0x31] = psxBios_sys_b0_31;
3573 biosB0[0x32] = psxBios_open;
3574 biosB0[0x33] = psxBios_lseek;
3575 biosB0[0x34] = psxBios_read;
3576 biosB0[0x35] = psxBios_write;
3577 biosB0[0x36] = psxBios_close;
3578 //biosB0[0x37] = psxBios_ioctl;
3579 //biosB0[0x38] = psxBios_exit;
3580 //biosB0[0x39] = psxBios_sys_b0_39;
3581 //biosB0[0x3a] = psxBios_getc;
3582 //biosB0[0x3b] = psxBios_putc;
3583 biosB0[0x3c] = psxBios_getchar;
3584 biosB0[0x3d] = psxBios_putchar;
3585 //biosB0[0x3e] = psxBios_gets;
3586 biosB0[0x3f] = psxBios_puts;
3587 biosB0[0x40] = psxBios_cd;
3588 biosB0[0x41] = psxBios_format;
3589 biosB0[0x42] = psxBios_firstfile;
3590 biosB0[0x43] = psxBios_nextfile;
3591 biosB0[0x44] = psxBios_rename;
3592 biosB0[0x45] = psxBios_delete;
3593 //biosB0[0x46] = psxBios_undelete;
3594 //biosB0[0x47] = psxBios_AddDevice;
3595 //biosB0[0x48] = psxBios_RemoteDevice;
3596 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3597 biosB0[0x4a] = psxBios_InitCARD;
3598 biosB0[0x4b] = psxBios_StartCARD;
3599 biosB0[0x4c] = psxBios_StopCARD;
3600 //biosB0[0x4d] = psxBios_sys_b0_4d;
3601 biosB0[0x4e] = psxBios__card_write;
3602 biosB0[0x4f] = psxBios__card_read;
3603 biosB0[0x50] = psxBios__new_card;
3604 biosB0[0x51] = psxBios_Krom2RawAdd;
3605 //biosB0[0x52] = psxBios_sys_b0_52;
3606 //biosB0[0x53] = psxBios_sys_b0_53;
3607 //biosB0[0x54] = psxBios__get_errno;
3608 biosB0[0x55] = psxBios__get_error;
3609 biosB0[0x56] = psxBios_GetC0Table;
3610 biosB0[0x57] = psxBios_GetB0Table;
3611 biosB0[0x58] = psxBios__card_chan;
3612 //biosB0[0x59] = psxBios_sys_b0_59;
3613 //biosB0[0x5a] = psxBios_sys_b0_5a;
3614 biosB0[0x5b] = psxBios_ChangeClearPad;
3615 biosB0[0x5c] = psxBios__card_status;
3616 biosB0[0x5d] = psxBios__card_wait;
3617 //*******************C0 CALLS****************************
3618 biosC0[0x00] = psxBios_InitRCnt;
3619 biosC0[0x01] = psxBios_InitException;
3620 biosC0[0x02] = psxBios_SysEnqIntRP;
3621 biosC0[0x03] = psxBios_SysDeqIntRP;
3622 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3623 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3624 //biosC0[0x06] = psxBios_ExceptionHandler;
3625 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3626 biosC0[0x08] = psxBios_SysInitMemory;
3627 //biosC0[0x09] = psxBios_SysInitKMem;
3628 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3629 //biosC0[0x0b] = psxBios_SystemError;
3630 biosC0[0x0c] = psxBios_InitDefInt;
3631 //biosC0[0x0d] = psxBios_sys_c0_0d;
3632 //biosC0[0x0e] = psxBios_sys_c0_0e;
3633 //biosC0[0x0f] = psxBios_sys_c0_0f;
3634 //biosC0[0x10] = psxBios_sys_c0_10;
3635 //biosC0[0x11] = psxBios_sys_c0_11;
3636 //biosC0[0x12] = psxBios_InstallDevices;
3637 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3638 //biosC0[0x14] = psxBios_sys_c0_14;
3639 //biosC0[0x15] = psxBios__cdevinput;
3640 //biosC0[0x16] = psxBios__cdevscan;
3641 //biosC0[0x17] = psxBios__circgetc;
3642 //biosC0[0x18] = psxBios__circputc;
3643 //biosC0[0x19] = psxBios_ioabort;
3644 //biosC0[0x1a] = psxBios_sys_c0_1a
3645 //biosC0[0x1b] = psxBios_KernelRedirect;
3646 //biosC0[0x1c] = psxBios_PatchAOTable;
3647 //************** THE END ***************************************
3650 memset(FDesc, 0, sizeof(FDesc));
3651 memset(cdir, 0, sizeof(cdir));
3654 // somewhat pretend to be a SCPH1001 BIOS
3655 // some games look for these and take an exception if they're missing
3656 rom32 = (u32 *)psxR;
3657 rom32[0x100/4] = SWAP32(0x19951204);
3658 rom32[0x104/4] = SWAP32(3);
3659 strcpy(psxR + 0x108, "PCSX authors");
3660 strcpy(psxR + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3661 strcpy(psxR + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3662 strcpy(psxR + 0x7ff54, "GPL-2.0-or-later");
3665 len = 0x80000 - 0x66000;
3666 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3667 len = 0x80000 - 0x69d68;
3668 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3670 // trap attempts to call bios directly
3671 rom32[0x00000/4] = HLEOP(hleop_dummy);
3672 rom32[0x00180/4] = HLEOP(hleop_dummy);
3673 rom32[0x3fffc/4] = HLEOP(hleop_dummy);
3674 rom32[0x65ffc/4] = HLEOP(hleop_dummy);
3675 rom32[0x7ff2c/4] = HLEOP(hleop_dummy);
3677 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3678 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3679 Here are some examples of games not working with this fix in place :
3680 R-type won't get past the Irem logo if not implemented.
3681 Crash Team Racing will softlock after the Sony logo.
3684 ram32 = (u32 *)psxM;
3685 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3686 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3687 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3688 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3690 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3691 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3693 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3694 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3695 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3696 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3698 ram32[0x00a0/4] = HLEOP(hleop_a0);
3699 ram32[0x00b0/4] = HLEOP(hleop_b0);
3700 ram32[0x00c0/4] = HLEOP(hleop_c0);
3702 setup_tt(4, 16, 0x801fff00);
3703 DeliverEvent(0xf0000003, 0x0010);
3705 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3706 strcpy((char *)&ram32[0xeff0/4], "bu");
3708 // default exception handler chains
3709 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3710 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3711 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3712 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3713 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3714 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3715 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3716 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3720 // fill the api jumptables with fake entries as some games patch them
3721 // (or rather the funcs listed there)
3722 ptr = (u32 *)&psxM[A_A0_TABLE];
3723 for (i = 0; i < 256; i++)
3724 ptr[i] = SWAP32(0x1000);
3726 ptr = (u32 *)&psxM[A_B0_TABLE];
3727 for (i = 0; i < 256; i++)
3728 ptr[i] = SWAP32(0x2000);
3729 // B(5b) is special because games patch (sometimes even jump to)
3730 // code at fixed offsets from it, nocash lists offsets:
3731 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3732 // call: +7a0=4b70, +884=4c54, +894=4c64
3733 ptr[0x5b] = SWAP32(0x43d0);
3734 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3736 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3737 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3738 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3740 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3741 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3743 ptr = (u32 *)&psxM[A_C0_TABLE];
3744 for (i = 0; i < 256/2; i++)
3745 ptr[i] = SWAP32(0x3000);
3746 ptr[6] = SWAP32(A_EXCEPTION);
3749 ram32[0x1000/4] = HLEOP(hleop_dummy);
3750 ram32[0x2000/4] = HLEOP(hleop_dummy);
3751 ram32[0x3000/4] = HLEOP(hleop_dummy);
3752 ram32[0x8000/4] = HLEOP(hleop_execret);
3754 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3755 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3756 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3757 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3758 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3759 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3760 ram32[A_RND_SEED/4] = SWAPu32(0x24040001); // was 0xac20cc00
3763 void psxBiosShutdown() {
3766 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 stack) {
3769 if (tcb_cnt != 4 || evcb_cnt != 16) {
3770 setup_tt(tcb_cnt, evcb_cnt, stack);
3771 DeliverEvent(0xf0000003, 0x0010);
3773 storeRam32(A_CONF_SP, stack);
3776 #define psxBios_PADpoll(pad) { \
3777 int i, more_data = 0; \
3778 pad_buf##pad[0] = PAD##pad##_startPoll(pad); \
3779 pad_buf##pad[1] = PAD##pad##_poll(0x42, &more_data); \
3781 while (more_data) { \
3782 pad_buf##pad[i++] = PAD##pad##_poll(0, &more_data); \
3786 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3790 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3791 psxBios_ReturnFromException();
3797 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3798 // so this is only partially implemented
3799 void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3801 u32 cdrom_dma_ack_enable = 1; // a000b93c
3802 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3805 void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3808 //PSXBIOS_LOG("%s\n", __func__);
3810 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3811 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3812 //if (--cdrom_irq_counter == 0) // 0xa0009180
3813 // DeliverEvent(0xf0000003, 0x10);
3817 mips_return_c(ret, 20);
3820 void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3822 u32 cdrom_irq_ack_enable = 1; // a000b938
3823 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3826 void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3829 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3830 PSXBIOS_LOG("%s TODO\n", __func__);
3833 mips_return_c(ret, 20);
3836 void hleExc0_2_2_syscall() // not in any A/B/C table
3838 u32 tcbPtr = loadRam32(A_TT_PCB);
3839 TCB *tcb = loadRam32ptr(tcbPtr);
3840 u32 code = (SWAP32(tcb->cause) & 0x3c) >> 2;
3842 if (code != R3000E_Syscall) {
3844 DeliverEvent(0xf0000010, 0x1000);
3845 //psxBios_SystemErrorUnresolvedException();
3847 mips_return_c(0, 17);
3851 //printf("%s c=%d a0=%d\n", __func__, code, SWAP32(tcb->reg[4]));
3852 tcb->epc += SWAP32(4);
3853 switch (SWAP32(tcb->reg[4])) { // a0
3857 case 1: { // EnterCritical - disable irqs
3858 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3859 tcb->reg[2] = SWAP32(was_enabled);
3860 tcb->sr &= SWAP32(~0x404);
3863 case 2: // ExitCritical - enable irqs
3864 tcb->sr |= SWAP32(0x404);
3867 case 3: { // ChangeThreadSubFunction
3868 u32 tcbPtr = loadRam32(A_TT_PCB);
3869 storeRam32(tcbPtr, SWAP32(tcb->reg[5])); // a1
3873 DeliverEvent(0xf0000010, 0x4000);
3877 psxBios_ReturnFromException();
3880 void hleExc1_0_1(void)
3882 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3883 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3886 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3889 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3890 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3893 mips_return_c(ret, 22);
3896 void hleExc1_0_2(void)
3898 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3901 void hleExc1_1_1(void)
3903 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3904 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3907 void hleExc1_1_2(void)
3909 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3912 void hleExc1_2_1(void)
3914 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3915 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3918 void hleExc1_2_2(void)
3920 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3923 void hleExc1_3_1(void)
3925 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3926 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3929 void hleExc1_3_2(void)
3931 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3934 void hleExc3_0_2_defint(void)
3936 static const struct {
3947 { 6, 6 }, // rcnt2 (bug)
3952 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3953 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3954 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3959 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3962 void hleExcPadCard1(void)
3964 if (loadRam32(A_PAD_IRQR_ENA)) {
3965 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3966 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
3971 if (loadRam32(A_PAD_DR_DST))
3974 if (loadRam32(A_PAD_ACK_VBL))
3975 psxHwWrite16(0x1f801070, ~1);
3976 if (loadRam32(A_CARD_IRQR_ENA)) {
3980 mips_return_c(0, 18);
3983 void hleExcPadCard2(void)
3985 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
3986 mips_return_c(ret, 15);
3989 void psxBiosException() {
3990 u32 tcbPtr = loadRam32(A_TT_PCB);
3991 u32 *chains = loadRam32ptr(A_TT_ExCB);
3992 TCB *tcb = loadRam32ptr(tcbPtr);
3998 // $at, $v0, $v1, $ra already saved by the mips code at A_EXCEPTION
3999 for (i = 4; i < 31; i++) {
4002 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
4004 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
4005 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
4006 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
4007 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
4008 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
4009 sp = fp = loadRam32(A_EXC_SP);
4013 // do the chains (always 4)
4014 for (c = lim = 0; c < 4; c++) {
4015 if (chains[c * 2] == 0)
4017 ptr = SWAP32(chains[c * 2]);
4018 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
4019 chain = castRam32ptr(ptr);
4024 softCallInException(SWAP32(chain[2]));
4025 if (returned_from_exception())
4028 if (v0 == 0 || chain[1] == 0)
4030 softCallInException(SWAP32(chain[1]));
4031 if (returned_from_exception())
4037 // return from exception (custom or default)
4039 ptr = loadRam32(A_EEXIT_PTR);
4040 if (ptr != A_EEXIT_DEF) {
4041 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
4042 longjmp_load(jmp_buf);
4047 psxBios_ReturnFromException();
4050 #define bfreeze(ptr, size) { \
4051 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
4052 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
4056 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
4057 #define bfreezel(ptr) bfreeze(ptr, sizeof(*(ptr)))
4059 void psxBiosFreeze(int Mode) {