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 char *biosA0n[256] = {
52 "open", "lseek", "read", "write",
53 "close", "ioctl", "exit", "sys_a0_07",
54 "getc", "putc", "todigit", "atof",
55 "strtoul", "strtol", "abs", "labs",
57 "atoi", "atol", "atob", "setjmp",
58 "longjmp", "strcat", "strncat", "strcmp",
59 "strncmp", "strcpy", "strncpy", "strlen",
60 "index", "rindex", "strchr", "strrchr",
62 "strpbrk", "strspn", "strcspn", "strtok",
63 "strstr", "toupper", "tolower", "bcopy",
64 "bzero", "bcmp", "memcpy", "memset",
65 "memmove", "memcmp", "memchr", "rand",
67 "srand", "qsort", "strtod", "malloc",
68 "free", "lsearch", "bsearch", "calloc",
69 "realloc", "InitHeap", "_exit", "getchar",
70 "putchar", "gets", "puts", "printf",
72 "SystemErrorUnresolvedException", "LoadTest", "Load", "Exec",
73 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
74 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
75 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
77 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
78 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
79 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
80 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
82 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
83 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
84 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
85 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
87 "_bu_init", "_96_init", "CdRemove", "sys_a0_73",
88 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
89 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
90 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
92 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
93 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
94 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
95 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
97 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
98 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
99 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
100 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
102 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
103 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
104 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
105 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
107 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
111 char *biosB0n[256] = {
113 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
114 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
115 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
116 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
118 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
119 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
120 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
121 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
123 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
124 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
125 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
126 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
128 "sys_b0_30", "sys_b0_31", "open", "lseek",
129 "read", "write", "close", "ioctl",
130 "exit", "sys_b0_39", "getc", "putc",
131 "getchar", "putchar", "gets", "puts",
133 "cd", "format", "firstfile", "nextfile",
134 "rename", "delete", "undelete", "AddDevice",
135 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
136 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
138 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
139 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
140 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
141 "_card_status", "_card_wait",
144 char *biosC0n[256] = {
146 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
147 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
148 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
149 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
151 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
152 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
153 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
157 //#define r0 (psxRegs.GPR.n.r0)
158 #define at (psxRegs.GPR.n.at)
159 #define v0 (psxRegs.GPR.n.v0)
160 #define v1 (psxRegs.GPR.n.v1)
161 #define a0 (psxRegs.GPR.n.a0)
162 #define a1 (psxRegs.GPR.n.a1)
163 #define a2 (psxRegs.GPR.n.a2)
164 #define a3 (psxRegs.GPR.n.a3)
165 #define t0 (psxRegs.GPR.n.t0)
166 #define t1 (psxRegs.GPR.n.t1)
167 #define t2 (psxRegs.GPR.n.t2)
168 #define t3 (psxRegs.GPR.n.t3)
169 #define t4 (psxRegs.GPR.n.t4)
170 #define t5 (psxRegs.GPR.n.t5)
171 #define t6 (psxRegs.GPR.n.t6)
172 #define t7 (psxRegs.GPR.n.t7)
173 #define t8 (psxRegs.GPR.n.t8)
174 #define t9 (psxRegs.GPR.n.t9)
175 #define s0 (psxRegs.GPR.n.s0)
176 #define s1 (psxRegs.GPR.n.s1)
177 #define s2 (psxRegs.GPR.n.s2)
178 #define s3 (psxRegs.GPR.n.s3)
179 #define s4 (psxRegs.GPR.n.s4)
180 #define s5 (psxRegs.GPR.n.s5)
181 #define s6 (psxRegs.GPR.n.s6)
182 #define s7 (psxRegs.GPR.n.s7)
183 #define k0 (psxRegs.GPR.n.k0)
184 #define k1 (psxRegs.GPR.n.k1)
185 #define gp (psxRegs.GPR.n.gp)
186 #define sp (psxRegs.GPR.n.sp)
187 #define fp (psxRegs.GPR.n.fp)
188 #define ra (psxRegs.GPR.n.ra)
189 #define pc0 (psxRegs.pc)
191 #define Ra0 ((char *)PSXM(a0))
192 #define Ra1 ((char *)PSXM(a1))
193 #define Ra2 ((char *)PSXM(a2))
194 #define Ra3 ((char *)PSXM(a3))
195 #define Rv0 ((char *)PSXM(v0))
196 #define Rsp ((char *)PSXM(sp))
207 #define EvStUNUSED 0x0000
208 #define EvStDISABLED 0x1000
209 #define EvStACTIVE 0x2000
210 #define EvStALREADY 0x4000
212 #define EvMdCALL 0x1000
213 #define EvMdMARK 0x2000
236 u32 _sp, _fp, _gp, ret, base;
256 // todo: FileDesc layout is wrong
257 // todo: get rid of these globals
258 static FileDesc FDesc[32];
259 static char ffile[64];
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_FLAG 0x900c
296 #define A_RND_SEED 0x9010
297 #define A_CD_EVENTS 0xb9b8
298 #define A_EXC_GP 0xf450
300 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
302 static u32 loadRam32(u32 addr)
304 assert(!(addr & 0x5f800000));
305 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
308 static void *castRam8ptr(u32 addr)
310 assert(!(addr & 0x5f800000));
311 return psxM + (addr & 0x1fffff);
314 static void *castRam32ptr(u32 addr)
316 assert(!(addr & 0x5f800003));
317 return psxM + (addr & 0x1ffffc);
320 static void *loadRam8ptr(u32 addr)
322 return castRam8ptr(loadRam32(addr));
325 static void *loadRam32ptr(u32 addr)
327 return castRam32ptr(loadRam32(addr));
330 static void storeRam8(u32 addr, u8 d)
332 assert(!(addr & 0x5f800000));
333 *((u8 *)psxM + (addr & 0x1fffff)) = d;
336 static void storeRam32(u32 addr, u32 d)
338 assert(!(addr & 0x5f800000));
339 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
342 static void mips_return(u32 val)
348 static void mips_return_void(void)
353 static void use_cycles(u32 cycle)
355 psxRegs.cycle += cycle * 2;
358 static void mips_return_c(u32 val, u32 cycle)
364 static void mips_return_void_c(u32 cycle)
370 static int returned_from_exception(void)
372 // 0x80000080 means it took another exception just after return
373 return pc0 == k0 || pc0 == 0x80000080;
376 static inline void softCall(u32 pc) {
378 u32 ssr = psxRegs.CP0.n.SR;
382 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
384 while (pc0 != 0x80001000 && ++lim < 1000000)
385 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
388 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
390 psxRegs.CP0.n.SR |= ssr & 0x404;
393 static inline void softCallInException(u32 pc) {
398 assert(ra != 0x80001000);
399 if (ra == 0x80001000)
403 while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 1000000)
404 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
407 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
408 if (pc0 == 0x80001000)
412 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
413 static u32 DeliverEvent(u32 class, u32 spec);
414 static u32 UnDeliverEvent(u32 class, u32 spec);
415 static void CloseEvent(u32 ev);
420 // System calls A0 */
423 #define buread(Ra1, mcd, length) { \
424 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); \
425 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
426 memcpy(Ra1, ptr, length); \
427 psxCpu->Clear(a1, (length + 3) / 4); \
428 if (FDesc[1 + mcd].mode & 0x8000) { \
429 DeliverEvent(0xf0000011, 0x0004); \
430 DeliverEvent(0xf4000001, 0x0004); \
433 FDesc[1 + mcd].offset += v0; \
436 #define buwrite(Ra1, mcd, length) { \
437 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
438 PSXBIOS_LOG("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
439 ptr = Mcd##mcd##Data + offset; \
440 memcpy(ptr, Ra1, length); \
441 FDesc[1 + mcd].offset += length; \
442 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
443 if (FDesc[1 + mcd].mode & 0x8000) { \
444 DeliverEvent(0xf0000011, 0x0004); \
445 DeliverEvent(0xf4000001, 0x0004); \
450 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
451 /* For some strange reason, the returned character is sign-expanded; */
452 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
453 /* TODO FIX ME : Properly implement this behaviour */
454 void psxBios_getc(void) // 0x03, 0x35
459 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
463 if (pa1 != INVALID_PTR) {
465 case 2: buread(pa1, 1, 1); break;
466 case 3: buread(pa1, 2, 1); break;
473 /* Copy of psxBios_write, except size is 1. */
474 void psxBios_putc(void) // 0x09, 0x3B
479 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
482 if (pa1 == INVALID_PTR) {
487 if (a0 == 1) { // stdout
488 char *ptr = (char *)pa1;
492 printf("%c", *ptr++); a2--;
498 case 2: buwrite(pa1, 1, 1); break;
499 case 3: buwrite(pa1, 2, 1); break;
505 void psxBios_todigit(void) // 0x0a
509 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
512 if (c >= 0x30 && c < 0x3A) {
515 else if (c > 0x60 && c < 0x7B) {
518 else if (c > 0x40 && c < 0x5B) {
521 else if (c >= 0x80) {
532 void psxBios_abs() { // 0x0e
533 if ((s32)a0 < 0) v0 = -(s32)a0;
538 void psxBios_labs() { // 0x0f
542 void psxBios_atoi() { // 0x10
544 char *p = (char *)Ra0;
548 case ' ': case '\t': continue;
555 while (*p >= '0' && *p <= '9') {
556 n = n * 10 + *p++ - '0';
563 void psxBios_atol() { // 0x11
573 static void psxBios_setjmp() { // 0x13
574 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
577 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
579 jmp_buf->ra_ = SWAP32(ra);
580 jmp_buf->sp_ = SWAP32(sp);
581 jmp_buf->fp_ = SWAP32(fp);
582 for (i = 0; i < 8; i++) // s0-s7
583 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
584 jmp_buf->gp_ = SWAP32(gp);
586 mips_return_c(0, 15);
589 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
593 ra = SWAP32(jmp_buf->ra_);
594 sp = SWAP32(jmp_buf->sp_);
595 fp = SWAP32(jmp_buf->fp_);
596 for (i = 0; i < 8; i++) // s0-s7
597 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
598 gp = SWAP32(jmp_buf->gp_);;
601 void psxBios_longjmp() { // 0x14
602 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
604 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
605 longjmp_load(jmp_buf);
606 mips_return_c(a1, 15);
609 void psxBios_strcat() { // 0x15
610 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
613 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
615 if (a0 == 0 || a1 == 0)
623 while ((*p1++ = *p2++) != '\0');
628 void psxBios_strncat() { // 0x16
629 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
633 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
635 if (a0 == 0 || a1 == 0)
643 while ((*p1++ = *p2++) != '\0') {
653 void psxBios_strcmp() { // 0x17
654 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
656 if (a0 == 0 && a1 == 0)
662 else if (a0 == 0 && a1 != 0)
668 else if (a0 != 0 && a1 == 0)
675 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
678 while (*p1 == *p2++) {
697 void psxBios_strncmp() { // 0x18
698 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
700 if (a0 == 0 && a1 == 0)
706 else if (a0 == 0 && a1 != 0)
712 else if (a0 != 0 && a1 == 0)
719 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
722 while (--n >= 0 && *p1 == *p2++) {
726 v1 = a2 - ((a2-n) - 1);
734 v0 = (n < 0 ? 0 : *p1 - *--p2);
736 v1 = a2 - ((a2-n) - 1);
742 void psxBios_strcpy() { // 0x19
743 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
744 if (a0 == 0 || a1 == 0)
750 while ((*p1++ = *p2++) != '\0');
755 void psxBios_strncpy() { // 0x1a
756 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
758 if (a0 == 0 || a1 == 0)
764 for (i = 0; i < n; i++) {
765 if ((*p1++ = *p2++) == '\0') {
777 void psxBios_strlen() { // 0x1b
778 char *p = (char *)Ra0;
789 void psxBios_index() { // 0x1c
790 char *p = (char *)Ra0;
800 v0 = a0 + (p - (char *)Ra0);
804 } while (*p++ != '\0');
809 void psxBios_rindex() { // 0x1d
810 char *p = (char *)Ra0;
820 v0 = a0 + (p - (char *)Ra0);
821 } while (*p++ != '\0');
826 void psxBios_strchr() { // 0x1e
830 void psxBios_strrchr() { // 0x1f
834 void psxBios_strpbrk() { // 0x20
835 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
837 while ((c = *p1++) != '\0') {
838 for (scanp = p2; (sc = *scanp++) != '\0';) {
840 v0 = a0 + (p1 - 1 - (char *)Ra0);
847 // BUG: return a0 instead of NULL if not found
851 void psxBios_strspn() { // 0x21
854 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
855 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
856 if (*p2 == '\0') break;
859 v0 = p1 - (char *)Ra0; pc0 = ra;
862 void psxBios_strcspn() { // 0x22
865 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
866 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
867 if (*p2 != '\0') break;
870 v0 = p1 - (char *)Ra0; pc0 = ra;
873 void psxBios_strtok() { // 0x23
874 char *pcA0 = (char *)Ra0;
875 char *pcRet = strtok(pcA0, (char *)Ra1);
877 v0 = a0 + pcRet - pcA0;
883 void psxBios_strstr() { // 0x24
884 char *p = (char *)Ra0, *p1, *p2;
890 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
895 v0 = a0 + (p - (char *)Ra0);
906 void psxBios_toupper() { // 0x25
907 v0 = (s8)(a0 & 0xff);
908 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
912 void psxBios_tolower() { // 0x26
913 v0 = (s8)(a0 & 0xff);
914 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
918 static void do_memset(u32 dst, u32 v, s32 len)
924 if (db != INVALID_PTR)
928 psxCpu->Clear(dst, (len + 3) / 4);
931 static void do_memcpy(u32 dst, u32 src, s32 len)
933 u32 d = dst, s = src;
936 const u8 *sb = PSXM(s);
938 if (db != INVALID_PTR && sb != INVALID_PTR)
943 psxCpu->Clear(dst, (len + 3) / 4);
946 static void psxBios_memcpy();
948 static void psxBios_bcopy() { // 0x27 - memcpy with args swapped
949 //PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x27], a0, a1, a2);
950 u32 ret = a0, cycles = 0;
951 if (a0 == 0) // ...but it checks src this time
958 do_memcpy(a1, a0, a2);
964 mips_return_c(ret, cycles + 5);
967 static void psxBios_bzero() { // 0x28
968 /* Same as memset here (See memset below) */
969 u32 ret = a0, cycles;
970 if (a0 == 0 || (s32)a1 <= 0)
975 do_memset(a0, 0, a1);
979 // todo: many more cycles due to uncached bios mem
980 mips_return_c(ret, cycles + 5);
983 void psxBios_bcmp() { // 0x29
984 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
986 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
988 while ((s32)a2-- > 0) {
989 if (*p1++ != *p2++) {
990 v0 = *p1 - *p2; // BUG: compare the NEXT byte
999 static void psxBios_memcpy() { // 0x2a
1000 u32 ret = a0, cycles = 0;
1003 mips_return_c(0, 4);
1008 do_memcpy(a0, a1, a2);
1014 mips_return_c(ret, cycles + 5);
1017 static void psxBios_memset() { // 0x2b
1018 u32 ret = a0, cycles;
1019 if (a0 == 0 || (s32)a2 <= 0)
1021 mips_return_c(0, 6);
1024 do_memset(a0, a1, a2);
1028 // todo: many more cycles due to uncached bios mem
1029 mips_return_c(ret, cycles + 5);
1032 void psxBios_memmove() { // 0x2c
1033 u32 ret = a0, cycles = 0;
1036 mips_return_c(0, 4);
1040 if ((s32)a2 > 0 && a0 > a1 && a0 < a1 + a2) {
1041 u32 dst = a0, len = a2 + 1;
1044 while ((s32)a2 >= 0) { // BUG: copies one more byte here
1045 const u8 *sb = PSXM(a1);
1047 if (db != INVALID_PTR && sb != INVALID_PTR)
1053 psxCpu->Clear(dst, (len + 3) / 4);
1054 cycles = 10 + len * 8;
1055 } else if ((s32)a2 > 0) {
1056 do_memcpy(a0, a1, a2);
1062 mips_return_c(ret, cycles + 5);
1065 void psxBios_memcmp() { // 0x2d
1069 void psxBios_memchr() { // 0x2e
1070 char *p = (char *)Ra0;
1072 if (a0 == 0 || a2 > 0x7FFFFFFF)
1078 while ((s32)a2-- > 0) {
1079 if (*p++ != (s8)a1) continue;
1080 v0 = a0 + (p - (char *)Ra0 - 1);
1088 static void psxBios_rand() { // 0x2f
1089 u32 s = loadRam32(A_RND_SEED) * 1103515245 + 12345;
1090 storeRam32(A_RND_SEED, s);
1092 mips_return_c((s >> 16) & 0x7fff, 12+37);
1095 static void psxBios_srand() { // 0x30
1096 storeRam32(A_RND_SEED, a0);
1097 mips_return_void_c(3);
1100 static u32 qscmpfunc, qswidth;
1102 static inline int qscmp(char *a, char *b) {
1105 a0 = sa0 + (a - (char *)PSXM(sa0));
1106 a1 = sa0 + (b - (char *)PSXM(sa0));
1108 softCall(qscmpfunc);
1114 static inline void qexchange(char *i, char *j) {
1125 static inline void q3exchange(char *i, char *j, char *k) {
1137 static void qsort_main(char *a, char *l) {
1138 char *i, *j, *lp, *hp;
1143 if ((n = l - a) <= qswidth)
1145 n = qswidth * (n / (2 * qswidth));
1151 if ((c = qscmp(i, lp)) == 0) {
1152 qexchange(i, lp -= qswidth);
1163 if ((c = qscmp(hp, j)) == 0) {
1164 qexchange(hp += qswidth, j);
1169 q3exchange(i, hp += qswidth, j);
1183 if (lp - a >= l - hp) {
1184 qsort_main(hp + qswidth, l);
1193 q3exchange(j, lp -= qswidth, i);
1198 void psxBios_qsort() { // 0x31
1201 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1206 // this isn't how the real bios works, but maybe good enough
1207 static void psxBios_malloc() { // 0x33
1208 u32 *heap_addr, *heap_end;
1209 u32 *chunk, *newchunk = NULL;
1210 unsigned int dsize = 0, csize, cstat;
1212 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x33], a0);
1213 heap_addr = loadRam32ptr(A_HEAP_BASE);
1214 heap_end = loadRam32ptr(A_HEAP_END);
1215 if (heap_addr >= heap_end) {
1221 // scan through heap and combine free chunks of space
1224 while(chunk < heap_end) {
1225 // get size and status of actual chunk
1226 csize = ((u32)*chunk) & 0xfffffffc;
1227 cstat = ((u32)*chunk) & 1;
1229 // most probably broken heap descriptor
1230 // this fixes Burning Road
1233 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1238 // it's a free chunk
1243 colflag = 1; // let's begin a new collection of free memory
1245 else dsize += (csize+4); // add the new size including header
1247 // not a free chunk: did we start a collection ?
1249 if(colflag == 1) { // collection is over
1251 *newchunk = SWAP32(dsize | 1);
1256 chunk = (u32*)((uptr)chunk + csize + 4);
1258 // if neccessary free memory on end of heap
1260 *newchunk = SWAP32(dsize | 1);
1263 csize = ((u32)*chunk) & 0xfffffffc;
1264 cstat = ((u32)*chunk) & 1;
1265 dsize = (a0 + 3) & 0xfffffffc;
1267 // exit on uninitialized heap
1268 if (chunk == NULL) {
1269 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1275 // search an unused chunk that is big enough until the end of the heap
1276 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1277 chunk = (u32*)((uptr)chunk + csize + 4);
1279 // catch out of memory
1280 if(chunk >= heap_end) {
1281 printf("malloc %x,%x: Out of memory error!\n",
1287 csize = ((u32)*chunk) & 0xfffffffc;
1288 cstat = ((u32)*chunk) & 1;
1292 if(dsize == csize) {
1293 // chunk has same size
1294 *chunk &= 0xfffffffc;
1295 } else if (dsize > csize) {
1300 *chunk = SWAP32(dsize);
1301 newchunk = (u32*)((uptr)chunk + dsize + 4);
1302 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1305 // return pointer to allocated memory
1306 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1308 //printf ("malloc %x,%x\n", v0, a0);
1312 static void psxBios_free() { // 0x34
1313 PSXBIOS_LOG("psxBios_%s %x (%x bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1314 storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1315 mips_return_void_c(5);
1318 static void psxBios_calloc() { // 0x37
1320 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
1322 a0 = size = a0 * a1;
1326 a0 = ret; a1 = size;
1329 mips_return_c(ret, 21);
1332 void psxBios_realloc() { // 0x38
1336 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1340 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1345 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1350 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1351 /* Note that it is not quite implemented this way here. */
1361 /* InitHeap(void *block , int n) */
1362 static void psxBios_InitHeap() { // 0x39
1363 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
1365 storeRam32(A_HEAP_BASE, a0);
1366 storeRam32(A_HEAP_SIZE, a1);
1367 storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
1368 storeRam32(A_HEAP_FLAG, 0);
1371 mips_return_void_c(14);
1374 void psxBios_getchar() { //0x3b
1375 v0 = getchar(); pc0 = ra;
1378 static void psxBios_printf_psxout() { // 0x3f
1387 if (psp != INVALID_PTR) {
1388 memcpy(save, psp, 4 * 4);
1389 psxMu32ref(sp) = SWAP32((u32)a0);
1390 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1391 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1392 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1404 tmp2[j++] = Ra0[i]; goto _start;
1406 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1417 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1421 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1427 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1429 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1431 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1433 *ptmp++ = Ra0[i]; break;
1443 if (psp != INVALID_PTR)
1444 memcpy(psp, save, 4 * 4);
1447 SysPrintf("%s", tmp);
1450 void psxBios_printf() { // 0x3f
1451 psxBios_printf_psxout();
1455 void psxBios_format() { // 0x41
1456 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1458 CreateMcd(Config.Mcd1);
1459 LoadMcd(1, Config.Mcd1);
1462 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1464 CreateMcd(Config.Mcd2);
1465 LoadMcd(2, Config.Mcd2);
1475 static void psxBios_SystemErrorUnresolvedException() {
1476 if (loadRam32(0xfffc) != 0x12345678) { // prevent log flood
1477 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1478 storeRam32(0xfffc, 0x12345678);
1480 mips_return_void_c(1000);
1483 static void FlushCache() {
1484 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1485 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1487 // runs from uncached mem so tons of cycles
1492 * long Load(char *name, struct EXEC *header);
1495 void psxBios_Load() { // 0x42
1500 if (pa1 != INVALID_PTR && LoadCdromFile(Ra0, &eheader) == 0) {
1501 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1502 psxCpu->Clear(a1, sizeof(EXEC) / 4);
1506 PSXBIOS_LOG("psxBios_%s: %s, %d -> %d\n", biosA0n[0x42], Ra0, a1, v0);
1512 * int Exec(struct EXEC *header , int argc , char **argv);
1515 void psxBios_Exec() { // 43
1516 EXEC *header = (EXEC *)castRam32ptr(a0);
1520 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1522 header->_sp = SWAP32(sp);
1523 header->_fp = SWAP32(fp);
1524 header->_sp = SWAP32(sp);
1525 header->_gp = SWAP32(gp);
1526 header->ret = SWAP32(ra);
1527 header->base = SWAP32(s0);
1529 ptr = SWAP32(header->b_addr);
1530 len = SWAP32(header->b_size);
1536 if (header->S_addr != 0)
1537 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1539 gp = SWAP32(header->gp0);
1547 pc0 = SWAP32(header->_pc0);
1550 static void psxBios_FlushCache() { // 44
1551 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1556 void psxBios_GPU_dw() { // 0x46
1561 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1564 GPU_writeData(0xa0000000);
1565 GPU_writeData((a1<<0x10)|(a0&0xffff));
1566 GPU_writeData((a3<<0x10)|(a2&0xffff));
1568 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1571 GPU_writeData(SWAPu32(*ptr++));
1577 void psxBios_mem2vram() { // 0x47
1579 gpuSyncPluginSR(); // flush
1580 GPU_writeData(0xa0000000);
1581 GPU_writeData((a1<<0x10)|(a0&0xffff));
1582 GPU_writeData((a3<<0x10)|(a2&0xffff));
1583 size = ((((a2 * a3) / 2) >> 4) << 16);
1584 GPU_writeStatus(0x04000002);
1585 psxHwWrite32(0x1f8010f4,0);
1586 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1587 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1588 psxHwWrite32(0x1f8010a4, size | 0x10);
1589 psxHwWrite32(0x1f8010a8,0x01000201);
1594 void psxBios_SendGPU() { // 0x48
1595 GPU_writeStatus(a0);
1600 void psxBios_GPU_cw() { // 0x49
1607 void psxBios_GPU_cwb() { // 0x4a
1608 u32 *ptr = (u32*)Ra0;
1613 GPU_writeData(SWAPu32(*ptr++));
1619 void psxBios_GPU_SendPackets() { //4b:
1621 GPU_writeStatus(0x04000002);
1622 psxHwWrite32(0x1f8010f4,0);
1623 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1624 psxHwWrite32(0x1f8010a0,a0);
1625 psxHwWrite32(0x1f8010a4,0);
1626 psxHwWrite32(0x1f8010a8,0x010000401);
1630 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1631 psxHwWrite32(0x1f8010a8,0x00000401);
1632 GPU_writeData(0x0400000);
1633 GPU_writeData(0x0200000);
1634 GPU_writeData(0x0100000);
1639 void psxBios_GPU_GetGPUStatus() { // 0x4d
1640 v0 = GPU_readStatus();
1646 void psxBios_LoadExec() { // 51
1647 EXEC *header = (EXEC*)PSXM(0xf000);
1651 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1653 s_addr = a1; s_size = a2;
1658 header->S_addr = s_addr;
1659 header->s_size = s_size;
1661 a0 = 0xf000; a1 = 0; a2 = 0;
1665 void psxBios__bu_init() { // 70
1667 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1670 DeliverEvent(0xf0000011, 0x0004);
1671 DeliverEvent(0xf4000001, 0x0004);
1676 void psxBios__96_init() { // 71
1678 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1684 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1685 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1686 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1688 static void psxBios_DequeueCdIntr_() {
1689 psxBios_SysDeqIntRP_(0, 0x91d0);
1690 psxBios_SysDeqIntRP_(0, 0x91e0);
1694 static void psxBios_DequeueCdIntr() { // a3
1695 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1696 psxBios_DequeueCdIntr_();
1699 static void psxBios_CdRemove() { // 56, 72
1700 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1702 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1703 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1704 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1705 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1706 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1707 psxBios_DequeueCdIntr_();
1709 // EnterCriticalSection - should be done at the beginning,
1710 // but this way is much easier to implement
1716 void psxBios_SetMem() { // 9f
1717 u32 new = psxHu32(0x1060);
1720 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1725 psxHu32ref(0x1060) = SWAP32(new);
1726 psxMu32ref(0x060) = a0;
1727 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1731 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1732 psxMu32ref(0x060) = a0;
1733 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1736 PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
1743 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1744 static void psxBios_get_cd_status() // a6
1746 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
1751 static void psxBios__card_info() { // ab
1752 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1754 storeRam32(A_CARD_CHAN1, a0);
1761 if (McdDisable[port & 1])
1765 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
1770 if (McdDisable[0] && McdDisable[1])
1773 DeliverEvent(0xf0000011, 0x0004);
1774 // DeliverEvent(0xf4000001, 0x0004);
1775 DeliverEvent(0xf4000001, ret);
1779 void psxBios__card_load() { // ac
1781 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1784 storeRam32(A_CARD_CHAN1, a0);
1786 // DeliverEvent(0xf0000011, 0x0004);
1787 DeliverEvent(0xf4000001, 0x0004);
1792 static void psxBios_GetSystemInfo() { // b4
1794 //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
1795 SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
1798 case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
1799 case 2: ret = 0xbfc0012c; break;
1800 case 5: ret = loadRam32(0x60) << 10; break;
1802 mips_return_c(ret, 20);
1805 /* System calls B0 */
1807 static u32 psxBios_SysMalloc_(u32 size);
1809 static void psxBios_SysMalloc() { // B 00
1810 u32 ret = psxBios_SysMalloc_(a0);
1812 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1813 mips_return_c(ret, 33);
1816 void psxBios_SetRCnt() { // 02
1818 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1825 psxRcntWtarget(a0, a1);
1826 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1827 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1828 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1829 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1830 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1832 psxRcntWmode(a0, mode);
1837 void psxBios_GetRCnt() { // 03
1839 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1843 if (a0 != 3) v0 = psxRcntRcount(a0);
1848 void psxBios_StartRCnt() { // 04
1850 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1854 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1855 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1859 void psxBios_StopRCnt() { // 05
1861 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1865 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1866 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1870 void psxBios_ResetRCnt() { // 06
1872 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1877 psxRcntWmode(a0, 0);
1878 psxRcntWtarget(a0, 0);
1879 psxRcntWcount(a0, 0);
1884 static u32 DeliverEvent(u32 class, u32 spec) {
1885 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1886 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1887 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1888 u32 i, lim = evcb_len / 0x1c;
1890 //printf("%s %08x %x\n", __func__, class, spec);
1891 for (i = 0; i < lim; i++, ev++) {
1893 if (SWAP32(ev->status) != EvStACTIVE)
1896 if (SWAP32(ev->class) != class)
1899 if (SWAP32(ev->spec) != spec)
1902 ret = SWAP32(ev->mode);
1903 if (ret == EvMdMARK) {
1904 ev->status = SWAP32(EvStALREADY);
1908 if (ret == EvMdCALL) {
1909 ret = SWAP32(ev->fhandler);
1921 static u32 UnDeliverEvent(u32 class, u32 spec) {
1922 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1923 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1924 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1925 u32 i, lim = evcb_len / 0x1c;
1927 for (i = 0; i < lim; i++, ev++) {
1929 if (SWAP32(ev->status) != EvStALREADY)
1932 if (SWAP32(ev->class) != class)
1935 if (SWAP32(ev->spec) != spec)
1938 if (SWAP32(ev->mode) == EvMdMARK)
1939 ev->status = SWAP32(EvStACTIVE);
1945 static void psxBios_DeliverEvent() { // 07
1947 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
1949 ret = DeliverEvent(a0, a1);
1953 static s32 get_free_EvCB_slot() {
1954 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1955 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
1958 for (i = 0; i < lim; i++, ev++) {
1960 if (ev->status == SWAP32(EvStUNUSED))
1966 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
1967 u32 ret = get_free_EvCB_slot();
1968 if ((s32)ret >= 0) {
1969 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
1970 ev->class = SWAP32(class);
1971 ev->status = SWAP32(EvStDISABLED);
1972 ev->spec = SWAP32(spec);
1973 ev->mode = SWAP32(mode);
1974 ev->fhandler = SWAP32(func);
1980 static void psxBios_OpenEvent() { // 08
1981 u32 ret = OpenEvent(a0, a1, a2, a3);
1982 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
1983 biosB0n[0x08], a0, a1, a2, a3, ret);
1984 mips_return_c(ret, 36);
1987 static void CloseEvent(u32 ev)
1989 u32 base = loadRam32(A_TT_EvCB);
1990 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
1993 static void psxBios_CloseEvent() { // 09
1994 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
1995 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
1997 mips_return_c(1, 10);
2000 static void psxBios_WaitEvent() { // 0a
2001 u32 base = loadRam32(A_TT_EvCB);
2002 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2003 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
2006 if (status == EvStALREADY) {
2007 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2011 if (status != EvStACTIVE)
2013 mips_return_c(0, 2);
2017 // retrigger this hlecall after the next emulation event
2019 if ((s32)(next_interupt - psxRegs.cycle) > 0)
2020 psxRegs.cycle = next_interupt;
2024 static void psxBios_TestEvent() { // 0b
2025 u32 base = loadRam32(A_TT_EvCB);
2026 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2028 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
2029 if (status == EvStALREADY) {
2030 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2034 mips_return_c(ret, 15);
2037 static void psxBios_EnableEvent() { // 0c
2038 u32 base = loadRam32(A_TT_EvCB);
2039 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2040 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
2041 if (status != EvStUNUSED)
2042 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2044 mips_return_c(1, 15);
2047 static void psxBios_DisableEvent() { // 0d
2048 u32 base = loadRam32(A_TT_EvCB);
2049 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2050 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2051 if (status != EvStUNUSED)
2052 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2054 mips_return_c(1, 15);
2058 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2061 void psxBios_OpenTh() { // 0e
2062 TCB *tcb = loadRam32ptr(A_TT_TCB);
2063 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2066 for (th = 1; th < limit; th++)
2068 if (tcb[th].status != SWAP32(0x4000)) break;
2072 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2073 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2075 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2077 mips_return_c(0xffffffff, 20);
2080 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
2082 tcb[th].status = SWAP32(0x4000);
2083 tcb[th].mode = SWAP32(0x1000);
2084 tcb[th].epc = SWAP32(a0);
2085 tcb[th].reg[30] = SWAP32(a1); // fp
2086 tcb[th].reg[29] = SWAP32(a1); // sp
2087 tcb[th].reg[28] = SWAP32(a2); // gp
2089 mips_return_c(0xff000000 + th, 34);
2093 * int CloseTh(long thread);
2096 void psxBios_CloseTh() { // 0f
2097 TCB *tcb = loadRam32ptr(A_TT_TCB);
2098 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2102 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
2104 /* The return value is always 1 (even if the handle was already closed). */
2106 if (th < limit && tcb[th].status == SWAP32(0x4000)) {
2107 tcb[th].status = SWAP32(0x1000);
2114 * int ChangeTh(long thread);
2117 void psxBios_ChangeTh() { // 10
2118 u32 tcbBase = loadRam32(A_TT_TCB);
2119 u32 th = a0 & 0xffff;
2121 // this is quite spammy
2122 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2124 // without doing any argument checks, just issue a syscall
2125 // (like the real bios does)
2127 a1 = tcbBase + th * sizeof(TCB);
2132 void psxBios_InitPAD() { // 0x12
2133 u32 i, *ram32 = (u32 *)psxM;
2134 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2136 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2137 ram32[A_PAD_DR_DST/4] = 0;
2138 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2139 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2140 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2141 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2142 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2143 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2144 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2145 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2147 for (i = 0; i < a1; i++) {
2149 storeRam8(a0 + i, 0);
2151 for (i = 0; i < a3; i++) {
2153 storeRam8(a2 + i, 0);
2155 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2157 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2159 mips_return_c(1, 200);
2162 void psxBios_StartPAD() { // 13
2163 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2165 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2166 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2167 psxHwWrite16(0x1f801070, ~1);
2168 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2169 storeRam32(A_PAD_ACK_VBL, 1);
2170 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2171 psxRegs.CP0.n.SR |= 0x401;
2173 mips_return_c(1, 300);
2176 void psxBios_StopPAD() { // 14
2177 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2178 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2179 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2180 psxRegs.CP0.n.SR |= 0x401;
2181 mips_return_void_c(200);
2184 static void psxBios_PAD_init() { // 15
2186 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2187 if (a0 == 0x20000000 || a0 == 0x20000001)
2190 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2191 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2194 storeRam32(A_PAD_DR_DST, dst);
2197 mips_return_c(ret, 100);
2200 static u32 psxBios_PAD_dr_() {
2201 u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2202 u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2203 u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2204 dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2205 if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2207 dst[0] = buf1[3], dst[1] = buf1[2];
2208 if (buf1[1] == 0x23) {
2209 dst[0] |= 0xc7, dst[1] |= 7;
2210 if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2211 if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2214 if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2216 dst[2] = buf2[3], dst[3] = buf2[2];
2217 if (buf2[1] == 0x23) {
2218 dst[2] |= 0xc7, dst[3] |= 7;
2219 if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2220 if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2224 return SWAP32(*(u32 *)dst);
2227 static void psxBios_PAD_dr() { // 16
2228 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2229 u32 ret = psxBios_PAD_dr_();
2233 static void psxBios_ReturnFromException() { // 17
2234 u32 tcbPtr = loadRam32(A_TT_PCB);
2235 const TCB *tcb = loadRam32ptr(tcbPtr);
2239 for (i = 1; i < 32; i++)
2240 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2241 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2242 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2243 sr = SWAP32(tcb->sr);
2245 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2246 pc0 = k0 = SWAP32(tcb->epc);
2248 // the interpreter wants to know about sr changes, so do a MTC0
2249 sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2250 MTC0(&psxRegs, 12, sr);
2256 void psxBios_ResetEntryInt() { // 18
2257 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2259 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2260 mips_return_void_c(5);
2263 void psxBios_HookEntryInt() { // 19
2264 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2266 storeRam32(A_EEXIT_PTR, a0);
2267 mips_return_void_c(3);
2270 static void psxBios_UnDeliverEvent() { // 0x20
2272 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2274 ret = UnDeliverEvent(a0, a1);
2278 static void buopen(int mcd, char *ptr, char *cfg)
2281 char *mcd_data = ptr;
2283 strcpy(FDesc[1 + mcd].name, Ra0+5);
2284 FDesc[1 + mcd].offset = 0;
2285 FDesc[1 + mcd].mode = a1;
2287 for (i=1; i<16; i++) {
2288 const char *fptr = mcd_data + 128 * i;
2289 if ((*fptr & 0xF0) != 0x50) continue;
2290 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2291 FDesc[1 + mcd].mcfile = i;
2292 PSXBIOS_LOG("open %s\n", fptr+0xa);
2296 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2297 for (i=1; i<16; i++) {
2298 int j, xor, nblk = a1 >> 16;
2300 char *fptr = mcd_data + 128 * i;
2302 if ((*fptr & 0xF0) != 0xa0) continue;
2304 FDesc[1 + mcd].mcfile = i;
2307 fptr[5] = 0x20 * nblk;
2310 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2311 pptr = fptr2 = fptr;
2312 for(j=2; j<=nblk; j++) {
2314 for(i++; i<16; i++) {
2317 memset(fptr2, 0, 128);
2318 fptr2[0] = j < nblk ? 0x52 : 0x53;
2321 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2326 /* shouldn't this return ENOSPC if i == 16? */
2328 pptr[8] = pptr[9] = 0xff;
2329 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2331 PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2333 /* just go ahead and resave them all */
2334 SaveMcd(cfg, ptr, 128, 128 * 15);
2337 /* shouldn't this return ENOSPC if i == 16? */
2342 * int open(char *name , int mode);
2345 void psxBios_open() { // 0x32
2348 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x32], Ra0, a1);
2352 if (pa0 != INVALID_PTR) {
2353 if (!strncmp(pa0, "bu00", 4)) {
2354 buopen(1, Mcd1Data, Config.Mcd1);
2357 if (!strncmp(pa0, "bu10", 4)) {
2358 buopen(2, Mcd2Data, Config.Mcd2);
2366 * int lseek(int fd , int offset , int whence);
2369 void psxBios_lseek() { // 0x33
2371 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2376 FDesc[a0].offset = a1;
2378 // DeliverEvent(0xf0000011, 0x0004);
2379 // DeliverEvent(0xf4000001, 0x0004);
2383 FDesc[a0].offset+= a1;
2384 v0 = FDesc[a0].offset;
2393 * int read(int fd , void *buf , int nbytes);
2396 void psxBios_read() { // 0x34
2401 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2406 if (pa1 != INVALID_PTR) {
2408 case 2: buread(pa1, 1, a2); break;
2409 case 3: buread(pa1, 2, a2); break;
2417 * int write(int fd , void *buf , int nbytes);
2420 void psxBios_write() { // 0x35/0x03
2424 if (a0 != 1) // stdout
2425 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2428 if (pa1 == INVALID_PTR) {
2433 if (a0 == 1) { // stdout
2437 if (Config.PsxOut) while (a2 > 0) {
2438 SysPrintf("%c", *ptr++); a2--;
2444 case 2: buwrite(pa1, 1, a2); break;
2445 case 3: buwrite(pa1, 2, a2); break;
2451 static void psxBios_write_psxout() {
2452 if (a0 == 1) { // stdout
2453 const char *ptr = Ra1;
2456 if (ptr != INVALID_PTR)
2458 SysPrintf("%c", *ptr++);
2462 static void psxBios_putchar_psxout() { // 3d
2463 SysPrintf("%c", (char)a0);
2466 static void psxBios_puts_psxout() { // 3e/3f
2467 SysPrintf("%s", Ra0);
2471 * int close(int fd);
2474 void psxBios_close() { // 0x36
2476 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2483 void psxBios_putchar() { // 3d
2484 if (Config.PsxOut) SysPrintf("%c", (char)a0);
2488 void psxBios_puts() { // 3e/3f
2489 if (Config.PsxOut) SysPrintf("%s", Ra0);
2494 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2495 * We want to mimic the PSX's behaviour in this case for bufile. */
2496 static size_t strlen_internal(char* p)
2498 size_t size_of_array = 0;
2499 while (*p++) size_of_array++;
2500 return size_of_array;
2503 #define bufile(mcd) { \
2504 size_t size_of_name = strlen_internal(dir->name); \
2506 while (nfile < 16) { \
2507 char *pfile = ffile+5; \
2510 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2512 if ((*ptr & 0xF0) != 0x50) continue; \
2513 /* Bug link files show up as free block. */ \
2514 if (!ptr[0xa]) continue; \
2516 if (pfile[0] == 0) { \
2517 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2518 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2519 } else for (i=0; i<20; i++) { \
2520 if (pfile[i] == ptr[i]) { \
2521 dir->name[i] = ptr[i]; continue; } \
2522 if (pfile[i] == '?') { \
2523 dir->name[i] = ptr[i]; continue; } \
2524 if (pfile[i] == '*') { \
2525 strcpy(dir->name+i, ptr+i); break; } \
2528 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2529 if (match == 0) { continue; } \
2537 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2540 static void psxBios_firstfile() { // 42
2541 struct DIRENTRY *dir = (struct DIRENTRY *)castRam8ptr(a1);
2542 char *pa0 = castRam8ptr(a0);
2550 snprintf(ffile, sizeof(ffile), "%s", pa0);
2552 if (!strncmp(pa0, "bu00", 4)) {
2553 // firstfile() calls _card_read() internally, so deliver it's event
2554 DeliverEvent(0xf0000011, 0x0004);
2556 } else if (!strncmp(pa0, "bu10", 4)) {
2557 // firstfile() calls _card_read() internally, so deliver it's event
2558 DeliverEvent(0xf0000011, 0x0004);
2562 PSXBIOS_LOG("psxBios_%s %s %x -> %x\n", biosB0n[0x42], pa0, a1, v0);
2568 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2571 void psxBios_nextfile() { // 43
2572 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2579 if (!strncmp(ffile, "bu00", 4)) {
2582 else if (!strncmp(ffile, "bu10", 4)) {
2585 PSXBIOS_LOG("psxBios_%s %s -> %x\n", biosB0n[0x43], dir->name, v0);
2590 #define burename(mcd) { \
2591 for (i=1; i<16; i++) { \
2592 int namelen, j, xor = 0; \
2593 ptr = Mcd##mcd##Data + 128 * i; \
2594 if ((*ptr & 0xF0) != 0x50) continue; \
2595 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2596 namelen = strlen(Ra1+5); \
2597 memcpy(ptr+0xa, Ra1+5, namelen); \
2598 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2599 for (j=0; j<127; j++) xor^= ptr[j]; \
2601 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2608 * int rename(char *old, char *new);
2611 void psxBios_rename() { // 44
2618 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2623 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2624 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2628 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2637 #define budelete(mcd) { \
2638 for (i=1; i<16; i++) { \
2639 ptr = Mcd##mcd##Data + 128 * i; \
2640 if ((*ptr & 0xF0) != 0x50) continue; \
2641 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2642 *ptr = (*ptr & 0xf) | 0xA0; \
2643 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2644 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2651 * int delete(char *name);
2654 void psxBios_delete() { // 45
2660 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2665 if (pa0 != INVALID_PTR) {
2666 if (!strncmp(pa0, "bu00", 4)) {
2670 if (!strncmp(pa0, "bu10", 4)) {
2678 void psxBios_InitCARD() { // 4a
2679 u32 *ram32 = (u32 *)psxM;
2680 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2681 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2682 // (maybe) todo: early_card_irq, etc
2684 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2686 psxBios_FlushCache();
2687 mips_return_c(0, 34+13+15+6);
2690 void psxBios_StartCARD() { // 4b
2691 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2692 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2693 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2695 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2696 storeRam32(A_PAD_ACK_VBL, 1);
2697 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2698 storeRam32(A_CARD_IRQR_ENA, 1);
2699 psxRegs.CP0.n.SR |= 0x401;
2701 mips_return_c(1, 200);
2704 void psxBios_StopCARD() { // 4c
2705 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2706 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2707 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2708 storeRam32(A_CARD_IRQR_ENA, 0);
2709 psxRegs.CP0.n.SR |= 0x401;
2710 mips_return_void_c(200);
2713 void psxBios__card_write() { // 0x4e
2718 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2721 Function also accepts sector 400h (a bug).
2722 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2726 /* Invalid sectors */
2730 storeRam32(A_CARD_CHAN1, a0);
2733 if (pa2 != INVALID_PTR) {
2735 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2736 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2738 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2739 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2743 DeliverEvent(0xf0000011, 0x0004);
2744 // DeliverEvent(0xf4000001, 0x0004);
2749 void psxBios__card_read() { // 0x4f
2754 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2757 Function also accepts sector 400h (a bug).
2758 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2762 /* Invalid sectors */
2766 storeRam32(A_CARD_CHAN1, a0);
2769 if (pa2 != INVALID_PTR) {
2771 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2773 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2777 DeliverEvent(0xf0000011, 0x0004);
2778 // DeliverEvent(0xf4000001, 0x0004);
2783 void psxBios__new_card() { // 0x50
2785 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2791 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2792 void psxBios__get_error(void) // 55
2794 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2799 void psxBios_Krom2RawAdd() { // 0x51
2802 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2803 const u32 table_8140[][2] = {
2804 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2805 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2806 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2807 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2808 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2809 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2810 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2811 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2812 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2816 const u32 table_889f[][2] = {
2817 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2818 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2819 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2820 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2821 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2822 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2823 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2824 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2828 if (a0 >= 0x8140 && a0 <= 0x84be) {
2829 while (table_8140[i][0] <= a0) i++;
2830 a0 -= table_8140[i - 1][0];
2831 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2832 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2833 while (table_889f[i][0] <= a0) i++;
2834 a0 -= table_889f[i - 1][0];
2835 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2843 void psxBios_GetC0Table() { // 56
2844 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2845 log_unhandled("GetC0Table @%08x\n", ra);
2847 mips_return_c(A_C0_TABLE, 3);
2850 void psxBios_GetB0Table() { // 57
2851 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2852 log_unhandled("GetB0Table @%08x\n", ra);
2854 mips_return_c(A_B0_TABLE, 3);
2857 static void psxBios__card_chan() { // 0x58
2859 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2861 // todo: should return active slot chan
2862 // (active - which was last processed by irq code)
2863 ret = loadRam32(A_CARD_CHAN1);
2864 mips_return_c(ret, 8);
2867 static void psxBios_ChangeClearPad() { // 5b
2869 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2870 ret = loadRam32(A_PAD_ACK_VBL);
2871 storeRam32(A_PAD_ACK_VBL, a0);
2873 mips_return_c(ret, 6);
2876 static void psxBios__card_status() { // 5c
2877 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
2883 static void psxBios__card_wait() { // 5d
2884 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
2890 /* System calls C0 */
2892 static void psxBios_InitRCnt() { // 00
2894 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2895 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2896 for (i = 0; i < 3; i++) {
2897 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2898 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2899 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2901 psxBios_SysEnqIntRP_(a0, 0x6d88);
2902 mips_return_c(0, 9);
2905 static void psxBios_InitException() { // 01
2906 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2907 psxBios_SysEnqIntRP_(a0, 0x6da8);
2908 mips_return_c(0, 9);
2912 * int SysEnqIntRP(int index , long *queue);
2915 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2916 u32 old, base = loadRam32(A_TT_ExCB);
2918 old = loadRam32(base + (priority << 3));
2919 storeRam32(base + (priority << 3), chain_eptr);
2920 storeRam32(chain_eptr, old);
2921 mips_return_c(0, 9);
2924 static void psxBios_SysEnqIntRP() { // 02
2925 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2926 psxBios_SysEnqIntRP_(a0, a1);
2930 * int SysDeqIntRP(int index , long *queue);
2933 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
2934 u32 ptr, next, base = loadRam32(A_TT_ExCB);
2935 u32 lim = 0, ret = 0;
2937 // as in original: no arg checks of any kind, bug if a1 == 0
2938 ptr = loadRam32(base + (priority << 3));
2940 next = loadRam32(ptr);
2941 if (ptr == chain_rm_eptr) {
2942 storeRam32(base + (priority << 3), next);
2947 while (next && next != chain_rm_eptr && lim++ < 100) {
2949 next = loadRam32(ptr);
2952 if (next == chain_rm_eptr) {
2953 next = loadRam32(next);
2954 storeRam32(ptr, next);
2961 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
2963 mips_return_c(ret, 12);
2966 static void psxBios_SysDeqIntRP() { // 03
2967 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
2968 psxBios_SysDeqIntRP_(a0, a1);
2971 static void psxBios_get_free_EvCB_slot() { // 04
2972 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
2973 s32 ret = get_free_EvCB_slot();
2974 mips_return_c(ret, 0);
2977 static void psxBios_SysInitMemory_(u32 base, u32 size) {
2978 storeRam32(base, 0);
2979 storeRam32(A_KMALLOC_PTR, base);
2980 storeRam32(A_KMALLOC_SIZE, size);
2981 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
2984 // this should be much more complicated, but maybe that'll be enough
2985 static u32 psxBios_SysMalloc_(u32 size) {
2986 u32 ptr = loadRam32(A_KMALLOC_PTR);
2988 size = (size + 3) & ~3;
2989 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
2990 storeRam32(ptr, size);
2994 static void psxBios_SysInitMemory() { // 08
2995 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
2997 psxBios_SysInitMemory_(a0, a1);
2998 mips_return_void_c(12);
3001 static void psxBios_ChangeClearRCnt() { // 0a
3004 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
3006 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
3007 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
3008 mips_return_c(ret, 8);
3011 static void psxBios_InitDefInt() { // 0c
3012 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3013 // should also clear the autoack table
3014 psxBios_SysEnqIntRP_(a0, 0x6d98);
3015 mips_return_c(0, 20 + 6*2);
3018 void psxBios_dummy() {
3019 u32 pc = (pc0 & 0x1fffff) - 4;
3020 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
3021 : pc == 0xc0 ? biosC0n : NULL;
3022 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
3023 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
3024 (void)pc; (void)ntab;
3025 mips_return_c(0, 100);
3028 void (*biosA0[256])();
3029 // C0 and B0 overlap (end of C0 is start of B0)
3030 void (*biosC0[256+128])();
3031 void (**biosB0)() = biosC0 + 128;
3033 static void setup_mips_code()
3036 ptr = (u32 *)&psxM[A_SYSCALL];
3037 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3038 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
3039 ptr[0x08/4] = SWAPu32(0x00000000); // nop
3041 ptr = (u32 *)&psxM[A_EXCEPTION];
3042 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
3043 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
3044 ptr[0x14/4] = SWAPu32(0x00000000); // nop
3045 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
3046 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3047 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
3048 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
3049 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
3050 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
3051 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
3053 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
3054 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
3055 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
3057 ptr[0xb0/4] = HLEOP(hleop_exception);
3060 static const struct {
3064 { 0xbfc050a4, hleop_exc0_0_1 },
3065 { 0xbfc04fbc, hleop_exc0_0_2 },
3066 { 0xbfc0506c, hleop_exc0_1_1 },
3067 { 0xbfc04dec, hleop_exc0_1_2 },
3068 { 0x1a00, hleop_exc0_2_2 },
3069 { 0x19c8, hleop_exc1_0_1 },
3070 { 0x18bc, hleop_exc1_0_2 },
3071 { 0x1990, hleop_exc1_1_1 },
3072 { 0x1858, hleop_exc1_1_2 },
3073 { 0x1958, hleop_exc1_2_1 },
3074 { 0x17f4, hleop_exc1_2_2 },
3075 { 0x1920, hleop_exc1_3_1 },
3076 { 0x1794, hleop_exc1_3_2 },
3077 { 0x2458, hleop_exc3_0_2 },
3078 { 0x49bc, hleop_exc_padcard1 },
3079 { 0x4a4c, hleop_exc_padcard2 },
3082 static int chain_hle_op(u32 handler)
3086 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3087 if (chainfns[i].addr == handler)
3088 return chainfns[i].op;
3092 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3094 d[0] = SWAPu32(next);
3095 d[1] = SWAPu32(handler1);
3096 d[2] = SWAPu32(handler2);
3098 // install the hle traps
3099 if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3100 if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3103 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt)
3105 u32 *ram32 = (u32 *)psxM;
3106 u32 s_excb = 0x20, s_evcb = 0x1c * evcb_cnt;
3107 u32 s_pcb = 4, s_tcb = 0xc0 * tcb_cnt;
3108 u32 p_excb, p_evcb, p_pcb, p_tcb;
3110 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3111 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3112 p_excb = psxBios_SysMalloc_(s_excb);
3113 p_evcb = psxBios_SysMalloc_(s_evcb);
3114 p_pcb = psxBios_SysMalloc_(s_pcb);
3115 p_tcb = psxBios_SysMalloc_(s_tcb);
3117 // "table of tables". Some games modify it
3118 assert(A_TT_ExCB == 0x0100);
3119 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3120 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3121 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3122 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3123 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3124 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3125 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3126 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3127 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3128 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3129 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3130 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3132 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3133 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3134 storeRam32(p_excb + 4*4, 0x0000); // chain2
3135 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3137 storeRam32(p_pcb, p_tcb);
3138 storeRam32(p_tcb, 0x4000); // first TCB
3141 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3142 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3143 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3144 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3145 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3146 DeliverEvent(0xf0000003, 0x0010);
3149 static const u32 gpu_ctl_def[] = {
3150 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3151 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3154 static const u32 gpu_data_def[] = {
3155 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3156 0xe5001000, 0xe6000000,
3157 0x02000000, 0x00000000, 0x01ff03ff
3161 static const u16 spu_config[] = {
3162 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3163 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3164 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3165 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3166 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3167 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3168 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3169 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3172 void psxBiosSetupBootState(void)
3174 boolean hle = Config.HLE;
3175 u32 *hw = (u32 *)psxH;
3178 // see also SetBootRegs()
3181 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3182 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3184 k0 = 0xbfc0d968; k1 = 0xf1c;
3185 ra = 0xf0001234; // just to easily detect attempts to return
3186 psxRegs.CP0.n.Cause = 0x20;
3187 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3189 hw[0x1000/4] = SWAP32(0x1f000000);
3190 hw[0x1004/4] = SWAP32(0x1f802000);
3191 hw[0x1008/4] = SWAP32(0x0013243f);
3192 hw[0x100c/4] = SWAP32(0x00003022);
3193 hw[0x1010/4] = SWAP32(0x0013243f);
3194 hw[0x1014/4] = SWAP32(0x200931e1);
3195 hw[0x1018/4] = SWAP32(0x00020943);
3196 hw[0x101c/4] = SWAP32(0x00070777);
3197 hw[0x1020/4] = SWAP32(0x0000132c);
3198 hw[0x1060/4] = SWAP32(0x00000b88);
3199 hw[0x1070/4] = SWAP32(0x00000001);
3200 hw[0x1074/4] = SWAP32(0x0000000c);
3201 hw[0x2040/4] = SWAP32(0x00000900);
3204 hw[0x10a0/4] = SWAP32(0x00ffffff);
3205 hw[0x10a8/4] = SWAP32(0x00000401);
3206 hw[0x10b0/4] = SWAP32(0x0008b000);
3207 hw[0x10b4/4] = SWAP32(0x00010200);
3208 hw[0x10e0/4] = SWAP32(0x000eccf4);
3209 hw[0x10e4/4] = SWAP32(0x00000400);
3210 hw[0x10e8/4] = SWAP32(0x00000002);
3211 hw[0x10f0/4] = SWAP32(0x00009099);
3212 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3221 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3222 GPU_writeStatus(gpu_ctl_def[i]);
3223 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3224 GPU_writeData(gpu_data_def[i]);
3225 HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
3228 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3229 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3232 #include "sjisfont.h"
3234 void psxBiosInit() {
3235 u32 *ptr, *ram32, *rom32;
3239 memset(psxM, 0, 0x10000);
3240 for(i = 0; i < 256; i++) {
3245 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3246 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3247 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3248 biosA0[0x3f] = psxBios_printf_psxout;
3250 if (!Config.HLE) return;
3252 for(i = 0; i < 256; i++) {
3253 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3254 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3255 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3258 biosA0[0x00] = psxBios_open;
3259 biosA0[0x01] = psxBios_lseek;
3260 biosA0[0x02] = psxBios_read;
3261 biosA0[0x03] = psxBios_write;
3262 biosA0[0x04] = psxBios_close;
3263 //biosA0[0x05] = psxBios_ioctl;
3264 //biosA0[0x06] = psxBios_exit;
3265 //biosA0[0x07] = psxBios_sys_a0_07;
3266 biosA0[0x08] = psxBios_getc;
3267 biosA0[0x09] = psxBios_putc;
3268 biosA0[0x0a] = psxBios_todigit;
3269 //biosA0[0x0b] = psxBios_atof;
3270 //biosA0[0x0c] = psxBios_strtoul;
3271 //biosA0[0x0d] = psxBios_strtol;
3272 biosA0[0x0e] = psxBios_abs;
3273 biosA0[0x0f] = psxBios_labs;
3274 biosA0[0x10] = psxBios_atoi;
3275 biosA0[0x11] = psxBios_atol;
3276 //biosA0[0x12] = psxBios_atob;
3277 biosA0[0x13] = psxBios_setjmp;
3278 biosA0[0x14] = psxBios_longjmp;
3279 biosA0[0x15] = psxBios_strcat;
3280 biosA0[0x16] = psxBios_strncat;
3281 biosA0[0x17] = psxBios_strcmp;
3282 biosA0[0x18] = psxBios_strncmp;
3283 biosA0[0x19] = psxBios_strcpy;
3284 biosA0[0x1a] = psxBios_strncpy;
3285 biosA0[0x1b] = psxBios_strlen;
3286 biosA0[0x1c] = psxBios_index;
3287 biosA0[0x1d] = psxBios_rindex;
3288 biosA0[0x1e] = psxBios_strchr;
3289 biosA0[0x1f] = psxBios_strrchr;
3290 biosA0[0x20] = psxBios_strpbrk;
3291 biosA0[0x21] = psxBios_strspn;
3292 biosA0[0x22] = psxBios_strcspn;
3293 biosA0[0x23] = psxBios_strtok;
3294 biosA0[0x24] = psxBios_strstr;
3295 biosA0[0x25] = psxBios_toupper;
3296 biosA0[0x26] = psxBios_tolower;
3297 biosA0[0x27] = psxBios_bcopy;
3298 biosA0[0x28] = psxBios_bzero;
3299 biosA0[0x29] = psxBios_bcmp;
3300 biosA0[0x2a] = psxBios_memcpy;
3301 biosA0[0x2b] = psxBios_memset;
3302 biosA0[0x2c] = psxBios_memmove;
3303 biosA0[0x2d] = psxBios_memcmp;
3304 biosA0[0x2e] = psxBios_memchr;
3305 biosA0[0x2f] = psxBios_rand;
3306 biosA0[0x30] = psxBios_srand;
3307 biosA0[0x31] = psxBios_qsort;
3308 //biosA0[0x32] = psxBios_strtod;
3309 biosA0[0x33] = psxBios_malloc;
3310 biosA0[0x34] = psxBios_free;
3311 //biosA0[0x35] = psxBios_lsearch;
3312 //biosA0[0x36] = psxBios_bsearch;
3313 biosA0[0x37] = psxBios_calloc;
3314 biosA0[0x38] = psxBios_realloc;
3315 biosA0[0x39] = psxBios_InitHeap;
3316 //biosA0[0x3a] = psxBios__exit;
3317 biosA0[0x3b] = psxBios_getchar;
3318 biosA0[0x3c] = psxBios_putchar;
3319 //biosA0[0x3d] = psxBios_gets;
3320 biosA0[0x3e] = psxBios_puts;
3321 biosA0[0x3f] = psxBios_printf;
3322 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3323 //biosA0[0x41] = psxBios_LoadTest;
3324 biosA0[0x42] = psxBios_Load;
3325 biosA0[0x43] = psxBios_Exec;
3326 biosA0[0x44] = psxBios_FlushCache;
3327 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3328 biosA0[0x46] = psxBios_GPU_dw;
3329 biosA0[0x47] = psxBios_mem2vram;
3330 biosA0[0x48] = psxBios_SendGPU;
3331 biosA0[0x49] = psxBios_GPU_cw;
3332 biosA0[0x4a] = psxBios_GPU_cwb;
3333 biosA0[0x4b] = psxBios_GPU_SendPackets;
3334 biosA0[0x4c] = psxBios_sys_a0_4c;
3335 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3336 //biosA0[0x4e] = psxBios_GPU_sync;
3337 //biosA0[0x4f] = psxBios_sys_a0_4f;
3338 //biosA0[0x50] = psxBios_sys_a0_50;
3339 biosA0[0x51] = psxBios_LoadExec;
3340 //biosA0[0x52] = psxBios_GetSysSp;
3341 //biosA0[0x53] = psxBios_sys_a0_53;
3342 //biosA0[0x54] = psxBios__96_init_a54;
3343 //biosA0[0x55] = psxBios__bu_init_a55;
3344 biosA0[0x56] = psxBios_CdRemove;
3345 //biosA0[0x57] = psxBios_sys_a0_57;
3346 //biosA0[0x58] = psxBios_sys_a0_58;
3347 //biosA0[0x59] = psxBios_sys_a0_59;
3348 //biosA0[0x5a] = psxBios_sys_a0_5a;
3349 //biosA0[0x5b] = psxBios_dev_tty_init;
3350 //biosA0[0x5c] = psxBios_dev_tty_open;
3351 //biosA0[0x5d] = psxBios_sys_a0_5d;
3352 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3353 //biosA0[0x5f] = psxBios_dev_cd_open;
3354 //biosA0[0x60] = psxBios_dev_cd_read;
3355 //biosA0[0x61] = psxBios_dev_cd_close;
3356 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3357 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3358 //biosA0[0x64] = psxBios_dev_cd_chdir;
3359 //biosA0[0x65] = psxBios_dev_card_open;
3360 //biosA0[0x66] = psxBios_dev_card_read;
3361 //biosA0[0x67] = psxBios_dev_card_write;
3362 //biosA0[0x68] = psxBios_dev_card_close;
3363 //biosA0[0x69] = psxBios_dev_card_firstfile;
3364 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3365 //biosA0[0x6b] = psxBios_dev_card_erase;
3366 //biosA0[0x6c] = psxBios_dev_card_undelete;
3367 //biosA0[0x6d] = psxBios_dev_card_format;
3368 //biosA0[0x6e] = psxBios_dev_card_rename;
3369 //biosA0[0x6f] = psxBios_dev_card_6f;
3370 biosA0[0x70] = psxBios__bu_init;
3371 biosA0[0x71] = psxBios__96_init;
3372 biosA0[0x72] = psxBios_CdRemove;
3373 //biosA0[0x73] = psxBios_sys_a0_73;
3374 //biosA0[0x74] = psxBios_sys_a0_74;
3375 //biosA0[0x75] = psxBios_sys_a0_75;
3376 //biosA0[0x76] = psxBios_sys_a0_76;
3377 //biosA0[0x77] = psxBios_sys_a0_77;
3378 //biosA0[0x78] = psxBios__96_CdSeekL;
3379 //biosA0[0x79] = psxBios_sys_a0_79;
3380 //biosA0[0x7a] = psxBios_sys_a0_7a;
3381 //biosA0[0x7b] = psxBios_sys_a0_7b;
3382 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3383 //biosA0[0x7d] = psxBios_sys_a0_7d;
3384 //biosA0[0x7e] = psxBios__96_CdRead;
3385 //biosA0[0x7f] = psxBios_sys_a0_7f;
3386 //biosA0[0x80] = psxBios_sys_a0_80;
3387 //biosA0[0x81] = psxBios_sys_a0_81;
3388 //biosA0[0x82] = psxBios_sys_a0_82;
3389 //biosA0[0x83] = psxBios_sys_a0_83;
3390 //biosA0[0x84] = psxBios_sys_a0_84;
3391 //biosA0[0x85] = psxBios__96_CdStop;
3392 //biosA0[0x86] = psxBios_sys_a0_86;
3393 //biosA0[0x87] = psxBios_sys_a0_87;
3394 //biosA0[0x88] = psxBios_sys_a0_88;
3395 //biosA0[0x89] = psxBios_sys_a0_89;
3396 //biosA0[0x8a] = psxBios_sys_a0_8a;
3397 //biosA0[0x8b] = psxBios_sys_a0_8b;
3398 //biosA0[0x8c] = psxBios_sys_a0_8c;
3399 //biosA0[0x8d] = psxBios_sys_a0_8d;
3400 //biosA0[0x8e] = psxBios_sys_a0_8e;
3401 //biosA0[0x8f] = psxBios_sys_a0_8f;
3402 biosA0[0x90] = hleExc0_1_2;
3403 biosA0[0x91] = hleExc0_0_2;
3404 biosA0[0x92] = hleExc0_1_1;
3405 biosA0[0x93] = hleExc0_0_1;
3406 //biosA0[0x94] = psxBios_sys_a0_94;
3407 //biosA0[0x95] = psxBios_sys_a0_95;
3408 //biosA0[0x96] = psxBios_AddCDROMDevice;
3409 //biosA0[0x97] = psxBios_AddMemCardDevide;
3410 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3411 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3412 //biosA0[0x9a] = psxBios_sys_a0_9a;
3413 //biosA0[0x9b] = psxBios_sys_a0_9b;
3414 //biosA0[0x9c] = psxBios_SetConf;
3415 //biosA0[0x9d] = psxBios_GetConf;
3416 //biosA0[0x9e] = psxBios_sys_a0_9e;
3417 biosA0[0x9f] = psxBios_SetMem;
3418 //biosA0[0xa0] = psxBios__boot;
3419 //biosA0[0xa1] = psxBios_SystemError;
3420 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3421 biosA0[0xa3] = psxBios_DequeueCdIntr;
3422 //biosA0[0xa4] = psxBios_sys_a0_a4;
3423 //biosA0[0xa5] = psxBios_ReadSector;
3424 biosA0[0xa6] = psxBios_get_cd_status;
3425 //biosA0[0xa7] = psxBios_bufs_cb_0;
3426 //biosA0[0xa8] = psxBios_bufs_cb_1;
3427 //biosA0[0xa9] = psxBios_bufs_cb_2;
3428 //biosA0[0xaa] = psxBios_bufs_cb_3;
3429 biosA0[0xab] = psxBios__card_info;
3430 biosA0[0xac] = psxBios__card_load;
3431 //biosA0[0axd] = psxBios__card_auto;
3432 //biosA0[0xae] = psxBios_bufs_cd_4;
3433 //biosA0[0xaf] = psxBios_sys_a0_af;
3434 //biosA0[0xb0] = psxBios_sys_a0_b0;
3435 //biosA0[0xb1] = psxBios_sys_a0_b1;
3436 //biosA0[0xb2] = psxBios_do_a_long_jmp
3437 //biosA0[0xb3] = psxBios_sys_a0_b3;
3438 biosA0[0xb4] = psxBios_GetSystemInfo;
3439 //*******************B0 CALLS****************************
3440 biosB0[0x00] = psxBios_SysMalloc;
3441 //biosB0[0x01] = psxBios_sys_b0_01;
3442 biosB0[0x02] = psxBios_SetRCnt;
3443 biosB0[0x03] = psxBios_GetRCnt;
3444 biosB0[0x04] = psxBios_StartRCnt;
3445 biosB0[0x05] = psxBios_StopRCnt;
3446 biosB0[0x06] = psxBios_ResetRCnt;
3447 biosB0[0x07] = psxBios_DeliverEvent;
3448 biosB0[0x08] = psxBios_OpenEvent;
3449 biosB0[0x09] = psxBios_CloseEvent;
3450 biosB0[0x0a] = psxBios_WaitEvent;
3451 biosB0[0x0b] = psxBios_TestEvent;
3452 biosB0[0x0c] = psxBios_EnableEvent;
3453 biosB0[0x0d] = psxBios_DisableEvent;
3454 biosB0[0x0e] = psxBios_OpenTh;
3455 biosB0[0x0f] = psxBios_CloseTh;
3456 biosB0[0x10] = psxBios_ChangeTh;
3457 //biosB0[0x11] = psxBios_psxBios_b0_11;
3458 biosB0[0x12] = psxBios_InitPAD;
3459 biosB0[0x13] = psxBios_StartPAD;
3460 biosB0[0x14] = psxBios_StopPAD;
3461 biosB0[0x15] = psxBios_PAD_init;
3462 biosB0[0x16] = psxBios_PAD_dr;
3463 biosB0[0x17] = psxBios_ReturnFromException;
3464 biosB0[0x18] = psxBios_ResetEntryInt;
3465 biosB0[0x19] = psxBios_HookEntryInt;
3466 //biosB0[0x1a] = psxBios_sys_b0_1a;
3467 //biosB0[0x1b] = psxBios_sys_b0_1b;
3468 //biosB0[0x1c] = psxBios_sys_b0_1c;
3469 //biosB0[0x1d] = psxBios_sys_b0_1d;
3470 //biosB0[0x1e] = psxBios_sys_b0_1e;
3471 //biosB0[0x1f] = psxBios_sys_b0_1f;
3472 biosB0[0x20] = psxBios_UnDeliverEvent;
3473 //biosB0[0x21] = psxBios_sys_b0_21;
3474 //biosB0[0x22] = psxBios_sys_b0_22;
3475 //biosB0[0x23] = psxBios_sys_b0_23;
3476 //biosB0[0x24] = psxBios_sys_b0_24;
3477 //biosB0[0x25] = psxBios_sys_b0_25;
3478 //biosB0[0x26] = psxBios_sys_b0_26;
3479 //biosB0[0x27] = psxBios_sys_b0_27;
3480 //biosB0[0x28] = psxBios_sys_b0_28;
3481 //biosB0[0x29] = psxBios_sys_b0_29;
3482 //biosB0[0x2a] = psxBios_sys_b0_2a;
3483 //biosB0[0x2b] = psxBios_sys_b0_2b;
3484 //biosB0[0x2c] = psxBios_sys_b0_2c;
3485 //biosB0[0x2d] = psxBios_sys_b0_2d;
3486 //biosB0[0x2e] = psxBios_sys_b0_2e;
3487 //biosB0[0x2f] = psxBios_sys_b0_2f;
3488 //biosB0[0x30] = psxBios_sys_b0_30;
3489 //biosB0[0x31] = psxBios_sys_b0_31;
3490 biosB0[0x32] = psxBios_open;
3491 biosB0[0x33] = psxBios_lseek;
3492 biosB0[0x34] = psxBios_read;
3493 biosB0[0x35] = psxBios_write;
3494 biosB0[0x36] = psxBios_close;
3495 //biosB0[0x37] = psxBios_ioctl;
3496 //biosB0[0x38] = psxBios_exit;
3497 //biosB0[0x39] = psxBios_sys_b0_39;
3498 //biosB0[0x3a] = psxBios_getc;
3499 //biosB0[0x3b] = psxBios_putc;
3500 biosB0[0x3c] = psxBios_getchar;
3501 biosB0[0x3d] = psxBios_putchar;
3502 //biosB0[0x3e] = psxBios_gets;
3503 biosB0[0x3f] = psxBios_puts;
3504 //biosB0[0x40] = psxBios_cd;
3505 biosB0[0x41] = psxBios_format;
3506 biosB0[0x42] = psxBios_firstfile;
3507 biosB0[0x43] = psxBios_nextfile;
3508 biosB0[0x44] = psxBios_rename;
3509 biosB0[0x45] = psxBios_delete;
3510 //biosB0[0x46] = psxBios_undelete;
3511 //biosB0[0x47] = psxBios_AddDevice;
3512 //biosB0[0x48] = psxBios_RemoteDevice;
3513 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3514 biosB0[0x4a] = psxBios_InitCARD;
3515 biosB0[0x4b] = psxBios_StartCARD;
3516 biosB0[0x4c] = psxBios_StopCARD;
3517 //biosB0[0x4d] = psxBios_sys_b0_4d;
3518 biosB0[0x4e] = psxBios__card_write;
3519 biosB0[0x4f] = psxBios__card_read;
3520 biosB0[0x50] = psxBios__new_card;
3521 biosB0[0x51] = psxBios_Krom2RawAdd;
3522 //biosB0[0x52] = psxBios_sys_b0_52;
3523 //biosB0[0x53] = psxBios_sys_b0_53;
3524 //biosB0[0x54] = psxBios__get_errno;
3525 biosB0[0x55] = psxBios__get_error;
3526 biosB0[0x56] = psxBios_GetC0Table;
3527 biosB0[0x57] = psxBios_GetB0Table;
3528 biosB0[0x58] = psxBios__card_chan;
3529 //biosB0[0x59] = psxBios_sys_b0_59;
3530 //biosB0[0x5a] = psxBios_sys_b0_5a;
3531 biosB0[0x5b] = psxBios_ChangeClearPad;
3532 biosB0[0x5c] = psxBios__card_status;
3533 biosB0[0x5d] = psxBios__card_wait;
3534 //*******************C0 CALLS****************************
3535 biosC0[0x00] = psxBios_InitRCnt;
3536 biosC0[0x01] = psxBios_InitException;
3537 biosC0[0x02] = psxBios_SysEnqIntRP;
3538 biosC0[0x03] = psxBios_SysDeqIntRP;
3539 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3540 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3541 //biosC0[0x06] = psxBios_ExceptionHandler;
3542 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3543 biosC0[0x08] = psxBios_SysInitMemory;
3544 //biosC0[0x09] = psxBios_SysInitKMem;
3545 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3546 //biosC0[0x0b] = psxBios_SystemError;
3547 biosC0[0x0c] = psxBios_InitDefInt;
3548 //biosC0[0x0d] = psxBios_sys_c0_0d;
3549 //biosC0[0x0e] = psxBios_sys_c0_0e;
3550 //biosC0[0x0f] = psxBios_sys_c0_0f;
3551 //biosC0[0x10] = psxBios_sys_c0_10;
3552 //biosC0[0x11] = psxBios_sys_c0_11;
3553 //biosC0[0x12] = psxBios_InstallDevices;
3554 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3555 //biosC0[0x14] = psxBios_sys_c0_14;
3556 //biosC0[0x15] = psxBios__cdevinput;
3557 //biosC0[0x16] = psxBios__cdevscan;
3558 //biosC0[0x17] = psxBios__circgetc;
3559 //biosC0[0x18] = psxBios__circputc;
3560 //biosC0[0x19] = psxBios_ioabort;
3561 //biosC0[0x1a] = psxBios_sys_c0_1a
3562 //biosC0[0x1b] = psxBios_KernelRedirect;
3563 //biosC0[0x1c] = psxBios_PatchAOTable;
3564 //************** THE END ***************************************
3567 memset(FDesc, 0, sizeof(FDesc));
3569 // somewhat pretend to be a SCPH1001 BIOS
3570 // some games look for these and take an exception if they're missing
3571 rom32 = (u32 *)psxR;
3572 rom32[0x100/4] = SWAP32(0x19951204);
3573 rom32[0x104/4] = SWAP32(3);
3574 strcpy(psxR + 0x108, "PCSX authors");
3575 strcpy(psxR + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3576 strcpy(psxR + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3577 strcpy(psxR + 0x7ff54, "GPL-2.0-or-later");
3580 len = 0x80000 - 0x66000;
3581 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3582 len = 0x80000 - 0x69d68;
3583 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3585 // trap attempts to call bios directly
3586 rom32[0x00000/4] = HLEOP(hleop_dummy);
3587 rom32[0x00180/4] = HLEOP(hleop_dummy);
3588 rom32[0x3fffc/4] = HLEOP(hleop_dummy);
3589 rom32[0x65ffc/4] = HLEOP(hleop_dummy);
3590 rom32[0x7ff2c/4] = HLEOP(hleop_dummy);
3592 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3593 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3594 Here are some examples of games not working with this fix in place :
3595 R-type won't get past the Irem logo if not implemented.
3596 Crash Team Racing will softlock after the Sony logo.
3599 ram32 = (u32 *)psxM;
3600 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3601 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3602 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3603 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3605 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3606 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3608 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3609 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3610 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3611 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3613 ram32[0x00a0/4] = HLEOP(hleop_a0);
3614 ram32[0x00b0/4] = HLEOP(hleop_b0);
3615 ram32[0x00c0/4] = HLEOP(hleop_c0);
3619 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3620 strcpy((char *)&ram32[0xeff0/4], "bu");
3622 // default exception handler chains
3623 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3624 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3625 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3626 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3627 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3628 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3629 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3630 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3634 // fill the api jumptables with fake entries as some games patch them
3635 // (or rather the funcs listed there)
3636 ptr = (u32 *)&psxM[A_A0_TABLE];
3637 for (i = 0; i < 256; i++)
3638 ptr[i] = SWAP32(0x1000);
3640 ptr = (u32 *)&psxM[A_B0_TABLE];
3641 for (i = 0; i < 256; i++)
3642 ptr[i] = SWAP32(0x2000);
3643 // B(5b) is special because games patch (sometimes even jump to)
3644 // code at fixed offsets from it, nocash lists offsets:
3645 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3646 // call: +7a0=4b70, +884=4c54, +894=4c64
3647 ptr[0x5b] = SWAP32(0x43d0);
3648 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3650 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3651 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3652 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3654 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3655 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3657 ptr = (u32 *)&psxM[A_C0_TABLE];
3658 for (i = 0; i < 256/2; i++)
3659 ptr[i] = SWAP32(0x3000);
3660 ptr[6] = SWAP32(A_EXCEPTION);
3663 ram32[0x1000/4] = HLEOP(hleop_dummy);
3664 ram32[0x2000/4] = HLEOP(hleop_dummy);
3665 ram32[0x3000/4] = HLEOP(hleop_dummy);
3666 ram32[0x8000/4] = HLEOP(hleop_execret);
3668 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3669 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3670 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3671 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3672 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3673 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3674 ram32[A_RND_SEED/4] = SWAPu32(0x24040001); // was 0xac20cc00
3677 void psxBiosShutdown() {
3680 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt) {
3681 if (tcb_cnt != 4 || evcb_cnt != 16)
3682 setup_tt(tcb_cnt, evcb_cnt);
3685 #define psxBios_PADpoll(pad) { \
3686 PAD##pad##_startPoll(pad); \
3687 pad_buf##pad[0] = 0; \
3688 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3689 if (!(pad_buf##pad[1] & 0x0f)) { \
3692 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3694 PAD##pad##_poll(0); \
3696 while (bufcount--) { \
3697 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3701 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3705 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3706 psxBios_ReturnFromException();
3712 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3713 // so this is only partially implemented
3714 void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3716 u32 cdrom_dma_ack_enable = 1; // a000b93c
3717 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3720 void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3723 //PSXBIOS_LOG("%s\n", __func__);
3725 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3726 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3727 //if (--cdrom_irq_counter == 0) // 0xa0009180
3728 // DeliverEvent(0xf0000003, 0x10);
3732 mips_return_c(ret, 20);
3735 void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3737 u32 cdrom_irq_ack_enable = 1; // a000b938
3738 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3741 void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3744 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3745 PSXBIOS_LOG("%s TODO\n", __func__);
3748 mips_return_c(ret, 20);
3751 void hleExc0_2_2_syscall() // not in any A/B/C table
3753 u32 tcbPtr = loadRam32(A_TT_PCB);
3754 TCB *tcb = loadRam32ptr(tcbPtr);
3755 u32 code = (SWAP32(tcb->cause) & 0x3c) >> 2;
3757 if (code != R3000E_Syscall) {
3759 DeliverEvent(0xf0000010, 0x1000);
3760 //psxBios_SystemErrorUnresolvedException();
3762 mips_return_c(0, 17);
3766 //printf("%s c=%d a0=%d\n", __func__, code, SWAP32(tcb->reg[4]));
3767 tcb->epc += SWAP32(4);
3768 switch (SWAP32(tcb->reg[4])) { // a0
3772 case 1: { // EnterCritical - disable irqs
3773 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3774 tcb->reg[2] = SWAP32(was_enabled);
3775 tcb->sr &= SWAP32(~0x404);
3778 case 2: // ExitCritical - enable irqs
3779 tcb->sr |= SWAP32(0x404);
3782 case 3: { // ChangeThreadSubFunction
3783 u32 tcbPtr = loadRam32(A_TT_PCB);
3784 storeRam32(tcbPtr, SWAP32(tcb->reg[5])); // a1
3788 DeliverEvent(0xf0000010, 0x4000);
3792 psxBios_ReturnFromException();
3795 void hleExc1_0_1(void)
3797 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3798 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3801 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3804 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3805 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3808 mips_return_c(ret, 22);
3811 void hleExc1_0_2(void)
3813 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3816 void hleExc1_1_1(void)
3818 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3819 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3822 void hleExc1_1_2(void)
3824 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3827 void hleExc1_2_1(void)
3829 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3830 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3833 void hleExc1_2_2(void)
3835 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3838 void hleExc1_3_1(void)
3840 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3841 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3844 void hleExc1_3_2(void)
3846 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3849 void hleExc3_0_2_defint(void)
3851 static const struct {
3862 { 6, 6 }, // rcnt2 (bug)
3867 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3868 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3869 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3874 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3877 void hleExcPadCard1(void)
3879 if (loadRam32(A_PAD_IRQR_ENA)) {
3880 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3881 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
3887 if (loadRam32(A_PAD_DR_DST))
3890 if (loadRam32(A_PAD_ACK_VBL))
3891 psxHwWrite16(0x1f801070, ~1);
3892 if (loadRam32(A_CARD_IRQR_ENA)) {
3896 mips_return_c(0, 18);
3899 void hleExcPadCard2(void)
3901 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
3902 mips_return_c(ret, 15);
3905 void psxBiosException() {
3906 u32 tcbPtr = loadRam32(A_TT_PCB);
3907 u32 *chains = loadRam32ptr(A_TT_ExCB);
3908 TCB *tcb = loadRam32ptr(tcbPtr);
3914 // $at, $v0, $v1 already saved by the mips code at A_EXCEPTION
3915 for (i = 4; i < 32; i++) {
3918 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
3920 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
3921 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
3922 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
3923 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
3924 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
3925 sp = fp = loadRam32(A_EXC_SP);
3929 // do the chains (always 4)
3930 for (c = lim = 0; c < 4; c++) {
3931 if (chains[c * 2] == 0)
3933 ptr = SWAP32(chains[c * 2]);
3934 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
3935 chain = castRam32ptr(ptr);
3940 softCallInException(SWAP32(chain[2]));
3941 if (returned_from_exception())
3944 if (v0 == 0 || chain[1] == 0)
3946 softCallInException(SWAP32(chain[1]));
3947 if (returned_from_exception())
3953 // return from exception (custom or default)
3955 ptr = loadRam32(A_EEXIT_PTR);
3956 if (ptr != A_EEXIT_DEF) {
3957 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
3958 longjmp_load(jmp_buf);
3963 psxBios_ReturnFromException();
3966 #define bfreeze(ptr, size) { \
3967 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3968 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3972 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3973 #define bfreezel(ptr) bfreeze(ptr, sizeof(*(ptr)))
3975 void psxBiosFreeze(int Mode) {