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_CONF_TCB 0xb940
298 #define A_CONF_EvCB 0xb944
299 #define A_CONF_SP 0xb948
300 #define A_CD_EVENTS 0xb9b8
301 #define A_EXC_GP 0xf450
303 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
305 static u32 loadRam32(u32 addr)
307 assert(!(addr & 0x5f800000));
308 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
311 static void *castRam8ptr(u32 addr)
313 assert(!(addr & 0x5f800000));
314 return psxM + (addr & 0x1fffff);
317 static void *castRam32ptr(u32 addr)
319 assert(!(addr & 0x5f800003));
320 return psxM + (addr & 0x1ffffc);
323 static void *loadRam8ptr(u32 addr)
325 return castRam8ptr(loadRam32(addr));
328 static void *loadRam32ptr(u32 addr)
330 return castRam32ptr(loadRam32(addr));
333 static void storeRam8(u32 addr, u8 d)
335 assert(!(addr & 0x5f800000));
336 *((u8 *)psxM + (addr & 0x1fffff)) = d;
339 static void storeRam32(u32 addr, u32 d)
341 assert(!(addr & 0x5f800000));
342 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
345 static void mips_return(u32 val)
351 static void mips_return_void(void)
356 static void use_cycles(u32 cycle)
358 psxRegs.cycle += cycle * 2;
361 static void mips_return_c(u32 val, u32 cycle)
367 static void mips_return_void_c(u32 cycle)
373 static int returned_from_exception(void)
375 // 0x80000080 means it took another exception just after return
376 return pc0 == k0 || pc0 == 0x80000080;
379 static inline void softCall(u32 pc) {
381 u32 ssr = psxRegs.CP0.n.SR;
385 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
387 while (pc0 != 0x80001000 && ++lim < 1000000)
388 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
391 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
393 psxRegs.CP0.n.SR |= ssr & 0x404;
396 static inline void softCallInException(u32 pc) {
401 assert(ra != 0x80001000);
402 if (ra == 0x80001000)
406 while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 1000000)
407 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
410 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
411 if (pc0 == 0x80001000)
415 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
416 static u32 DeliverEvent(u32 class, u32 spec);
417 static u32 UnDeliverEvent(u32 class, u32 spec);
418 static void CloseEvent(u32 ev);
423 // System calls A0 */
426 #define buread(Ra1, mcd, length) { \
427 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); \
428 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
429 memcpy(Ra1, ptr, length); \
430 psxCpu->Clear(a1, (length + 3) / 4); \
431 if (FDesc[1 + mcd].mode & 0x8000) { \
432 DeliverEvent(0xf0000011, 0x0004); \
433 DeliverEvent(0xf4000001, 0x0004); \
436 FDesc[1 + mcd].offset += v0; \
439 #define buwrite(Ra1, mcd, length) { \
440 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
441 PSXBIOS_LOG("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
442 ptr = Mcd##mcd##Data + offset; \
443 memcpy(ptr, Ra1, length); \
444 FDesc[1 + mcd].offset += length; \
445 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
446 if (FDesc[1 + mcd].mode & 0x8000) { \
447 DeliverEvent(0xf0000011, 0x0004); \
448 DeliverEvent(0xf4000001, 0x0004); \
453 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
454 /* For some strange reason, the returned character is sign-expanded; */
455 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
456 /* TODO FIX ME : Properly implement this behaviour */
457 void psxBios_getc(void) // 0x03, 0x35
462 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
466 if (pa1 != INVALID_PTR) {
468 case 2: buread(pa1, 1, 1); break;
469 case 3: buread(pa1, 2, 1); break;
476 /* Copy of psxBios_write, except size is 1. */
477 void psxBios_putc(void) // 0x09, 0x3B
482 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
485 if (pa1 == INVALID_PTR) {
490 if (a0 == 1) { // stdout
491 char *ptr = (char *)pa1;
495 printf("%c", *ptr++); a2--;
501 case 2: buwrite(pa1, 1, 1); break;
502 case 3: buwrite(pa1, 2, 1); break;
508 void psxBios_todigit(void) // 0x0a
512 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
515 if (c >= 0x30 && c < 0x3A) {
518 else if (c > 0x60 && c < 0x7B) {
521 else if (c > 0x40 && c < 0x5B) {
524 else if (c >= 0x80) {
535 void psxBios_abs() { // 0x0e
536 if ((s32)a0 < 0) v0 = -(s32)a0;
541 void psxBios_labs() { // 0x0f
545 void psxBios_atoi() { // 0x10
547 char *p = (char *)Ra0;
551 case ' ': case '\t': continue;
558 while (*p >= '0' && *p <= '9') {
559 n = n * 10 + *p++ - '0';
566 void psxBios_atol() { // 0x11
576 static void psxBios_setjmp() { // 0x13
577 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
580 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
582 jmp_buf->ra_ = SWAP32(ra);
583 jmp_buf->sp_ = SWAP32(sp);
584 jmp_buf->fp_ = SWAP32(fp);
585 for (i = 0; i < 8; i++) // s0-s7
586 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
587 jmp_buf->gp_ = SWAP32(gp);
589 mips_return_c(0, 15);
592 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
596 ra = SWAP32(jmp_buf->ra_);
597 sp = SWAP32(jmp_buf->sp_);
598 fp = SWAP32(jmp_buf->fp_);
599 for (i = 0; i < 8; i++) // s0-s7
600 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
601 gp = SWAP32(jmp_buf->gp_);;
604 void psxBios_longjmp() { // 0x14
605 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
607 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
608 longjmp_load(jmp_buf);
609 mips_return_c(a1, 15);
612 void psxBios_strcat() { // 0x15
613 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
616 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
618 if (a0 == 0 || a1 == 0)
626 while ((*p1++ = *p2++) != '\0');
631 void psxBios_strncat() { // 0x16
632 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
636 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
638 if (a0 == 0 || a1 == 0)
646 while ((*p1++ = *p2++) != '\0') {
656 void psxBios_strcmp() { // 0x17
657 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
659 if (a0 == 0 && a1 == 0)
665 else if (a0 == 0 && a1 != 0)
671 else if (a0 != 0 && a1 == 0)
678 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
681 while (*p1 == *p2++) {
700 void psxBios_strncmp() { // 0x18
701 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
703 if (a0 == 0 && a1 == 0)
709 else if (a0 == 0 && a1 != 0)
715 else if (a0 != 0 && a1 == 0)
722 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
725 while (--n >= 0 && *p1 == *p2++) {
729 v1 = a2 - ((a2-n) - 1);
737 v0 = (n < 0 ? 0 : *p1 - *--p2);
739 v1 = a2 - ((a2-n) - 1);
745 void psxBios_strcpy() { // 0x19
746 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
747 if (a0 == 0 || a1 == 0)
753 while ((*p1++ = *p2++) != '\0');
758 void psxBios_strncpy() { // 0x1a
759 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
761 if (a0 == 0 || a1 == 0)
767 for (i = 0; i < n; i++) {
768 if ((*p1++ = *p2++) == '\0') {
780 void psxBios_strlen() { // 0x1b
781 char *p = (char *)Ra0;
792 void psxBios_index() { // 0x1c
793 char *p = (char *)Ra0;
803 v0 = a0 + (p - (char *)Ra0);
807 } while (*p++ != '\0');
812 void psxBios_rindex() { // 0x1d
813 char *p = (char *)Ra0;
823 v0 = a0 + (p - (char *)Ra0);
824 } while (*p++ != '\0');
829 void psxBios_strchr() { // 0x1e
833 void psxBios_strrchr() { // 0x1f
837 void psxBios_strpbrk() { // 0x20
838 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
840 while ((c = *p1++) != '\0') {
841 for (scanp = p2; (sc = *scanp++) != '\0';) {
843 v0 = a0 + (p1 - 1 - (char *)Ra0);
850 // BUG: return a0 instead of NULL if not found
854 void psxBios_strspn() { // 0x21
857 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
858 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
859 if (*p2 == '\0') break;
862 v0 = p1 - (char *)Ra0; pc0 = ra;
865 void psxBios_strcspn() { // 0x22
868 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
869 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
870 if (*p2 != '\0') break;
873 v0 = p1 - (char *)Ra0; pc0 = ra;
876 void psxBios_strtok() { // 0x23
877 char *pcA0 = (char *)Ra0;
878 char *pcRet = strtok(pcA0, (char *)Ra1);
880 v0 = a0 + pcRet - pcA0;
886 void psxBios_strstr() { // 0x24
887 char *p = (char *)Ra0, *p1, *p2;
893 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
898 v0 = a0 + (p - (char *)Ra0);
909 void psxBios_toupper() { // 0x25
910 v0 = (s8)(a0 & 0xff);
911 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
915 void psxBios_tolower() { // 0x26
916 v0 = (s8)(a0 & 0xff);
917 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
921 static void do_memset(u32 dst, u32 v, s32 len)
927 if (db != INVALID_PTR)
931 psxCpu->Clear(dst, (len + 3) / 4);
934 static void do_memcpy(u32 dst, u32 src, s32 len)
936 u32 d = dst, s = src;
939 const u8 *sb = PSXM(s);
941 if (db != INVALID_PTR && sb != INVALID_PTR)
946 psxCpu->Clear(dst, (len + 3) / 4);
949 static void psxBios_memcpy();
951 static void psxBios_bcopy() { // 0x27 - memcpy with args swapped
952 //PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x27], a0, a1, a2);
953 u32 ret = a0, cycles = 0;
954 if (a0 == 0) // ...but it checks src this time
961 do_memcpy(a1, a0, a2);
967 mips_return_c(ret, cycles + 5);
970 static void psxBios_bzero() { // 0x28
971 /* Same as memset here (See memset below) */
972 u32 ret = a0, cycles;
973 if (a0 == 0 || (s32)a1 <= 0)
978 do_memset(a0, 0, a1);
982 // todo: many more cycles due to uncached bios mem
983 mips_return_c(ret, cycles + 5);
986 void psxBios_bcmp() { // 0x29
987 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
989 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
991 while ((s32)a2-- > 0) {
992 if (*p1++ != *p2++) {
993 v0 = *p1 - *p2; // BUG: compare the NEXT byte
1002 static void psxBios_memcpy() { // 0x2a
1003 u32 ret = a0, cycles = 0;
1006 mips_return_c(0, 4);
1011 do_memcpy(a0, a1, a2);
1017 mips_return_c(ret, cycles + 5);
1020 static void psxBios_memset() { // 0x2b
1021 u32 ret = a0, cycles;
1022 if (a0 == 0 || (s32)a2 <= 0)
1024 mips_return_c(0, 6);
1027 do_memset(a0, a1, a2);
1031 // todo: many more cycles due to uncached bios mem
1032 mips_return_c(ret, cycles + 5);
1035 void psxBios_memmove() { // 0x2c
1036 u32 ret = a0, cycles = 0;
1039 mips_return_c(0, 4);
1043 if ((s32)a2 > 0 && a0 > a1 && a0 < a1 + a2) {
1044 u32 dst = a0, len = a2 + 1;
1047 while ((s32)a2 >= 0) { // BUG: copies one more byte here
1048 const u8 *sb = PSXM(a1);
1050 if (db != INVALID_PTR && sb != INVALID_PTR)
1056 psxCpu->Clear(dst, (len + 3) / 4);
1057 cycles = 10 + len * 8;
1058 } else if ((s32)a2 > 0) {
1059 do_memcpy(a0, a1, a2);
1065 mips_return_c(ret, cycles + 5);
1068 void psxBios_memcmp() { // 0x2d
1072 void psxBios_memchr() { // 0x2e
1073 char *p = (char *)Ra0;
1075 if (a0 == 0 || a2 > 0x7FFFFFFF)
1081 while ((s32)a2-- > 0) {
1082 if (*p++ != (s8)a1) continue;
1083 v0 = a0 + (p - (char *)Ra0 - 1);
1091 static void psxBios_rand() { // 0x2f
1092 u32 s = loadRam32(A_RND_SEED) * 1103515245 + 12345;
1093 storeRam32(A_RND_SEED, s);
1095 mips_return_c((s >> 16) & 0x7fff, 12+37);
1098 static void psxBios_srand() { // 0x30
1099 storeRam32(A_RND_SEED, a0);
1100 mips_return_void_c(3);
1103 static u32 qscmpfunc, qswidth;
1105 static inline int qscmp(char *a, char *b) {
1108 a0 = sa0 + (a - (char *)PSXM(sa0));
1109 a1 = sa0 + (b - (char *)PSXM(sa0));
1111 softCall(qscmpfunc);
1117 static inline void qexchange(char *i, char *j) {
1128 static inline void q3exchange(char *i, char *j, char *k) {
1140 static void qsort_main(char *a, char *l) {
1141 char *i, *j, *lp, *hp;
1146 if ((n = l - a) <= qswidth)
1148 n = qswidth * (n / (2 * qswidth));
1154 if ((c = qscmp(i, lp)) == 0) {
1155 qexchange(i, lp -= qswidth);
1166 if ((c = qscmp(hp, j)) == 0) {
1167 qexchange(hp += qswidth, j);
1172 q3exchange(i, hp += qswidth, j);
1186 if (lp - a >= l - hp) {
1187 qsort_main(hp + qswidth, l);
1196 q3exchange(j, lp -= qswidth, i);
1201 void psxBios_qsort() { // 0x31
1204 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1209 // this isn't how the real bios works, but maybe good enough
1210 static void psxBios_malloc() { // 0x33
1211 u32 *heap_addr, *heap_end;
1212 u32 *chunk, *newchunk = NULL;
1213 unsigned int dsize = 0, csize, cstat;
1215 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x33], a0);
1216 heap_addr = loadRam32ptr(A_HEAP_BASE);
1217 heap_end = loadRam32ptr(A_HEAP_END);
1218 if (heap_addr >= heap_end) {
1224 // scan through heap and combine free chunks of space
1227 while(chunk < heap_end) {
1228 // get size and status of actual chunk
1229 csize = ((u32)*chunk) & 0xfffffffc;
1230 cstat = ((u32)*chunk) & 1;
1232 // most probably broken heap descriptor
1233 // this fixes Burning Road
1236 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1241 // it's a free chunk
1246 colflag = 1; // let's begin a new collection of free memory
1248 else dsize += (csize+4); // add the new size including header
1250 // not a free chunk: did we start a collection ?
1252 if(colflag == 1) { // collection is over
1254 *newchunk = SWAP32(dsize | 1);
1259 chunk = (u32*)((uptr)chunk + csize + 4);
1261 // if neccessary free memory on end of heap
1263 *newchunk = SWAP32(dsize | 1);
1266 csize = ((u32)*chunk) & 0xfffffffc;
1267 cstat = ((u32)*chunk) & 1;
1268 dsize = (a0 + 3) & 0xfffffffc;
1270 // exit on uninitialized heap
1271 if (chunk == NULL) {
1272 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1278 // search an unused chunk that is big enough until the end of the heap
1279 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1280 chunk = (u32*)((uptr)chunk + csize + 4);
1282 // catch out of memory
1283 if(chunk >= heap_end) {
1284 printf("malloc %x,%x: Out of memory error!\n",
1290 csize = ((u32)*chunk) & 0xfffffffc;
1291 cstat = ((u32)*chunk) & 1;
1295 if(dsize == csize) {
1296 // chunk has same size
1297 *chunk &= 0xfffffffc;
1298 } else if (dsize > csize) {
1303 *chunk = SWAP32(dsize);
1304 newchunk = (u32*)((uptr)chunk + dsize + 4);
1305 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1308 // return pointer to allocated memory
1309 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1311 //printf ("malloc %x,%x\n", v0, a0);
1315 static void psxBios_free() { // 0x34
1316 PSXBIOS_LOG("psxBios_%s %x (%x bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1317 storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1318 mips_return_void_c(5);
1321 static void psxBios_calloc() { // 0x37
1323 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
1325 a0 = size = a0 * a1;
1329 a0 = ret; a1 = size;
1332 mips_return_c(ret, 21);
1335 void psxBios_realloc() { // 0x38
1339 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1343 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1348 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1353 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1354 /* Note that it is not quite implemented this way here. */
1364 /* InitHeap(void *block , int n) */
1365 static void psxBios_InitHeap() { // 0x39
1366 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
1368 storeRam32(A_HEAP_BASE, a0);
1369 storeRam32(A_HEAP_SIZE, a1);
1370 storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
1371 storeRam32(A_HEAP_FLAG, 0);
1374 mips_return_void_c(14);
1377 void psxBios_getchar() { //0x3b
1378 v0 = getchar(); pc0 = ra;
1381 static void psxBios_printf_psxout() { // 0x3f
1390 if (psp != INVALID_PTR) {
1391 memcpy(save, psp, 4 * 4);
1392 psxMu32ref(sp) = SWAP32((u32)a0);
1393 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1394 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1395 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1407 tmp2[j++] = Ra0[i]; goto _start;
1409 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1420 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1424 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1430 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1432 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1434 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1436 *ptmp++ = Ra0[i]; break;
1446 if (psp != INVALID_PTR)
1447 memcpy(psp, save, 4 * 4);
1450 SysPrintf("%s", tmp);
1453 void psxBios_printf() { // 0x3f
1454 psxBios_printf_psxout();
1458 void psxBios_format() { // 0x41
1459 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1461 CreateMcd(Config.Mcd1);
1462 LoadMcd(1, Config.Mcd1);
1465 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1467 CreateMcd(Config.Mcd2);
1468 LoadMcd(2, Config.Mcd2);
1478 static void psxBios_SystemErrorUnresolvedException() {
1479 if (loadRam32(0xfffc) != 0x12345678) { // prevent log flood
1480 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1481 storeRam32(0xfffc, 0x12345678);
1483 mips_return_void_c(1000);
1486 static void FlushCache() {
1487 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1488 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1490 // runs from uncached mem so tons of cycles
1495 * long Load(char *name, struct EXEC *header);
1498 void psxBios_Load() { // 0x42
1503 if (pa1 != INVALID_PTR && LoadCdromFile(Ra0, &eheader) == 0) {
1504 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1505 psxCpu->Clear(a1, sizeof(EXEC) / 4);
1509 PSXBIOS_LOG("psxBios_%s: %s, %d -> %d\n", biosA0n[0x42], Ra0, a1, v0);
1515 * int Exec(struct EXEC *header , int argc , char **argv);
1518 void psxBios_Exec() { // 43
1519 EXEC *header = (EXEC *)castRam32ptr(a0);
1523 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1525 header->_sp = SWAP32(sp);
1526 header->_fp = SWAP32(fp);
1527 header->_sp = SWAP32(sp);
1528 header->_gp = SWAP32(gp);
1529 header->ret = SWAP32(ra);
1530 header->base = SWAP32(s0);
1532 ptr = SWAP32(header->b_addr);
1533 len = SWAP32(header->b_size);
1539 if (header->S_addr != 0)
1540 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1542 gp = SWAP32(header->gp0);
1550 pc0 = SWAP32(header->_pc0);
1553 static void psxBios_FlushCache() { // 44
1554 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1559 void psxBios_GPU_dw() { // 0x46
1564 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1567 GPU_writeData(0xa0000000);
1568 GPU_writeData((a1<<0x10)|(a0&0xffff));
1569 GPU_writeData((a3<<0x10)|(a2&0xffff));
1571 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1574 GPU_writeData(SWAPu32(*ptr++));
1580 void psxBios_mem2vram() { // 0x47
1582 gpuSyncPluginSR(); // flush
1583 GPU_writeData(0xa0000000);
1584 GPU_writeData((a1<<0x10)|(a0&0xffff));
1585 GPU_writeData((a3<<0x10)|(a2&0xffff));
1586 size = ((((a2 * a3) / 2) >> 4) << 16);
1587 GPU_writeStatus(0x04000002);
1588 psxHwWrite32(0x1f8010f4,0);
1589 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1590 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1591 psxHwWrite32(0x1f8010a4, size | 0x10);
1592 psxHwWrite32(0x1f8010a8,0x01000201);
1597 void psxBios_SendGPU() { // 0x48
1598 GPU_writeStatus(a0);
1603 void psxBios_GPU_cw() { // 0x49
1610 void psxBios_GPU_cwb() { // 0x4a
1611 u32 *ptr = (u32*)Ra0;
1616 GPU_writeData(SWAPu32(*ptr++));
1622 void psxBios_GPU_SendPackets() { //4b:
1624 GPU_writeStatus(0x04000002);
1625 psxHwWrite32(0x1f8010f4,0);
1626 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1627 psxHwWrite32(0x1f8010a0,a0);
1628 psxHwWrite32(0x1f8010a4,0);
1629 psxHwWrite32(0x1f8010a8,0x010000401);
1633 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1634 psxHwWrite32(0x1f8010a8,0x00000401);
1635 GPU_writeData(0x0400000);
1636 GPU_writeData(0x0200000);
1637 GPU_writeData(0x0100000);
1642 void psxBios_GPU_GetGPUStatus() { // 0x4d
1643 v0 = GPU_readStatus();
1649 void psxBios_LoadExec() { // 51
1650 EXEC *header = (EXEC*)PSXM(0xf000);
1654 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1656 s_addr = a1; s_size = a2;
1661 header->S_addr = s_addr;
1662 header->s_size = s_size;
1664 a0 = 0xf000; a1 = 0; a2 = 0;
1668 void psxBios__bu_init() { // 70
1670 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1673 DeliverEvent(0xf0000011, 0x0004);
1674 DeliverEvent(0xf4000001, 0x0004);
1679 void psxBios__96_init() { // 71
1681 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1687 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1688 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1689 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1691 static void psxBios_DequeueCdIntr_() {
1692 psxBios_SysDeqIntRP_(0, 0x91d0);
1693 psxBios_SysDeqIntRP_(0, 0x91e0);
1697 static void psxBios_DequeueCdIntr() { // a3
1698 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1699 psxBios_DequeueCdIntr_();
1702 static void psxBios_CdRemove() { // 56, 72
1703 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1705 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1706 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1707 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1708 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1709 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1710 psxBios_DequeueCdIntr_();
1712 // EnterCriticalSection - should be done at the beginning,
1713 // but this way is much easier to implement
1719 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack);
1721 static void psxBios_SetConf() { // 9c
1722 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9c], a0, a1, a2);
1723 setup_tt(a1, a0, a2);
1724 psxRegs.CP0.n.SR |= 0x401;
1725 mips_return_void_c(500);
1728 static void psxBios_GetConf() { // 9d
1729 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9d], a0, a1, a2);
1730 storeRam32(a0, loadRam32(A_CONF_EvCB));
1731 storeRam32(a1, loadRam32(A_CONF_TCB));
1732 storeRam32(a2, loadRam32(A_CONF_SP));
1733 mips_return_void_c(10);
1736 void psxBios_SetMem() { // 9f
1737 u32 new = psxHu32(0x1060);
1740 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1745 psxHu32ref(0x1060) = SWAP32(new);
1746 psxMu32ref(0x060) = a0;
1747 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1751 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1752 psxMu32ref(0x060) = a0;
1753 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1756 PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
1763 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1764 static void psxBios_get_cd_status() // a6
1766 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
1771 static void psxBios__card_info() { // ab
1772 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1774 storeRam32(A_CARD_CHAN1, a0);
1781 if (McdDisable[port & 1])
1785 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
1790 if (McdDisable[0] && McdDisable[1])
1793 DeliverEvent(0xf0000011, 0x0004);
1794 // DeliverEvent(0xf4000001, 0x0004);
1795 DeliverEvent(0xf4000001, ret);
1799 void psxBios__card_load() { // ac
1801 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1804 storeRam32(A_CARD_CHAN1, a0);
1806 // DeliverEvent(0xf0000011, 0x0004);
1807 DeliverEvent(0xf4000001, 0x0004);
1812 static void psxBios_GetSystemInfo() { // b4
1814 //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
1815 SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
1818 case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
1819 case 2: ret = 0xbfc0012c; break;
1820 case 5: ret = loadRam32(0x60) << 10; break;
1822 mips_return_c(ret, 20);
1825 /* System calls B0 */
1827 static u32 psxBios_SysMalloc_(u32 size);
1829 static void psxBios_SysMalloc() { // B 00
1830 u32 ret = psxBios_SysMalloc_(a0);
1832 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1833 mips_return_c(ret, 33);
1836 void psxBios_SetRCnt() { // 02
1838 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1845 psxRcntWtarget(a0, a1);
1846 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1847 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1848 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1849 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1850 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1852 psxRcntWmode(a0, mode);
1857 void psxBios_GetRCnt() { // 03
1859 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1863 if (a0 != 3) v0 = psxRcntRcount(a0);
1868 void psxBios_StartRCnt() { // 04
1870 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1874 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1875 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1879 void psxBios_StopRCnt() { // 05
1881 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1885 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1886 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1890 void psxBios_ResetRCnt() { // 06
1892 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1897 psxRcntWmode(a0, 0);
1898 psxRcntWtarget(a0, 0);
1899 psxRcntWcount(a0, 0);
1904 static u32 DeliverEvent(u32 class, u32 spec) {
1905 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1906 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1907 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1908 u32 i, lim = evcb_len / 0x1c;
1910 //printf("%s %08x %x\n", __func__, class, spec);
1911 for (i = 0; i < lim; i++, ev++) {
1913 if (SWAP32(ev->status) != EvStACTIVE)
1916 if (SWAP32(ev->class) != class)
1919 if (SWAP32(ev->spec) != spec)
1922 ret = SWAP32(ev->mode);
1923 if (ret == EvMdMARK) {
1924 ev->status = SWAP32(EvStALREADY);
1928 if (ret == EvMdCALL) {
1929 ret = SWAP32(ev->fhandler);
1941 static u32 UnDeliverEvent(u32 class, u32 spec) {
1942 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1943 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1944 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1945 u32 i, lim = evcb_len / 0x1c;
1947 for (i = 0; i < lim; i++, ev++) {
1949 if (SWAP32(ev->status) != EvStALREADY)
1952 if (SWAP32(ev->class) != class)
1955 if (SWAP32(ev->spec) != spec)
1958 if (SWAP32(ev->mode) == EvMdMARK)
1959 ev->status = SWAP32(EvStACTIVE);
1965 static void psxBios_DeliverEvent() { // 07
1967 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
1969 ret = DeliverEvent(a0, a1);
1973 static s32 get_free_EvCB_slot() {
1974 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1975 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
1978 for (i = 0; i < lim; i++, ev++) {
1980 if (ev->status == SWAP32(EvStUNUSED))
1986 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
1987 u32 ret = get_free_EvCB_slot();
1988 if ((s32)ret >= 0) {
1989 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
1990 ev->class = SWAP32(class);
1991 ev->status = SWAP32(EvStDISABLED);
1992 ev->spec = SWAP32(spec);
1993 ev->mode = SWAP32(mode);
1994 ev->fhandler = SWAP32(func);
2000 static void psxBios_OpenEvent() { // 08
2001 u32 ret = OpenEvent(a0, a1, a2, a3);
2002 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
2003 biosB0n[0x08], a0, a1, a2, a3, ret);
2004 mips_return_c(ret, 36);
2007 static void CloseEvent(u32 ev)
2009 u32 base = loadRam32(A_TT_EvCB);
2010 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
2013 static void psxBios_CloseEvent() { // 09
2014 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
2015 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
2017 mips_return_c(1, 10);
2020 static void psxBios_WaitEvent() { // 0a
2021 u32 base = loadRam32(A_TT_EvCB);
2022 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2023 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
2026 if (status == EvStALREADY) {
2027 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2031 if (status != EvStACTIVE)
2033 mips_return_c(0, 2);
2037 // retrigger this hlecall after the next emulation event
2039 if ((s32)(next_interupt - psxRegs.cycle) > 0)
2040 psxRegs.cycle = next_interupt;
2044 static void psxBios_TestEvent() { // 0b
2045 u32 base = loadRam32(A_TT_EvCB);
2046 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2048 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
2049 if (status == EvStALREADY) {
2050 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2054 mips_return_c(ret, 15);
2057 static void psxBios_EnableEvent() { // 0c
2058 u32 base = loadRam32(A_TT_EvCB);
2059 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2060 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
2061 if (status != EvStUNUSED)
2062 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2064 mips_return_c(1, 15);
2067 static void psxBios_DisableEvent() { // 0d
2068 u32 base = loadRam32(A_TT_EvCB);
2069 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2070 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2071 if (status != EvStUNUSED)
2072 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2074 mips_return_c(1, 15);
2078 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2081 void psxBios_OpenTh() { // 0e
2082 TCB *tcb = loadRam32ptr(A_TT_TCB);
2083 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2086 for (th = 1; th < limit; th++)
2088 if (tcb[th].status != SWAP32(0x4000)) break;
2092 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2093 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2095 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2097 mips_return_c(0xffffffff, 20);
2100 PSXBIOS_LOG("psxBios_%s -> %x\n", biosB0n[0x0e], 0xff000000 + th);
2102 tcb[th].status = SWAP32(0x4000);
2103 tcb[th].mode = SWAP32(0x1000);
2104 tcb[th].epc = SWAP32(a0);
2105 tcb[th].reg[30] = SWAP32(a1); // fp
2106 tcb[th].reg[29] = SWAP32(a1); // sp
2107 tcb[th].reg[28] = SWAP32(a2); // gp
2109 mips_return_c(0xff000000 + th, 34);
2113 * int CloseTh(long thread);
2116 static void psxBios_CloseTh() { // 0f
2117 u32 tcb = loadRam32(A_TT_TCB);
2118 u32 th = a0 & 0xffff;
2120 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x0f], a0);
2121 // in the usual bios fashion no checks, just write and return 1
2122 storeRam32(tcb + th * sizeof(TCB), 0x1000);
2124 mips_return_c(1, 11);
2128 * int ChangeTh(long thread);
2131 void psxBios_ChangeTh() { // 10
2132 u32 tcbBase = loadRam32(A_TT_TCB);
2133 u32 th = a0 & 0xffff;
2135 // this is quite spammy
2136 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2138 // without doing any argument checks, just issue a syscall
2139 // (like the real bios does)
2141 a1 = tcbBase + th * sizeof(TCB);
2146 void psxBios_InitPAD() { // 0x12
2147 u32 i, *ram32 = (u32 *)psxM;
2148 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2150 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2151 ram32[A_PAD_DR_DST/4] = 0;
2152 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2153 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2154 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2155 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2156 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2157 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2158 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2159 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2161 for (i = 0; i < a1; i++) {
2163 storeRam8(a0 + i, 0);
2165 for (i = 0; i < a3; i++) {
2167 storeRam8(a2 + i, 0);
2169 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2171 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2173 mips_return_c(1, 200);
2176 void psxBios_StartPAD() { // 13
2177 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2179 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2180 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2181 psxHwWrite16(0x1f801070, ~1);
2182 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2183 storeRam32(A_PAD_ACK_VBL, 1);
2184 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2185 psxRegs.CP0.n.SR |= 0x401;
2187 mips_return_c(1, 300);
2190 void psxBios_StopPAD() { // 14
2191 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2192 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2193 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2194 psxRegs.CP0.n.SR |= 0x401;
2195 mips_return_void_c(200);
2198 static void psxBios_PAD_init() { // 15
2200 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2201 if (a0 == 0x20000000 || a0 == 0x20000001)
2204 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2205 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2208 storeRam32(A_PAD_DR_DST, dst);
2211 mips_return_c(ret, 100);
2214 static u32 psxBios_PAD_dr_() {
2215 u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2216 u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2217 u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2218 dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2219 if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2221 dst[0] = buf1[3], dst[1] = buf1[2];
2222 if (buf1[1] == 0x23) {
2223 dst[0] |= 0xc7, dst[1] |= 7;
2224 if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2225 if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2228 if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2230 dst[2] = buf2[3], dst[3] = buf2[2];
2231 if (buf2[1] == 0x23) {
2232 dst[2] |= 0xc7, dst[3] |= 7;
2233 if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2234 if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2238 return SWAP32(*(u32 *)dst);
2241 static void psxBios_PAD_dr() { // 16
2242 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2243 u32 ret = psxBios_PAD_dr_();
2247 static void psxBios_ReturnFromException() { // 17
2248 u32 tcbPtr = loadRam32(A_TT_PCB);
2249 const TCB *tcb = loadRam32ptr(tcbPtr);
2253 for (i = 1; i < 32; i++)
2254 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2255 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2256 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2257 sr = SWAP32(tcb->sr);
2259 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2260 pc0 = k0 = SWAP32(tcb->epc);
2262 // the interpreter wants to know about sr changes, so do a MTC0
2263 sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2264 MTC0(&psxRegs, 12, sr);
2270 void psxBios_ResetEntryInt() { // 18
2271 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2273 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2274 mips_return_void_c(5);
2277 void psxBios_HookEntryInt() { // 19
2278 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2280 storeRam32(A_EEXIT_PTR, a0);
2281 mips_return_void_c(3);
2284 static void psxBios_UnDeliverEvent() { // 0x20
2286 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2288 ret = UnDeliverEvent(a0, a1);
2292 static void buopen(int mcd, char *ptr, char *cfg)
2295 char *mcd_data = ptr;
2297 strcpy(FDesc[1 + mcd].name, Ra0+5);
2298 FDesc[1 + mcd].offset = 0;
2299 FDesc[1 + mcd].mode = a1;
2301 for (i=1; i<16; i++) {
2302 const char *fptr = mcd_data + 128 * i;
2303 if ((*fptr & 0xF0) != 0x50) continue;
2304 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2305 FDesc[1 + mcd].mcfile = i;
2306 PSXBIOS_LOG("open %s\n", fptr+0xa);
2310 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2311 for (i=1; i<16; i++) {
2312 int j, xor, nblk = a1 >> 16;
2314 char *fptr = mcd_data + 128 * i;
2316 if ((*fptr & 0xF0) != 0xa0) continue;
2318 FDesc[1 + mcd].mcfile = i;
2321 fptr[5] = 0x20 * nblk;
2324 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2325 pptr = fptr2 = fptr;
2326 for(j=2; j<=nblk; j++) {
2328 for(i++; i<16; i++) {
2331 memset(fptr2, 0, 128);
2332 fptr2[0] = j < nblk ? 0x52 : 0x53;
2335 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2340 /* shouldn't this return ENOSPC if i == 16? */
2342 pptr[8] = pptr[9] = 0xff;
2343 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2345 PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2347 /* just go ahead and resave them all */
2348 SaveMcd(cfg, ptr, 128, 128 * 15);
2351 /* shouldn't this return ENOSPC if i == 16? */
2356 * int open(char *name , int mode);
2359 void psxBios_open() { // 0x32
2362 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x32], Ra0, a1);
2366 if (pa0 != INVALID_PTR) {
2367 if (!strncmp(pa0, "bu00", 4)) {
2368 buopen(1, Mcd1Data, Config.Mcd1);
2371 if (!strncmp(pa0, "bu10", 4)) {
2372 buopen(2, Mcd2Data, Config.Mcd2);
2380 * int lseek(int fd , int offset , int whence);
2383 void psxBios_lseek() { // 0x33
2385 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2390 FDesc[a0].offset = a1;
2392 // DeliverEvent(0xf0000011, 0x0004);
2393 // DeliverEvent(0xf4000001, 0x0004);
2397 FDesc[a0].offset+= a1;
2398 v0 = FDesc[a0].offset;
2407 * int read(int fd , void *buf , int nbytes);
2410 void psxBios_read() { // 0x34
2415 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2420 if (pa1 != INVALID_PTR) {
2422 case 2: buread(pa1, 1, a2); break;
2423 case 3: buread(pa1, 2, a2); break;
2431 * int write(int fd , void *buf , int nbytes);
2434 void psxBios_write() { // 0x35/0x03
2438 if (a0 != 1) // stdout
2439 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2442 if (pa1 == INVALID_PTR) {
2447 if (a0 == 1) { // stdout
2451 if (Config.PsxOut) while (a2 > 0) {
2452 SysPrintf("%c", *ptr++); a2--;
2458 case 2: buwrite(pa1, 1, a2); break;
2459 case 3: buwrite(pa1, 2, a2); break;
2465 static void psxBios_write_psxout() {
2466 if (a0 == 1) { // stdout
2467 const char *ptr = Ra1;
2470 if (ptr != INVALID_PTR)
2472 SysPrintf("%c", *ptr++);
2476 static void psxBios_putchar_psxout() { // 3d
2477 SysPrintf("%c", (char)a0);
2480 static void psxBios_puts_psxout() { // 3e/3f
2481 SysPrintf("%s", Ra0);
2485 * int close(int fd);
2488 void psxBios_close() { // 0x36
2490 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2497 void psxBios_putchar() { // 3d
2498 if (Config.PsxOut) SysPrintf("%c", (char)a0);
2502 void psxBios_puts() { // 3e/3f
2503 if (Config.PsxOut) SysPrintf("%s", Ra0);
2507 static void bufile(const u8 *mcd_data, u32 dir_) {
2508 struct DIRENTRY *dir = (struct DIRENTRY *)castRam8ptr(dir_);
2509 const char *pfile = ffile + 5;
2510 const u8 *data = mcd_data;
2511 int i = 0, match = 0;
2516 for (; nfile <= 15 && !match; nfile++) {
2519 head = nfile * 0x40;
2520 data = mcd_data + 128 * nfile;
2521 name = (const char *)data + 0x0a;
2522 if ((data[0] & 0xF0) != 0x50) continue;
2523 /* Bug link files show up as free block. */
2524 if (!name[0]) continue;
2526 for (i = 0; i < 20; i++) {
2527 if (pfile[i] == name[i] || pfile[i] == '?')
2528 dir->name[i] = name[i];
2529 else if (pfile[i] == '*') {
2530 int len = strlen(name + i);
2533 memcpy(dir->name + i, name + i, len + 1);
2544 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n",
2545 nfile, dir->name, pfile, name, match);
2547 for (; nfile <= 15; nfile++, blocks++) {
2548 const u8 *data2 = mcd_data + 128 * nfile;
2549 const char *name = data2 + 0x0a;
2550 if ((data2[0] & 0xF0) != 0x50 || name[0])
2554 // nul char of full lenth name seems to overwrite .attr
2555 dir->attr = SWAP32(i < 20 ? data[0] & 0xf0 : 0); // ?
2556 dir->size = 8192 * blocks;
2560 PSXBIOS_LOG(" -> %x '%s' %x %x %x %x\n", v0, v0 ? dir->name : "",
2561 dir->attr, dir->size, dir->next, dir->head);
2565 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2568 static void psxBios_firstfile() { // 42
2569 char *pa0 = castRam8ptr(a0);
2571 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x42], pa0, a1);
2575 snprintf(ffile, sizeof(ffile), "%s", pa0);
2577 strcpy(ffile + 5, "*"); // maybe?
2579 if (!strncmp(pa0, "bu00", 4)) {
2580 // firstfile() calls _card_read() internally, so deliver it's event
2581 DeliverEvent(0xf0000011, 0x0004);
2582 bufile(Mcd1Data, a1);
2583 } else if (!strncmp(pa0, "bu10", 4)) {
2584 // firstfile() calls _card_read() internally, so deliver it's event
2585 DeliverEvent(0xf0000011, 0x0004);
2586 bufile(Mcd2Data, a1);
2594 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2597 void psxBios_nextfile() { // 43
2598 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x43], a0);
2601 if (!strncmp(ffile, "bu00", 4))
2602 bufile(Mcd1Data, a0);
2603 else if (!strncmp(ffile, "bu10", 4))
2604 bufile(Mcd2Data, a0);
2609 #define burename(mcd) { \
2610 for (i=1; i<16; i++) { \
2611 int namelen, j, xor = 0; \
2612 ptr = Mcd##mcd##Data + 128 * i; \
2613 if ((*ptr & 0xF0) != 0x50) continue; \
2614 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2615 namelen = strlen(Ra1+5); \
2616 memcpy(ptr+0xa, Ra1+5, namelen); \
2617 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2618 for (j=0; j<127; j++) xor^= ptr[j]; \
2620 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2627 * int rename(char *old, char *new);
2630 void psxBios_rename() { // 44
2637 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2642 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2643 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2647 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2656 #define budelete(mcd) { \
2657 for (i=1; i<16; i++) { \
2658 ptr = Mcd##mcd##Data + 128 * i; \
2659 if ((*ptr & 0xF0) != 0x50) continue; \
2660 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2661 *ptr = (*ptr & 0xf) | 0xA0; \
2662 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2663 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2670 * int delete(char *name);
2673 void psxBios_delete() { // 45
2679 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2684 if (pa0 != INVALID_PTR) {
2685 if (!strncmp(pa0, "bu00", 4)) {
2689 if (!strncmp(pa0, "bu10", 4)) {
2697 void psxBios_InitCARD() { // 4a
2698 u32 *ram32 = (u32 *)psxM;
2699 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2700 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2701 // (maybe) todo: early_card_irq, etc
2703 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2705 psxBios_FlushCache();
2706 mips_return_c(0, 34+13+15+6);
2709 void psxBios_StartCARD() { // 4b
2710 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2711 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2712 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2714 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2715 storeRam32(A_PAD_ACK_VBL, 1);
2716 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2717 storeRam32(A_CARD_IRQR_ENA, 1);
2718 psxRegs.CP0.n.SR |= 0x401;
2720 mips_return_c(1, 200);
2723 void psxBios_StopCARD() { // 4c
2724 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2725 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2726 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2727 storeRam32(A_CARD_IRQR_ENA, 0);
2728 psxRegs.CP0.n.SR |= 0x401;
2729 mips_return_void_c(200);
2732 void psxBios__card_write() { // 0x4e
2737 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2740 Function also accepts sector 400h (a bug).
2741 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2745 /* Invalid sectors */
2749 storeRam32(A_CARD_CHAN1, a0);
2752 if (pa2 != INVALID_PTR) {
2754 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2755 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2757 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2758 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2762 DeliverEvent(0xf0000011, 0x0004);
2763 // DeliverEvent(0xf4000001, 0x0004);
2768 void psxBios__card_read() { // 0x4f
2773 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2776 Function also accepts sector 400h (a bug).
2777 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2781 /* Invalid sectors */
2785 storeRam32(A_CARD_CHAN1, a0);
2788 if (pa2 != INVALID_PTR) {
2790 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2792 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2796 DeliverEvent(0xf0000011, 0x0004);
2797 // DeliverEvent(0xf4000001, 0x0004);
2802 void psxBios__new_card() { // 0x50
2804 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2810 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2811 void psxBios__get_error(void) // 55
2813 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2818 void psxBios_Krom2RawAdd() { // 0x51
2821 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2822 const u32 table_8140[][2] = {
2823 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2824 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2825 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2826 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2827 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2828 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2829 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2830 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2831 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2835 const u32 table_889f[][2] = {
2836 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2837 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2838 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2839 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2840 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2841 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2842 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2843 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2847 if (a0 >= 0x8140 && a0 <= 0x84be) {
2848 while (table_8140[i][0] <= a0) i++;
2849 a0 -= table_8140[i - 1][0];
2850 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2851 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2852 while (table_889f[i][0] <= a0) i++;
2853 a0 -= table_889f[i - 1][0];
2854 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2862 void psxBios_GetC0Table() { // 56
2863 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2864 log_unhandled("GetC0Table @%08x\n", ra);
2866 mips_return_c(A_C0_TABLE, 3);
2869 void psxBios_GetB0Table() { // 57
2870 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2871 log_unhandled("GetB0Table @%08x\n", ra);
2873 mips_return_c(A_B0_TABLE, 3);
2876 static void psxBios__card_chan() { // 0x58
2878 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2880 // todo: should return active slot chan
2881 // (active - which was last processed by irq code)
2882 ret = loadRam32(A_CARD_CHAN1);
2883 mips_return_c(ret, 8);
2886 static void psxBios_ChangeClearPad() { // 5b
2888 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2889 ret = loadRam32(A_PAD_ACK_VBL);
2890 storeRam32(A_PAD_ACK_VBL, a0);
2892 mips_return_c(ret, 6);
2895 static void psxBios__card_status() { // 5c
2896 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
2902 static void psxBios__card_wait() { // 5d
2903 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
2909 /* System calls C0 */
2911 static void psxBios_InitRCnt() { // 00
2913 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2914 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2915 for (i = 0; i < 3; i++) {
2916 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2917 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2918 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2920 psxBios_SysEnqIntRP_(a0, 0x6d88);
2921 mips_return_c(0, 9);
2924 static void psxBios_InitException() { // 01
2925 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2926 psxBios_SysEnqIntRP_(a0, 0x6da8);
2927 mips_return_c(0, 9);
2931 * int SysEnqIntRP(int index , long *queue);
2934 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2935 u32 old, base = loadRam32(A_TT_ExCB);
2937 old = loadRam32(base + (priority << 3));
2938 storeRam32(base + (priority << 3), chain_eptr);
2939 storeRam32(chain_eptr, old);
2940 mips_return_c(0, 9);
2943 static void psxBios_SysEnqIntRP() { // 02
2944 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2945 psxBios_SysEnqIntRP_(a0, a1);
2949 * int SysDeqIntRP(int index , long *queue);
2952 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
2953 u32 ptr, next, base = loadRam32(A_TT_ExCB);
2954 u32 lim = 0, ret = 0;
2956 // as in original: no arg checks of any kind, bug if a1 == 0
2957 ptr = loadRam32(base + (priority << 3));
2959 next = loadRam32(ptr);
2960 if (ptr == chain_rm_eptr) {
2961 storeRam32(base + (priority << 3), next);
2966 while (next && next != chain_rm_eptr && lim++ < 100) {
2968 next = loadRam32(ptr);
2971 if (next == chain_rm_eptr) {
2972 next = loadRam32(next);
2973 storeRam32(ptr, next);
2980 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
2982 mips_return_c(ret, 12);
2985 static void psxBios_SysDeqIntRP() { // 03
2986 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
2987 psxBios_SysDeqIntRP_(a0, a1);
2990 static void psxBios_get_free_EvCB_slot() { // 04
2991 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
2992 s32 ret = get_free_EvCB_slot();
2993 mips_return_c(ret, 0);
2996 static void psxBios_SysInitMemory_(u32 base, u32 size) {
2997 storeRam32(base, 0);
2998 storeRam32(A_KMALLOC_PTR, base);
2999 storeRam32(A_KMALLOC_SIZE, size);
3000 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
3003 // this should be much more complicated, but maybe that'll be enough
3004 static u32 psxBios_SysMalloc_(u32 size) {
3005 u32 ptr = loadRam32(A_KMALLOC_PTR);
3007 size = (size + 3) & ~3;
3008 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
3009 storeRam32(ptr, size);
3013 static void psxBios_SysInitMemory() { // 08
3014 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
3016 psxBios_SysInitMemory_(a0, a1);
3017 mips_return_void_c(12);
3020 static void psxBios_ChangeClearRCnt() { // 0a
3023 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
3025 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
3026 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
3027 mips_return_c(ret, 8);
3030 static void psxBios_InitDefInt() { // 0c
3031 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3032 // should also clear the autoack table
3033 psxBios_SysEnqIntRP_(a0, 0x6d98);
3034 mips_return_c(0, 20 + 6*2);
3037 void psxBios_dummy() {
3038 u32 pc = (pc0 & 0x1fffff) - 4;
3039 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
3040 : pc == 0xc0 ? biosC0n : NULL;
3041 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
3042 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
3043 (void)pc; (void)ntab;
3044 mips_return_c(0, 100);
3047 void (*biosA0[256])();
3048 // C0 and B0 overlap (end of C0 is start of B0)
3049 void (*biosC0[256+128])();
3050 void (**biosB0)() = biosC0 + 128;
3052 static void setup_mips_code()
3055 ptr = (u32 *)&psxM[A_SYSCALL];
3056 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3057 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
3058 ptr[0x08/4] = SWAPu32(0x00000000); // nop
3060 ptr = (u32 *)&psxM[A_EXCEPTION];
3061 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
3062 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
3063 ptr[0x14/4] = SWAPu32(0x00000000); // nop
3064 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
3065 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3066 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
3067 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
3068 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
3069 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
3070 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
3072 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
3073 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
3074 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
3076 ptr[0xb0/4] = HLEOP(hleop_exception);
3079 static const struct {
3083 { 0xbfc050a4, hleop_exc0_0_1 },
3084 { 0xbfc04fbc, hleop_exc0_0_2 },
3085 { 0xbfc0506c, hleop_exc0_1_1 },
3086 { 0xbfc04dec, hleop_exc0_1_2 },
3087 { 0x1a00, hleop_exc0_2_2 },
3088 { 0x19c8, hleop_exc1_0_1 },
3089 { 0x18bc, hleop_exc1_0_2 },
3090 { 0x1990, hleop_exc1_1_1 },
3091 { 0x1858, hleop_exc1_1_2 },
3092 { 0x1958, hleop_exc1_2_1 },
3093 { 0x17f4, hleop_exc1_2_2 },
3094 { 0x1920, hleop_exc1_3_1 },
3095 { 0x1794, hleop_exc1_3_2 },
3096 { 0x2458, hleop_exc3_0_2 },
3097 { 0x49bc, hleop_exc_padcard1 },
3098 { 0x4a4c, hleop_exc_padcard2 },
3101 static int chain_hle_op(u32 handler)
3105 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3106 if (chainfns[i].addr == handler)
3107 return chainfns[i].op;
3111 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3113 d[0] = SWAPu32(next);
3114 d[1] = SWAPu32(handler1);
3115 d[2] = SWAPu32(handler2);
3117 // install the hle traps
3118 if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3119 if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3122 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack)
3124 u32 *ram32 = (u32 *)psxM;
3125 u32 s_excb = 0x20, s_evcb, s_pcb = 4, s_tcb;
3126 u32 p_excb, p_evcb, p_pcb, p_tcb;
3129 PSXBIOS_LOG("setup: tcb %u, evcb %u\n", tcb_cnt, evcb_cnt);
3131 // the real bios doesn't care, but we just don't
3132 // want to crash in case of garbage parameters
3133 if (tcb_cnt > 1024) tcb_cnt = 1024;
3134 if (evcb_cnt > 1024) evcb_cnt = 1024;
3135 s_evcb = 0x1c * evcb_cnt;
3136 s_tcb = 0xc0 * tcb_cnt;
3138 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3139 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3140 p_excb = psxBios_SysMalloc_(s_excb);
3141 p_evcb = psxBios_SysMalloc_(s_evcb);
3142 p_pcb = psxBios_SysMalloc_(s_pcb);
3143 p_tcb = psxBios_SysMalloc_(s_tcb);
3145 // "table of tables". Some games modify it
3146 assert(A_TT_ExCB == 0x0100);
3147 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3148 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3149 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3150 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3151 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3152 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3153 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3154 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3155 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3156 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3157 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3158 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3160 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3161 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3162 storeRam32(p_excb + 4*4, 0x0000); // chain2
3163 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3165 storeRam32(p_pcb, p_tcb);
3166 storeRam32(p_tcb, 0x4000); // first TCB
3167 for (i = 1; i < tcb_cnt; i++)
3168 storeRam32(p_tcb + sizeof(TCB) * i, 0x1000);
3171 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3172 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3173 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3174 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3175 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3177 storeRam32(A_CONF_EvCB, evcb_cnt);
3178 storeRam32(A_CONF_TCB, tcb_cnt);
3179 storeRam32(A_CONF_SP, stack);
3182 static const u32 gpu_ctl_def[] = {
3183 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3184 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3187 static const u32 gpu_data_def[] = {
3188 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3189 0xe5001000, 0xe6000000,
3190 0x02000000, 0x00000000, 0x01ff03ff
3194 static const u16 spu_config[] = {
3195 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3196 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3197 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3198 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3199 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3200 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3201 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3202 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3205 void psxBiosSetupBootState(void)
3207 boolean hle = Config.HLE;
3208 u32 *hw = (u32 *)psxH;
3211 // see also SetBootRegs()
3214 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3215 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3217 k0 = 0xbfc0d968; k1 = 0xf1c;
3218 ra = 0xf0001234; // just to easily detect attempts to return
3219 psxRegs.CP0.n.Cause = 0x20;
3220 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3222 hw[0x1000/4] = SWAP32(0x1f000000);
3223 hw[0x1004/4] = SWAP32(0x1f802000);
3224 hw[0x1008/4] = SWAP32(0x0013243f);
3225 hw[0x100c/4] = SWAP32(0x00003022);
3226 hw[0x1010/4] = SWAP32(0x0013243f);
3227 hw[0x1014/4] = SWAP32(0x200931e1);
3228 hw[0x1018/4] = SWAP32(0x00020943);
3229 hw[0x101c/4] = SWAP32(0x00070777);
3230 hw[0x1020/4] = SWAP32(0x0000132c);
3231 hw[0x1060/4] = SWAP32(0x00000b88);
3232 hw[0x1070/4] = SWAP32(0x00000001);
3233 hw[0x1074/4] = SWAP32(0x0000000c);
3234 hw[0x2040/4] = SWAP32(0x00000900);
3237 hw[0x10a0/4] = SWAP32(0x00ffffff);
3238 hw[0x10a8/4] = SWAP32(0x00000401);
3239 hw[0x10b0/4] = SWAP32(0x0008b000);
3240 hw[0x10b4/4] = SWAP32(0x00010200);
3241 hw[0x10e0/4] = SWAP32(0x000eccf4);
3242 hw[0x10e4/4] = SWAP32(0x00000400);
3243 hw[0x10e8/4] = SWAP32(0x00000002);
3244 hw[0x10f0/4] = SWAP32(0x00009099);
3245 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3254 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3255 GPU_writeStatus(gpu_ctl_def[i]);
3256 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3257 GPU_writeData(gpu_data_def[i]);
3258 HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
3261 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3262 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3265 #include "sjisfont.h"
3267 void psxBiosInit() {
3268 u32 *ptr, *ram32, *rom32;
3272 memset(psxM, 0, 0x10000);
3273 for(i = 0; i < 256; i++) {
3278 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3279 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3280 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3281 biosA0[0x3f] = psxBios_printf_psxout;
3283 if (!Config.HLE) return;
3285 for(i = 0; i < 256; i++) {
3286 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3287 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3288 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3291 biosA0[0x00] = psxBios_open;
3292 biosA0[0x01] = psxBios_lseek;
3293 biosA0[0x02] = psxBios_read;
3294 biosA0[0x03] = psxBios_write;
3295 biosA0[0x04] = psxBios_close;
3296 //biosA0[0x05] = psxBios_ioctl;
3297 //biosA0[0x06] = psxBios_exit;
3298 //biosA0[0x07] = psxBios_sys_a0_07;
3299 biosA0[0x08] = psxBios_getc;
3300 biosA0[0x09] = psxBios_putc;
3301 biosA0[0x0a] = psxBios_todigit;
3302 //biosA0[0x0b] = psxBios_atof;
3303 //biosA0[0x0c] = psxBios_strtoul;
3304 //biosA0[0x0d] = psxBios_strtol;
3305 biosA0[0x0e] = psxBios_abs;
3306 biosA0[0x0f] = psxBios_labs;
3307 biosA0[0x10] = psxBios_atoi;
3308 biosA0[0x11] = psxBios_atol;
3309 //biosA0[0x12] = psxBios_atob;
3310 biosA0[0x13] = psxBios_setjmp;
3311 biosA0[0x14] = psxBios_longjmp;
3312 biosA0[0x15] = psxBios_strcat;
3313 biosA0[0x16] = psxBios_strncat;
3314 biosA0[0x17] = psxBios_strcmp;
3315 biosA0[0x18] = psxBios_strncmp;
3316 biosA0[0x19] = psxBios_strcpy;
3317 biosA0[0x1a] = psxBios_strncpy;
3318 biosA0[0x1b] = psxBios_strlen;
3319 biosA0[0x1c] = psxBios_index;
3320 biosA0[0x1d] = psxBios_rindex;
3321 biosA0[0x1e] = psxBios_strchr;
3322 biosA0[0x1f] = psxBios_strrchr;
3323 biosA0[0x20] = psxBios_strpbrk;
3324 biosA0[0x21] = psxBios_strspn;
3325 biosA0[0x22] = psxBios_strcspn;
3326 biosA0[0x23] = psxBios_strtok;
3327 biosA0[0x24] = psxBios_strstr;
3328 biosA0[0x25] = psxBios_toupper;
3329 biosA0[0x26] = psxBios_tolower;
3330 biosA0[0x27] = psxBios_bcopy;
3331 biosA0[0x28] = psxBios_bzero;
3332 biosA0[0x29] = psxBios_bcmp;
3333 biosA0[0x2a] = psxBios_memcpy;
3334 biosA0[0x2b] = psxBios_memset;
3335 biosA0[0x2c] = psxBios_memmove;
3336 biosA0[0x2d] = psxBios_memcmp;
3337 biosA0[0x2e] = psxBios_memchr;
3338 biosA0[0x2f] = psxBios_rand;
3339 biosA0[0x30] = psxBios_srand;
3340 biosA0[0x31] = psxBios_qsort;
3341 //biosA0[0x32] = psxBios_strtod;
3342 biosA0[0x33] = psxBios_malloc;
3343 biosA0[0x34] = psxBios_free;
3344 //biosA0[0x35] = psxBios_lsearch;
3345 //biosA0[0x36] = psxBios_bsearch;
3346 biosA0[0x37] = psxBios_calloc;
3347 biosA0[0x38] = psxBios_realloc;
3348 biosA0[0x39] = psxBios_InitHeap;
3349 //biosA0[0x3a] = psxBios__exit;
3350 biosA0[0x3b] = psxBios_getchar;
3351 biosA0[0x3c] = psxBios_putchar;
3352 //biosA0[0x3d] = psxBios_gets;
3353 biosA0[0x3e] = psxBios_puts;
3354 biosA0[0x3f] = psxBios_printf;
3355 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3356 //biosA0[0x41] = psxBios_LoadTest;
3357 biosA0[0x42] = psxBios_Load;
3358 biosA0[0x43] = psxBios_Exec;
3359 biosA0[0x44] = psxBios_FlushCache;
3360 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3361 biosA0[0x46] = psxBios_GPU_dw;
3362 biosA0[0x47] = psxBios_mem2vram;
3363 biosA0[0x48] = psxBios_SendGPU;
3364 biosA0[0x49] = psxBios_GPU_cw;
3365 biosA0[0x4a] = psxBios_GPU_cwb;
3366 biosA0[0x4b] = psxBios_GPU_SendPackets;
3367 biosA0[0x4c] = psxBios_sys_a0_4c;
3368 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3369 //biosA0[0x4e] = psxBios_GPU_sync;
3370 //biosA0[0x4f] = psxBios_sys_a0_4f;
3371 //biosA0[0x50] = psxBios_sys_a0_50;
3372 biosA0[0x51] = psxBios_LoadExec;
3373 //biosA0[0x52] = psxBios_GetSysSp;
3374 //biosA0[0x53] = psxBios_sys_a0_53;
3375 //biosA0[0x54] = psxBios__96_init_a54;
3376 //biosA0[0x55] = psxBios__bu_init_a55;
3377 biosA0[0x56] = psxBios_CdRemove;
3378 //biosA0[0x57] = psxBios_sys_a0_57;
3379 //biosA0[0x58] = psxBios_sys_a0_58;
3380 //biosA0[0x59] = psxBios_sys_a0_59;
3381 //biosA0[0x5a] = psxBios_sys_a0_5a;
3382 //biosA0[0x5b] = psxBios_dev_tty_init;
3383 //biosA0[0x5c] = psxBios_dev_tty_open;
3384 //biosA0[0x5d] = psxBios_sys_a0_5d;
3385 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3386 //biosA0[0x5f] = psxBios_dev_cd_open;
3387 //biosA0[0x60] = psxBios_dev_cd_read;
3388 //biosA0[0x61] = psxBios_dev_cd_close;
3389 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3390 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3391 //biosA0[0x64] = psxBios_dev_cd_chdir;
3392 //biosA0[0x65] = psxBios_dev_card_open;
3393 //biosA0[0x66] = psxBios_dev_card_read;
3394 //biosA0[0x67] = psxBios_dev_card_write;
3395 //biosA0[0x68] = psxBios_dev_card_close;
3396 //biosA0[0x69] = psxBios_dev_card_firstfile;
3397 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3398 //biosA0[0x6b] = psxBios_dev_card_erase;
3399 //biosA0[0x6c] = psxBios_dev_card_undelete;
3400 //biosA0[0x6d] = psxBios_dev_card_format;
3401 //biosA0[0x6e] = psxBios_dev_card_rename;
3402 //biosA0[0x6f] = psxBios_dev_card_6f;
3403 biosA0[0x70] = psxBios__bu_init;
3404 biosA0[0x71] = psxBios__96_init;
3405 biosA0[0x72] = psxBios_CdRemove;
3406 //biosA0[0x73] = psxBios_sys_a0_73;
3407 //biosA0[0x74] = psxBios_sys_a0_74;
3408 //biosA0[0x75] = psxBios_sys_a0_75;
3409 //biosA0[0x76] = psxBios_sys_a0_76;
3410 //biosA0[0x77] = psxBios_sys_a0_77;
3411 //biosA0[0x78] = psxBios__96_CdSeekL;
3412 //biosA0[0x79] = psxBios_sys_a0_79;
3413 //biosA0[0x7a] = psxBios_sys_a0_7a;
3414 //biosA0[0x7b] = psxBios_sys_a0_7b;
3415 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3416 //biosA0[0x7d] = psxBios_sys_a0_7d;
3417 //biosA0[0x7e] = psxBios__96_CdRead;
3418 //biosA0[0x7f] = psxBios_sys_a0_7f;
3419 //biosA0[0x80] = psxBios_sys_a0_80;
3420 //biosA0[0x81] = psxBios_sys_a0_81;
3421 //biosA0[0x82] = psxBios_sys_a0_82;
3422 //biosA0[0x83] = psxBios_sys_a0_83;
3423 //biosA0[0x84] = psxBios_sys_a0_84;
3424 //biosA0[0x85] = psxBios__96_CdStop;
3425 //biosA0[0x86] = psxBios_sys_a0_86;
3426 //biosA0[0x87] = psxBios_sys_a0_87;
3427 //biosA0[0x88] = psxBios_sys_a0_88;
3428 //biosA0[0x89] = psxBios_sys_a0_89;
3429 //biosA0[0x8a] = psxBios_sys_a0_8a;
3430 //biosA0[0x8b] = psxBios_sys_a0_8b;
3431 //biosA0[0x8c] = psxBios_sys_a0_8c;
3432 //biosA0[0x8d] = psxBios_sys_a0_8d;
3433 //biosA0[0x8e] = psxBios_sys_a0_8e;
3434 //biosA0[0x8f] = psxBios_sys_a0_8f;
3435 biosA0[0x90] = hleExc0_1_2;
3436 biosA0[0x91] = hleExc0_0_2;
3437 biosA0[0x92] = hleExc0_1_1;
3438 biosA0[0x93] = hleExc0_0_1;
3439 //biosA0[0x94] = psxBios_sys_a0_94;
3440 //biosA0[0x95] = psxBios_sys_a0_95;
3441 //biosA0[0x96] = psxBios_AddCDROMDevice;
3442 //biosA0[0x97] = psxBios_AddMemCardDevide;
3443 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3444 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3445 //biosA0[0x9a] = psxBios_sys_a0_9a;
3446 //biosA0[0x9b] = psxBios_sys_a0_9b;
3447 biosA0[0x9c] = psxBios_SetConf;
3448 biosA0[0x9d] = psxBios_GetConf;
3449 //biosA0[0x9e] = psxBios_sys_a0_9e;
3450 biosA0[0x9f] = psxBios_SetMem;
3451 //biosA0[0xa0] = psxBios__boot;
3452 //biosA0[0xa1] = psxBios_SystemError;
3453 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3454 biosA0[0xa3] = psxBios_DequeueCdIntr;
3455 //biosA0[0xa4] = psxBios_sys_a0_a4;
3456 //biosA0[0xa5] = psxBios_ReadSector;
3457 biosA0[0xa6] = psxBios_get_cd_status;
3458 //biosA0[0xa7] = psxBios_bufs_cb_0;
3459 //biosA0[0xa8] = psxBios_bufs_cb_1;
3460 //biosA0[0xa9] = psxBios_bufs_cb_2;
3461 //biosA0[0xaa] = psxBios_bufs_cb_3;
3462 biosA0[0xab] = psxBios__card_info;
3463 biosA0[0xac] = psxBios__card_load;
3464 //biosA0[0axd] = psxBios__card_auto;
3465 //biosA0[0xae] = psxBios_bufs_cd_4;
3466 //biosA0[0xaf] = psxBios_sys_a0_af;
3467 //biosA0[0xb0] = psxBios_sys_a0_b0;
3468 //biosA0[0xb1] = psxBios_sys_a0_b1;
3469 //biosA0[0xb2] = psxBios_do_a_long_jmp
3470 //biosA0[0xb3] = psxBios_sys_a0_b3;
3471 biosA0[0xb4] = psxBios_GetSystemInfo;
3472 //*******************B0 CALLS****************************
3473 biosB0[0x00] = psxBios_SysMalloc;
3474 //biosB0[0x01] = psxBios_sys_b0_01;
3475 biosB0[0x02] = psxBios_SetRCnt;
3476 biosB0[0x03] = psxBios_GetRCnt;
3477 biosB0[0x04] = psxBios_StartRCnt;
3478 biosB0[0x05] = psxBios_StopRCnt;
3479 biosB0[0x06] = psxBios_ResetRCnt;
3480 biosB0[0x07] = psxBios_DeliverEvent;
3481 biosB0[0x08] = psxBios_OpenEvent;
3482 biosB0[0x09] = psxBios_CloseEvent;
3483 biosB0[0x0a] = psxBios_WaitEvent;
3484 biosB0[0x0b] = psxBios_TestEvent;
3485 biosB0[0x0c] = psxBios_EnableEvent;
3486 biosB0[0x0d] = psxBios_DisableEvent;
3487 biosB0[0x0e] = psxBios_OpenTh;
3488 biosB0[0x0f] = psxBios_CloseTh;
3489 biosB0[0x10] = psxBios_ChangeTh;
3490 //biosB0[0x11] = psxBios_psxBios_b0_11;
3491 biosB0[0x12] = psxBios_InitPAD;
3492 biosB0[0x13] = psxBios_StartPAD;
3493 biosB0[0x14] = psxBios_StopPAD;
3494 biosB0[0x15] = psxBios_PAD_init;
3495 biosB0[0x16] = psxBios_PAD_dr;
3496 biosB0[0x17] = psxBios_ReturnFromException;
3497 biosB0[0x18] = psxBios_ResetEntryInt;
3498 biosB0[0x19] = psxBios_HookEntryInt;
3499 //biosB0[0x1a] = psxBios_sys_b0_1a;
3500 //biosB0[0x1b] = psxBios_sys_b0_1b;
3501 //biosB0[0x1c] = psxBios_sys_b0_1c;
3502 //biosB0[0x1d] = psxBios_sys_b0_1d;
3503 //biosB0[0x1e] = psxBios_sys_b0_1e;
3504 //biosB0[0x1f] = psxBios_sys_b0_1f;
3505 biosB0[0x20] = psxBios_UnDeliverEvent;
3506 //biosB0[0x21] = psxBios_sys_b0_21;
3507 //biosB0[0x22] = psxBios_sys_b0_22;
3508 //biosB0[0x23] = psxBios_sys_b0_23;
3509 //biosB0[0x24] = psxBios_sys_b0_24;
3510 //biosB0[0x25] = psxBios_sys_b0_25;
3511 //biosB0[0x26] = psxBios_sys_b0_26;
3512 //biosB0[0x27] = psxBios_sys_b0_27;
3513 //biosB0[0x28] = psxBios_sys_b0_28;
3514 //biosB0[0x29] = psxBios_sys_b0_29;
3515 //biosB0[0x2a] = psxBios_sys_b0_2a;
3516 //biosB0[0x2b] = psxBios_sys_b0_2b;
3517 //biosB0[0x2c] = psxBios_sys_b0_2c;
3518 //biosB0[0x2d] = psxBios_sys_b0_2d;
3519 //biosB0[0x2e] = psxBios_sys_b0_2e;
3520 //biosB0[0x2f] = psxBios_sys_b0_2f;
3521 //biosB0[0x30] = psxBios_sys_b0_30;
3522 //biosB0[0x31] = psxBios_sys_b0_31;
3523 biosB0[0x32] = psxBios_open;
3524 biosB0[0x33] = psxBios_lseek;
3525 biosB0[0x34] = psxBios_read;
3526 biosB0[0x35] = psxBios_write;
3527 biosB0[0x36] = psxBios_close;
3528 //biosB0[0x37] = psxBios_ioctl;
3529 //biosB0[0x38] = psxBios_exit;
3530 //biosB0[0x39] = psxBios_sys_b0_39;
3531 //biosB0[0x3a] = psxBios_getc;
3532 //biosB0[0x3b] = psxBios_putc;
3533 biosB0[0x3c] = psxBios_getchar;
3534 biosB0[0x3d] = psxBios_putchar;
3535 //biosB0[0x3e] = psxBios_gets;
3536 biosB0[0x3f] = psxBios_puts;
3537 //biosB0[0x40] = psxBios_cd;
3538 biosB0[0x41] = psxBios_format;
3539 biosB0[0x42] = psxBios_firstfile;
3540 biosB0[0x43] = psxBios_nextfile;
3541 biosB0[0x44] = psxBios_rename;
3542 biosB0[0x45] = psxBios_delete;
3543 //biosB0[0x46] = psxBios_undelete;
3544 //biosB0[0x47] = psxBios_AddDevice;
3545 //biosB0[0x48] = psxBios_RemoteDevice;
3546 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3547 biosB0[0x4a] = psxBios_InitCARD;
3548 biosB0[0x4b] = psxBios_StartCARD;
3549 biosB0[0x4c] = psxBios_StopCARD;
3550 //biosB0[0x4d] = psxBios_sys_b0_4d;
3551 biosB0[0x4e] = psxBios__card_write;
3552 biosB0[0x4f] = psxBios__card_read;
3553 biosB0[0x50] = psxBios__new_card;
3554 biosB0[0x51] = psxBios_Krom2RawAdd;
3555 //biosB0[0x52] = psxBios_sys_b0_52;
3556 //biosB0[0x53] = psxBios_sys_b0_53;
3557 //biosB0[0x54] = psxBios__get_errno;
3558 biosB0[0x55] = psxBios__get_error;
3559 biosB0[0x56] = psxBios_GetC0Table;
3560 biosB0[0x57] = psxBios_GetB0Table;
3561 biosB0[0x58] = psxBios__card_chan;
3562 //biosB0[0x59] = psxBios_sys_b0_59;
3563 //biosB0[0x5a] = psxBios_sys_b0_5a;
3564 biosB0[0x5b] = psxBios_ChangeClearPad;
3565 biosB0[0x5c] = psxBios__card_status;
3566 biosB0[0x5d] = psxBios__card_wait;
3567 //*******************C0 CALLS****************************
3568 biosC0[0x00] = psxBios_InitRCnt;
3569 biosC0[0x01] = psxBios_InitException;
3570 biosC0[0x02] = psxBios_SysEnqIntRP;
3571 biosC0[0x03] = psxBios_SysDeqIntRP;
3572 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3573 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3574 //biosC0[0x06] = psxBios_ExceptionHandler;
3575 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3576 biosC0[0x08] = psxBios_SysInitMemory;
3577 //biosC0[0x09] = psxBios_SysInitKMem;
3578 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3579 //biosC0[0x0b] = psxBios_SystemError;
3580 biosC0[0x0c] = psxBios_InitDefInt;
3581 //biosC0[0x0d] = psxBios_sys_c0_0d;
3582 //biosC0[0x0e] = psxBios_sys_c0_0e;
3583 //biosC0[0x0f] = psxBios_sys_c0_0f;
3584 //biosC0[0x10] = psxBios_sys_c0_10;
3585 //biosC0[0x11] = psxBios_sys_c0_11;
3586 //biosC0[0x12] = psxBios_InstallDevices;
3587 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3588 //biosC0[0x14] = psxBios_sys_c0_14;
3589 //biosC0[0x15] = psxBios__cdevinput;
3590 //biosC0[0x16] = psxBios__cdevscan;
3591 //biosC0[0x17] = psxBios__circgetc;
3592 //biosC0[0x18] = psxBios__circputc;
3593 //biosC0[0x19] = psxBios_ioabort;
3594 //biosC0[0x1a] = psxBios_sys_c0_1a
3595 //biosC0[0x1b] = psxBios_KernelRedirect;
3596 //biosC0[0x1c] = psxBios_PatchAOTable;
3597 //************** THE END ***************************************
3600 memset(FDesc, 0, sizeof(FDesc));
3602 // somewhat pretend to be a SCPH1001 BIOS
3603 // some games look for these and take an exception if they're missing
3604 rom32 = (u32 *)psxR;
3605 rom32[0x100/4] = SWAP32(0x19951204);
3606 rom32[0x104/4] = SWAP32(3);
3607 strcpy(psxR + 0x108, "PCSX authors");
3608 strcpy(psxR + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3609 strcpy(psxR + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3610 strcpy(psxR + 0x7ff54, "GPL-2.0-or-later");
3613 len = 0x80000 - 0x66000;
3614 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3615 len = 0x80000 - 0x69d68;
3616 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3618 // trap attempts to call bios directly
3619 rom32[0x00000/4] = HLEOP(hleop_dummy);
3620 rom32[0x00180/4] = HLEOP(hleop_dummy);
3621 rom32[0x3fffc/4] = HLEOP(hleop_dummy);
3622 rom32[0x65ffc/4] = HLEOP(hleop_dummy);
3623 rom32[0x7ff2c/4] = HLEOP(hleop_dummy);
3625 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3626 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3627 Here are some examples of games not working with this fix in place :
3628 R-type won't get past the Irem logo if not implemented.
3629 Crash Team Racing will softlock after the Sony logo.
3632 ram32 = (u32 *)psxM;
3633 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3634 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3635 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3636 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3638 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3639 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3641 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3642 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3643 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3644 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3646 ram32[0x00a0/4] = HLEOP(hleop_a0);
3647 ram32[0x00b0/4] = HLEOP(hleop_b0);
3648 ram32[0x00c0/4] = HLEOP(hleop_c0);
3650 setup_tt(4, 16, 0x801fff00);
3651 DeliverEvent(0xf0000003, 0x0010);
3653 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3654 strcpy((char *)&ram32[0xeff0/4], "bu");
3656 // default exception handler chains
3657 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3658 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3659 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3660 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3661 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3662 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3663 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3664 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3668 // fill the api jumptables with fake entries as some games patch them
3669 // (or rather the funcs listed there)
3670 ptr = (u32 *)&psxM[A_A0_TABLE];
3671 for (i = 0; i < 256; i++)
3672 ptr[i] = SWAP32(0x1000);
3674 ptr = (u32 *)&psxM[A_B0_TABLE];
3675 for (i = 0; i < 256; i++)
3676 ptr[i] = SWAP32(0x2000);
3677 // B(5b) is special because games patch (sometimes even jump to)
3678 // code at fixed offsets from it, nocash lists offsets:
3679 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3680 // call: +7a0=4b70, +884=4c54, +894=4c64
3681 ptr[0x5b] = SWAP32(0x43d0);
3682 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3684 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3685 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3686 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3688 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3689 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3691 ptr = (u32 *)&psxM[A_C0_TABLE];
3692 for (i = 0; i < 256/2; i++)
3693 ptr[i] = SWAP32(0x3000);
3694 ptr[6] = SWAP32(A_EXCEPTION);
3697 ram32[0x1000/4] = HLEOP(hleop_dummy);
3698 ram32[0x2000/4] = HLEOP(hleop_dummy);
3699 ram32[0x3000/4] = HLEOP(hleop_dummy);
3700 ram32[0x8000/4] = HLEOP(hleop_execret);
3702 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3703 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3704 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3705 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3706 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3707 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3708 ram32[A_RND_SEED/4] = SWAPu32(0x24040001); // was 0xac20cc00
3711 void psxBiosShutdown() {
3714 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 stack) {
3717 if (tcb_cnt != 4 || evcb_cnt != 16) {
3718 setup_tt(tcb_cnt, evcb_cnt, stack);
3719 DeliverEvent(0xf0000003, 0x0010);
3721 storeRam32(A_CONF_SP, stack);
3724 #define psxBios_PADpoll(pad) { \
3725 PAD##pad##_startPoll(pad); \
3726 pad_buf##pad[0] = 0; \
3727 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3728 if (!(pad_buf##pad[1] & 0x0f)) { \
3731 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3733 PAD##pad##_poll(0); \
3735 while (bufcount--) { \
3736 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3740 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3744 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3745 psxBios_ReturnFromException();
3751 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3752 // so this is only partially implemented
3753 void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3755 u32 cdrom_dma_ack_enable = 1; // a000b93c
3756 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3759 void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3762 //PSXBIOS_LOG("%s\n", __func__);
3764 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3765 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3766 //if (--cdrom_irq_counter == 0) // 0xa0009180
3767 // DeliverEvent(0xf0000003, 0x10);
3771 mips_return_c(ret, 20);
3774 void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3776 u32 cdrom_irq_ack_enable = 1; // a000b938
3777 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3780 void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3783 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3784 PSXBIOS_LOG("%s TODO\n", __func__);
3787 mips_return_c(ret, 20);
3790 void hleExc0_2_2_syscall() // not in any A/B/C table
3792 u32 tcbPtr = loadRam32(A_TT_PCB);
3793 TCB *tcb = loadRam32ptr(tcbPtr);
3794 u32 code = (SWAP32(tcb->cause) & 0x3c) >> 2;
3796 if (code != R3000E_Syscall) {
3798 DeliverEvent(0xf0000010, 0x1000);
3799 //psxBios_SystemErrorUnresolvedException();
3801 mips_return_c(0, 17);
3805 //printf("%s c=%d a0=%d\n", __func__, code, SWAP32(tcb->reg[4]));
3806 tcb->epc += SWAP32(4);
3807 switch (SWAP32(tcb->reg[4])) { // a0
3811 case 1: { // EnterCritical - disable irqs
3812 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3813 tcb->reg[2] = SWAP32(was_enabled);
3814 tcb->sr &= SWAP32(~0x404);
3817 case 2: // ExitCritical - enable irqs
3818 tcb->sr |= SWAP32(0x404);
3821 case 3: { // ChangeThreadSubFunction
3822 u32 tcbPtr = loadRam32(A_TT_PCB);
3823 storeRam32(tcbPtr, SWAP32(tcb->reg[5])); // a1
3827 DeliverEvent(0xf0000010, 0x4000);
3831 psxBios_ReturnFromException();
3834 void hleExc1_0_1(void)
3836 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3837 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3840 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3843 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3844 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3847 mips_return_c(ret, 22);
3850 void hleExc1_0_2(void)
3852 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3855 void hleExc1_1_1(void)
3857 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3858 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3861 void hleExc1_1_2(void)
3863 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3866 void hleExc1_2_1(void)
3868 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3869 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3872 void hleExc1_2_2(void)
3874 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3877 void hleExc1_3_1(void)
3879 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3880 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3883 void hleExc1_3_2(void)
3885 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3888 void hleExc3_0_2_defint(void)
3890 static const struct {
3901 { 6, 6 }, // rcnt2 (bug)
3906 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3907 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3908 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3913 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3916 void hleExcPadCard1(void)
3918 if (loadRam32(A_PAD_IRQR_ENA)) {
3919 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3920 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
3926 if (loadRam32(A_PAD_DR_DST))
3929 if (loadRam32(A_PAD_ACK_VBL))
3930 psxHwWrite16(0x1f801070, ~1);
3931 if (loadRam32(A_CARD_IRQR_ENA)) {
3935 mips_return_c(0, 18);
3938 void hleExcPadCard2(void)
3940 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
3941 mips_return_c(ret, 15);
3944 void psxBiosException() {
3945 u32 tcbPtr = loadRam32(A_TT_PCB);
3946 u32 *chains = loadRam32ptr(A_TT_ExCB);
3947 TCB *tcb = loadRam32ptr(tcbPtr);
3953 // $at, $v0, $v1 already saved by the mips code at A_EXCEPTION
3954 for (i = 4; i < 32; i++) {
3957 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
3959 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
3960 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
3961 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
3962 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
3963 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
3964 sp = fp = loadRam32(A_EXC_SP);
3968 // do the chains (always 4)
3969 for (c = lim = 0; c < 4; c++) {
3970 if (chains[c * 2] == 0)
3972 ptr = SWAP32(chains[c * 2]);
3973 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
3974 chain = castRam32ptr(ptr);
3979 softCallInException(SWAP32(chain[2]));
3980 if (returned_from_exception())
3983 if (v0 == 0 || chain[1] == 0)
3985 softCallInException(SWAP32(chain[1]));
3986 if (returned_from_exception())
3992 // return from exception (custom or default)
3994 ptr = loadRam32(A_EEXIT_PTR);
3995 if (ptr != A_EEXIT_DEF) {
3996 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
3997 longjmp_load(jmp_buf);
4002 psxBios_ReturnFromException();
4005 #define bfreeze(ptr, size) { \
4006 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
4007 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
4011 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
4012 #define bfreezel(ptr) bfreeze(ptr, sizeof(*(ptr)))
4014 void psxBiosFreeze(int Mode) {