1 /***************************************************************************
2 * Copyright (C) 2019 Ryan Schultz, PCSX-df Team, PCSX team, gameblabla, *
3 * dmitrysmagin, senquack *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
19 ***************************************************************************/
21 /* Gameblabla 2018-2019 :
22 * Numerous changes to bios calls as well as improvements in order to conform to nocash's findings
23 * for the PSX bios calls. Thanks senquack for helping out with some of the changes
24 * and helping to spot issues and refine my patches.
28 * Internal simulated HLE BIOS.
31 // TODO: implement all system calls, count the exact CPU cycles of system calls.
38 #include "psxinterpreter.h"
42 //#define PSXBIOS_LOG printf
43 #define PSXBIOS_LOG(...)
46 #define PTR_1 (void *)(size_t)1
48 char *biosA0n[256] = {
50 "open", "lseek", "read", "write",
51 "close", "ioctl", "exit", "sys_a0_07",
52 "getc", "putc", "todigit", "atof",
53 "strtoul", "strtol", "abs", "labs",
55 "atoi", "atol", "atob", "setjmp",
56 "longjmp", "strcat", "strncat", "strcmp",
57 "strncmp", "strcpy", "strncpy", "strlen",
58 "index", "rindex", "strchr", "strrchr",
60 "strpbrk", "strspn", "strcspn", "strtok",
61 "strstr", "toupper", "tolower", "bcopy",
62 "bzero", "bcmp", "memcpy", "memset",
63 "memmove", "memcmp", "memchr", "rand",
65 "srand", "qsort", "strtod", "malloc",
66 "free", "lsearch", "bsearch", "calloc",
67 "realloc", "InitHeap", "_exit", "getchar",
68 "putchar", "gets", "puts", "printf",
70 "SystemErrorUnresolvedException", "LoadTest", "Load", "Exec",
71 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
72 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
73 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
75 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
76 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
77 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
78 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
80 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
81 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
82 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
83 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
85 "_bu_init", "_96_init", "CdRemove", "sys_a0_73",
86 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
87 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
88 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
90 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
91 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
92 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
93 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
95 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
96 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
97 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
98 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
100 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
101 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
102 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
103 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
105 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
109 char *biosB0n[256] = {
111 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
112 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
113 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
114 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
116 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
117 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
118 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
119 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
121 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
122 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
123 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
124 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
126 "sys_b0_30", "sys_b0_31", "open", "lseek",
127 "read", "write", "close", "ioctl",
128 "exit", "sys_b0_39", "getc", "putc",
129 "getchar", "putchar", "gets", "puts",
131 "cd", "format", "firstfile", "nextfile",
132 "rename", "delete", "undelete", "AddDevice",
133 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
134 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
136 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
137 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
138 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
139 "_card_status", "_card_wait",
142 char *biosC0n[256] = {
144 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
145 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
146 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
147 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
149 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
150 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
151 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
155 //#define r0 (psxRegs.GPR.n.r0)
156 #define at (psxRegs.GPR.n.at)
157 #define v0 (psxRegs.GPR.n.v0)
158 #define v1 (psxRegs.GPR.n.v1)
159 #define a0 (psxRegs.GPR.n.a0)
160 #define a1 (psxRegs.GPR.n.a1)
161 #define a2 (psxRegs.GPR.n.a2)
162 #define a3 (psxRegs.GPR.n.a3)
163 #define t0 (psxRegs.GPR.n.t0)
164 #define t1 (psxRegs.GPR.n.t1)
165 #define t2 (psxRegs.GPR.n.t2)
166 #define t3 (psxRegs.GPR.n.t3)
167 #define t4 (psxRegs.GPR.n.t4)
168 #define t5 (psxRegs.GPR.n.t5)
169 #define t6 (psxRegs.GPR.n.t6)
170 #define t7 (psxRegs.GPR.n.t7)
171 #define t8 (psxRegs.GPR.n.t8)
172 #define t9 (psxRegs.GPR.n.t9)
173 #define s0 (psxRegs.GPR.n.s0)
174 #define s1 (psxRegs.GPR.n.s1)
175 #define s2 (psxRegs.GPR.n.s2)
176 #define s3 (psxRegs.GPR.n.s3)
177 #define s4 (psxRegs.GPR.n.s4)
178 #define s5 (psxRegs.GPR.n.s5)
179 #define s6 (psxRegs.GPR.n.s6)
180 #define s7 (psxRegs.GPR.n.s7)
181 #define k0 (psxRegs.GPR.n.k0)
182 #define k1 (psxRegs.GPR.n.k1)
183 #define gp (psxRegs.GPR.n.gp)
184 #define sp (psxRegs.GPR.n.sp)
185 #define fp (psxRegs.GPR.n.fp)
186 #define ra (psxRegs.GPR.n.ra)
187 #define pc0 (psxRegs.pc)
189 #define Ra0 ((char *)PSXM(a0))
190 #define Ra1 ((char *)PSXM(a1))
191 #define Ra2 ((char *)PSXM(a2))
192 #define Ra3 ((char *)PSXM(a3))
193 #define Rv0 ((char *)PSXM(v0))
194 #define Rsp ((char *)PSXM(sp))
205 #define EvStUNUSED 0x0000
206 #define EvStDISABLED 0x1000
207 #define EvStACTIVE 0x2000
208 #define EvStALREADY 0x4000
210 #define EvMdCALL 0x1000
211 #define EvMdMARK 0x2000
234 u32 _sp, _fp, _gp, ret, base;
254 // todo: FileDesc layout is wrong
255 // todo: get rid of these globals
256 static FileDesc FDesc[32];
257 static char ffile[64];
259 static char cdir[8*8+8];
262 // fixed RAM offsets, SCPH1001 compatible
263 #define A_TT_ExCB 0x0100
264 #define A_TT_PCB 0x0108
265 #define A_TT_TCB 0x0110
266 #define A_TT_EvCB 0x0120
267 #define A_A0_TABLE 0x0200
268 #define A_B0_TABLE 0x0874
269 #define A_C0_TABLE 0x0674
270 #define A_SYSCALL 0x0650
271 #define A_EXCEPTION 0x0c80
272 #define A_EXC_SP 0x6cf0
273 #define A_EEXIT_DEF 0x6cf4
274 #define A_KMALLOC_PTR 0x7460
275 #define A_KMALLOC_SIZE 0x7464
276 #define A_KMALLOC_END 0x7468
277 #define A_PADCRD_CHN_E 0x74a8 // pad/card irq chain entry, see hleExcPadCard1()
278 #define A_PAD_IRQR_ENA 0x74b8 // pad read on vint irq (nocash 'pad_enable_flag')
279 #define A_CARD_IRQR_ENA 0x74bc // same for card
280 #define A_PAD_INBUF 0x74c8 // 2x buffers for rx pad data
281 #define A_PAD_OUTBUF 0x74d0 // 2x buffers for tx pad data
282 #define A_PAD_IN_LEN 0x74d8
283 #define A_PAD_OUT_LEN 0x74e0
284 #define A_PAD_DR_DST 0x74c4
285 #define A_CARD_CHAN1 0x7500
286 #define A_PAD_DR_BUF1 0x7570
287 #define A_PAD_DR_BUF2 0x7598
288 #define A_EEXIT_PTR 0x75d0
289 #define A_EXC_STACK 0x85d8 // exception stack top
290 #define A_RCNT_VBL_ACK 0x8600
291 #define A_PAD_ACK_VBL 0x8914 // enable vint ack by pad reading code
292 #define A_HEAP_BASE 0x9000
293 #define A_HEAP_SIZE 0x9004
294 #define A_HEAP_END 0x9008
295 #define A_HEAP_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 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
389 while (pc0 != 0x80001000 && ++lim < 1000000)
390 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
392 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
395 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
397 psxRegs.CP0.n.SR |= ssr & 0x404;
400 static inline void softCallInException(u32 pc) {
405 assert(ra != 0x80001000);
406 if (ra == 0x80001000)
410 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
412 while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 1000000)
413 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
415 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
418 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
419 if (pc0 == 0x80001000)
423 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
424 static u32 DeliverEvent(u32 class, u32 spec);
425 static u32 UnDeliverEvent(u32 class, u32 spec);
426 static void CloseEvent(u32 ev);
431 // System calls A0 */
434 #define buread(Ra1, mcd, length) { \
435 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); \
436 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
437 memcpy(Ra1, ptr, length); \
438 psxCpu->Clear(a1, (length + 3) / 4); \
439 if (FDesc[1 + mcd].mode & 0x8000) { \
440 DeliverEvent(0xf0000011, 0x0004); \
441 DeliverEvent(0xf4000001, 0x0004); \
444 FDesc[1 + mcd].offset += v0; \
447 #define buwrite(Ra1, mcd, length) { \
448 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
449 PSXBIOS_LOG("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
450 ptr = Mcd##mcd##Data + offset; \
451 memcpy(ptr, Ra1, length); \
452 FDesc[1 + mcd].offset += length; \
453 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
454 if (FDesc[1 + mcd].mode & 0x8000) { \
455 DeliverEvent(0xf0000011, 0x0004); \
456 DeliverEvent(0xf4000001, 0x0004); \
461 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
462 /* For some strange reason, the returned character is sign-expanded; */
463 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
464 /* TODO FIX ME : Properly implement this behaviour */
465 void psxBios_getc(void) // 0x03, 0x35
470 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
474 if (pa1 != INVALID_PTR) {
476 case 2: buread(pa1, 1, 1); break;
477 case 3: buread(pa1, 2, 1); break;
484 /* Copy of psxBios_write, except size is 1. */
485 void psxBios_putc(void) // 0x09, 0x3B
490 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
493 if (pa1 == INVALID_PTR) {
498 if (a0 == 1) { // stdout
499 char *ptr = (char *)pa1;
503 printf("%c", *ptr++); a2--;
509 case 2: buwrite(pa1, 1, 1); break;
510 case 3: buwrite(pa1, 2, 1); break;
516 void psxBios_todigit(void) // 0x0a
520 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
523 if (c >= 0x30 && c < 0x3A) {
526 else if (c > 0x60 && c < 0x7B) {
529 else if (c > 0x40 && c < 0x5B) {
532 else if (c >= 0x80) {
543 void psxBios_abs() { // 0x0e
544 if ((s32)a0 < 0) v0 = -(s32)a0;
549 void psxBios_labs() { // 0x0f
553 void psxBios_atoi() { // 0x10
555 char *p = (char *)Ra0;
559 case ' ': case '\t': continue;
566 while (*p >= '0' && *p <= '9') {
567 n = n * 10 + *p++ - '0';
574 void psxBios_atol() { // 0x11
584 static void psxBios_setjmp() { // 0x13
585 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
588 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
590 jmp_buf->ra_ = SWAP32(ra);
591 jmp_buf->sp_ = SWAP32(sp);
592 jmp_buf->fp_ = SWAP32(fp);
593 for (i = 0; i < 8; i++) // s0-s7
594 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
595 jmp_buf->gp_ = SWAP32(gp);
597 mips_return_c(0, 15);
600 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
604 ra = SWAP32(jmp_buf->ra_);
605 sp = SWAP32(jmp_buf->sp_);
606 fp = SWAP32(jmp_buf->fp_);
607 for (i = 0; i < 8; i++) // s0-s7
608 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
609 gp = SWAP32(jmp_buf->gp_);;
612 void psxBios_longjmp() { // 0x14
613 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
615 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
616 longjmp_load(jmp_buf);
617 mips_return_c(a1, 15);
620 void psxBios_strcat() { // 0x15
621 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
624 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
626 if (a0 == 0 || a1 == 0)
634 while ((*p1++ = *p2++) != '\0');
639 void psxBios_strncat() { // 0x16
640 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
644 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
646 if (a0 == 0 || a1 == 0)
654 while ((*p1++ = *p2++) != '\0') {
664 void psxBios_strcmp() { // 0x17
665 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
667 if (a0 == 0 && a1 == 0)
673 else if (a0 == 0 && a1 != 0)
679 else if (a0 != 0 && a1 == 0)
686 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
689 while (*p1 == *p2++) {
708 void psxBios_strncmp() { // 0x18
709 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
711 if (a0 == 0 && a1 == 0)
717 else if (a0 == 0 && a1 != 0)
723 else if (a0 != 0 && a1 == 0)
730 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
733 while (--n >= 0 && *p1 == *p2++) {
737 v1 = a2 - ((a2-n) - 1);
745 v0 = (n < 0 ? 0 : *p1 - *--p2);
747 v1 = a2 - ((a2-n) - 1);
753 void psxBios_strcpy() { // 0x19
754 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
755 if (a0 == 0 || a1 == 0)
761 while ((*p1++ = *p2++) != '\0');
766 void psxBios_strncpy() { // 0x1a
767 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
769 if (a0 == 0 || a1 == 0)
775 for (i = 0; i < n; i++) {
776 if ((*p1++ = *p2++) == '\0') {
788 void psxBios_strlen() { // 0x1b
789 char *p = (char *)Ra0;
800 void psxBios_index() { // 0x1c
801 char *p = (char *)Ra0;
811 v0 = a0 + (p - (char *)Ra0);
815 } while (*p++ != '\0');
820 void psxBios_rindex() { // 0x1d
821 char *p = (char *)Ra0;
831 v0 = a0 + (p - (char *)Ra0);
832 } while (*p++ != '\0');
837 void psxBios_strchr() { // 0x1e
841 void psxBios_strrchr() { // 0x1f
845 void psxBios_strpbrk() { // 0x20
846 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
848 while ((c = *p1++) != '\0') {
849 for (scanp = p2; (sc = *scanp++) != '\0';) {
851 v0 = a0 + (p1 - 1 - (char *)Ra0);
858 // BUG: return a0 instead of NULL if not found
862 void psxBios_strspn() { // 0x21
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_strcspn() { // 0x22
876 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
877 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
878 if (*p2 != '\0') break;
881 v0 = p1 - (char *)Ra0; pc0 = ra;
884 void psxBios_strtok() { // 0x23
885 char *pcA0 = (char *)Ra0;
886 char *pcRet = strtok(pcA0, (char *)Ra1);
888 v0 = a0 + pcRet - pcA0;
894 void psxBios_strstr() { // 0x24
895 char *p = (char *)Ra0, *p1, *p2;
901 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
906 v0 = a0 + (p - (char *)Ra0);
917 void psxBios_toupper() { // 0x25
918 v0 = (s8)(a0 & 0xff);
919 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
923 void psxBios_tolower() { // 0x26
924 v0 = (s8)(a0 & 0xff);
925 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
929 static void do_memset(u32 dst, u32 v, s32 len)
935 if (db != INVALID_PTR)
939 psxCpu->Clear(dst, (len + 3) / 4);
942 static void do_memcpy(u32 dst, u32 src, s32 len)
944 u32 d = dst, s = src;
947 const u8 *sb = PSXM(s);
949 if (db != INVALID_PTR && sb != INVALID_PTR)
954 psxCpu->Clear(dst, (len + 3) / 4);
957 static void psxBios_memcpy();
959 static void psxBios_bcopy() { // 0x27 - memcpy with args swapped
960 //PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x27], a0, a1, a2);
961 u32 ret = a0, cycles = 0;
962 if (a0 == 0) // ...but it checks src this time
969 do_memcpy(a1, a0, a2);
975 mips_return_c(ret, cycles + 5);
978 static void psxBios_bzero() { // 0x28
979 /* Same as memset here (See memset below) */
980 u32 ret = a0, cycles;
981 if (a0 == 0 || (s32)a1 <= 0)
986 do_memset(a0, 0, a1);
990 // todo: many more cycles due to uncached bios mem
991 mips_return_c(ret, cycles + 5);
994 void psxBios_bcmp() { // 0x29
995 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
997 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
999 while ((s32)a2-- > 0) {
1000 if (*p1++ != *p2++) {
1001 v0 = *p1 - *p2; // BUG: compare the NEXT byte
1010 static void psxBios_memcpy() { // 0x2a
1011 u32 ret = a0, cycles = 0;
1014 mips_return_c(0, 4);
1019 do_memcpy(a0, a1, a2);
1025 mips_return_c(ret, cycles + 5);
1028 static void psxBios_memset() { // 0x2b
1029 u32 ret = a0, cycles;
1030 if (a0 == 0 || (s32)a2 <= 0)
1032 mips_return_c(0, 6);
1035 do_memset(a0, a1, a2);
1039 // todo: many more cycles due to uncached bios mem
1040 mips_return_c(ret, cycles + 5);
1043 void psxBios_memmove() { // 0x2c
1044 u32 ret = a0, cycles = 0;
1047 mips_return_c(0, 4);
1051 if ((s32)a2 > 0 && a0 > a1 && a0 < a1 + a2) {
1052 u32 dst = a0, len = a2 + 1;
1055 while ((s32)a2 >= 0) { // BUG: copies one more byte here
1056 const u8 *sb = PSXM(a1);
1058 if (db != INVALID_PTR && sb != INVALID_PTR)
1064 psxCpu->Clear(dst, (len + 3) / 4);
1065 cycles = 10 + len * 8;
1066 } else if ((s32)a2 > 0) {
1067 do_memcpy(a0, a1, a2);
1073 mips_return_c(ret, cycles + 5);
1076 void psxBios_memcmp() { // 0x2d
1080 void psxBios_memchr() { // 0x2e
1081 char *p = (char *)Ra0;
1083 if (a0 == 0 || a2 > 0x7FFFFFFF)
1089 while ((s32)a2-- > 0) {
1090 if (*p++ != (s8)a1) continue;
1091 v0 = a0 + (p - (char *)Ra0 - 1);
1099 static void psxBios_rand() { // 0x2f
1100 u32 s = loadRam32(A_RND_SEED) * 1103515245 + 12345;
1101 storeRam32(A_RND_SEED, s);
1103 mips_return_c((s >> 16) & 0x7fff, 12+37);
1106 static void psxBios_srand() { // 0x30
1107 storeRam32(A_RND_SEED, a0);
1108 mips_return_void_c(3);
1111 static u32 qscmpfunc, qswidth;
1113 static inline int qscmp(char *a, char *b) {
1116 a0 = sa0 + (a - (char *)PSXM(sa0));
1117 a1 = sa0 + (b - (char *)PSXM(sa0));
1119 softCall(qscmpfunc);
1125 static inline void qexchange(char *i, char *j) {
1136 static inline void q3exchange(char *i, char *j, char *k) {
1148 static void qsort_main(char *a, char *l) {
1149 char *i, *j, *lp, *hp;
1154 if ((n = l - a) <= qswidth)
1156 n = qswidth * (n / (2 * qswidth));
1162 if ((c = qscmp(i, lp)) == 0) {
1163 qexchange(i, lp -= qswidth);
1174 if ((c = qscmp(hp, j)) == 0) {
1175 qexchange(hp += qswidth, j);
1180 q3exchange(i, hp += qswidth, j);
1194 if (lp - a >= l - hp) {
1195 qsort_main(hp + qswidth, l);
1204 q3exchange(j, lp -= qswidth, i);
1209 void psxBios_qsort() { // 0x31
1212 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1217 // this isn't how the real bios works, but maybe good enough
1218 static void psxBios_malloc() { // 0x33
1219 u32 *heap_addr, *heap_end;
1220 u32 *chunk, *newchunk = NULL;
1221 unsigned int dsize = 0, csize, cstat;
1223 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x33], a0);
1224 heap_addr = loadRam32ptr(A_HEAP_BASE);
1225 heap_end = loadRam32ptr(A_HEAP_END);
1226 if (heap_addr >= heap_end) {
1232 // scan through heap and combine free chunks of space
1235 while(chunk < heap_end) {
1236 // get size and status of actual chunk
1237 csize = ((u32)*chunk) & 0xfffffffc;
1238 cstat = ((u32)*chunk) & 1;
1240 // most probably broken heap descriptor
1241 // this fixes Burning Road
1244 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1249 // it's a free chunk
1254 colflag = 1; // let's begin a new collection of free memory
1256 else dsize += (csize+4); // add the new size including header
1258 // not a free chunk: did we start a collection ?
1260 if(colflag == 1) { // collection is over
1262 *newchunk = SWAP32(dsize | 1);
1267 chunk = (u32*)((uptr)chunk + csize + 4);
1269 // if neccessary free memory on end of heap
1271 *newchunk = SWAP32(dsize | 1);
1274 csize = ((u32)*chunk) & 0xfffffffc;
1275 cstat = ((u32)*chunk) & 1;
1276 dsize = (a0 + 3) & 0xfffffffc;
1278 // exit on uninitialized heap
1279 if (chunk == NULL) {
1280 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1286 // search an unused chunk that is big enough until the end of the heap
1287 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1288 chunk = (u32*)((uptr)chunk + csize + 4);
1290 // catch out of memory
1291 if(chunk >= heap_end) {
1292 printf("malloc %x,%x: Out of memory error!\n",
1298 csize = ((u32)*chunk) & 0xfffffffc;
1299 cstat = ((u32)*chunk) & 1;
1303 if(dsize == csize) {
1304 // chunk has same size
1305 *chunk &= 0xfffffffc;
1306 } else if (dsize > csize) {
1311 *chunk = SWAP32(dsize);
1312 newchunk = (u32*)((uptr)chunk + dsize + 4);
1313 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1316 // return pointer to allocated memory
1317 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1319 //printf ("malloc %x,%x\n", v0, a0);
1323 static void psxBios_free() { // 0x34
1324 PSXBIOS_LOG("psxBios_%s %x (%x bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1325 storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1326 mips_return_void_c(5);
1329 static void psxBios_calloc() { // 0x37
1331 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
1333 a0 = size = a0 * a1;
1337 a0 = ret; a1 = size;
1340 mips_return_c(ret, 21);
1343 void psxBios_realloc() { // 0x38
1347 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1351 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1356 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1361 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1362 /* Note that it is not quite implemented this way here. */
1372 /* InitHeap(void *block , int n) */
1373 static void psxBios_InitHeap() { // 0x39
1374 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
1376 storeRam32(A_HEAP_BASE, a0);
1377 storeRam32(A_HEAP_SIZE, a1);
1378 storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
1379 storeRam32(A_HEAP_FLAG, 0);
1382 mips_return_void_c(14);
1385 void psxBios_getchar() { //0x3b
1386 v0 = getchar(); pc0 = ra;
1389 static void psxBios_printf_psxout() { // 0x3f
1398 if (psp != INVALID_PTR) {
1399 memcpy(save, psp, 4 * 4);
1400 psxMu32ref(sp) = SWAP32((u32)a0);
1401 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1402 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1403 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1415 tmp2[j++] = Ra0[i]; goto _start;
1417 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1428 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1432 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1438 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1440 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1442 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1444 *ptmp++ = Ra0[i]; break;
1454 if (psp != INVALID_PTR)
1455 memcpy(psp, save, 4 * 4);
1458 SysPrintf("%s", tmp);
1461 void psxBios_printf() { // 0x3f
1462 psxBios_printf_psxout();
1466 static void psxBios_cd() { // 0x40
1467 const char *p, *dir = castRam8ptr(a0);
1468 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x40], a0, dir);
1469 if ((p = strchr(dir, ':')))
1473 snprintf(cdir, sizeof(cdir), "%s", dir);
1474 mips_return_c(1, 100);
1477 static void psxBios_format() { // 0x41
1478 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x41], a0, Ra0);
1479 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1481 CreateMcd(Config.Mcd1);
1482 LoadMcd(1, Config.Mcd1);
1485 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1487 CreateMcd(Config.Mcd2);
1488 LoadMcd(2, Config.Mcd2);
1498 static void psxBios_SystemErrorUnresolvedException() {
1499 if (floodchk != 0x12340a40) { // prevent log flood
1500 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1501 floodchk = 0x12340a40;
1503 mips_return_void_c(1000);
1506 static void FlushCache() {
1507 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1508 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1510 // runs from uncached mem so tons of cycles
1515 * long Load(char *name, struct EXEC *header);
1518 void psxBios_Load() { // 0x42
1526 PSXBIOS_LOG("psxBios_%s %x(%s), %x\n", biosA0n[0x42], a0, pa0, a1);
1527 if (pa0 == INVALID_PTR || pa1 == INVALID_PTR) {
1531 if ((p = strchr(pa0, ':')))
1536 snprintf(path, sizeof(path), "%s\\%s", cdir, (char *)pa0);
1538 snprintf(path, sizeof(path), "%s", (char *)pa0);
1540 if (LoadCdromFile(path, &eheader) == 0) {
1541 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1542 psxCpu->Clear(a1, sizeof(EXEC) / 4);
1546 PSXBIOS_LOG(" -> %d\n", v0);
1552 * int Exec(struct EXEC *header , int argc , char **argv);
1555 void psxBios_Exec() { // 43
1556 EXEC *header = (EXEC *)castRam32ptr(a0);
1560 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1562 header->_sp = SWAP32(sp);
1563 header->_fp = SWAP32(fp);
1564 header->_sp = SWAP32(sp);
1565 header->_gp = SWAP32(gp);
1566 header->ret = SWAP32(ra);
1567 header->base = SWAP32(s0);
1569 ptr = SWAP32(header->b_addr);
1570 len = SWAP32(header->b_size);
1576 if (header->S_addr != 0)
1577 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1579 gp = SWAP32(header->gp0);
1587 pc0 = SWAP32(header->_pc0);
1590 static void psxBios_FlushCache() { // 44
1591 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1596 void psxBios_GPU_dw() { // 0x46
1601 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1604 GPU_writeData(0xa0000000);
1605 GPU_writeData((a1<<0x10)|(a0&0xffff));
1606 GPU_writeData((a3<<0x10)|(a2&0xffff));
1608 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1611 GPU_writeData(SWAPu32(*ptr++));
1617 void psxBios_mem2vram() { // 0x47
1619 gpuSyncPluginSR(); // flush
1620 GPU_writeData(0xa0000000);
1621 GPU_writeData((a1<<0x10)|(a0&0xffff));
1622 GPU_writeData((a3<<0x10)|(a2&0xffff));
1623 size = ((((a2 * a3) / 2) >> 4) << 16);
1624 GPU_writeStatus(0x04000002);
1625 psxHwWrite32(0x1f8010f4,0);
1626 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1627 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1628 psxHwWrite32(0x1f8010a4, size | 0x10);
1629 psxHwWrite32(0x1f8010a8,0x01000201);
1634 void psxBios_SendGPU() { // 0x48
1635 GPU_writeStatus(a0);
1640 void psxBios_GPU_cw() { // 0x49
1647 void psxBios_GPU_cwb() { // 0x4a
1648 u32 *ptr = (u32*)Ra0;
1653 GPU_writeData(SWAPu32(*ptr++));
1659 void psxBios_GPU_SendPackets() { //4b:
1661 GPU_writeStatus(0x04000002);
1662 psxHwWrite32(0x1f8010f4,0);
1663 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1664 psxHwWrite32(0x1f8010a0,a0);
1665 psxHwWrite32(0x1f8010a4,0);
1666 psxHwWrite32(0x1f8010a8,0x010000401);
1670 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1671 psxHwWrite32(0x1f8010a8,0x00000401);
1672 GPU_writeData(0x0400000);
1673 GPU_writeData(0x0200000);
1674 GPU_writeData(0x0100000);
1679 void psxBios_GPU_GetGPUStatus() { // 0x4d
1680 v0 = GPU_readStatus();
1686 void psxBios_LoadExec() { // 51
1687 EXEC *header = (EXEC*)PSXM(0xf000);
1691 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1693 s_addr = a1; s_size = a2;
1698 header->S_addr = s_addr;
1699 header->s_size = s_size;
1701 a0 = 0xf000; a1 = 0; a2 = 0;
1705 void psxBios__bu_init() { // 70
1707 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1710 DeliverEvent(0xf0000011, 0x0004);
1711 DeliverEvent(0xf4000001, 0x0004);
1716 void psxBios__96_init() { // 71
1718 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1724 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1725 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1726 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1728 static void psxBios_DequeueCdIntr_() {
1729 psxBios_SysDeqIntRP_(0, 0x91d0);
1730 psxBios_SysDeqIntRP_(0, 0x91e0);
1734 static void psxBios_DequeueCdIntr() { // a3
1735 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1736 psxBios_DequeueCdIntr_();
1739 static void psxBios_CdRemove() { // 56, 72
1740 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1742 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1743 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1744 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1745 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1746 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1747 psxBios_DequeueCdIntr_();
1749 // EnterCriticalSection - should be done at the beginning,
1750 // but this way is much easier to implement
1756 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack);
1758 static void psxBios_SetConf() { // 9c
1759 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9c], a0, a1, a2);
1760 setup_tt(a1, a0, a2);
1761 psxRegs.CP0.n.SR |= 0x401;
1762 mips_return_void_c(500);
1765 static void psxBios_GetConf() { // 9d
1766 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9d], a0, a1, a2);
1767 storeRam32(a0, loadRam32(A_CONF_EvCB));
1768 storeRam32(a1, loadRam32(A_CONF_TCB));
1769 storeRam32(a2, loadRam32(A_CONF_SP));
1770 mips_return_void_c(10);
1773 void psxBios_SetMem() { // 9f
1774 u32 new = psxHu32(0x1060);
1777 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1782 psxHu32ref(0x1060) = SWAP32(new);
1783 psxMu32ref(0x060) = a0;
1784 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1788 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1789 psxMu32ref(0x060) = a0;
1790 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1793 PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
1800 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1801 static void psxBios_get_cd_status() // a6
1803 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
1808 static void psxBios__card_info() { // ab
1809 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1811 storeRam32(A_CARD_CHAN1, a0);
1818 if (McdDisable[port & 1])
1822 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
1827 if (McdDisable[0] && McdDisable[1])
1830 DeliverEvent(0xf0000011, 0x0004);
1831 // DeliverEvent(0xf4000001, 0x0004);
1832 DeliverEvent(0xf4000001, ret);
1836 void psxBios__card_load() { // ac
1838 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1841 storeRam32(A_CARD_CHAN1, a0);
1843 // DeliverEvent(0xf0000011, 0x0004);
1844 DeliverEvent(0xf4000001, 0x0004);
1849 static void psxBios_GetSystemInfo() { // b4
1851 //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
1852 SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
1855 case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
1856 case 2: ret = 0xbfc0012c; break;
1857 case 5: ret = loadRam32(0x60) << 10; break;
1859 mips_return_c(ret, 20);
1862 /* System calls B0 */
1864 static u32 psxBios_SysMalloc_(u32 size);
1866 static void psxBios_SysMalloc() { // B 00
1867 u32 ret = psxBios_SysMalloc_(a0);
1869 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1870 mips_return_c(ret, 33);
1873 void psxBios_SetRCnt() { // 02
1875 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1882 psxRcntWtarget(a0, a1);
1883 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1884 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1885 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1886 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1887 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1889 psxRcntWmode(a0, mode);
1894 void psxBios_GetRCnt() { // 03
1896 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1901 case 0: v0 = psxRcntRcount0(); break;
1902 case 1: v0 = psxRcntRcount1(); break;
1903 case 2: v0 = psxRcntRcount2(); break;
1904 case 3: v0 = 0; break;
1909 void psxBios_StartRCnt() { // 04
1911 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1915 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1916 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1920 void psxBios_StopRCnt() { // 05
1922 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1926 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1927 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1931 void psxBios_ResetRCnt() { // 06
1933 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1938 psxRcntWmode(a0, 0);
1939 psxRcntWtarget(a0, 0);
1940 psxRcntWcount(a0, 0);
1945 static u32 DeliverEvent(u32 class, u32 spec) {
1946 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1947 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1948 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1949 u32 i, lim = evcb_len / 0x1c;
1951 //printf("%s %08x %x\n", __func__, class, spec);
1952 for (i = 0; i < lim; i++, ev++) {
1954 if (SWAP32(ev->status) != EvStACTIVE)
1957 if (SWAP32(ev->class) != class)
1960 if (SWAP32(ev->spec) != spec)
1963 ret = SWAP32(ev->mode);
1964 if (ret == EvMdMARK) {
1965 ev->status = SWAP32(EvStALREADY);
1969 if (ret == EvMdCALL) {
1970 ret = SWAP32(ev->fhandler);
1983 static u32 UnDeliverEvent(u32 class, u32 spec) {
1984 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1985 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1986 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1987 u32 i, lim = evcb_len / 0x1c;
1989 for (i = 0; i < lim; i++, ev++) {
1991 if (SWAP32(ev->status) != EvStALREADY)
1994 if (SWAP32(ev->class) != class)
1997 if (SWAP32(ev->spec) != spec)
2000 if (SWAP32(ev->mode) == EvMdMARK)
2001 ev->status = SWAP32(EvStACTIVE);
2007 static void psxBios_DeliverEvent() { // 07
2009 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
2011 ret = DeliverEvent(a0, a1);
2015 static s32 get_free_EvCB_slot() {
2016 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
2017 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
2020 for (i = 0; i < lim; i++, ev++) {
2022 if (ev->status == SWAP32(EvStUNUSED))
2028 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
2029 u32 ret = get_free_EvCB_slot();
2030 if ((s32)ret >= 0) {
2031 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
2032 ev->class = SWAP32(class);
2033 ev->status = SWAP32(EvStDISABLED);
2034 ev->spec = SWAP32(spec);
2035 ev->mode = SWAP32(mode);
2036 ev->fhandler = SWAP32(func);
2042 static void psxBios_OpenEvent() { // 08
2043 u32 ret = OpenEvent(a0, a1, a2, a3);
2044 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
2045 biosB0n[0x08], a0, a1, a2, a3, ret);
2046 mips_return_c(ret, 36);
2049 static void CloseEvent(u32 ev)
2051 u32 base = loadRam32(A_TT_EvCB);
2052 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
2055 static void psxBios_CloseEvent() { // 09
2056 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
2057 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
2059 mips_return_c(1, 10);
2062 static void psxBios_WaitEvent() { // 0a
2063 u32 base = loadRam32(A_TT_EvCB);
2064 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2065 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
2068 if (status == EvStALREADY) {
2069 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2073 if (status != EvStACTIVE)
2075 mips_return_c(0, 2);
2079 // retrigger this hlecall after the next emulation event
2081 if ((s32)(next_interupt - psxRegs.cycle) > 0)
2082 psxRegs.cycle = next_interupt;
2086 static void psxBios_TestEvent() { // 0b
2087 u32 base = loadRam32(A_TT_EvCB);
2088 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2091 if (psxRegs.cycle - floodchk > 16*1024u) { // prevent log flood
2092 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
2093 floodchk = psxRegs.cycle;
2095 if (status == EvStALREADY) {
2096 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2100 mips_return_c(ret, 15);
2103 static void psxBios_EnableEvent() { // 0c
2104 u32 base = loadRam32(A_TT_EvCB);
2105 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2106 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
2107 if (status != EvStUNUSED)
2108 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2110 mips_return_c(1, 15);
2113 static void psxBios_DisableEvent() { // 0d
2114 u32 base = loadRam32(A_TT_EvCB);
2115 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2116 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2117 if (status != EvStUNUSED)
2118 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2120 mips_return_c(1, 15);
2124 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2127 void psxBios_OpenTh() { // 0e
2128 TCB *tcb = loadRam32ptr(A_TT_TCB);
2129 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2132 for (th = 1; th < limit; th++)
2134 if (tcb[th].status != SWAP32(0x4000)) break;
2138 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2139 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2141 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2143 mips_return_c(0xffffffff, 20);
2146 PSXBIOS_LOG("psxBios_%s -> %x\n", biosB0n[0x0e], 0xff000000 + th);
2148 tcb[th].status = SWAP32(0x4000);
2149 tcb[th].mode = SWAP32(0x1000);
2150 tcb[th].epc = SWAP32(a0);
2151 tcb[th].reg[30] = SWAP32(a1); // fp
2152 tcb[th].reg[29] = SWAP32(a1); // sp
2153 tcb[th].reg[28] = SWAP32(a2); // gp
2155 mips_return_c(0xff000000 + th, 34);
2159 * int CloseTh(long thread);
2162 static void psxBios_CloseTh() { // 0f
2163 u32 tcb = loadRam32(A_TT_TCB);
2164 u32 th = a0 & 0xffff;
2166 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x0f], a0);
2167 // in the usual bios fashion no checks, just write and return 1
2168 storeRam32(tcb + th * sizeof(TCB), 0x1000);
2170 mips_return_c(1, 11);
2174 * int ChangeTh(long thread);
2177 void psxBios_ChangeTh() { // 10
2178 u32 tcbBase = loadRam32(A_TT_TCB);
2179 u32 th = a0 & 0xffff;
2181 // this is quite spammy
2182 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2184 // without doing any argument checks, just issue a syscall
2185 // (like the real bios does)
2187 a1 = tcbBase + th * sizeof(TCB);
2192 void psxBios_InitPAD() { // 0x12
2193 u32 i, *ram32 = (u32 *)psxM;
2194 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2196 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2197 ram32[A_PAD_DR_DST/4] = 0;
2198 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2199 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2200 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2201 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2202 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2203 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2204 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2205 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2207 for (i = 0; i < a1; i++) {
2209 storeRam8(a0 + i, 0);
2211 for (i = 0; i < a3; i++) {
2213 storeRam8(a2 + i, 0);
2215 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2217 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2219 mips_return_c(1, 200);
2222 void psxBios_StartPAD() { // 13
2223 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2225 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2226 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2227 psxHwWrite16(0x1f801070, ~1);
2228 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2229 storeRam32(A_PAD_ACK_VBL, 1);
2230 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2231 psxRegs.CP0.n.SR |= 0x401;
2233 mips_return_c(1, 300);
2236 void psxBios_StopPAD() { // 14
2237 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2238 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2239 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2240 psxRegs.CP0.n.SR |= 0x401;
2241 mips_return_void_c(200);
2244 static void psxBios_PAD_init() { // 15
2246 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2247 if (a0 == 0x20000000 || a0 == 0x20000001)
2250 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2251 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2254 storeRam32(A_PAD_DR_DST, dst);
2257 mips_return_c(ret, 100);
2260 static u32 psxBios_PAD_dr_() {
2261 u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2262 u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2263 u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2264 dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2265 if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2267 dst[0] = buf1[3], dst[1] = buf1[2];
2268 if (buf1[1] == 0x23) {
2269 dst[0] |= 0xc7, dst[1] |= 7;
2270 if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2271 if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2274 if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2276 dst[2] = buf2[3], dst[3] = buf2[2];
2277 if (buf2[1] == 0x23) {
2278 dst[2] |= 0xc7, dst[3] |= 7;
2279 if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2280 if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2284 return SWAP32(*(u32 *)dst);
2287 static void psxBios_PAD_dr() { // 16
2288 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2289 u32 ret = psxBios_PAD_dr_();
2293 static void psxBios_ReturnFromException() { // 17
2294 u32 tcbPtr = loadRam32(A_TT_PCB);
2295 const TCB *tcb = loadRam32ptr(tcbPtr);
2299 for (i = 1; i < 32; i++)
2300 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2301 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2302 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2303 sr = SWAP32(tcb->sr);
2305 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2306 pc0 = k0 = SWAP32(tcb->epc);
2308 // the interpreter wants to know about sr changes, so do a MTC0
2309 sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2310 MTC0(&psxRegs, 12, sr);
2316 void psxBios_ResetEntryInt() { // 18
2317 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2319 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2320 mips_return_void_c(5);
2323 void psxBios_HookEntryInt() { // 19
2324 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2326 storeRam32(A_EEXIT_PTR, a0);
2327 mips_return_void_c(3);
2330 static void psxBios_UnDeliverEvent() { // 0x20
2332 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2334 ret = UnDeliverEvent(a0, a1);
2338 static void buopen(int mcd, char *ptr, char *cfg)
2341 char *mcd_data = ptr;
2343 strcpy(FDesc[1 + mcd].name, Ra0+5);
2344 FDesc[1 + mcd].offset = 0;
2345 FDesc[1 + mcd].mode = a1;
2347 for (i=1; i<16; i++) {
2348 const char *fptr = mcd_data + 128 * i;
2349 if ((*fptr & 0xF0) != 0x50) continue;
2350 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2351 FDesc[1 + mcd].mcfile = i;
2352 PSXBIOS_LOG("open %s\n", fptr+0xa);
2356 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2357 for (i=1; i<16; i++) {
2358 int j, xor, nblk = a1 >> 16;
2360 char *fptr = mcd_data + 128 * i;
2362 if ((*fptr & 0xF0) != 0xa0) continue;
2364 FDesc[1 + mcd].mcfile = i;
2367 fptr[5] = 0x20 * nblk;
2370 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2371 pptr = fptr2 = fptr;
2372 for(j=2; j<=nblk; j++) {
2374 for(i++; i<16; i++) {
2377 memset(fptr2, 0, 128);
2378 fptr2[0] = j < nblk ? 0x52 : 0x53;
2381 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2386 /* shouldn't this return ENOSPC if i == 16? */
2388 pptr[8] = pptr[9] = 0xff;
2389 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2391 PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2393 /* just go ahead and resave them all */
2394 SaveMcd(cfg, ptr, 128, 128 * 15);
2397 /* shouldn't this return ENOSPC if i == 16? */
2402 * int open(char *name , int mode);
2405 void psxBios_open() { // 0x32
2408 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x32], Ra0, a1);
2412 if (pa0 != INVALID_PTR) {
2413 if (!strncmp(pa0, "bu00", 4)) {
2414 buopen(1, Mcd1Data, Config.Mcd1);
2417 if (!strncmp(pa0, "bu10", 4)) {
2418 buopen(2, Mcd2Data, Config.Mcd2);
2426 * int lseek(int fd , int offset , int whence);
2429 void psxBios_lseek() { // 0x33
2431 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2436 FDesc[a0].offset = a1;
2438 // DeliverEvent(0xf0000011, 0x0004);
2439 // DeliverEvent(0xf4000001, 0x0004);
2443 FDesc[a0].offset+= a1;
2444 v0 = FDesc[a0].offset;
2453 * int read(int fd , void *buf , int nbytes);
2456 void psxBios_read() { // 0x34
2461 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2466 if (pa1 != INVALID_PTR) {
2468 case 2: buread(pa1, 1, a2); break;
2469 case 3: buread(pa1, 2, a2); break;
2477 * int write(int fd , void *buf , int nbytes);
2480 void psxBios_write() { // 0x35/0x03
2484 if (a0 != 1) // stdout
2485 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2488 if (pa1 == INVALID_PTR) {
2493 if (a0 == 1) { // stdout
2497 if (Config.PsxOut) while (a2 > 0) {
2498 SysPrintf("%c", *ptr++); a2--;
2504 case 2: buwrite(pa1, 1, a2); break;
2505 case 3: buwrite(pa1, 2, a2); break;
2511 static void psxBios_write_psxout() {
2512 if (a0 == 1) { // stdout
2513 const char *ptr = Ra1;
2516 if (ptr != INVALID_PTR)
2518 SysPrintf("%c", *ptr++);
2522 static void psxBios_putchar_psxout() { // 3d
2523 SysPrintf("%c", (char)a0);
2526 static void psxBios_puts_psxout() { // 3e/3f
2527 SysPrintf("%s", Ra0);
2531 * int close(int fd);
2534 void psxBios_close() { // 0x36
2536 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2543 void psxBios_putchar() { // 3d
2544 if (Config.PsxOut) SysPrintf("%c", (char)a0);
2548 void psxBios_puts() { // 3e/3f
2549 if (Config.PsxOut) SysPrintf("%s", Ra0);
2553 static void bufile(const u8 *mcd_data, u32 dir_) {
2554 struct DIRENTRY *dir = (struct DIRENTRY *)castRam8ptr(dir_);
2555 const char *pfile = ffile + 5;
2556 const u8 *data = mcd_data;
2557 int i = 0, match = 0;
2562 for (; nfile <= 15 && !match; nfile++) {
2565 head = nfile * 0x40;
2566 data = mcd_data + 128 * nfile;
2567 name = (const char *)data + 0x0a;
2568 if ((data[0] & 0xF0) != 0x50) continue;
2569 /* Bug link files show up as free block. */
2570 if (!name[0]) continue;
2572 for (i = 0; i < 20; i++) {
2573 if (pfile[i] == name[i] || pfile[i] == '?')
2574 dir->name[i] = name[i];
2575 else if (pfile[i] == '*') {
2576 int len = strlen(name + i);
2579 memcpy(dir->name + i, name + i, len + 1);
2590 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n",
2591 nfile, dir->name, pfile, name, match);
2593 for (; nfile <= 15; nfile++, blocks++) {
2594 const u8 *data2 = mcd_data + 128 * nfile;
2595 const char *name = (const char *)data2 + 0x0a;
2596 if ((data2[0] & 0xF0) != 0x50 || name[0])
2600 // nul char of full lenth name seems to overwrite .attr
2601 dir->attr = SWAP32(i < 20 ? data[0] & 0xf0 : 0); // ?
2602 dir->size = 8192 * blocks;
2606 PSXBIOS_LOG(" -> %x '%s' %x %x %x %x\n", v0, v0 ? dir->name : "",
2607 dir->attr, dir->size, dir->next, dir->head);
2611 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2614 static void psxBios_firstfile() { // 42
2615 char *pa0 = castRam8ptr(a0);
2617 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x42], pa0, a1);
2621 snprintf(ffile, sizeof(ffile), "%s", pa0);
2623 strcpy(ffile + 5, "*"); // maybe?
2625 if (!strncmp(pa0, "bu00", 4)) {
2626 // firstfile() calls _card_read() internally, so deliver it's event
2627 DeliverEvent(0xf0000011, 0x0004);
2628 bufile((u8 *)Mcd1Data, a1);
2629 } else if (!strncmp(pa0, "bu10", 4)) {
2630 // firstfile() calls _card_read() internally, so deliver it's event
2631 DeliverEvent(0xf0000011, 0x0004);
2632 bufile((u8 *)Mcd2Data, a1);
2640 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2643 void psxBios_nextfile() { // 43
2644 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x43], a0);
2647 if (!strncmp(ffile, "bu00", 4))
2648 bufile((u8 *)Mcd1Data, a0);
2649 else if (!strncmp(ffile, "bu10", 4))
2650 bufile((u8 *)Mcd2Data, a0);
2655 #define burename(mcd) { \
2656 for (i=1; i<16; i++) { \
2657 int namelen, j, xor = 0; \
2658 ptr = Mcd##mcd##Data + 128 * i; \
2659 if ((*ptr & 0xF0) != 0x50) continue; \
2660 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2661 namelen = strlen(Ra1+5); \
2662 memcpy(ptr+0xa, Ra1+5, namelen); \
2663 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2664 for (j=0; j<127; j++) xor^= ptr[j]; \
2666 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2673 * int rename(char *old, char *new);
2676 void psxBios_rename() { // 44
2683 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2688 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2689 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2693 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2702 #define budelete(mcd) { \
2703 for (i=1; i<16; i++) { \
2704 ptr = Mcd##mcd##Data + 128 * i; \
2705 if ((*ptr & 0xF0) != 0x50) continue; \
2706 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2707 *ptr = (*ptr & 0xf) | 0xA0; \
2708 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2709 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2716 * int delete(char *name);
2719 void psxBios_delete() { // 45
2725 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2730 if (pa0 != INVALID_PTR) {
2731 if (!strncmp(pa0, "bu00", 4)) {
2735 if (!strncmp(pa0, "bu10", 4)) {
2743 void psxBios_InitCARD() { // 4a
2744 u32 *ram32 = (u32 *)psxM;
2745 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2746 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2747 // (maybe) todo: early_card_irq, etc
2749 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2751 psxBios_FlushCache();
2752 mips_return_c(0, 34+13+15+6);
2755 void psxBios_StartCARD() { // 4b
2756 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2757 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2758 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2760 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2761 storeRam32(A_PAD_ACK_VBL, 1);
2762 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2763 storeRam32(A_CARD_IRQR_ENA, 1);
2764 psxRegs.CP0.n.SR |= 0x401;
2766 mips_return_c(1, 200);
2769 void psxBios_StopCARD() { // 4c
2770 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2771 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2772 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2773 storeRam32(A_CARD_IRQR_ENA, 0);
2774 psxRegs.CP0.n.SR |= 0x401;
2775 mips_return_void_c(200);
2778 void psxBios__card_write() { // 0x4e
2783 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2786 Function also accepts sector 400h (a bug).
2787 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2791 /* Invalid sectors */
2795 storeRam32(A_CARD_CHAN1, a0);
2798 if (pa2 != INVALID_PTR) {
2800 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2801 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2803 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2804 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2808 DeliverEvent(0xf0000011, 0x0004);
2809 // DeliverEvent(0xf4000001, 0x0004);
2814 void psxBios__card_read() { // 0x4f
2819 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2822 Function also accepts sector 400h (a bug).
2823 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2827 /* Invalid sectors */
2831 storeRam32(A_CARD_CHAN1, a0);
2834 if (pa2 != INVALID_PTR) {
2836 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2838 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2842 DeliverEvent(0xf0000011, 0x0004);
2843 // DeliverEvent(0xf4000001, 0x0004);
2848 void psxBios__new_card() { // 0x50
2850 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2856 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2857 void psxBios__get_error(void) // 55
2859 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2864 void psxBios_Krom2RawAdd() { // 0x51
2867 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2868 const u32 table_8140[][2] = {
2869 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2870 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2871 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2872 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2873 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2874 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2875 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2876 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2877 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2881 const u32 table_889f[][2] = {
2882 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2883 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2884 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2885 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2886 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2887 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2888 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2889 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2893 if (a0 >= 0x8140 && a0 <= 0x84be) {
2894 while (table_8140[i][0] <= a0) i++;
2895 a0 -= table_8140[i - 1][0];
2896 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2897 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2898 while (table_889f[i][0] <= a0) i++;
2899 a0 -= table_889f[i - 1][0];
2900 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2908 void psxBios_GetC0Table() { // 56
2909 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2910 log_unhandled("GetC0Table @%08x\n", ra);
2912 mips_return_c(A_C0_TABLE, 3);
2915 void psxBios_GetB0Table() { // 57
2916 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2917 log_unhandled("GetB0Table @%08x\n", ra);
2919 mips_return_c(A_B0_TABLE, 3);
2922 static void psxBios__card_chan() { // 0x58
2924 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2926 // todo: should return active slot chan
2927 // (active - which was last processed by irq code)
2928 ret = loadRam32(A_CARD_CHAN1);
2929 mips_return_c(ret, 8);
2932 static void psxBios_ChangeClearPad() { // 5b
2934 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2935 ret = loadRam32(A_PAD_ACK_VBL);
2936 storeRam32(A_PAD_ACK_VBL, a0);
2938 mips_return_c(ret, 6);
2941 static void psxBios__card_status() { // 5c
2942 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
2948 static void psxBios__card_wait() { // 5d
2949 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
2955 /* System calls C0 */
2957 static void psxBios_InitRCnt() { // 00
2959 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2960 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2961 for (i = 0; i < 3; i++) {
2962 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2963 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2964 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2966 psxBios_SysEnqIntRP_(a0, 0x6d88);
2967 mips_return_c(0, 9);
2970 static void psxBios_InitException() { // 01
2971 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2972 psxBios_SysEnqIntRP_(a0, 0x6da8);
2973 mips_return_c(0, 9);
2977 * int SysEnqIntRP(int index , long *queue);
2980 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2981 u32 old, base = loadRam32(A_TT_ExCB);
2983 old = loadRam32(base + (priority << 3));
2984 storeRam32(base + (priority << 3), chain_eptr);
2985 storeRam32(chain_eptr, old);
2986 mips_return_c(0, 9);
2989 static void psxBios_SysEnqIntRP() { // 02
2990 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2991 psxBios_SysEnqIntRP_(a0, a1);
2995 * int SysDeqIntRP(int index , long *queue);
2998 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
2999 u32 ptr, next, base = loadRam32(A_TT_ExCB);
3000 u32 lim = 0, ret = 0;
3002 // as in original: no arg checks of any kind, bug if a1 == 0
3003 ptr = loadRam32(base + (priority << 3));
3005 next = loadRam32(ptr);
3006 if (ptr == chain_rm_eptr) {
3007 storeRam32(base + (priority << 3), next);
3012 while (next && next != chain_rm_eptr && lim++ < 100) {
3014 next = loadRam32(ptr);
3017 if (next == chain_rm_eptr) {
3018 next = loadRam32(next);
3019 storeRam32(ptr, next);
3026 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
3028 mips_return_c(ret, 12);
3031 static void psxBios_SysDeqIntRP() { // 03
3032 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
3033 psxBios_SysDeqIntRP_(a0, a1);
3036 static void psxBios_get_free_EvCB_slot() { // 04
3037 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
3038 s32 ret = get_free_EvCB_slot();
3039 mips_return_c(ret, 0);
3042 static void psxBios_SysInitMemory_(u32 base, u32 size) {
3043 storeRam32(base, 0);
3044 storeRam32(A_KMALLOC_PTR, base);
3045 storeRam32(A_KMALLOC_SIZE, size);
3046 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
3049 // this should be much more complicated, but maybe that'll be enough
3050 static u32 psxBios_SysMalloc_(u32 size) {
3051 u32 ptr = loadRam32(A_KMALLOC_PTR);
3053 size = (size + 3) & ~3;
3054 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
3055 storeRam32(ptr, size);
3059 static void psxBios_SysInitMemory() { // 08
3060 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
3062 psxBios_SysInitMemory_(a0, a1);
3063 mips_return_void_c(12);
3066 static void psxBios_ChangeClearRCnt() { // 0a
3069 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
3071 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
3072 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
3073 mips_return_c(ret, 8);
3076 static void psxBios_InitDefInt() { // 0c
3077 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3078 // should also clear the autoack table
3079 psxBios_SysEnqIntRP_(a0, 0x6d98);
3080 mips_return_c(0, 20 + 6*2);
3083 void psxBios_dummy() {
3084 u32 pc = (pc0 & 0x1fffff) - 4;
3085 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
3086 : pc == 0xc0 ? biosC0n : NULL;
3087 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
3088 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
3089 (void)pc; (void)ntab;
3090 mips_return_c(0, 100);
3093 void (*biosA0[256])();
3094 // C0 and B0 overlap (end of C0 is start of B0)
3095 void (*biosC0[256+128])();
3096 void (**biosB0)() = biosC0 + 128;
3098 static void setup_mips_code()
3101 ptr = (u32 *)&psxM[A_SYSCALL];
3102 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3103 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
3104 ptr[0x08/4] = SWAPu32(0x00000000); // nop
3106 ptr = (u32 *)&psxM[A_EXCEPTION];
3107 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
3108 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
3109 ptr[0x14/4] = SWAPu32(0x00000000); // nop
3110 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
3111 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3112 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
3113 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
3114 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
3115 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
3116 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
3118 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
3119 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
3120 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
3122 ptr[0xb0/4] = HLEOP(hleop_exception);
3125 static const struct {
3129 { 0xbfc050a4, hleop_exc0_0_1 },
3130 { 0xbfc04fbc, hleop_exc0_0_2 },
3131 { 0xbfc0506c, hleop_exc0_1_1 },
3132 { 0xbfc04dec, hleop_exc0_1_2 },
3133 { 0x1a00, hleop_exc0_2_2 },
3134 { 0x19c8, hleop_exc1_0_1 },
3135 { 0x18bc, hleop_exc1_0_2 },
3136 { 0x1990, hleop_exc1_1_1 },
3137 { 0x1858, hleop_exc1_1_2 },
3138 { 0x1958, hleop_exc1_2_1 },
3139 { 0x17f4, hleop_exc1_2_2 },
3140 { 0x1920, hleop_exc1_3_1 },
3141 { 0x1794, hleop_exc1_3_2 },
3142 { 0x2458, hleop_exc3_0_2 },
3143 { 0x49bc, hleop_exc_padcard1 },
3144 { 0x4a4c, hleop_exc_padcard2 },
3147 static int chain_hle_op(u32 handler)
3151 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3152 if (chainfns[i].addr == handler)
3153 return chainfns[i].op;
3157 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3159 d[0] = SWAPu32(next);
3160 d[1] = SWAPu32(handler1);
3161 d[2] = SWAPu32(handler2);
3163 // install the hle traps
3164 if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3165 if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3168 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack)
3170 u32 *ram32 = (u32 *)psxM;
3171 u32 s_excb = 0x20, s_evcb, s_pcb = 4, s_tcb;
3172 u32 p_excb, p_evcb, p_pcb, p_tcb;
3175 PSXBIOS_LOG("setup: tcb %u, evcb %u\n", tcb_cnt, evcb_cnt);
3177 // the real bios doesn't care, but we just don't
3178 // want to crash in case of garbage parameters
3179 if (tcb_cnt > 1024) tcb_cnt = 1024;
3180 if (evcb_cnt > 1024) evcb_cnt = 1024;
3181 s_evcb = 0x1c * evcb_cnt;
3182 s_tcb = 0xc0 * tcb_cnt;
3184 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3185 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3186 p_excb = psxBios_SysMalloc_(s_excb);
3187 p_evcb = psxBios_SysMalloc_(s_evcb);
3188 p_pcb = psxBios_SysMalloc_(s_pcb);
3189 p_tcb = psxBios_SysMalloc_(s_tcb);
3191 // "table of tables". Some games modify it
3192 assert(A_TT_ExCB == 0x0100);
3193 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3194 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3195 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3196 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3197 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3198 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3199 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3200 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3201 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3202 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3203 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3204 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3206 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3207 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3208 storeRam32(p_excb + 4*4, 0x0000); // chain2
3209 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3211 storeRam32(p_pcb, p_tcb);
3212 storeRam32(p_tcb, 0x4000); // first TCB
3213 for (i = 1; i < tcb_cnt; i++)
3214 storeRam32(p_tcb + sizeof(TCB) * i, 0x1000);
3217 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3218 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3219 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3220 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3221 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3223 storeRam32(A_CONF_EvCB, evcb_cnt);
3224 storeRam32(A_CONF_TCB, tcb_cnt);
3225 storeRam32(A_CONF_SP, stack);
3228 static const u32 gpu_ctl_def[] = {
3229 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3230 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3233 static const u32 gpu_data_def[] = {
3234 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3235 0xe5001000, 0xe6000000,
3236 0x02000000, 0x00000000, 0x01ff03ff
3240 static const u16 spu_config[] = {
3241 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3242 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3243 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3244 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3245 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3246 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3247 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3248 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3251 void psxBiosSetupBootState(void)
3253 boolean hle = Config.HLE;
3254 u32 *hw = (u32 *)psxH;
3257 // see also SetBootRegs()
3260 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3261 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3263 k0 = 0xbfc0d968; k1 = 0xf1c;
3264 ra = 0xf0001234; // just to easily detect attempts to return
3265 psxRegs.CP0.n.Cause = 0x20;
3266 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3268 hw[0x1000/4] = SWAP32(0x1f000000);
3269 hw[0x1004/4] = SWAP32(0x1f802000);
3270 hw[0x1008/4] = SWAP32(0x0013243f);
3271 hw[0x100c/4] = SWAP32(0x00003022);
3272 hw[0x1010/4] = SWAP32(0x0013243f);
3273 hw[0x1014/4] = SWAP32(0x200931e1);
3274 hw[0x1018/4] = SWAP32(0x00020943);
3275 hw[0x101c/4] = SWAP32(0x00070777);
3276 hw[0x1020/4] = SWAP32(0x0000132c);
3277 hw[0x1060/4] = SWAP32(0x00000b88);
3278 hw[0x1070/4] = SWAP32(0x00000001);
3279 hw[0x1074/4] = SWAP32(0x0000000c);
3280 hw[0x2040/4] = SWAP32(0x00000900);
3283 hw[0x10a0/4] = SWAP32(0x00ffffff);
3284 hw[0x10a8/4] = SWAP32(0x00000401);
3285 hw[0x10b0/4] = SWAP32(0x0008b000);
3286 hw[0x10b4/4] = SWAP32(0x00010200);
3287 hw[0x10e0/4] = SWAP32(0x000eccf4);
3288 hw[0x10e4/4] = SWAP32(0x00000400);
3289 hw[0x10e8/4] = SWAP32(0x00000002);
3290 hw[0x10f0/4] = SWAP32(0x00009099);
3291 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3300 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3301 GPU_writeStatus(gpu_ctl_def[i]);
3302 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3303 GPU_writeData(gpu_data_def[i]);
3304 HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
3307 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3308 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3311 #include "sjisfont.h"
3313 void psxBiosInit() {
3314 u32 *ptr, *ram32, *rom32;
3319 memset(psxM, 0, 0x10000);
3320 for(i = 0; i < 256; i++) {
3325 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3326 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3327 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3328 biosA0[0x3f] = psxBios_printf_psxout;
3330 if (!Config.HLE) return;
3332 for(i = 0; i < 256; i++) {
3333 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3334 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3335 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3338 biosA0[0x00] = psxBios_open;
3339 biosA0[0x01] = psxBios_lseek;
3340 biosA0[0x02] = psxBios_read;
3341 biosA0[0x03] = psxBios_write;
3342 biosA0[0x04] = psxBios_close;
3343 //biosA0[0x05] = psxBios_ioctl;
3344 //biosA0[0x06] = psxBios_exit;
3345 //biosA0[0x07] = psxBios_sys_a0_07;
3346 biosA0[0x08] = psxBios_getc;
3347 biosA0[0x09] = psxBios_putc;
3348 biosA0[0x0a] = psxBios_todigit;
3349 //biosA0[0x0b] = psxBios_atof;
3350 //biosA0[0x0c] = psxBios_strtoul;
3351 //biosA0[0x0d] = psxBios_strtol;
3352 biosA0[0x0e] = psxBios_abs;
3353 biosA0[0x0f] = psxBios_labs;
3354 biosA0[0x10] = psxBios_atoi;
3355 biosA0[0x11] = psxBios_atol;
3356 //biosA0[0x12] = psxBios_atob;
3357 biosA0[0x13] = psxBios_setjmp;
3358 biosA0[0x14] = psxBios_longjmp;
3359 biosA0[0x15] = psxBios_strcat;
3360 biosA0[0x16] = psxBios_strncat;
3361 biosA0[0x17] = psxBios_strcmp;
3362 biosA0[0x18] = psxBios_strncmp;
3363 biosA0[0x19] = psxBios_strcpy;
3364 biosA0[0x1a] = psxBios_strncpy;
3365 biosA0[0x1b] = psxBios_strlen;
3366 biosA0[0x1c] = psxBios_index;
3367 biosA0[0x1d] = psxBios_rindex;
3368 biosA0[0x1e] = psxBios_strchr;
3369 biosA0[0x1f] = psxBios_strrchr;
3370 biosA0[0x20] = psxBios_strpbrk;
3371 biosA0[0x21] = psxBios_strspn;
3372 biosA0[0x22] = psxBios_strcspn;
3373 biosA0[0x23] = psxBios_strtok;
3374 biosA0[0x24] = psxBios_strstr;
3375 biosA0[0x25] = psxBios_toupper;
3376 biosA0[0x26] = psxBios_tolower;
3377 biosA0[0x27] = psxBios_bcopy;
3378 biosA0[0x28] = psxBios_bzero;
3379 biosA0[0x29] = psxBios_bcmp;
3380 biosA0[0x2a] = psxBios_memcpy;
3381 biosA0[0x2b] = psxBios_memset;
3382 biosA0[0x2c] = psxBios_memmove;
3383 biosA0[0x2d] = psxBios_memcmp;
3384 biosA0[0x2e] = psxBios_memchr;
3385 biosA0[0x2f] = psxBios_rand;
3386 biosA0[0x30] = psxBios_srand;
3387 biosA0[0x31] = psxBios_qsort;
3388 //biosA0[0x32] = psxBios_strtod;
3389 biosA0[0x33] = psxBios_malloc;
3390 biosA0[0x34] = psxBios_free;
3391 //biosA0[0x35] = psxBios_lsearch;
3392 //biosA0[0x36] = psxBios_bsearch;
3393 biosA0[0x37] = psxBios_calloc;
3394 biosA0[0x38] = psxBios_realloc;
3395 biosA0[0x39] = psxBios_InitHeap;
3396 //biosA0[0x3a] = psxBios__exit;
3397 biosA0[0x3b] = psxBios_getchar;
3398 biosA0[0x3c] = psxBios_putchar;
3399 //biosA0[0x3d] = psxBios_gets;
3400 biosA0[0x3e] = psxBios_puts;
3401 biosA0[0x3f] = psxBios_printf;
3402 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3403 //biosA0[0x41] = psxBios_LoadTest;
3404 biosA0[0x42] = psxBios_Load;
3405 biosA0[0x43] = psxBios_Exec;
3406 biosA0[0x44] = psxBios_FlushCache;
3407 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3408 biosA0[0x46] = psxBios_GPU_dw;
3409 biosA0[0x47] = psxBios_mem2vram;
3410 biosA0[0x48] = psxBios_SendGPU;
3411 biosA0[0x49] = psxBios_GPU_cw;
3412 biosA0[0x4a] = psxBios_GPU_cwb;
3413 biosA0[0x4b] = psxBios_GPU_SendPackets;
3414 biosA0[0x4c] = psxBios_sys_a0_4c;
3415 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3416 //biosA0[0x4e] = psxBios_GPU_sync;
3417 //biosA0[0x4f] = psxBios_sys_a0_4f;
3418 //biosA0[0x50] = psxBios_sys_a0_50;
3419 biosA0[0x51] = psxBios_LoadExec;
3420 //biosA0[0x52] = psxBios_GetSysSp;
3421 //biosA0[0x53] = psxBios_sys_a0_53;
3422 //biosA0[0x54] = psxBios__96_init_a54;
3423 //biosA0[0x55] = psxBios__bu_init_a55;
3424 biosA0[0x56] = psxBios_CdRemove;
3425 //biosA0[0x57] = psxBios_sys_a0_57;
3426 //biosA0[0x58] = psxBios_sys_a0_58;
3427 //biosA0[0x59] = psxBios_sys_a0_59;
3428 //biosA0[0x5a] = psxBios_sys_a0_5a;
3429 //biosA0[0x5b] = psxBios_dev_tty_init;
3430 //biosA0[0x5c] = psxBios_dev_tty_open;
3431 //biosA0[0x5d] = psxBios_sys_a0_5d;
3432 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3433 //biosA0[0x5f] = psxBios_dev_cd_open;
3434 //biosA0[0x60] = psxBios_dev_cd_read;
3435 //biosA0[0x61] = psxBios_dev_cd_close;
3436 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3437 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3438 //biosA0[0x64] = psxBios_dev_cd_chdir;
3439 //biosA0[0x65] = psxBios_dev_card_open;
3440 //biosA0[0x66] = psxBios_dev_card_read;
3441 //biosA0[0x67] = psxBios_dev_card_write;
3442 //biosA0[0x68] = psxBios_dev_card_close;
3443 //biosA0[0x69] = psxBios_dev_card_firstfile;
3444 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3445 //biosA0[0x6b] = psxBios_dev_card_erase;
3446 //biosA0[0x6c] = psxBios_dev_card_undelete;
3447 //biosA0[0x6d] = psxBios_dev_card_format;
3448 //biosA0[0x6e] = psxBios_dev_card_rename;
3449 //biosA0[0x6f] = psxBios_dev_card_6f;
3450 biosA0[0x70] = psxBios__bu_init;
3451 biosA0[0x71] = psxBios__96_init;
3452 biosA0[0x72] = psxBios_CdRemove;
3453 //biosA0[0x73] = psxBios_sys_a0_73;
3454 //biosA0[0x74] = psxBios_sys_a0_74;
3455 //biosA0[0x75] = psxBios_sys_a0_75;
3456 //biosA0[0x76] = psxBios_sys_a0_76;
3457 //biosA0[0x77] = psxBios_sys_a0_77;
3458 //biosA0[0x78] = psxBios__96_CdSeekL;
3459 //biosA0[0x79] = psxBios_sys_a0_79;
3460 //biosA0[0x7a] = psxBios_sys_a0_7a;
3461 //biosA0[0x7b] = psxBios_sys_a0_7b;
3462 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3463 //biosA0[0x7d] = psxBios_sys_a0_7d;
3464 //biosA0[0x7e] = psxBios__96_CdRead;
3465 //biosA0[0x7f] = psxBios_sys_a0_7f;
3466 //biosA0[0x80] = psxBios_sys_a0_80;
3467 //biosA0[0x81] = psxBios_sys_a0_81;
3468 //biosA0[0x82] = psxBios_sys_a0_82;
3469 //biosA0[0x83] = psxBios_sys_a0_83;
3470 //biosA0[0x84] = psxBios_sys_a0_84;
3471 //biosA0[0x85] = psxBios__96_CdStop;
3472 //biosA0[0x86] = psxBios_sys_a0_86;
3473 //biosA0[0x87] = psxBios_sys_a0_87;
3474 //biosA0[0x88] = psxBios_sys_a0_88;
3475 //biosA0[0x89] = psxBios_sys_a0_89;
3476 //biosA0[0x8a] = psxBios_sys_a0_8a;
3477 //biosA0[0x8b] = psxBios_sys_a0_8b;
3478 //biosA0[0x8c] = psxBios_sys_a0_8c;
3479 //biosA0[0x8d] = psxBios_sys_a0_8d;
3480 //biosA0[0x8e] = psxBios_sys_a0_8e;
3481 //biosA0[0x8f] = psxBios_sys_a0_8f;
3482 biosA0[0x90] = hleExc0_1_2;
3483 biosA0[0x91] = hleExc0_0_2;
3484 biosA0[0x92] = hleExc0_1_1;
3485 biosA0[0x93] = hleExc0_0_1;
3486 //biosA0[0x94] = psxBios_sys_a0_94;
3487 //biosA0[0x95] = psxBios_sys_a0_95;
3488 //biosA0[0x96] = psxBios_AddCDROMDevice;
3489 //biosA0[0x97] = psxBios_AddMemCardDevide;
3490 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3491 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3492 //biosA0[0x9a] = psxBios_sys_a0_9a;
3493 //biosA0[0x9b] = psxBios_sys_a0_9b;
3494 biosA0[0x9c] = psxBios_SetConf;
3495 biosA0[0x9d] = psxBios_GetConf;
3496 //biosA0[0x9e] = psxBios_sys_a0_9e;
3497 biosA0[0x9f] = psxBios_SetMem;
3498 //biosA0[0xa0] = psxBios__boot;
3499 //biosA0[0xa1] = psxBios_SystemError;
3500 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3501 biosA0[0xa3] = psxBios_DequeueCdIntr;
3502 //biosA0[0xa4] = psxBios_sys_a0_a4;
3503 //biosA0[0xa5] = psxBios_ReadSector;
3504 biosA0[0xa6] = psxBios_get_cd_status;
3505 //biosA0[0xa7] = psxBios_bufs_cb_0;
3506 //biosA0[0xa8] = psxBios_bufs_cb_1;
3507 //biosA0[0xa9] = psxBios_bufs_cb_2;
3508 //biosA0[0xaa] = psxBios_bufs_cb_3;
3509 biosA0[0xab] = psxBios__card_info;
3510 biosA0[0xac] = psxBios__card_load;
3511 //biosA0[0axd] = psxBios__card_auto;
3512 //biosA0[0xae] = psxBios_bufs_cd_4;
3513 //biosA0[0xaf] = psxBios_sys_a0_af;
3514 //biosA0[0xb0] = psxBios_sys_a0_b0;
3515 //biosA0[0xb1] = psxBios_sys_a0_b1;
3516 //biosA0[0xb2] = psxBios_do_a_long_jmp
3517 //biosA0[0xb3] = psxBios_sys_a0_b3;
3518 biosA0[0xb4] = psxBios_GetSystemInfo;
3519 //*******************B0 CALLS****************************
3520 biosB0[0x00] = psxBios_SysMalloc;
3521 //biosB0[0x01] = psxBios_sys_b0_01;
3522 biosB0[0x02] = psxBios_SetRCnt;
3523 biosB0[0x03] = psxBios_GetRCnt;
3524 biosB0[0x04] = psxBios_StartRCnt;
3525 biosB0[0x05] = psxBios_StopRCnt;
3526 biosB0[0x06] = psxBios_ResetRCnt;
3527 biosB0[0x07] = psxBios_DeliverEvent;
3528 biosB0[0x08] = psxBios_OpenEvent;
3529 biosB0[0x09] = psxBios_CloseEvent;
3530 biosB0[0x0a] = psxBios_WaitEvent;
3531 biosB0[0x0b] = psxBios_TestEvent;
3532 biosB0[0x0c] = psxBios_EnableEvent;
3533 biosB0[0x0d] = psxBios_DisableEvent;
3534 biosB0[0x0e] = psxBios_OpenTh;
3535 biosB0[0x0f] = psxBios_CloseTh;
3536 biosB0[0x10] = psxBios_ChangeTh;
3537 //biosB0[0x11] = psxBios_psxBios_b0_11;
3538 biosB0[0x12] = psxBios_InitPAD;
3539 biosB0[0x13] = psxBios_StartPAD;
3540 biosB0[0x14] = psxBios_StopPAD;
3541 biosB0[0x15] = psxBios_PAD_init;
3542 biosB0[0x16] = psxBios_PAD_dr;
3543 biosB0[0x17] = psxBios_ReturnFromException;
3544 biosB0[0x18] = psxBios_ResetEntryInt;
3545 biosB0[0x19] = psxBios_HookEntryInt;
3546 //biosB0[0x1a] = psxBios_sys_b0_1a;
3547 //biosB0[0x1b] = psxBios_sys_b0_1b;
3548 //biosB0[0x1c] = psxBios_sys_b0_1c;
3549 //biosB0[0x1d] = psxBios_sys_b0_1d;
3550 //biosB0[0x1e] = psxBios_sys_b0_1e;
3551 //biosB0[0x1f] = psxBios_sys_b0_1f;
3552 biosB0[0x20] = psxBios_UnDeliverEvent;
3553 //biosB0[0x21] = psxBios_sys_b0_21;
3554 //biosB0[0x22] = psxBios_sys_b0_22;
3555 //biosB0[0x23] = psxBios_sys_b0_23;
3556 //biosB0[0x24] = psxBios_sys_b0_24;
3557 //biosB0[0x25] = psxBios_sys_b0_25;
3558 //biosB0[0x26] = psxBios_sys_b0_26;
3559 //biosB0[0x27] = psxBios_sys_b0_27;
3560 //biosB0[0x28] = psxBios_sys_b0_28;
3561 //biosB0[0x29] = psxBios_sys_b0_29;
3562 //biosB0[0x2a] = psxBios_sys_b0_2a;
3563 //biosB0[0x2b] = psxBios_sys_b0_2b;
3564 //biosB0[0x2c] = psxBios_sys_b0_2c;
3565 //biosB0[0x2d] = psxBios_sys_b0_2d;
3566 //biosB0[0x2e] = psxBios_sys_b0_2e;
3567 //biosB0[0x2f] = psxBios_sys_b0_2f;
3568 //biosB0[0x30] = psxBios_sys_b0_30;
3569 //biosB0[0x31] = psxBios_sys_b0_31;
3570 biosB0[0x32] = psxBios_open;
3571 biosB0[0x33] = psxBios_lseek;
3572 biosB0[0x34] = psxBios_read;
3573 biosB0[0x35] = psxBios_write;
3574 biosB0[0x36] = psxBios_close;
3575 //biosB0[0x37] = psxBios_ioctl;
3576 //biosB0[0x38] = psxBios_exit;
3577 //biosB0[0x39] = psxBios_sys_b0_39;
3578 //biosB0[0x3a] = psxBios_getc;
3579 //biosB0[0x3b] = psxBios_putc;
3580 biosB0[0x3c] = psxBios_getchar;
3581 biosB0[0x3d] = psxBios_putchar;
3582 //biosB0[0x3e] = psxBios_gets;
3583 biosB0[0x3f] = psxBios_puts;
3584 biosB0[0x40] = psxBios_cd;
3585 biosB0[0x41] = psxBios_format;
3586 biosB0[0x42] = psxBios_firstfile;
3587 biosB0[0x43] = psxBios_nextfile;
3588 biosB0[0x44] = psxBios_rename;
3589 biosB0[0x45] = psxBios_delete;
3590 //biosB0[0x46] = psxBios_undelete;
3591 //biosB0[0x47] = psxBios_AddDevice;
3592 //biosB0[0x48] = psxBios_RemoteDevice;
3593 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3594 biosB0[0x4a] = psxBios_InitCARD;
3595 biosB0[0x4b] = psxBios_StartCARD;
3596 biosB0[0x4c] = psxBios_StopCARD;
3597 //biosB0[0x4d] = psxBios_sys_b0_4d;
3598 biosB0[0x4e] = psxBios__card_write;
3599 biosB0[0x4f] = psxBios__card_read;
3600 biosB0[0x50] = psxBios__new_card;
3601 biosB0[0x51] = psxBios_Krom2RawAdd;
3602 //biosB0[0x52] = psxBios_sys_b0_52;
3603 //biosB0[0x53] = psxBios_sys_b0_53;
3604 //biosB0[0x54] = psxBios__get_errno;
3605 biosB0[0x55] = psxBios__get_error;
3606 biosB0[0x56] = psxBios_GetC0Table;
3607 biosB0[0x57] = psxBios_GetB0Table;
3608 biosB0[0x58] = psxBios__card_chan;
3609 //biosB0[0x59] = psxBios_sys_b0_59;
3610 //biosB0[0x5a] = psxBios_sys_b0_5a;
3611 biosB0[0x5b] = psxBios_ChangeClearPad;
3612 biosB0[0x5c] = psxBios__card_status;
3613 biosB0[0x5d] = psxBios__card_wait;
3614 //*******************C0 CALLS****************************
3615 biosC0[0x00] = psxBios_InitRCnt;
3616 biosC0[0x01] = psxBios_InitException;
3617 biosC0[0x02] = psxBios_SysEnqIntRP;
3618 biosC0[0x03] = psxBios_SysDeqIntRP;
3619 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3620 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3621 //biosC0[0x06] = psxBios_ExceptionHandler;
3622 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3623 biosC0[0x08] = psxBios_SysInitMemory;
3624 //biosC0[0x09] = psxBios_SysInitKMem;
3625 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3626 //biosC0[0x0b] = psxBios_SystemError;
3627 biosC0[0x0c] = psxBios_InitDefInt;
3628 //biosC0[0x0d] = psxBios_sys_c0_0d;
3629 //biosC0[0x0e] = psxBios_sys_c0_0e;
3630 //biosC0[0x0f] = psxBios_sys_c0_0f;
3631 //biosC0[0x10] = psxBios_sys_c0_10;
3632 //biosC0[0x11] = psxBios_sys_c0_11;
3633 //biosC0[0x12] = psxBios_InstallDevices;
3634 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3635 //biosC0[0x14] = psxBios_sys_c0_14;
3636 //biosC0[0x15] = psxBios__cdevinput;
3637 //biosC0[0x16] = psxBios__cdevscan;
3638 //biosC0[0x17] = psxBios__circgetc;
3639 //biosC0[0x18] = psxBios__circputc;
3640 //biosC0[0x19] = psxBios_ioabort;
3641 //biosC0[0x1a] = psxBios_sys_c0_1a
3642 //biosC0[0x1b] = psxBios_KernelRedirect;
3643 //biosC0[0x1c] = psxBios_PatchAOTable;
3644 //************** THE END ***************************************
3647 memset(FDesc, 0, sizeof(FDesc));
3648 memset(cdir, 0, sizeof(cdir));
3651 // somewhat pretend to be a SCPH1001 BIOS
3652 // some games look for these and take an exception if they're missing
3653 rom32 = (u32 *)psxR;
3654 rom32[0x100/4] = SWAP32(0x19951204);
3655 rom32[0x104/4] = SWAP32(3);
3656 romc = (char *)psxR;
3657 strcpy(romc + 0x108, "PCSX authors");
3658 strcpy(romc + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3659 strcpy(romc + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3660 strcpy(romc + 0x7ff54, "GPL-2.0-or-later");
3663 len = 0x80000 - 0x66000;
3664 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3665 len = 0x80000 - 0x69d68;
3666 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3668 // trap attempts to call bios directly
3669 rom32[0x00000/4] = HLEOP(hleop_dummy);
3670 rom32[0x00180/4] = HLEOP(hleop_dummy);
3671 rom32[0x3fffc/4] = HLEOP(hleop_dummy);
3672 rom32[0x65ffc/4] = HLEOP(hleop_dummy);
3673 rom32[0x7ff2c/4] = HLEOP(hleop_dummy);
3675 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3676 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3677 Here are some examples of games not working with this fix in place :
3678 R-type won't get past the Irem logo if not implemented.
3679 Crash Team Racing will softlock after the Sony logo.
3682 ram32 = (u32 *)psxM;
3683 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3684 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3685 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3686 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3688 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3689 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3691 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3692 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3693 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3694 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3696 ram32[0x00a0/4] = HLEOP(hleop_a0);
3697 ram32[0x00b0/4] = HLEOP(hleop_b0);
3698 ram32[0x00c0/4] = HLEOP(hleop_c0);
3700 setup_tt(4, 16, 0x801fff00);
3701 DeliverEvent(0xf0000003, 0x0010);
3703 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3704 strcpy((char *)&ram32[0xeff0/4], "bu");
3706 // default exception handler chains
3707 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3708 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3709 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3710 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3711 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3712 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3713 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3714 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3718 // fill the api jumptables with fake entries as some games patch them
3719 // (or rather the funcs listed there)
3720 ptr = (u32 *)&psxM[A_A0_TABLE];
3721 for (i = 0; i < 256; i++)
3722 ptr[i] = SWAP32(0x1000);
3724 ptr = (u32 *)&psxM[A_B0_TABLE];
3725 for (i = 0; i < 256; i++)
3726 ptr[i] = SWAP32(0x2000);
3727 // B(5b) is special because games patch (sometimes even jump to)
3728 // code at fixed offsets from it, nocash lists offsets:
3729 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3730 // call: +7a0=4b70, +884=4c54, +894=4c64
3731 ptr[0x5b] = SWAP32(0x43d0);
3732 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3734 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3735 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3736 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3738 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3739 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3741 ptr = (u32 *)&psxM[A_C0_TABLE];
3742 for (i = 0; i < 256/2; i++)
3743 ptr[i] = SWAP32(0x3000);
3744 ptr[6] = SWAP32(A_EXCEPTION);
3747 ram32[0x1000/4] = HLEOP(hleop_dummy);
3748 ram32[0x2000/4] = HLEOP(hleop_dummy);
3749 ram32[0x3000/4] = HLEOP(hleop_dummy);
3750 ram32[0x8000/4] = HLEOP(hleop_execret);
3752 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3753 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3754 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3755 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3756 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3757 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3758 ram32[A_RND_SEED/4] = SWAPu32(0x24040001); // was 0xac20cc00
3761 void psxBiosShutdown() {
3764 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 stack) {
3767 if (tcb_cnt != 4 || evcb_cnt != 16) {
3768 setup_tt(tcb_cnt, evcb_cnt, stack);
3769 DeliverEvent(0xf0000003, 0x0010);
3771 storeRam32(A_CONF_SP, stack);
3774 #define psxBios_PADpoll(pad) { \
3775 int i, more_data = 0; \
3776 PAD##pad##_startPoll(pad); \
3777 pad_buf##pad[1] = PAD##pad##_poll(0x42, &more_data); \
3778 pad_buf##pad[0] = more_data ? 0 : 0xff; \
3779 PAD##pad##_poll(0, &more_data); \
3781 while (more_data) { \
3782 pad_buf##pad[i++] = PAD##pad##_poll(0, &more_data); \
3786 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3790 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3791 psxBios_ReturnFromException();
3797 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3798 // so this is only partially implemented
3799 void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3801 u32 cdrom_dma_ack_enable = 1; // a000b93c
3802 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3805 void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3808 //PSXBIOS_LOG("%s\n", __func__);
3810 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3811 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3812 //if (--cdrom_irq_counter == 0) // 0xa0009180
3813 // DeliverEvent(0xf0000003, 0x10);
3817 mips_return_c(ret, 20);
3820 void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3822 u32 cdrom_irq_ack_enable = 1; // a000b938
3823 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3826 void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3829 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3830 PSXBIOS_LOG("%s TODO\n", __func__);
3833 mips_return_c(ret, 20);
3836 void hleExc0_2_2_syscall() // not in any A/B/C table
3838 u32 tcbPtr = loadRam32(A_TT_PCB);
3839 TCB *tcb = loadRam32ptr(tcbPtr);
3840 u32 code = (SWAP32(tcb->cause) & 0x3c) >> 2;
3842 if (code != R3000E_Syscall) {
3844 DeliverEvent(0xf0000010, 0x1000);
3845 //psxBios_SystemErrorUnresolvedException();
3847 mips_return_c(0, 17);
3851 //printf("%s c=%d a0=%d\n", __func__, code, SWAP32(tcb->reg[4]));
3852 tcb->epc += SWAP32(4);
3853 switch (SWAP32(tcb->reg[4])) { // a0
3857 case 1: { // EnterCritical - disable irqs
3858 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3859 tcb->reg[2] = SWAP32(was_enabled);
3860 tcb->sr &= SWAP32(~0x404);
3863 case 2: // ExitCritical - enable irqs
3864 tcb->sr |= SWAP32(0x404);
3867 case 3: { // ChangeThreadSubFunction
3868 u32 tcbPtr = loadRam32(A_TT_PCB);
3869 storeRam32(tcbPtr, SWAP32(tcb->reg[5])); // a1
3873 DeliverEvent(0xf0000010, 0x4000);
3877 psxBios_ReturnFromException();
3880 void hleExc1_0_1(void)
3882 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3883 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3886 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3889 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3890 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3893 mips_return_c(ret, 22);
3896 void hleExc1_0_2(void)
3898 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3901 void hleExc1_1_1(void)
3903 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3904 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3907 void hleExc1_1_2(void)
3909 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3912 void hleExc1_2_1(void)
3914 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3915 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3918 void hleExc1_2_2(void)
3920 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3923 void hleExc1_3_1(void)
3925 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3926 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3929 void hleExc1_3_2(void)
3931 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3934 void hleExc3_0_2_defint(void)
3936 static const struct {
3947 { 6, 6 }, // rcnt2 (bug)
3952 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3953 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3954 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3959 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3962 void hleExcPadCard1(void)
3964 if (loadRam32(A_PAD_IRQR_ENA)) {
3965 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3966 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
3971 if (loadRam32(A_PAD_DR_DST))
3974 if (loadRam32(A_PAD_ACK_VBL))
3975 psxHwWrite16(0x1f801070, ~1);
3976 if (loadRam32(A_CARD_IRQR_ENA)) {
3980 mips_return_c(0, 18);
3983 void hleExcPadCard2(void)
3985 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
3986 mips_return_c(ret, 15);
3989 void psxBiosException() {
3990 u32 tcbPtr = loadRam32(A_TT_PCB);
3991 u32 *chains = loadRam32ptr(A_TT_ExCB);
3992 TCB *tcb = loadRam32ptr(tcbPtr);
3998 // $at, $v0, $v1, $ra already saved by the mips code at A_EXCEPTION
3999 for (i = 4; i < 31; i++) {
4002 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
4004 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
4005 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
4006 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
4007 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
4008 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
4009 sp = fp = loadRam32(A_EXC_SP);
4013 // do the chains (always 4)
4014 for (c = lim = 0; c < 4; c++) {
4015 if (chains[c * 2] == 0)
4017 ptr = SWAP32(chains[c * 2]);
4018 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
4019 chain = castRam32ptr(ptr);
4024 softCallInException(SWAP32(chain[2]));
4025 if (returned_from_exception())
4028 if (v0 == 0 || chain[1] == 0)
4030 softCallInException(SWAP32(chain[1]));
4031 if (returned_from_exception())
4037 // return from exception (custom or default)
4039 ptr = loadRam32(A_EEXIT_PTR);
4040 if (ptr != A_EEXIT_DEF) {
4041 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
4042 longjmp_load(jmp_buf);
4047 psxBios_ReturnFromException();
4050 #define bfreeze(ptr, size) { \
4051 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
4052 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
4056 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
4057 #define bfreezel(ptr) bfreeze(ptr, sizeof(*(ptr)))
4059 void psxBiosFreeze(int Mode) {