log unhandled io more clearly
[pcsx_rearmed.git] / libpcsxcore / psxbios.c
CommitLineData
ef79bbde 1/***************************************************************************
8254b5a7 2 * Copyright (C) 2019 Ryan Schultz, PCSX-df Team, PCSX team, gameblabla, *
3 * dmitrysmagin, senquack *
ef79bbde
P
4 * *
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. *
9 * *
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. *
14 * *
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 ***************************************************************************/
20
7a8d521f 21/* Gameblabla 2018-2019 :
8254b5a7 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.
25 * */
26
ef79bbde
P
27/*
28 * Internal simulated HLE BIOS.
29 */
30
31// TODO: implement all system calls, count the exact CPU cycles of system calls.
32
33#include "psxbios.h"
34#include "psxhw.h"
ddbaf678 35#include "gpu.h"
7a8d521f 36#include "sio.h"
dc4fa8bc 37#include "psxhle.h"
496d88d4 38#include <zlib.h>
ef79bbde 39
3cf51e08 40#if (defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)
41#pragma GCC diagnostic ignored "-Wpointer-sign"
42#endif
43
452b85f9 44#undef SysPrintf
45#define SysPrintf if (Config.PsxOut) printf
46
ef79bbde
P
47char *biosA0n[256] = {
48// 0x00
49 "open", "lseek", "read", "write",
50 "close", "ioctl", "exit", "sys_a0_07",
51 "getc", "putc", "todigit", "atof",
52 "strtoul", "strtol", "abs", "labs",
53// 0x10
54 "atoi", "atol", "atob", "setjmp",
55 "longjmp", "strcat", "strncat", "strcmp",
56 "strncmp", "strcpy", "strncpy", "strlen",
57 "index", "rindex", "strchr", "strrchr",
58// 0x20
59 "strpbrk", "strspn", "strcspn", "strtok",
60 "strstr", "toupper", "tolower", "bcopy",
61 "bzero", "bcmp", "memcpy", "memset",
62 "memmove", "memcmp", "memchr", "rand",
63// 0x30
64 "srand", "qsort", "strtod", "malloc",
65 "free", "lsearch", "bsearch", "calloc",
66 "realloc", "InitHeap", "_exit", "getchar",
67 "putchar", "gets", "puts", "printf",
68// 0x40
69 "sys_a0_40", "LoadTest", "Load", "Exec",
70 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
71 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
72 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
73// 0x50
74 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
75 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
76 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
77 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
78// 0x60
79 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
80 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
81 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
82 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
83// 0x70
dc4fa8bc 84 "_bu_init", "_96_init", "CdRemove", "sys_a0_73",
ef79bbde
P
85 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
86 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
87 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
88// 0x80
89 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
90 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
91 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
92 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
93// 0x90
94 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
95 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
96 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
97 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
98// 0xa0
99 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
100 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
101 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
102 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
103// 0xb0
104 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
105 "?? sub_function",
106};
107
108char *biosB0n[256] = {
109// 0x00
110 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
111 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
112 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
113 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
114// 0x10
115 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
116 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
117 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
118 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
119// 0x20
120 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
121 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
122 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
123 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
124// 0x30
125 "sys_b0_30", "sys_b0_31", "open", "lseek",
126 "read", "write", "close", "ioctl",
127 "exit", "sys_b0_39", "getc", "putc",
128 "getchar", "putchar", "gets", "puts",
129// 0x40
130 "cd", "format", "firstfile", "nextfile",
131 "rename", "delete", "undelete", "AddDevice",
132 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
133 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
134// 0x50
135 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
136 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
137 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
138 "_card_status", "_card_wait",
139};
140
141char *biosC0n[256] = {
142// 0x00
143 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
144 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
145 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
146 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
147// 0x10
148 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
149 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
150 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
151 "PatchAOTable",
152};
153
154//#define r0 (psxRegs.GPR.n.r0)
155#define at (psxRegs.GPR.n.at)
156#define v0 (psxRegs.GPR.n.v0)
157#define v1 (psxRegs.GPR.n.v1)
158#define a0 (psxRegs.GPR.n.a0)
159#define a1 (psxRegs.GPR.n.a1)
160#define a2 (psxRegs.GPR.n.a2)
161#define a3 (psxRegs.GPR.n.a3)
162#define t0 (psxRegs.GPR.n.t0)
163#define t1 (psxRegs.GPR.n.t1)
164#define t2 (psxRegs.GPR.n.t2)
165#define t3 (psxRegs.GPR.n.t3)
166#define t4 (psxRegs.GPR.n.t4)
167#define t5 (psxRegs.GPR.n.t5)
168#define t6 (psxRegs.GPR.n.t6)
169#define t7 (psxRegs.GPR.n.t7)
170#define t8 (psxRegs.GPR.n.t8)
171#define t9 (psxRegs.GPR.n.t9)
172#define s0 (psxRegs.GPR.n.s0)
173#define s1 (psxRegs.GPR.n.s1)
174#define s2 (psxRegs.GPR.n.s2)
175#define s3 (psxRegs.GPR.n.s3)
176#define s4 (psxRegs.GPR.n.s4)
177#define s5 (psxRegs.GPR.n.s5)
178#define s6 (psxRegs.GPR.n.s6)
179#define s7 (psxRegs.GPR.n.s7)
180#define k0 (psxRegs.GPR.n.k0)
181#define k1 (psxRegs.GPR.n.k1)
182#define gp (psxRegs.GPR.n.gp)
183#define sp (psxRegs.GPR.n.sp)
184#define fp (psxRegs.GPR.n.s8)
185#define ra (psxRegs.GPR.n.ra)
186#define pc0 (psxRegs.pc)
187
188#define Ra0 ((char *)PSXM(a0))
189#define Ra1 ((char *)PSXM(a1))
190#define Ra2 ((char *)PSXM(a2))
191#define Ra3 ((char *)PSXM(a3))
192#define Rv0 ((char *)PSXM(v0))
193#define Rsp ((char *)PSXM(sp))
194
195typedef struct {
196 u32 desc;
197 s32 status;
198 s32 mode;
199 u32 fhandler;
200} EvCB[32];
201
202#define EvStUNUSED 0x0000
203#define EvStWAIT 0x1000
204#define EvStACTIVE 0x2000
205#define EvStALREADY 0x4000
206
207#define EvMdINTR 0x1000
208#define EvMdNOINTR 0x2000
209
210/*
211typedef struct {
212 s32 next;
213 s32 func1;
214 s32 func2;
215 s32 pad;
216} SysRPst;
217*/
218
219typedef struct {
dc4fa8bc 220 u32 status;
221 u32 mode;
ef79bbde 222 u32 reg[32];
dc4fa8bc 223 u32 epc;
224 u32 hi, lo;
225 u32 sr, cause;
226 u32 unused[9];
ef79bbde
P
227} TCB;
228
7a8d521f 229typedef struct {
ef79bbde
P
230 u32 _pc0;
231 u32 gp0;
232 u32 t_addr;
233 u32 t_size;
234 u32 d_addr;
235 u32 d_size;
236 u32 b_addr;
237 u32 b_size;
238 u32 S_addr;
239 u32 s_size;
240 u32 _sp, _fp, _gp, ret, base;
241} EXEC;
242
243struct DIRENTRY {
244 char name[20];
245 s32 attr;
246 s32 size;
247 u32 next;
248 s32 head;
249 char system[4];
250};
251
252typedef struct {
253 char name[32];
254 u32 mode;
255 u32 offset;
256 u32 size;
257 u32 mcfile;
258} FileDesc;
259
ef79bbde
P
260static int *pad_buf = NULL;
261static char *pad_buf1 = NULL, *pad_buf2 = NULL;
262static int pad_buf1len, pad_buf2len;
f25c285b 263static int pad_stopped = 0;
ef79bbde
P
264
265static u32 regs[35];
7a8d521f 266static EvCB *EventCB;
ef79bbde
P
267static EvCB *HwEV; // 0xf0
268static EvCB *EvEV; // 0xf1
269static EvCB *RcEV; // 0xf2
270static EvCB *UeEV; // 0xf3
271static EvCB *SwEV; // 0xf4
272static EvCB *ThEV; // 0xff
26b964b5 273static u32 heap_size = 0;
ef79bbde
P
274static u32 *heap_addr = NULL;
275static u32 *heap_end = NULL;
ef79bbde 276static int CardState = -1;
ef79bbde
P
277static int CurThread = 0;
278static FileDesc FDesc[32];
7a8d521f 279static u32 card_active_chan = 0;
ef79bbde 280
dc4fa8bc 281// fixed RAM offsets, SCPH1001 compatible
282#define A_TT_ExCB 0x0100
283#define A_TT_PCB 0x0108
284#define A_TT_TCB 0x0110
285#define A_A0_TABLE 0x0200
286#define A_B0_TABLE 0x0874
287#define A_C0_TABLE 0x0674
288#define A_SYSCALL 0x0650
289#define A_EXCEPTION 0x0c80
290#define A_EXC_SP 0x6cf0
291#define A_EEXIT_DEF 0x6cf4
7650b754 292#define A_KMALLOC_PTR 0x7460
293#define A_KMALLOC_SIZE 0x7464
294#define A_KMALLOC_END 0x7468
dc4fa8bc 295#define A_EEXIT_PTR 0x75d0
296#define A_EXC_STACK 0x85d8 // exception stack top
297#define A_RCNT_VBL_ACK 0x8600
298#define A_EXC_GP 0xf450
299
300#define HLEOP(n) SWAPu32((0x3b << 26) | (n));
301
302static u32 loadRam32(u32 addr)
303{
304 assert(!(addr & 0x5f800000));
305 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
306}
ef79bbde 307
dc4fa8bc 308static void *castRam32ptr(u32 addr)
309{
310 assert(!(addr & 0x5f800003));
311 return psxM + (addr & 0x1ffffc);
312}
313
314static void *loadRam32ptr(u32 addr)
315{
316 return castRam32ptr(loadRam32(addr));
317}
318
319static void storeRam32(u32 addr, u32 d)
320{
321 assert(!(addr & 0x5f800000));
322 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
323}
ef79bbde 324
dc4fa8bc 325static void mips_return(u32 val)
326{
327 v0 = val;
328 pc0 = ra;
329}
ef79bbde 330
dc4fa8bc 331static void use_cycles(u32 cycle)
332{
333 psxRegs.cycle += cycle * 2;
334}
ef79bbde 335
dc4fa8bc 336static void mips_return_c(u32 val, u32 cycle)
337{
338 use_cycles(cycle);
339 mips_return(val);
ef79bbde
P
340}
341
dc4fa8bc 342static void mips_return_void_c(u32 cycle)
343{
344 use_cycles(cycle);
345 pc0 = ra;
346}
347
348static int returned_from_exception(void)
349{
350 // 0x80000080 means it took another exception just after return
351 return pc0 == k0 || pc0 == 0x80000080;
352}
353
354static inline void softCall(u32 pc) {
ef79bbde 355 u32 sra = ra;
dc4fa8bc 356 u32 ssr = psxRegs.CP0.n.SR;
ef79bbde
P
357 pc0 = pc;
358 ra = 0x80001000;
dc4fa8bc 359 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
ef79bbde 360
dc4fa8bc 361 while (pc0 != 0x80001000)
362 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
ef79bbde 363
ef79bbde 364 ra = sra;
dc4fa8bc 365 psxRegs.CP0.n.SR = ssr;
366}
ef79bbde 367
dc4fa8bc 368static inline void softCallInException(u32 pc) {
369 u32 sra = ra;
370 pc0 = pc;
371 ra = 0x80001000;
372
373 while (!returned_from_exception() && pc0 != 0x80001000)
374 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
375
376 if (pc0 == 0x80001000)
377 ra = sra;
ef79bbde
P
378}
379
380static inline void DeliverEvent(u32 ev, u32 spec) {
7a8d521f 381 if (EventCB[ev][spec].status != EvStACTIVE) return;
ef79bbde 382
7a8d521f 383// EventCB[ev][spec].status = EvStALREADY;
384 if (EventCB[ev][spec].mode == EvMdINTR) {
dc4fa8bc 385 softCall(EventCB[ev][spec].fhandler);
7a8d521f 386 } else EventCB[ev][spec].status = EvStALREADY;
ef79bbde
P
387}
388
ef79bbde
P
389/* *
390// *
391// *
392// System calls A0 */
393
d99f6068 394
395#define buread(Ra1, mcd, length) { \
396 SysPrintf("read %d: %x,%x (%s)\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2, Mcd##mcd##Data + 128 * FDesc[1 + mcd].mcfile + 0xa); \
397 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
398 memcpy(Ra1, ptr, length); \
f1514614 399 if (FDesc[1 + mcd].mode & 0x8000) { \
d99f6068 400 DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
401 DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
f1514614 402 v0 = 0; } \
d99f6068 403 else v0 = length; \
404 FDesc[1 + mcd].offset += v0; \
405}
406
407#define buwrite(Ra1, mcd, length) { \
408 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
409 SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
410 ptr = Mcd##mcd##Data + offset; \
411 memcpy(ptr, Ra1, length); \
f1514614 412 FDesc[1 + mcd].offset += length; \
e49ac7a5 413 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
f1514614 414 if (FDesc[1 + mcd].mode & 0x8000) { \
d99f6068 415 DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
416 DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
f1514614 417 v0 = 0; } \
d99f6068 418 else v0 = length; \
419}
420
dc4fa8bc 421#ifndef PSXBIOS_LOG
422//#define PSXBIOS_LOG printf
423#define PSXBIOS_LOG(...)
424#endif
d99f6068 425
324cec89 426/* Internally redirects to "FileRead(fd,tempbuf,1)".*/
427/* For some strange reason, the returned character is sign-expanded; */
428/* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
429/* TODO FIX ME : Properly implement this behaviour */
430void psxBios_getc(void) // 0x03, 0x35
431{
d99f6068 432 char *ptr;
324cec89 433 void *pa1 = Ra1;
434#ifdef PSXBIOS_LOG
435 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
436#endif
437 v0 = -1;
438
7a8d521f 439 if (pa1 != INVALID_PTR) {
324cec89 440 switch (a0) {
441 case 2: buread(pa1, 1, 1); break;
442 case 3: buread(pa1, 2, 1); break;
443 }
444 }
445
446 pc0 = ra;
447}
448
449/* Copy of psxBios_write, except size is 1. */
450void psxBios_putc(void) // 0x09, 0x3B
451{
d99f6068 452 char *ptr;
324cec89 453 void *pa1 = Ra1;
454#ifdef PSXBIOS_LOG
455 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
456#endif
457 v0 = -1;
7a8d521f 458 if (pa1 == INVALID_PTR) {
324cec89 459 pc0 = ra;
460 return;
461 }
462
463 if (a0 == 1) { // stdout
464 char *ptr = (char *)pa1;
465
466 v0 = a2;
467 while (a2 > 0) {
468 printf("%c", *ptr++); a2--;
469 }
470 pc0 = ra; return;
471 }
472
473 switch (a0) {
474 case 2: buwrite(pa1, 1, 1); break;
475 case 3: buwrite(pa1, 2, 1); break;
476 }
477
478 pc0 = ra;
479}
ef79bbde 480
ba11675c 481void psxBios_todigit(void) // 0x0a
482{
483 int c = a0;
484#ifdef PSXBIOS_LOG
485 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
486#endif
487 c &= 0xFF;
488 if (c >= 0x30 && c < 0x3A) {
489 c -= 0x30;
490 }
491 else if (c > 0x60 && c < 0x7B) {
492 c -= 0x20;
493 }
494 else if (c > 0x40 && c < 0x5B) {
495 c = c - 0x41 + 10;
496 }
497 else if (c >= 0x80) {
498 c = -1;
499 }
500 else
501 {
502 c = 0x0098967F;
503 }
504 v0 = c;
505 pc0 = ra;
506}
507
ef79bbde
P
508void psxBios_abs() { // 0x0e
509 if ((s32)a0 < 0) v0 = -(s32)a0;
510 else v0 = a0;
511 pc0 = ra;
512}
513
514void psxBios_labs() { // 0x0f
515 psxBios_abs();
516}
517
518void psxBios_atoi() { // 0x10
519 s32 n = 0, f = 0;
520 char *p = (char *)Ra0;
521
522 for (;;p++) {
523 switch (*p) {
524 case ' ': case '\t': continue;
525 case '-': f++;
526 case '+': p++;
527 }
528 break;
529 }
530
531 while (*p >= '0' && *p <= '9') {
532 n = n * 10 + *p++ - '0';
533 }
534
535 v0 = (f ? -n : n);
536 pc0 = ra;
537}
538
539void psxBios_atol() { // 0x11
540 psxBios_atoi();
541}
542
dc4fa8bc 543struct jmp_buf_ {
544 u32 ra_, sp_, fp_;
545 u32 s[8];
546 u32 gp_;
547};
548
549static void psxBios_setjmp() { // 0x13
550 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
ef79bbde
P
551 int i;
552
dc4fa8bc 553 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
ef79bbde 554
dc4fa8bc 555 jmp_buf->ra_ = SWAP32(ra);
556 jmp_buf->sp_ = SWAP32(sp);
557 jmp_buf->fp_ = SWAP32(fp);
ef79bbde 558 for (i = 0; i < 8; i++) // s0-s7
dc4fa8bc 559 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
560 jmp_buf->gp_ = SWAP32(gp);
ef79bbde 561
dc4fa8bc 562 mips_return_c(0, 15);
ef79bbde
P
563}
564
dc4fa8bc 565static void longjmp_load(const struct jmp_buf_ *jmp_buf)
566{
ef79bbde
P
567 int i;
568
dc4fa8bc 569 ra = SWAP32(jmp_buf->ra_);
570 sp = SWAP32(jmp_buf->sp_);
571 fp = SWAP32(jmp_buf->fp_);
ef79bbde 572 for (i = 0; i < 8; i++) // s0-s7
dc4fa8bc 573 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
574 gp = SWAP32(jmp_buf->gp_);;
575}
ef79bbde 576
dc4fa8bc 577void psxBios_longjmp() { // 0x14
578 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
579
580 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
581 longjmp_load(jmp_buf);
582 mips_return_c(a1, 15);
ef79bbde
P
583}
584
585void psxBios_strcat() { // 0x15
586 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
587
588#ifdef PSXBIOS_LOG
589 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
590#endif
bee52312 591 if (a0 == 0 || a1 == 0)
592 {
593 v0 = 0;
594 pc0 = ra;
595 return;
596 }
ef79bbde
P
597 while (*p1++);
598 --p1;
599 while ((*p1++ = *p2++) != '\0');
600
601 v0 = a0; pc0 = ra;
602}
603
604void psxBios_strncat() { // 0x16
605 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
606 s32 n = a2;
607
608#ifdef PSXBIOS_LOG
609 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
610#endif
f42e1e90 611 if (a0 == 0 || a1 == 0)
612 {
613 v0 = 0;
614 pc0 = ra;
615 return;
616 }
ef79bbde
P
617 while (*p1++);
618 --p1;
619 while ((*p1++ = *p2++) != '\0') {
620 if (--n < 0) {
621 *--p1 = '\0';
622 break;
623 }
624 }
625
626 v0 = a0; pc0 = ra;
627}
628
629void psxBios_strcmp() { // 0x17
630 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
c044e3e5 631 s32 n=0;
632 if (a0 == 0 && a1 == 0)
633 {
634 v0 = 0;
635 pc0 = ra;
636 return;
637 }
638 else if (a0 == 0 && a1 != 0)
639 {
640 v0 = -1;
641 pc0 = ra;
642 return;
643 }
644 else if (a0 != 0 && a1 == 0)
645 {
646 v0 = 1;
647 pc0 = ra;
648 return;
649 }
ef79bbde
P
650#ifdef PSXBIOS_LOG
651 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
652#endif
653
654 while (*p1 == *p2++) {
c044e3e5 655 n++;
ef79bbde 656 if (*p1++ == '\0') {
c044e3e5 657 v1=n-1;
658 a0+=n;
659 a1+=n;
ef79bbde
P
660 v0 = 0;
661 pc0 = ra;
662 return;
663 }
664 }
665
666 v0 = (*p1 - *--p2);
c044e3e5 667 v1 = n;
668 a0+=n;
669 a1+=n;
ef79bbde
P
670 pc0 = ra;
671}
672
673void psxBios_strncmp() { // 0x18
674 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
675 s32 n = a2;
ba4ecb8c 676 if (a0 == 0 && a1 == 0)
677 {
678 v0 = 0;
679 pc0 = ra;
680 return;
681 }
682 else if (a0 == 0 && a1 != 0)
683 {
684 v0 = -1;
685 pc0 = ra;
686 return;
687 }
688 else if (a0 != 0 && a1 == 0)
689 {
690 v0 = 1;
691 pc0 = ra;
692 return;
693 }
ef79bbde
P
694#ifdef PSXBIOS_LOG
695 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
696#endif
697
698 while (--n >= 0 && *p1 == *p2++) {
699 if (*p1++ == '\0') {
700 v0 = 0;
701 pc0 = ra;
ba4ecb8c 702 v1 = a2 - ((a2-n) - 1);
703 a0 += (a2-n) - 1;
704 a1 += (a2-n) - 1;
705 a2 = n;
ef79bbde
P
706 return;
707 }
708 }
709
710 v0 = (n < 0 ? 0 : *p1 - *--p2);
711 pc0 = ra;
ba4ecb8c 712 v1 = a2 - ((a2-n) - 1);
713 a0 += (a2-n) - 1;
714 a1 += (a2-n) - 1;
715 a2 = n;
ef79bbde
P
716}
717
718void psxBios_strcpy() { // 0x19
719 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
c3d791f1 720 if (a0 == 0 || a1 == 0)
721 {
722 v0 = 0;
723 pc0 = ra;
724 return;
725 }
ef79bbde
P
726 while ((*p1++ = *p2++) != '\0');
727
728 v0 = a0; pc0 = ra;
729}
730
731void psxBios_strncpy() { // 0x1a
732 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
733 s32 n = a2, i;
c3d791f1 734 if (a0 == 0 || a1 == 0)
735 {
736 v0 = 0;
737 pc0 = ra;
738 return;
739 }
ef79bbde
P
740 for (i = 0; i < n; i++) {
741 if ((*p1++ = *p2++) == '\0') {
742 while (++i < n) {
743 *p1++ = '\0';
744 }
745 v0 = a0; pc0 = ra;
746 return;
747 }
748 }
749
750 v0 = a0; pc0 = ra;
751}
752
753void psxBios_strlen() { // 0x1b
754 char *p = (char *)Ra0;
755 v0 = 0;
2c6a5df8 756 if (a0 == 0)
757 {
758 pc0 = ra;
759 return;
760 }
ef79bbde
P
761 while (*p++) v0++;
762 pc0 = ra;
763}
764
765void psxBios_index() { // 0x1c
766 char *p = (char *)Ra0;
fcf7ec6c 767 if (a0 == 0)
768 {
769 v0 = 0;
770 pc0 = ra;
771 return;
772 }
7a8d521f 773
ef79bbde
P
774 do {
775 if (*p == a1) {
776 v0 = a0 + (p - (char *)Ra0);
777 pc0 = ra;
778 return;
779 }
780 } while (*p++ != '\0');
781
782 v0 = 0; pc0 = ra;
783}
784
785void psxBios_rindex() { // 0x1d
786 char *p = (char *)Ra0;
787
788 v0 = 0;
fcf7ec6c 789 if (a0 == 0)
790 {
791 pc0 = ra;
792 return;
793 }
ef79bbde
P
794 do {
795 if (*p == a1)
796 v0 = a0 + (p - (char *)Ra0);
797 } while (*p++ != '\0');
798
799 pc0 = ra;
800}
801
802void psxBios_strchr() { // 0x1e
803 psxBios_index();
804}
805
806void psxBios_strrchr() { // 0x1f
807 psxBios_rindex();
808}
809
810void psxBios_strpbrk() { // 0x20
811 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
812
813 while ((c = *p1++) != '\0') {
814 for (scanp = p2; (sc = *scanp++) != '\0';) {
815 if (sc == c) {
816 v0 = a0 + (p1 - 1 - (char *)Ra0);
817 pc0 = ra;
818 return;
819 }
820 }
821 }
822
823 // BUG: return a0 instead of NULL if not found
824 v0 = a0; pc0 = ra;
825}
826
827void psxBios_strspn() { // 0x21
828 char *p1, *p2;
829
830 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
831 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
832 if (*p2 == '\0') break;
833 }
834
835 v0 = p1 - (char *)Ra0; pc0 = ra;
836}
837
838void psxBios_strcspn() { // 0x22
839 char *p1, *p2;
840
841 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
842 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
843 if (*p2 != '\0') break;
844 }
845
846 v0 = p1 - (char *)Ra0; pc0 = ra;
847}
848
849void psxBios_strtok() { // 0x23
850 char *pcA0 = (char *)Ra0;
851 char *pcRet = strtok(pcA0, (char *)Ra1);
852 if (pcRet)
853 v0 = a0 + pcRet - pcA0;
854 else
855 v0 = 0;
856 pc0 = ra;
857}
858
859void psxBios_strstr() { // 0x24
860 char *p = (char *)Ra0, *p1, *p2;
861
862 while (*p != '\0') {
863 p1 = p;
864 p2 = (char *)Ra1;
865
866 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
867 p1++; p2++;
868 }
869
870 if (*p2 == '\0') {
871 v0 = a0 + (p - (char *)Ra0);
872 pc0 = ra;
873 return;
874 }
875
876 p++;
877 }
878
879 v0 = 0; pc0 = ra;
880}
881
882void psxBios_toupper() { // 0x25
883 v0 = (s8)(a0 & 0xff);
884 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
885 pc0 = ra;
886}
887
888void psxBios_tolower() { // 0x26
889 v0 = (s8)(a0 & 0xff);
890 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
891 pc0 = ra;
892}
893
894void psxBios_bcopy() { // 0x27
895 char *p1 = (char *)Ra1, *p2 = (char *)Ra0;
0148ffb7 896 v0 = a0;
897 if (a0 == 0 || a2 > 0x7FFFFFFF)
898 {
899 pc0 = ra;
900 return;
901 }
5ec7acdf 902 while ((s32)a2-- > 0) *p1++ = *p2++;
0148ffb7 903 a2 = 0;
ef79bbde
P
904 pc0 = ra;
905}
906
907void psxBios_bzero() { // 0x28
908 char *p = (char *)Ra0;
01724d23 909 v0 = a0;
910 /* Same as memset here (See memset below) */
911 if (a1 > 0x7FFFFFFF || a1 == 0)
912 {
913 v0 = 0;
914 pc0 = ra;
915 return;
916 }
917 else if (a0 == 0)
918 {
919 pc0 = ra;
920 return;
921 }
5ec7acdf 922 while ((s32)a1-- > 0) *p++ = '\0';
01724d23 923 a1 = 0;
ef79bbde
P
924 pc0 = ra;
925}
926
927void psxBios_bcmp() { // 0x29
928 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
929
930 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
931
5ec7acdf 932 while ((s32)a2-- > 0) {
ef79bbde
P
933 if (*p1++ != *p2++) {
934 v0 = *p1 - *p2; // BUG: compare the NEXT byte
935 pc0 = ra;
936 return;
937 }
938 }
939
940 v0 = 0; pc0 = ra;
941}
942
943void psxBios_memcpy() { // 0x2a
944 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
ef1da3dc 945 v0 = a0;
946 if (a0 == 0 || a2 > 0x7FFFFFFF)
947 {
948 pc0 = ra;
949 return;
950 }
951 while ((s32)a2-- > 0) {
ef1da3dc 952 *p1++ = *p2++;
953 }
954 a2 = 0;
955 pc0 = ra;
ef79bbde
P
956}
957
958void psxBios_memset() { // 0x2b
959 char *p = (char *)Ra0;
3f28b64f 960 v0 = a0;
961 if (a2 > 0x7FFFFFFF || a2 == 0)
962 {
963 v0 = 0;
964 pc0 = ra;
965 return;
966 }
967 if (a0 == 0)
968 {
969 pc0 = ra;
970 return;
971 }
5ec7acdf 972 while ((s32)a2-- > 0) *p++ = (char)a1;
5ec7acdf 973 a2 = 0;
ef79bbde
P
974 v0 = a0; pc0 = ra;
975}
976
977void psxBios_memmove() { // 0x2c
978 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
112dddf5 979 v0 = a0;
980 if (a0 == 0 || a2 > 0x7FFFFFFF)
981 {
982 pc0 = ra;
983 return;
984 }
ef79bbde
P
985 if (p2 <= p1 && p2 + a2 > p1) {
986 a2++; // BUG: copy one more byte here
987 p1 += a2;
988 p2 += a2;
5ec7acdf 989 while ((s32)a2-- > 0) *--p1 = *--p2;
ef79bbde 990 } else {
5ec7acdf 991 while ((s32)a2-- > 0) *p1++ = *p2++;
ef79bbde 992 }
112dddf5 993 pc0 = ra;
ef79bbde
P
994}
995
996void psxBios_memcmp() { // 0x2d
997 psxBios_bcmp();
998}
999
1000void psxBios_memchr() { // 0x2e
1001 char *p = (char *)Ra0;
7a8d521f 1002
0f598f20 1003 if (a0 == 0 || a2 > 0x7FFFFFFF)
1004 {
1005 pc0 = ra;
1006 return;
1007 }
ef79bbde 1008
5ec7acdf 1009 while ((s32)a2-- > 0) {
ef79bbde
P
1010 if (*p++ != (s8)a1) continue;
1011 v0 = a0 + (p - (char *)Ra0 - 1);
1012 pc0 = ra;
1013 return;
1014 }
1015
1016 v0 = 0; pc0 = ra;
1017}
1018
1019void psxBios_rand() { // 0x2f
1020 u32 s = psxMu32(0x9010) * 1103515245 + 12345;
1021 v0 = (s >> 16) & 0x7fff;
1022 psxMu32ref(0x9010) = SWAPu32(s);
1023 pc0 = ra;
1024}
1025
1026void psxBios_srand() { // 0x30
1027 psxMu32ref(0x9010) = SWAPu32(a0);
1028 pc0 = ra;
1029}
1030
1031static u32 qscmpfunc, qswidth;
1032
1033static inline int qscmp(char *a, char *b) {
1034 u32 sa0 = a0;
1035
1036 a0 = sa0 + (a - (char *)PSXM(sa0));
1037 a1 = sa0 + (b - (char *)PSXM(sa0));
1038
dc4fa8bc 1039 softCall(qscmpfunc);
ef79bbde
P
1040
1041 a0 = sa0;
1042 return (s32)v0;
1043}
1044
1045static inline void qexchange(char *i, char *j) {
1046 char t;
1047 int n = qswidth;
1048
1049 do {
1050 t = *i;
1051 *i++ = *j;
1052 *j++ = t;
1053 } while (--n);
1054}
1055
1056static inline void q3exchange(char *i, char *j, char *k) {
1057 char t;
1058 int n = qswidth;
1059
1060 do {
1061 t = *i;
1062 *i++ = *k;
1063 *k++ = *j;
1064 *j++ = t;
1065 } while (--n);
1066}
1067
1068static void qsort_main(char *a, char *l) {
1069 char *i, *j, *lp, *hp;
1070 int c;
1071 unsigned int n;
1072
1073start:
1074 if ((n = l - a) <= qswidth)
1075 return;
1076 n = qswidth * (n / (2 * qswidth));
1077 hp = lp = a + n;
1078 i = a;
1079 j = l - qswidth;
1080 while (TRUE) {
1081 if (i < lp) {
1082 if ((c = qscmp(i, lp)) == 0) {
1083 qexchange(i, lp -= qswidth);
1084 continue;
1085 }
1086 if (c < 0) {
1087 i += qswidth;
1088 continue;
1089 }
1090 }
1091
1092loop:
1093 if (j > hp) {
1094 if ((c = qscmp(hp, j)) == 0) {
1095 qexchange(hp += qswidth, j);
1096 goto loop;
1097 }
1098 if (c > 0) {
1099 if (i == lp) {
1100 q3exchange(i, hp += qswidth, j);
1101 i = lp += qswidth;
1102 goto loop;
1103 }
1104 qexchange(i, j);
1105 j -= qswidth;
1106 i += qswidth;
1107 continue;
1108 }
1109 j -= qswidth;
1110 goto loop;
1111 }
1112
1113 if (i == lp) {
1114 if (lp - a >= l - hp) {
1115 qsort_main(hp + qswidth, l);
1116 l = lp;
1117 } else {
1118 qsort_main(a, lp);
1119 a = hp + qswidth;
1120 }
1121 goto start;
1122 }
1123
1124 q3exchange(j, lp -= qswidth, i);
1125 j = hp -= qswidth;
1126 }
1127}
1128
1129void psxBios_qsort() { // 0x31
1130 qswidth = a2;
1131 qscmpfunc = a3;
1132 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1133
1134 pc0 = ra;
1135}
1136
1137void psxBios_malloc() { // 0x33
33788798 1138 u32 *chunk, *newchunk = NULL;
808a13bd 1139 unsigned int dsize = 0, csize, cstat;
ef79bbde
P
1140 int colflag;
1141#ifdef PSXBIOS_LOG
1142 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]);
1143#endif
26b964b5 1144 if (!a0 || (!heap_size || !heap_addr)) {
1145 v0 = 0;
1146 pc0 = ra;
1147 return;
1148 }
ef79bbde
P
1149
1150 // scan through heap and combine free chunks of space
1151 chunk = heap_addr;
1152 colflag = 0;
1153 while(chunk < heap_end) {
1154 // get size and status of actual chunk
1155 csize = ((u32)*chunk) & 0xfffffffc;
1156 cstat = ((u32)*chunk) & 1;
1157
26b964b5 1158 // most probably broken heap descriptor
1159 // this fixes Burning Road
1160 if (*chunk == 0) {
1161 newchunk = chunk;
1162 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1163 colflag = 1;
1164 break;
1165 }
1166
ef79bbde
P
1167 // it's a free chunk
1168 if(cstat == 1) {
1169 if(colflag == 0) {
1170 newchunk = chunk;
1171 dsize = csize;
1172 colflag = 1; // let's begin a new collection of free memory
1173 }
1174 else dsize += (csize+4); // add the new size including header
1175 }
1176 // not a free chunk: did we start a collection ?
1177 else {
1178 if(colflag == 1) { // collection is over
1179 colflag = 0;
1180 *newchunk = SWAP32(dsize | 1);
1181 }
1182 }
1183
1184 // next chunk
1185 chunk = (u32*)((uptr)chunk + csize + 4);
1186 }
1187 // if neccessary free memory on end of heap
1188 if (colflag == 1)
1189 *newchunk = SWAP32(dsize | 1);
1190
1191 chunk = heap_addr;
1192 csize = ((u32)*chunk) & 0xfffffffc;
1193 cstat = ((u32)*chunk) & 1;
1194 dsize = (a0 + 3) & 0xfffffffc;
1195
1196 // exit on uninitialized heap
1197 if (chunk == NULL) {
26b964b5 1198 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
ef79bbde
P
1199 v0 = 0;
1200 pc0 = ra;
1201 return;
1202 }
1203
1204 // search an unused chunk that is big enough until the end of the heap
26b964b5 1205 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
ef79bbde 1206 chunk = (u32*)((uptr)chunk + csize + 4);
26b964b5 1207
1208 // catch out of memory
1209 if(chunk >= heap_end) {
1210 printf("malloc %x,%x: Out of memory error!\n",
1211 v0, a0);
1212 v0 = 0; pc0 = ra;
1213 return;
1214 }
1215
ef79bbde
P
1216 csize = ((u32)*chunk) & 0xfffffffc;
1217 cstat = ((u32)*chunk) & 1;
1218 }
1219
ef79bbde
P
1220 // allocate memory
1221 if(dsize == csize) {
1222 // chunk has same size
1223 *chunk &= 0xfffffffc;
26b964b5 1224 } else if (dsize > csize) {
1225 v0 = 0; pc0 = ra;
1226 return;
1227 } else {
ef79bbde
P
1228 // split free chunk
1229 *chunk = SWAP32(dsize);
1230 newchunk = (u32*)((uptr)chunk + dsize + 4);
808a13bd 1231 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
ef79bbde
P
1232 }
1233
1234 // return pointer to allocated memory
26b964b5 1235 v0 = ((uptr)chunk - (uptr)psxM) + 4;
ef79bbde 1236 v0|= 0x80000000;
26b964b5 1237 //printf ("malloc %x,%x\n", v0, a0);
ef79bbde
P
1238 pc0 = ra;
1239}
1240
1241void psxBios_free() { // 0x34
1242
1243#ifdef PSXBIOS_LOG
1244 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x34]);
1245#endif
1246
1247 SysPrintf("free %x: %x bytes\n", a0, *(u32*)(Ra0-4));
1248
ba4ecb8c 1249 if (a0)
1250 *(u32*)(Ra0-4) |= 1; // set chunk to free
ef79bbde
P
1251 pc0 = ra;
1252}
1253
1254void psxBios_calloc() { // 0x37
02949f79 1255 void *pv0;
ef79bbde
P
1256#ifdef PSXBIOS_LOG
1257 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]);
1258#endif
1259
1260 a0 = a0 * a1;
1261 psxBios_malloc();
02949f79 1262 pv0 = Rv0;
1263 if (pv0)
1264 memset(pv0, 0, a0);
ef79bbde
P
1265}
1266
1267void psxBios_realloc() { // 0x38
1268 u32 block = a0;
1269 u32 size = a1;
1270#ifdef PSXBIOS_LOG
1271 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1272#endif
1273
1274 a0 = block;
391b1d5b 1275 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1276 if (block == 0)
1277 {
1278 psxBios_malloc();
1279 }
1280 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1281 else if (size == 0)
1282 {
1283 psxBios_free();
1284 }
1285 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1286 /* Note that it is not quite implemented this way here. */
1287 else
1288 {
1289 psxBios_free();
1290 a0 = size;
1291 psxBios_malloc();
1292 }
ef79bbde
P
1293}
1294
1295
1296/* InitHeap(void *block , int n) */
1297void psxBios_InitHeap() { // 0x39
1298 unsigned int size;
1299
1300#ifdef PSXBIOS_LOG
1301 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x39]);
1302#endif
1303
1304 if (((a0 & 0x1fffff) + a1)>= 0x200000) size = 0x1ffffc - (a0 & 0x1fffff);
1305 else size = a1;
1306
1307 size &= 0xfffffffc;
1308
1309 heap_addr = (u32 *)Ra0;
a85ffa0e 1310 heap_size = size;
1311 heap_end = (u32 *)((u8 *)heap_addr + heap_size);
1312 /* HACKFIX: Commenting out this line fixes GTA2 crash */
1313 //*heap_addr = SWAP32(size | 1);
ef79bbde 1314
c979c3ee 1315 SysPrintf("InitHeap %x,%x : %x %x\n",a0,a1, (int)((uptr)heap_addr-(uptr)psxM), size);
ef79bbde
P
1316
1317 pc0 = ra;
1318}
1319
1320void psxBios_getchar() { //0x3b
1321 v0 = getchar(); pc0 = ra;
1322}
1323
a94ccc7f 1324static void psxBios_printf_psxout() { // 0x3f
ef79bbde
P
1325 char tmp[1024];
1326 char tmp2[1024];
1327 u32 save[4];
1328 char *ptmp = tmp;
1329 int n=1, i=0, j;
02949f79 1330 void *psp;
1331
1332 psp = PSXM(sp);
7a8d521f 1333 if (psp != INVALID_PTR) {
02949f79 1334 memcpy(save, psp, 4 * 4);
1335 psxMu32ref(sp) = SWAP32((u32)a0);
1336 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1337 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1338 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1339 }
ef79bbde
P
1340
1341 while (Ra0[i]) {
1342 switch (Ra0[i]) {
1343 case '%':
1344 j = 0;
1345 tmp2[j++] = '%';
1346_start:
1347 switch (Ra0[++i]) {
1348 case '.':
1349 case 'l':
1350 tmp2[j++] = Ra0[i]; goto _start;
1351 default:
1352 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1353 tmp2[j++] = Ra0[i];
1354 goto _start;
1355 }
1356 break;
1357 }
1358 tmp2[j++] = Ra0[i];
1359 tmp2[j] = 0;
1360
1361 switch (Ra0[i]) {
1362 case 'f': case 'F':
1363 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1364 case 'a': case 'A':
1365 case 'e': case 'E':
1366 case 'g': case 'G':
1367 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1368 case 'p':
888468ff 1369 case 'i': case 'u':
ef79bbde
P
1370 case 'd': case 'D':
1371 case 'o': case 'O':
1372 case 'x': case 'X':
1373 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1374 case 'c':
1375 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1376 case 's':
1377 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1378 case '%':
1379 *ptmp++ = Ra0[i]; break;
1380 }
1381 i++;
1382 break;
1383 default:
1384 *ptmp++ = Ra0[i++];
1385 }
1386 }
1387 *ptmp = 0;
1388
a94ccc7f 1389 if (psp != INVALID_PTR)
02949f79 1390 memcpy(psp, save, 4 * 4);
ef79bbde 1391
808a13bd 1392 SysPrintf("%s", tmp);
a94ccc7f 1393}
ef79bbde 1394
a94ccc7f 1395void psxBios_printf() { // 0x3f
1396 psxBios_printf_psxout();
ef79bbde
P
1397 pc0 = ra;
1398}
1399
e7e1f572 1400void psxBios_format() { // 0x41
1401 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1402 {
1403 CreateMcd(Config.Mcd1);
1404 LoadMcd(1, Config.Mcd1);
1405 v0 = 1;
1406 }
1407 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1408 {
1409 CreateMcd(Config.Mcd2);
1410 LoadMcd(2, Config.Mcd2);
1411 v0 = 1;
1412 }
1413 else
1414 {
1415 v0 = 0;
1416 }
1417 pc0 = ra;
1418}
1419
dc4fa8bc 1420static void psxBios_SystemErrorUnresolvedException() {
1421 if (loadRam32(0xfffc) != 0x12345678) { // prevent log flood
1422 SysPrintf("psxBios_%s\n", biosA0n[0x40]);
1423 storeRam32(0xfffc, 0x12345678);
1424 }
1425 mips_return_void_c(1000);
1426}
1427
ef79bbde
P
1428/*
1429 * long Load(char *name, struct EXEC *header);
1430 */
1431
1432void psxBios_Load() { // 0x42
1433 EXE_HEADER eheader;
02949f79 1434 void *pa1;
ef79bbde 1435
02949f79 1436 pa1 = Ra1;
1437 if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
1438 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
ef79bbde
P
1439 v0 = 1;
1440 } else v0 = 0;
7650b754 1441 PSXBIOS_LOG("psxBios_%s: %s, %d -> %d\n", biosA0n[0x42], Ra0, a1, v0);
ef79bbde
P
1442
1443 pc0 = ra;
1444}
1445
1446/*
1447 * int Exec(struct EXEC *header , int argc , char **argv);
1448 */
1449
1450void psxBios_Exec() { // 43
1451 EXEC *header = (EXEC*)Ra0;
1452 u32 tmp;
1453
1454#ifdef PSXBIOS_LOG
1455 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1456#endif
1457
1458 header->_sp = sp;
1459 header->_fp = fp;
1460 header->_sp = sp;
1461 header->_gp = gp;
1462 header->ret = ra;
1463 header->base = s0;
1464
1465 if (header->S_addr != 0) {
1466 tmp = header->S_addr + header->s_size;
1467 sp = tmp;
1468 fp = sp;
1469 }
1470
1471 gp = header->gp0;
1472
1473 s0 = a0;
1474
1475 a0 = a1;
1476 a1 = a2;
1477
1478 ra = 0x8000;
1479 pc0 = header->_pc0;
1480}
1481
1482void psxBios_FlushCache() { // 44
1483#ifdef PSXBIOS_LOG
1484 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1485#endif
943a507a 1486 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1487 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
ef79bbde
P
1488 pc0 = ra;
1489}
1490
1491void psxBios_GPU_dw() { // 0x46
1492 int size;
3a284665 1493 u32 *ptr;
ef79bbde
P
1494
1495#ifdef PSXBIOS_LOG
1496 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1497#endif
1498
1499 GPU_writeData(0xa0000000);
3a284665 1500 GPU_writeData((a1<<0x10)|(a0&0xffff));
1501 GPU_writeData((a3<<0x10)|(a2&0xffff));
1502 size = (a2*a3)/2;
1503 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1504 while(size--)
1505 {
1506 GPU_writeData(SWAPu32(*ptr++));
1507 }
ef79bbde
P
1508
1509 pc0 = ra;
7a8d521f 1510}
ef79bbde
P
1511
1512void psxBios_mem2vram() { // 0x47
1513 int size;
3a284665 1514 gpuSyncPluginSR();
ef79bbde 1515 GPU_writeData(0xa0000000);
3a284665 1516 GPU_writeData((a1<<0x10)|(a0&0xffff));
1517 GPU_writeData((a3<<0x10)|(a2&0xffff));
1518 size = ((((a2 * a3) / 2) >> 4) << 16);
ef79bbde
P
1519 GPU_writeStatus(0x04000002);
1520 psxHwWrite32(0x1f8010f4,0);
1521 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1522 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
3a284665 1523 psxHwWrite32(0x1f8010a4, size | 0x10);
ef79bbde
P
1524 psxHwWrite32(0x1f8010a8,0x01000201);
1525
1526 pc0 = ra;
1527}
1528
1529void psxBios_SendGPU() { // 0x48
1530 GPU_writeStatus(a0);
ddbaf678 1531 gpuSyncPluginSR();
ef79bbde
P
1532 pc0 = ra;
1533}
1534
1535void psxBios_GPU_cw() { // 0x49
3a284665 1536 gpuSyncPluginSR();
ef79bbde 1537 GPU_writeData(a0);
3a284665 1538 v0 = HW_GPU_STATUS;
7a8d521f 1539 pc0 = ra;
ef79bbde
P
1540}
1541
1542void psxBios_GPU_cwb() { // 0x4a
3a284665 1543 u32 *ptr = (u32*)Ra0;
ef79bbde 1544 int size = a1;
3a284665 1545 gpuSyncPluginSR();
1546 while(size--)
1547 {
1548 GPU_writeData(SWAPu32(*ptr++));
ef79bbde
P
1549 }
1550
1551 pc0 = ra;
1552}
1553
1554void psxBios_GPU_SendPackets() { //4b:
3a284665 1555 gpuSyncPluginSR();
ef79bbde
P
1556 GPU_writeStatus(0x04000002);
1557 psxHwWrite32(0x1f8010f4,0);
1558 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1559 psxHwWrite32(0x1f8010a0,a0);
1560 psxHwWrite32(0x1f8010a4,0);
1561 psxHwWrite32(0x1f8010a8,0x010000401);
1562 pc0 = ra;
1563}
1564
1565void psxBios_sys_a0_4c() { // 0x4c GPU relate
1566 psxHwWrite32(0x1f8010a8,0x00000401);
1567 GPU_writeData(0x0400000);
1568 GPU_writeData(0x0200000);
1569 GPU_writeData(0x0100000);
cd1ea245 1570 v0 = 0x1f801814;
ef79bbde
P
1571 pc0 = ra;
1572}
1573
1574void psxBios_GPU_GetGPUStatus() { // 0x4d
1575 v0 = GPU_readStatus();
1576 pc0 = ra;
1577}
1578
1579#undef s_addr
1580
1581void psxBios_LoadExec() { // 51
1582 EXEC *header = (EXEC*)PSXM(0xf000);
1583 u32 s_addr, s_size;
1584
1585#ifdef PSXBIOS_LOG
1586 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1587#endif
1588 s_addr = a1; s_size = a2;
1589
7a8d521f 1590 a1 = 0xf000;
ef79bbde
P
1591 psxBios_Load();
1592
1593 header->S_addr = s_addr;
1594 header->s_size = s_size;
1595
1596 a0 = 0xf000; a1 = 0; a2 = 0;
1597 psxBios_Exec();
1598}
1599
1600void psxBios__bu_init() { // 70
1601#ifdef PSXBIOS_LOG
1602 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1603#endif
1604
1605 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1606 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1607
1608 pc0 = ra;
1609}
1610
1611void psxBios__96_init() { // 71
1612#ifdef PSXBIOS_LOG
1613 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1614#endif
1615
1616 pc0 = ra;
1617}
1618
dc4fa8bc 1619static void psxBios_SysDeqIntRP_();
1620
1621static void psxBios_DequeueCdIntr_() {
1622 a0 = 0; a1 = 0x91d0;
1623 psxBios_SysDeqIntRP_();
1624 a0 = 0; a1 = 0x91e0;
1625 psxBios_SysDeqIntRP_();
1626 use_cycles(16);
1627}
1628
1629static void psxBios_DequeueCdIntr() { // a3
1630 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1631 psxBios_DequeueCdIntr_();
1632}
1633
1634static void psxBios_CdRemove() { // 56, 72
ef79bbde 1635 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
ef79bbde 1636
dc4fa8bc 1637 // CloseEvent 0xf1000000
1638 // CloseEvent 0xf1000001
1639 // CloseEvent 0xf1000002
1640 // CloseEvent 0xf1000003
1641 // CloseEvent 0xf1000004
1642 psxBios_DequeueCdIntr_();
1643
1644 // EnterCriticalSection - should be done at the beginning,
1645 // but this way is much easier to implement
1646 a0 = 1;
1647 pc0 = A_SYSCALL;
1648 use_cycles(30);
ef79bbde
P
1649}
1650
1651void psxBios_SetMem() { // 9f
1652 u32 new = psxHu32(0x1060);
1653
1654#ifdef PSXBIOS_LOG
1655 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1656#endif
1657
1658 switch(a0) {
1659 case 2:
1660 psxHu32ref(0x1060) = SWAP32(new);
1661 psxMu32ref(0x060) = a0;
1662 SysPrintf("Change effective memory : %d MBytes\n",a0);
1663 break;
1664
1665 case 8:
1666 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1667 psxMu32ref(0x060) = a0;
1668 SysPrintf("Change effective memory : %d MBytes\n",a0);
7a8d521f 1669
ef79bbde
P
1670 default:
1671 SysPrintf("Effective memory must be 2/8 MBytes\n");
1672 break;
1673 }
1674
1675 pc0 = ra;
1676}
1677
18dd7e9e 1678/* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1679void psxBios_get_cd_status(void) //a6
1680{
1681 v0 = 1;
1682 pc0 = ra;
1683}
1684
ef79bbde
P
1685void psxBios__card_info() { // ab
1686#ifdef PSXBIOS_LOG
1687 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1688#endif
7a8d521f 1689 u32 ret, port;
e9fda093 1690 card_active_chan = a0;
7a8d521f 1691 port = card_active_chan >> 4;
1692
1693 switch (port) {
1694 case 0x0:
1695 case 0x1:
1696 ret = 0x2;
1697 if (McdDisable[port & 1])
1698 ret = 0x8;
76b81516 1699 break;
1700 default:
1701#ifdef PSXBIOS_LOG
1702 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
1703#endif
1704 ret = 0x11;
1705 break;
1706 }
7a8d521f 1707
1708 if (McdDisable[0] && McdDisable[1])
1709 ret = 0x8;
1710
1711 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1712// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
76b81516 1713 DeliverEvent(0x81, ret); // 0xf4000001, 0x0004
ef79bbde
P
1714 v0 = 1; pc0 = ra;
1715}
1716
1717void psxBios__card_load() { // ac
1718#ifdef PSXBIOS_LOG
1719 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1720#endif
1721
e9fda093 1722 card_active_chan = a0;
1723
ef79bbde
P
1724// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1725 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1726
1727 v0 = 1; pc0 = ra;
1728}
1729
1730/* System calls B0 */
1731
7650b754 1732static u32 psxBios_SysMalloc_(u32 size);
1733
1734static void psxBios_SysMalloc() { // B 00
1735 u32 ret = psxBios_SysMalloc_(a0);
1736
1737 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1738 mips_return_c(ret, 33);
1739}
1740
ef79bbde
P
1741void psxBios_SetRCnt() { // 02
1742#ifdef PSXBIOS_LOG
1743 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1744#endif
1745
1746 a0&= 0x3;
1747 if (a0 != 3) {
1748 u32 mode=0;
1749
1750 psxRcntWtarget(a0, a1);
1751 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1752 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1753 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1754 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1755 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1756
1757 psxRcntWmode(a0, mode);
1758 }
1759 pc0 = ra;
1760}
1761
1762void psxBios_GetRCnt() { // 03
1763#ifdef PSXBIOS_LOG
1764 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1765#endif
1766
1767 a0&= 0x3;
1768 if (a0 != 3) v0 = psxRcntRcount(a0);
1769 else v0 = 0;
1770 pc0 = ra;
1771}
1772
1773void psxBios_StartRCnt() { // 04
1774#ifdef PSXBIOS_LOG
1775 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1776#endif
1777
1778 a0&= 0x3;
1779 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1780 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1781 v0 = 1; pc0 = ra;
1782}
1783
1784void psxBios_StopRCnt() { // 05
1785#ifdef PSXBIOS_LOG
1786 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1787#endif
1788
1789 a0&= 0x3;
1790 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1791 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1792 pc0 = ra;
1793}
1794
1795void psxBios_ResetRCnt() { // 06
1796#ifdef PSXBIOS_LOG
1797 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1798#endif
1799
1800 a0&= 0x3;
1801 if (a0 != 3) {
1802 psxRcntWmode(a0, 0);
1803 psxRcntWtarget(a0, 0);
1804 psxRcntWcount(a0, 0);
1805 }
1806 pc0 = ra;
1807}
1808
1809
7a8d521f 1810/* gets ev for use with EventCB */
ef79bbde
P
1811#define GetEv() \
1812 ev = (a0 >> 24) & 0xf; \
1813 if (ev == 0xf) ev = 0x5; \
1814 ev*= 32; \
1815 ev+= a0&0x1f;
1816
7a8d521f 1817/* gets spec for use with EventCB */
ef79bbde
P
1818#define GetSpec() \
1819 spec = 0; \
1820 switch (a1) { \
1821 case 0x0301: spec = 16; break; \
1822 case 0x0302: spec = 17; break; \
1823 default: \
1824 for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \
1825 break; \
1826 }
1827
1828void psxBios_DeliverEvent() { // 07
1829 int ev, spec;
1830 int i;
1831
1832 GetEv();
1833 GetSpec();
1834
1835#ifdef PSXBIOS_LOG
1836 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x07], ev, spec);
1837#endif
1838
1839 DeliverEvent(ev, spec);
1840
1841 pc0 = ra;
1842}
1843
1844void psxBios_OpenEvent() { // 08
1845 int ev, spec;
1846 int i;
1847
1848 GetEv();
1849 GetSpec();
1850
1851#ifdef PSXBIOS_LOG
1852 PSXBIOS_LOG("psxBios_%s %x,%x (class:%x, spec:%x, mode:%x, func:%x)\n", biosB0n[0x08], ev, spec, a0, a1, a2, a3);
1853#endif
1854
7a8d521f 1855 EventCB[ev][spec].status = EvStWAIT;
1856 EventCB[ev][spec].mode = a2;
1857 EventCB[ev][spec].fhandler = a3;
ef79bbde
P
1858
1859 v0 = ev | (spec << 8);
1860 pc0 = ra;
1861}
1862
1863void psxBios_CloseEvent() { // 09
1864 int ev, spec;
1865
1866 ev = a0 & 0xff;
1867 spec = (a0 >> 8) & 0xff;
1868
1869#ifdef PSXBIOS_LOG
1870 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x09], ev, spec);
1871#endif
1872
7a8d521f 1873 EventCB[ev][spec].status = EvStUNUSED;
ef79bbde
P
1874
1875 v0 = 1; pc0 = ra;
1876}
1877
1878void psxBios_WaitEvent() { // 0a
1879 int ev, spec;
1880
1881 ev = a0 & 0xff;
1882 spec = (a0 >> 8) & 0xff;
ef79bbde
P
1883#ifdef PSXBIOS_LOG
1884 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0a], ev, spec);
1885#endif
7a8d521f 1886 if (EventCB[ev][spec].status == EvStUNUSED)
d95c9dcb 1887 {
1888 v0 = 0;
7a8d521f 1889 pc0 = ra;
d95c9dcb 1890 return;
1891 }
ef79bbde 1892
7a8d521f 1893 if (EventCB[ev][spec].status == EvStALREADY)
d95c9dcb 1894 {
1895 /* Callback events (mode=EvMdINTR) do never set the ready flag (and thus WaitEvent would hang forever). */
7a8d521f 1896 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
d95c9dcb 1897 v0 = 1;
1898 pc0 = ra;
1899 return;
1900 }
ef79bbde 1901
d95c9dcb 1902 v0 = 0;
1903 pc0 = ra;
ef79bbde
P
1904}
1905
1906void psxBios_TestEvent() { // 0b
1907 int ev, spec;
1908
1909 ev = a0 & 0xff;
1910 spec = (a0 >> 8) & 0xff;
1911
7a8d521f 1912 if (EventCB[ev][spec].status == EvStALREADY)
b4ae2532 1913 {
7a8d521f 1914 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
b4ae2532 1915 v0 = 1;
7a8d521f 1916 }
1917 else
b4ae2532 1918 {
1919 v0 = 0;
1920 }
ef79bbde
P
1921
1922#ifdef PSXBIOS_LOG
1923 PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0);
1924#endif
1925
1926 pc0 = ra;
1927}
1928
1929void psxBios_EnableEvent() { // 0c
1930 int ev, spec;
1931
1932 ev = a0 & 0xff;
1933 spec = (a0 >> 8) & 0xff;
1934
1935#ifdef PSXBIOS_LOG
1936 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0c], ev, spec);
1937#endif
1938
7a8d521f 1939 EventCB[ev][spec].status = EvStACTIVE;
ef79bbde
P
1940
1941 v0 = 1; pc0 = ra;
1942}
1943
1944void psxBios_DisableEvent() { // 0d
1945 int ev, spec;
1946
1947 ev = a0 & 0xff;
1948 spec = (a0 >> 8) & 0xff;
1949
1950#ifdef PSXBIOS_LOG
1951 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0d], ev, spec);
1952#endif
1953
7a8d521f 1954 EventCB[ev][spec].status = EvStWAIT;
ef79bbde
P
1955
1956 v0 = 1; pc0 = ra;
1957}
1958
1959/*
1960 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
1961 */
1962
1963void psxBios_OpenTh() { // 0e
dc4fa8bc 1964 TCB *tcb = loadRam32ptr(A_TT_TCB);
1965 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
ef79bbde
P
1966 int th;
1967
dc4fa8bc 1968 for (th = 1; th < limit; th++)
a66d3058 1969 {
dc4fa8bc 1970 if (tcb[th].status != SWAP32(0x4000)) break;
ef79bbde 1971
a66d3058 1972 }
dc4fa8bc 1973 if (th == limit) {
a66d3058 1974 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
1975 // When no free TCB is found, return 0xffffffff according to Nocash doc.
1976#ifdef PSXBIOS_LOG
1977 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
1978#endif
dc4fa8bc 1979 mips_return_c(0xffffffff, 20);
a66d3058 1980 return;
1981 }
ef79bbde 1982 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
ef79bbde 1983
dc4fa8bc 1984 tcb[th].status = SWAP32(0x4000);
1985 tcb[th].mode = SWAP32(0x1000);
1986 tcb[th].epc = SWAP32(a0);
1987 tcb[th].reg[30] = SWAP32(a1); // fp
1988 tcb[th].reg[29] = SWAP32(a1); // sp
1989 tcb[th].reg[28] = SWAP32(a2); // gp
ef79bbde 1990
dc4fa8bc 1991 mips_return_c(0xff000000 + th, 34);
ef79bbde
P
1992}
1993
1994/*
1995 * int CloseTh(long thread);
1996 */
1997
1998void psxBios_CloseTh() { // 0f
dc4fa8bc 1999 TCB *tcb = loadRam32ptr(A_TT_TCB);
2000 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2001 u32 th = a0 & 0xff;
ef79bbde
P
2002
2003#ifdef PSXBIOS_LOG
2004 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
2005#endif
9ee77db1 2006 /* The return value is always 1 (even if the handle was already closed). */
2007 v0 = 1;
dc4fa8bc 2008 if (th < limit && tcb[th].status == SWAP32(0x4000)) {
2009 tcb[th].status = SWAP32(0x1000);
ef79bbde
P
2010 }
2011
2012 pc0 = ra;
2013}
2014
2015/*
2016 * int ChangeTh(long thread);
2017 */
2018
2019void psxBios_ChangeTh() { // 10
dc4fa8bc 2020 u32 tcbBase = loadRam32(A_TT_TCB);
2021 u32 th = a0 & 0xffff;
ef79bbde
P
2022
2023#ifdef PSXBIOS_LOG
2024// PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
2025#endif
dc4fa8bc 2026 // without doing any argument checks, just issue a syscall
2027 // (like the real bios does)
2028 a0 = 3;
2029 a1 = tcbBase + th * sizeof(TCB);
2030 pc0 = A_SYSCALL;
2031 use_cycles(15);
ef79bbde
P
2032}
2033
2034void psxBios_InitPAD() { // 0x12
2035#ifdef PSXBIOS_LOG
2036 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x12]);
2037#endif
2038
2039 pad_buf1 = (char*)Ra0;
2040 pad_buf1len = a1;
2041 pad_buf2 = (char*)Ra2;
2042 pad_buf2len = a3;
2043
2044 v0 = 1; pc0 = ra;
2045}
2046
2047void psxBios_StartPAD() { // 13
2048#ifdef PSXBIOS_LOG
2049 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2050#endif
f25c285b 2051 pad_stopped = 0;
ef79bbde 2052 psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1));
bc7c5acb 2053 psxRegs.CP0.n.SR |= 0x401;
ef79bbde
P
2054 pc0 = ra;
2055}
2056
2057void psxBios_StopPAD() { // 14
2058#ifdef PSXBIOS_LOG
2059 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2060#endif
f25c285b 2061 pad_stopped = 1;
ef79bbde
P
2062 pad_buf1 = NULL;
2063 pad_buf2 = NULL;
2064 pc0 = ra;
2065}
2066
2067void psxBios_PAD_init() { // 15
2068#ifdef PSXBIOS_LOG
2069 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2070#endif
a824e83d 2071 if (!(a0 == 0x20000000 || a0 == 0x20000001))
2072 {
2073 v0 = 0;
2074 pc0 = ra;
2075 return;
2076 }
ef79bbde
P
2077 psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
2078 pad_buf = (int *)Ra1;
2079 *pad_buf = -1;
bc7c5acb 2080 psxRegs.CP0.n.SR |= 0x401;
a824e83d 2081 v0 = 2;
ef79bbde
P
2082 pc0 = ra;
2083}
2084
2085void psxBios_PAD_dr() { // 16
2086#ifdef PSXBIOS_LOG
2087 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2088#endif
2089
2090 v0 = -1; pc0 = ra;
2091}
2092
dc4fa8bc 2093static void psxBios_ReturnFromException() { // 17
2094 u32 tcbPtr = loadRam32(A_TT_PCB);
2095 const TCB *tcb = loadRam32ptr(tcbPtr);
2096 int i;
2097
2098 for (i = 1; i < 32; i++)
2099 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2100 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2101 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2102 psxRegs.CP0.n.SR = SWAP32(tcb->sr);
ef79bbde 2103
dc4fa8bc 2104 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2105 pc0 = k0 = SWAP32(tcb->epc);
ef79bbde 2106
bc7c5acb 2107 psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
dc4fa8bc 2108 use_cycles(53);
2109 psxBranchTest();
ef79bbde
P
2110}
2111
2112void psxBios_ResetEntryInt() { // 18
ef79bbde 2113 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
ef79bbde 2114
dc4fa8bc 2115 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2116 mips_return_void_c(5);
ef79bbde
P
2117}
2118
2119void psxBios_HookEntryInt() { // 19
dc4fa8bc 2120 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
ef79bbde 2121
dc4fa8bc 2122 storeRam32(A_EEXIT_PTR, a0);
2123 mips_return_void_c(3);
ef79bbde
P
2124}
2125
2126void psxBios_UnDeliverEvent() { // 0x20
2127 int ev, spec;
2128 int i;
2129
2130 GetEv();
2131 GetSpec();
2132
2133#ifdef PSXBIOS_LOG
2134 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec);
2135#endif
2136
7a8d521f 2137 if (EventCB[ev][spec].status == EvStALREADY &&
2138 EventCB[ev][spec].mode == EvMdNOINTR)
2139 EventCB[ev][spec].status = EvStACTIVE;
ef79bbde
P
2140
2141 pc0 = ra;
2142}
2143
595a136b 2144char ffile[64], *pfile;
2145int nfile;
7a8d521f 2146
857275a9 2147static void buopen(int mcd, char *ptr, char *cfg)
595a136b 2148{
2149 int i;
7a8d521f 2150 char *mcd_data = ptr;
595a136b 2151
2152 strcpy(FDesc[1 + mcd].name, Ra0+5);
2153 FDesc[1 + mcd].offset = 0;
2154 FDesc[1 + mcd].mode = a1;
2155
2156 for (i=1; i<16; i++) {
7a8d521f 2157 const char *fptr = mcd_data + 128 * i;
595a136b 2158 if ((*fptr & 0xF0) != 0x50) continue;
2159 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2160 FDesc[1 + mcd].mcfile = i;
2161 SysPrintf("open %s\n", fptr+0xa);
2162 v0 = 1 + mcd;
2163 break;
2164 }
2165 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
595a136b 2166 for (i=1; i<16; i++) {
2167 int j, xor, nblk = a1 >> 16;
7a8d521f 2168 char *pptr, *fptr2;
2169 char *fptr = mcd_data + 128 * i;
595a136b 2170
595a136b 2171 if ((*fptr & 0xF0) != 0xa0) continue;
2172
2173 FDesc[1 + mcd].mcfile = i;
2174 fptr[0] = 0x51;
2175 fptr[4] = 0x00;
2176 fptr[5] = 0x20 * nblk;
2177 fptr[6] = 0x00;
2178 fptr[7] = 0x00;
2179 strcpy(fptr+0xa, FDesc[1 + mcd].name);
7a8d521f 2180 pptr = fptr2 = fptr;
595a136b 2181 for(j=2; j<=nblk; j++) {
2182 int k;
2183 for(i++; i<16; i++) {
2184 fptr2 += 128;
7a8d521f 2185
595a136b 2186 memset(fptr2, 0, 128);
2187 fptr2[0] = j < nblk ? 0x52 : 0x53;
2188 pptr[8] = i - 1;
2189 pptr[9] = 0;
2190 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2191 pptr[127] = xor;
2192 pptr = fptr2;
2193 break;
2194 }
2195 /* shouldn't this return ENOSPC if i == 16? */
2196 }
2197 pptr[8] = pptr[9] = 0xff;
2198 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2199 pptr[127] = xor;
2200 SysPrintf("openC %s %d\n", ptr, nblk);
2201 v0 = 1 + mcd;
2202 /* just go ahead and resave them all */
2203 SaveMcd(cfg, ptr, 128, 128 * 15);
2204 break;
2205 }
2206 /* shouldn't this return ENOSPC if i == 16? */
2207 }
ef79bbde
P
2208}
2209
2210/*
2211 * int open(char *name , int mode);
2212 */
2213
2214void psxBios_open() { // 0x32
02949f79 2215 void *pa0 = Ra0;
ef79bbde
P
2216
2217#ifdef PSXBIOS_LOG
2218 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2219#endif
2220
2221 v0 = -1;
2222
7a8d521f 2223 if (pa0 != INVALID_PTR) {
02949f79 2224 if (!strncmp(pa0, "bu00", 4)) {
595a136b 2225 buopen(1, Mcd1Data, Config.Mcd1);
02949f79 2226 }
ef79bbde 2227
02949f79 2228 if (!strncmp(pa0, "bu10", 4)) {
595a136b 2229 buopen(2, Mcd2Data, Config.Mcd2);
02949f79 2230 }
ef79bbde
P
2231 }
2232
2233 pc0 = ra;
2234}
2235
2236/*
2237 * int lseek(int fd , int offset , int whence);
2238 */
2239
2240void psxBios_lseek() { // 0x33
2241#ifdef PSXBIOS_LOG
2242 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2243#endif
2244
2245 switch (a2) {
2246 case 0: // SEEK_SET
2247 FDesc[a0].offset = a1;
2248 v0 = a1;
2249// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2250// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2251 break;
2252
2253 case 1: // SEEK_CUR
2254 FDesc[a0].offset+= a1;
2255 v0 = FDesc[a0].offset;
2256 break;
2257 }
2258
2259 pc0 = ra;
2260}
2261
595a136b 2262
ef79bbde
P
2263/*
2264 * int read(int fd , void *buf , int nbytes);
2265 */
2266
2267void psxBios_read() { // 0x34
2268 char *ptr;
02949f79 2269 void *pa1 = Ra1;
ef79bbde
P
2270
2271#ifdef PSXBIOS_LOG
2272 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2273#endif
2274
2275 v0 = -1;
2276
7a8d521f 2277 if (pa1 != INVALID_PTR) {
02949f79 2278 switch (a0) {
595a136b 2279 case 2: buread(pa1, 1, a2); break;
2280 case 3: buread(pa1, 2, a2); break;
02949f79 2281 }
ef79bbde 2282 }
7a8d521f 2283
ef79bbde
P
2284 pc0 = ra;
2285}
2286
ef79bbde
P
2287/*
2288 * int write(int fd , void *buf , int nbytes);
2289 */
2290
2291void psxBios_write() { // 0x35/0x03
2292 char *ptr;
02949f79 2293 void *pa1 = Ra1;
2294
2295#ifdef PSXBIOS_LOG
2296 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2297#endif
2298
2299 v0 = -1;
7a8d521f 2300 if (pa1 == INVALID_PTR) {
02949f79 2301 pc0 = ra;
2302 return;
2303 }
ef79bbde
P
2304
2305 if (a0 == 1) { // stdout
02949f79 2306 char *ptr = pa1;
ef79bbde 2307
02949f79 2308 v0 = a2;
ef79bbde
P
2309 while (a2 > 0) {
2310 SysPrintf("%c", *ptr++); a2--;
2311 }
2312 pc0 = ra; return;
2313 }
ef79bbde
P
2314
2315 switch (a0) {
595a136b 2316 case 2: buwrite(pa1, 1, a2); break;
2317 case 3: buwrite(pa1, 2, a2); break;
ef79bbde
P
2318 }
2319
2320 pc0 = ra;
2321}
2322
a94ccc7f 2323static void psxBios_write_psxout() {
2324 if (a0 == 1) { // stdout
2325 const char *ptr = Ra1;
2326 int len = a2;
2327
2328 if (ptr != INVALID_PTR)
2329 while (len-- > 0)
2330 SysPrintf("%c", *ptr++);
2331 }
2332}
2333
2334static void psxBios_putchar_psxout() { // 3d
2335 SysPrintf("%c", (char)a0);
2336}
2337
2338static void psxBios_puts_psxout() { // 3e/3f
2339 SysPrintf("%s", Ra0);
2340}
2341
ef79bbde
P
2342/*
2343 * int close(int fd);
2344 */
2345
2346void psxBios_close() { // 0x36
2347#ifdef PSXBIOS_LOG
2348 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2349#endif
2350
2351 v0 = a0;
2352 pc0 = ra;
2353}
2354
2355void psxBios_putchar() { // 3d
2356 SysPrintf("%c", (char)a0);
2357 pc0 = ra;
2358}
2359
2360void psxBios_puts() { // 3e/3f
808a13bd 2361 SysPrintf("%s", Ra0);
ef79bbde
P
2362 pc0 = ra;
2363}
2364
f1514614 2365
2366/* To avoid any issues with different behaviour when using the libc's own strlen instead.
2367 * We want to mimic the PSX's behaviour in this case for bufile. */
7a8d521f 2368static size_t strlen_internal(char* p)
f1514614 2369{
2370 size_t size_of_array = 0;
2371 while (*p++) size_of_array++;
2372 return size_of_array;
2373}
2374
ef79bbde 2375#define bufile(mcd) { \
f1514614 2376 size_t size_of_name = strlen_internal(dir->name); \
ef79bbde
P
2377 while (nfile < 16) { \
2378 int match=1; \
2379 \
595a136b 2380 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
ef79bbde
P
2381 nfile++; \
2382 if ((*ptr & 0xF0) != 0x50) continue; \
595a136b 2383 /* Bug link files show up as free block. */ \
2384 if (!ptr[0xa]) continue; \
ef79bbde
P
2385 ptr+= 0xa; \
2386 if (pfile[0] == 0) { \
f1514614 2387 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2388 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
ef79bbde
P
2389 } else for (i=0; i<20; i++) { \
2390 if (pfile[i] == ptr[i]) { \
595a136b 2391 dir->name[i] = ptr[i]; continue; } \
ef79bbde
P
2392 if (pfile[i] == '?') { \
2393 dir->name[i] = ptr[i]; continue; } \
2394 if (pfile[i] == '*') { \
2395 strcpy(dir->name+i, ptr+i); break; } \
2396 match = 0; break; \
2397 } \
2398 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
595a136b 2399 if (match == 0) { continue; } \
ef79bbde
P
2400 dir->size = 8192; \
2401 v0 = _dir; \
2402 break; \
2403 } \
2404}
2405
2406/*
2407 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2408 */
7a8d521f 2409
ef79bbde
P
2410void psxBios_firstfile() { // 42
2411 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
02949f79 2412 void *pa0 = Ra0;
ef79bbde
P
2413 u32 _dir = a1;
2414 char *ptr;
2415 int i;
2416
2417#ifdef PSXBIOS_LOG
2418 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2419#endif
2420
2421 v0 = 0;
2422
7a8d521f 2423 if (pa0 != INVALID_PTR) {
02949f79 2424 strcpy(ffile, pa0);
2425 pfile = ffile+5;
8f3b2bd3 2426 nfile = 0;
02949f79 2427 if (!strncmp(pa0, "bu00", 4)) {
857fabea 2428 // firstfile() calls _card_read() internally, so deliver it's event
2429 DeliverEvent(0x11, 0x2);
02949f79 2430 bufile(1);
2431 } else if (!strncmp(pa0, "bu10", 4)) {
857fabea 2432 // firstfile() calls _card_read() internally, so deliver it's event
2433 DeliverEvent(0x11, 0x2);
02949f79 2434 bufile(2);
2435 }
ef79bbde
P
2436 }
2437
2438 pc0 = ra;
2439}
2440
2441/*
2442 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2443 */
2444
2445void psxBios_nextfile() { // 43
2446 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2447 u32 _dir = a0;
2448 char *ptr;
2449 int i;
2450
2451#ifdef PSXBIOS_LOG
2452 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2453#endif
2454
2455 v0 = 0;
2456
2457 if (!strncmp(ffile, "bu00", 4)) {
2458 bufile(1);
2459 }
2460
2461 if (!strncmp(ffile, "bu10", 4)) {
2462 bufile(2);
2463 }
2464
2465 pc0 = ra;
2466}
2467
2468#define burename(mcd) { \
2469 for (i=1; i<16; i++) { \
2470 int namelen, j, xor = 0; \
2471 ptr = Mcd##mcd##Data + 128 * i; \
2472 if ((*ptr & 0xF0) != 0x50) continue; \
2473 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2474 namelen = strlen(Ra1+5); \
2475 memcpy(ptr+0xa, Ra1+5, namelen); \
2476 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2477 for (j=0; j<127; j++) xor^= ptr[j]; \
2478 ptr[127] = xor; \
2479 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2480 v0 = 1; \
2481 break; \
2482 } \
2483}
2484
2485/*
2486 * int rename(char *old, char *new);
2487 */
2488
2489void psxBios_rename() { // 44
02949f79 2490 void *pa0 = Ra0;
2491 void *pa1 = Ra1;
ef79bbde
P
2492 char *ptr;
2493 int i;
2494
2495#ifdef PSXBIOS_LOG
2496 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2497#endif
2498
2499 v0 = 0;
2500
7a8d521f 2501 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
02949f79 2502 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2503 burename(1);
2504 }
ef79bbde 2505
02949f79 2506 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2507 burename(2);
2508 }
ef79bbde
P
2509 }
2510
2511 pc0 = ra;
2512}
2513
2514
2515#define budelete(mcd) { \
2516 for (i=1; i<16; i++) { \
2517 ptr = Mcd##mcd##Data + 128 * i; \
2518 if ((*ptr & 0xF0) != 0x50) continue; \
2519 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2520 *ptr = (*ptr & 0xf) | 0xA0; \
2521 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2522 SysPrintf("delete %s\n", ptr+0xa); \
2523 v0 = 1; \
2524 break; \
2525 } \
2526}
2527
2528/*
2529 * int delete(char *name);
2530 */
2531
2532void psxBios_delete() { // 45
02949f79 2533 void *pa0 = Ra0;
ef79bbde
P
2534 char *ptr;
2535 int i;
2536
2537#ifdef PSXBIOS_LOG
2538 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2539#endif
2540
2541 v0 = 0;
2542
7a8d521f 2543 if (pa0 != INVALID_PTR) {
02949f79 2544 if (!strncmp(pa0, "bu00", 4)) {
2545 budelete(1);
2546 }
ef79bbde 2547
02949f79 2548 if (!strncmp(pa0, "bu10", 4)) {
2549 budelete(2);
2550 }
ef79bbde
P
2551 }
2552
2553 pc0 = ra;
2554}
2555
2556void psxBios_InitCARD() { // 4a
2557#ifdef PSXBIOS_LOG
2558 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2559#endif
2560
2561 CardState = 0;
2562
2563 pc0 = ra;
2564}
2565
2566void psxBios_StartCARD() { // 4b
2567#ifdef PSXBIOS_LOG
2568 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2569#endif
2570
2571 if (CardState == 0) CardState = 1;
2572
2573 pc0 = ra;
2574}
2575
2576void psxBios_StopCARD() { // 4c
2577#ifdef PSXBIOS_LOG
2578 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2579#endif
2580
2581 if (CardState == 1) CardState = 0;
2582
2583 pc0 = ra;
2584}
2585
2586void psxBios__card_write() { // 0x4e
02949f79 2587 void *pa2 = Ra2;
ef79bbde
P
2588 int port;
2589
2590#ifdef PSXBIOS_LOG
2591 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2592#endif
1059caaf 2593 /*
2594 Function also accepts sector 400h (a bug).
2595 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2596 */
2597 if (!(a1 <= 0x3FF))
bd48ba5e 2598 {
2599 /* Invalid sectors */
2600 v0 = 0; pc0 = ra;
2601 return;
2602 }
e9fda093 2603 card_active_chan = a0;
ef79bbde
P
2604 port = a0 >> 4;
2605
7a8d521f 2606 if (pa2 != INVALID_PTR) {
02949f79 2607 if (port == 0) {
2608 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2609 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2610 } else {
2611 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2612 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2613 }
ef79bbde
P
2614 }
2615
2616 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2617// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2618
2619 v0 = 1; pc0 = ra;
2620}
2621
2622void psxBios__card_read() { // 0x4f
02949f79 2623 void *pa2 = Ra2;
ef79bbde
P
2624 int port;
2625
2626#ifdef PSXBIOS_LOG
2627 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2628#endif
1059caaf 2629 /*
2630 Function also accepts sector 400h (a bug).
2631 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2632 */
2633 if (!(a1 <= 0x3FF))
bd48ba5e 2634 {
2635 /* Invalid sectors */
2636 v0 = 0; pc0 = ra;
2637 return;
2638 }
e9fda093 2639 card_active_chan = a0;
ef79bbde
P
2640 port = a0 >> 4;
2641
7a8d521f 2642 if (pa2 != INVALID_PTR) {
02949f79 2643 if (port == 0) {
2644 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2645 } else {
2646 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2647 }
ef79bbde
P
2648 }
2649
2650 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2651// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2652
2653 v0 = 1; pc0 = ra;
2654}
2655
2656void psxBios__new_card() { // 0x50
2657#ifdef PSXBIOS_LOG
2658 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2659#endif
2660
2661 pc0 = ra;
2662}
2663
002b2f7d 2664/* According to a user, this allows Final Fantasy Tactics to save/load properly */
2665void psxBios__get_error(void) // 55
7a8d521f 2666{
dc4fa8bc 2667 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
002b2f7d 2668 v0 = 0;
2669 pc0 = ra;
2670}
2671
ef79bbde
P
2672void psxBios_Krom2RawAdd() { // 0x51
2673 int i = 0;
2674
dc4fa8bc 2675 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
ef79bbde
P
2676 const u32 table_8140[][2] = {
2677 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2678 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2679 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2680 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2681 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2682 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2683 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2684 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2685 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2686 {0xffff, 0}
2687 };
2688
2689 const u32 table_889f[][2] = {
2690 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2691 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2692 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2693 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2694 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2695 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2696 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2697 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2698 {0xffff, 0}
2699 };
2700
2701 if (a0 >= 0x8140 && a0 <= 0x84be) {
2702 while (table_8140[i][0] <= a0) i++;
2703 a0 -= table_8140[i - 1][0];
2704 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2705 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2706 while (table_889f[i][0] <= a0) i++;
2707 a0 -= table_889f[i - 1][0];
2708 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2709 } else {
2710 v0 = 0xffffffff;
2711 }
2712
2713 pc0 = ra;
2714}
2715
2716void psxBios_GetC0Table() { // 56
ef79bbde 2717 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
dc4fa8bc 2718 log_unhandled("GetC0Table @%08x\n", ra);
ef79bbde 2719
dc4fa8bc 2720 mips_return_c(A_C0_TABLE, 3);
ef79bbde
P
2721}
2722
2723void psxBios_GetB0Table() { // 57
ef79bbde 2724 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
dc4fa8bc 2725 log_unhandled("GetB0Table @%08x\n", ra);
ef79bbde 2726
dc4fa8bc 2727 mips_return_c(A_B0_TABLE, 3);
ef79bbde
P
2728}
2729
e9fda093 2730void psxBios__card_chan() { // 0x58
2731#ifdef PSXBIOS_LOG
2732 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2733#endif
2734
2735 v0 = card_active_chan;
2736 pc0 = ra;
2737}
2738
ef79bbde
P
2739void psxBios_ChangeClearPad() { // 5b
2740#ifdef PSXBIOS_LOG
2741 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
7a8d521f 2742#endif
ef79bbde
P
2743
2744 pc0 = ra;
2745}
2746
21af3ff6 2747void psxBios__card_status() { // 5c
2748#ifdef PSXBIOS_LOG
2749 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2750#endif
2751
cf1af0ed 2752 v0 = card_active_chan;
21af3ff6 2753 pc0 = ra;
2754}
2755
5f652aa9 2756void psxBios__card_wait() { // 5d
2757#ifdef PSXBIOS_LOG
2758 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2759#endif
2760
2761 v0 = 1;
2762 pc0 = ra;
2763}
2764
ef79bbde
P
2765/* System calls C0 */
2766
7650b754 2767static void psxBios_SysEnqIntRP();
2768
2769static void psxBios_InitRCnt() { // 00
2770 int i;
2771 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2772 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2773 for (i = 0; i < 3; i++) {
2774 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2775 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2776 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2777 }
2778 a1 = 0x6d88;
2779 psxBios_SysEnqIntRP();
2780 mips_return_c(0, 9);
2781}
2782
2783static void psxBios_InitException() { // 01
2784 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2785 a1 = 0x6da8;
2786 psxBios_SysEnqIntRP();
2787 mips_return_c(0, 9);
2788}
2789
ef79bbde
P
2790/*
2791 * int SysEnqIntRP(int index , long *queue);
2792 */
2793
7650b754 2794static void psxBios_SysEnqIntRP() { // 02
dc4fa8bc 2795 u32 old, base = loadRam32(A_TT_ExCB);
2796 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
ef79bbde 2797
dc4fa8bc 2798 old = loadRam32(base + (a0 << 3));
2799 storeRam32(base + (a0 << 3), a1);
2800 storeRam32(a1, old);
2801 mips_return_c(0, 9);
ef79bbde
P
2802}
2803
2804/*
2805 * int SysDeqIntRP(int index , long *queue);
2806 */
2807
dc4fa8bc 2808static void psxBios_SysDeqIntRP_() { // 03
2809 u32 ptr, next, base = loadRam32(A_TT_ExCB);
2810 u32 lim = 0, ret = 0;
2811
2812 // as in original: no arg checks of any kind, bug if a1 == 0
2813 ptr = loadRam32(base + (a0 << 3));
2814 while (ptr) {
2815 next = loadRam32(ptr);
2816 if (ptr == a1) {
2817 storeRam32(base + (a0 << 3), next);
2818 ret = ptr;
2819 use_cycles(6);
2820 break;
2821 }
2822 while (next && next != a1 && lim++ < 100) {
2823 ptr = next;
2824 next = loadRam32(ptr);
2825 use_cycles(8);
2826 }
2827 if (next == a1) {
2828 next = loadRam32(next);
2829 storeRam32(ptr, next);
2830 ret = ptr;
2831 use_cycles(6);
2832 }
2833 break;
2834 }
2835 if (lim == 100)
2836 PSXBIOS_LOG("bad chain %u %x\n", a0, base);
ef79bbde 2837
dc4fa8bc 2838 mips_return_c(ret, 12);
2839}
ef79bbde 2840
dc4fa8bc 2841static void psxBios_SysDeqIntRP() { // 03
2842 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
2843 psxBios_SysDeqIntRP_();
ef79bbde
P
2844}
2845
7650b754 2846static void psxBios_SysInitMemory_(u32 base, u32 size) {
2847 storeRam32(base, 0);
2848 storeRam32(A_KMALLOC_PTR, base);
2849 storeRam32(A_KMALLOC_SIZE, size);
2850 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
2851}
2852
2853// this should be much more complicated, but maybe that'll be enough
2854static u32 psxBios_SysMalloc_(u32 size) {
2855 u32 ptr = loadRam32(A_KMALLOC_PTR);
2856
2857 size = (size + 3) & ~3;
2858 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
2859 storeRam32(ptr, size);
2860 return ptr + 4;
2861}
2862
2863static void psxBios_SysInitMemory() { // 08
2864 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
2865
2866 psxBios_SysInitMemory_(a0, a1);
2867 mips_return_void_c(12);
2868}
2869
2870static void psxBios_ChangeClearRCnt() { // 0a
dc4fa8bc 2871 u32 ret;
ef79bbde 2872
ef79bbde 2873 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
ef79bbde 2874
dc4fa8bc 2875 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
2876 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
2877 mips_return_c(ret, 8);
ef79bbde
P
2878}
2879
7650b754 2880static void psxBios_InitDefInt() { // 0c
2881 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
2882 // should also clear the autoack table
2883 a1 = 0x6d98;
2884 psxBios_SysEnqIntRP();
2885 mips_return_c(0, 20 + 6*2);
2886}
2887
7a8d521f 2888void psxBios_dummy() {
dc4fa8bc 2889 u32 pc = (pc0 & 0x1fffff) - 4;
2890 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
2891 : pc == 0xc0 ? biosC0n : NULL;
2892 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
2893 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
2894 (void)pc; (void)ntab;
2895 mips_return_c(0, 100);
ef79bbde
P
2896}
2897
2898void (*biosA0[256])();
dc4fa8bc 2899// C0 and B0 overlap (end of C0 is start of B0)
2900void (*biosC0[256+128])();
2901void (**biosB0)() = biosC0 + 128;
ef79bbde
P
2902
2903#include "sjisfont.h"
2904
dc4fa8bc 2905void setup_mips_code()
2906{
2907 u32 *ptr;
2908 ptr = (u32 *)&psxM[A_SYSCALL];
2909 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
2910 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
2911 ptr[0x08/4] = SWAPu32(0x00000000); // nop
2912
2913 ptr = (u32 *)&psxM[A_EXCEPTION];
2914 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
2915 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
2916 ptr[0x14/4] = SWAPu32(0x00000000); // nop
2917 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
2918 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
2919 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
2920 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
2921 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
2922 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
2923 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
2924
2925 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
2926 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
2927 ptr[0x68/4] = SWAPu32(0x24630004); // addiu $v1, $v1, 4
2928 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
2929
2930 ptr[0xb0/4] = HLEOP(hleop_exception);
2931}
2932
2933static const struct {
2934 u32 addr;
2935 enum hle_op op;
2936} chainfns[] = {
2937 { 0xbfc050a4, hleop_exc0_0_1 },
2938 { 0xbfc04fbc, hleop_exc0_0_2 },
2939 { 0xbfc0506c, hleop_exc0_1_1 },
2940 { 0xbfc04dec, hleop_exc0_1_2 },
2941 { 0x1a00, hleop_exc0_2_2 },
2942 { 0x19c8, hleop_exc1_0_1 },
2943 { 0x18bc, hleop_exc1_0_2 },
2944 { 0x1990, hleop_exc1_1_1 },
2945 { 0x1858, hleop_exc1_1_2 },
2946 { 0x1958, hleop_exc1_2_1 },
2947 { 0x17f4, hleop_exc1_2_2 },
2948 { 0x1920, hleop_exc1_3_1 },
2949 { 0x1794, hleop_exc1_3_2 },
2950 { 0x2458, hleop_exc3_0_2 },
2951};
2952
2953static int chain_hle_op(u32 handler)
2954{
2955 size_t i;
2956
2957 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
2958 if (chainfns[i].addr == handler)
2959 return chainfns[i].op;
2960 return hleop_dummy;
2961}
2962
2963static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
2964{
2965 d[0] = SWAPu32(next);
2966 d[1] = SWAPu32(handler1);
2967 d[2] = SWAPu32(handler2);
2968
2969 // install hle traps
2970 PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
2971 PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
2972}
2973
7650b754 2974static void setup_tt(u32 tcb_cnt, u32 evcb_cnt)
2975{
2976 u32 *ram32 = (u32 *)psxM;
2977 u32 s_excb = 0x20, s_evcb = 0x1c * evcb_cnt;
2978 u32 s_pcb = 4, s_tcb = 0xc0 * tcb_cnt;
2979 u32 p_excb, p_evcb, p_pcb, p_tcb;
2980
2981 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
2982 psxBios_SysInitMemory_(0xa000e000, 0x2000);
2983 p_excb = psxBios_SysMalloc_(s_excb);
2984 p_evcb = psxBios_SysMalloc_(s_evcb);
2985 p_pcb = psxBios_SysMalloc_(s_pcb);
2986 p_tcb = psxBios_SysMalloc_(s_tcb);
2987
2988 // "table of tables". Some games modify it
2989 assert(A_TT_ExCB == 0x0100);
2990 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
2991 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
2992 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
2993 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
2994 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
2995 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
2996 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
2997 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
2998 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
2999 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3000 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3001 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3002
3003 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3004 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3005 storeRam32(p_excb + 4*4, 0x0000); // chain2
3006 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3007
3008 storeRam32(p_pcb, p_tcb);
3009 storeRam32(p_tcb, 0x4000); // first TCB
3010}
3011
ef79bbde
P
3012void psxBiosInit() {
3013 u32 base, size;
dc4fa8bc 3014 u32 *ptr, *ram32;
ef79bbde
P
3015 int i;
3016 uLongf len;
3017
dc4fa8bc 3018 memset(psxM, 0, 0x10000);
ef79bbde
P
3019 for(i = 0; i < 256; i++) {
3020 biosA0[i] = NULL;
3021 biosB0[i] = NULL;
3022 biosC0[i] = NULL;
3023 }
a94ccc7f 3024 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3025 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3026 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3027 biosA0[0x3f] = psxBios_printf_psxout;
ef79bbde
P
3028
3029 if (!Config.HLE) return;
3030
3031 for(i = 0; i < 256; i++) {
3032 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3033 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3034 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3035 }
3036
3037 biosA0[0x00] = psxBios_open;
3038 biosA0[0x01] = psxBios_lseek;
3039 biosA0[0x02] = psxBios_read;
3040 biosA0[0x03] = psxBios_write;
3041 biosA0[0x04] = psxBios_close;
3042 //biosA0[0x05] = psxBios_ioctl;
3043 //biosA0[0x06] = psxBios_exit;
3044 //biosA0[0x07] = psxBios_sys_a0_07;
324cec89 3045 biosA0[0x08] = psxBios_getc;
3046 biosA0[0x09] = psxBios_putc;
ba11675c 3047 biosA0[0x0a] = psxBios_todigit;
ef79bbde
P
3048 //biosA0[0x0b] = psxBios_atof;
3049 //biosA0[0x0c] = psxBios_strtoul;
3050 //biosA0[0x0d] = psxBios_strtol;
3051 biosA0[0x0e] = psxBios_abs;
3052 biosA0[0x0f] = psxBios_labs;
3053 biosA0[0x10] = psxBios_atoi;
3054 biosA0[0x11] = psxBios_atol;
3055 //biosA0[0x12] = psxBios_atob;
3056 biosA0[0x13] = psxBios_setjmp;
3057 biosA0[0x14] = psxBios_longjmp;
3058 biosA0[0x15] = psxBios_strcat;
3059 biosA0[0x16] = psxBios_strncat;
3060 biosA0[0x17] = psxBios_strcmp;
3061 biosA0[0x18] = psxBios_strncmp;
3062 biosA0[0x19] = psxBios_strcpy;
3063 biosA0[0x1a] = psxBios_strncpy;
3064 biosA0[0x1b] = psxBios_strlen;
3065 biosA0[0x1c] = psxBios_index;
3066 biosA0[0x1d] = psxBios_rindex;
3067 biosA0[0x1e] = psxBios_strchr;
3068 biosA0[0x1f] = psxBios_strrchr;
3069 biosA0[0x20] = psxBios_strpbrk;
3070 biosA0[0x21] = psxBios_strspn;
3071 biosA0[0x22] = psxBios_strcspn;
3072 biosA0[0x23] = psxBios_strtok;
3073 biosA0[0x24] = psxBios_strstr;
3074 biosA0[0x25] = psxBios_toupper;
3075 biosA0[0x26] = psxBios_tolower;
3076 biosA0[0x27] = psxBios_bcopy;
3077 biosA0[0x28] = psxBios_bzero;
3078 biosA0[0x29] = psxBios_bcmp;
3079 biosA0[0x2a] = psxBios_memcpy;
3080 biosA0[0x2b] = psxBios_memset;
3081 biosA0[0x2c] = psxBios_memmove;
3082 biosA0[0x2d] = psxBios_memcmp;
3083 biosA0[0x2e] = psxBios_memchr;
3084 biosA0[0x2f] = psxBios_rand;
3085 biosA0[0x30] = psxBios_srand;
3086 biosA0[0x31] = psxBios_qsort;
3087 //biosA0[0x32] = psxBios_strtod;
3088 biosA0[0x33] = psxBios_malloc;
3089 biosA0[0x34] = psxBios_free;
3090 //biosA0[0x35] = psxBios_lsearch;
3091 //biosA0[0x36] = psxBios_bsearch;
3092 biosA0[0x37] = psxBios_calloc;
3093 biosA0[0x38] = psxBios_realloc;
3094 biosA0[0x39] = psxBios_InitHeap;
3095 //biosA0[0x3a] = psxBios__exit;
3096 biosA0[0x3b] = psxBios_getchar;
7a8d521f 3097 biosA0[0x3c] = psxBios_putchar;
ef79bbde 3098 //biosA0[0x3d] = psxBios_gets;
dc4fa8bc 3099 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
ef79bbde
P
3100 //biosA0[0x41] = psxBios_LoadTest;
3101 biosA0[0x42] = psxBios_Load;
3102 biosA0[0x43] = psxBios_Exec;
3103 biosA0[0x44] = psxBios_FlushCache;
3104 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3105 biosA0[0x46] = psxBios_GPU_dw;
3106 biosA0[0x47] = psxBios_mem2vram;
3107 biosA0[0x48] = psxBios_SendGPU;
3108 biosA0[0x49] = psxBios_GPU_cw;
3109 biosA0[0x4a] = psxBios_GPU_cwb;
3110 biosA0[0x4b] = psxBios_GPU_SendPackets;
3111 biosA0[0x4c] = psxBios_sys_a0_4c;
3112 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
7a8d521f 3113 //biosA0[0x4e] = psxBios_GPU_sync;
ef79bbde
P
3114 //biosA0[0x4f] = psxBios_sys_a0_4f;
3115 //biosA0[0x50] = psxBios_sys_a0_50;
3116 biosA0[0x51] = psxBios_LoadExec;
3117 //biosA0[0x52] = psxBios_GetSysSp;
3118 //biosA0[0x53] = psxBios_sys_a0_53;
3119 //biosA0[0x54] = psxBios__96_init_a54;
3120 //biosA0[0x55] = psxBios__bu_init_a55;
dc4fa8bc 3121 biosA0[0x56] = psxBios_CdRemove;
ef79bbde
P
3122 //biosA0[0x57] = psxBios_sys_a0_57;
3123 //biosA0[0x58] = psxBios_sys_a0_58;
3124 //biosA0[0x59] = psxBios_sys_a0_59;
3125 //biosA0[0x5a] = psxBios_sys_a0_5a;
3126 //biosA0[0x5b] = psxBios_dev_tty_init;
3127 //biosA0[0x5c] = psxBios_dev_tty_open;
3128 //biosA0[0x5d] = psxBios_sys_a0_5d;
3129 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3130 //biosA0[0x5f] = psxBios_dev_cd_open;
3131 //biosA0[0x60] = psxBios_dev_cd_read;
3132 //biosA0[0x61] = psxBios_dev_cd_close;
3133 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3134 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3135 //biosA0[0x64] = psxBios_dev_cd_chdir;
3136 //biosA0[0x65] = psxBios_dev_card_open;
3137 //biosA0[0x66] = psxBios_dev_card_read;
3138 //biosA0[0x67] = psxBios_dev_card_write;
3139 //biosA0[0x68] = psxBios_dev_card_close;
3140 //biosA0[0x69] = psxBios_dev_card_firstfile;
3141 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3142 //biosA0[0x6b] = psxBios_dev_card_erase;
3143 //biosA0[0x6c] = psxBios_dev_card_undelete;
3144 //biosA0[0x6d] = psxBios_dev_card_format;
3145 //biosA0[0x6e] = psxBios_dev_card_rename;
3146 //biosA0[0x6f] = psxBios_dev_card_6f;
3147 biosA0[0x70] = psxBios__bu_init;
3148 biosA0[0x71] = psxBios__96_init;
dc4fa8bc 3149 biosA0[0x72] = psxBios_CdRemove;
ef79bbde
P
3150 //biosA0[0x73] = psxBios_sys_a0_73;
3151 //biosA0[0x74] = psxBios_sys_a0_74;
3152 //biosA0[0x75] = psxBios_sys_a0_75;
3153 //biosA0[0x76] = psxBios_sys_a0_76;
3154 //biosA0[0x77] = psxBios_sys_a0_77;
3155 //biosA0[0x78] = psxBios__96_CdSeekL;
3156 //biosA0[0x79] = psxBios_sys_a0_79;
3157 //biosA0[0x7a] = psxBios_sys_a0_7a;
3158 //biosA0[0x7b] = psxBios_sys_a0_7b;
3159 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3160 //biosA0[0x7d] = psxBios_sys_a0_7d;
3161 //biosA0[0x7e] = psxBios__96_CdRead;
3162 //biosA0[0x7f] = psxBios_sys_a0_7f;
3163 //biosA0[0x80] = psxBios_sys_a0_80;
3164 //biosA0[0x81] = psxBios_sys_a0_81;
7a8d521f 3165 //biosA0[0x82] = psxBios_sys_a0_82;
ef79bbde
P
3166 //biosA0[0x83] = psxBios_sys_a0_83;
3167 //biosA0[0x84] = psxBios_sys_a0_84;
7a8d521f 3168 //biosA0[0x85] = psxBios__96_CdStop;
ef79bbde
P
3169 //biosA0[0x86] = psxBios_sys_a0_86;
3170 //biosA0[0x87] = psxBios_sys_a0_87;
3171 //biosA0[0x88] = psxBios_sys_a0_88;
3172 //biosA0[0x89] = psxBios_sys_a0_89;
3173 //biosA0[0x8a] = psxBios_sys_a0_8a;
3174 //biosA0[0x8b] = psxBios_sys_a0_8b;
3175 //biosA0[0x8c] = psxBios_sys_a0_8c;
3176 //biosA0[0x8d] = psxBios_sys_a0_8d;
3177 //biosA0[0x8e] = psxBios_sys_a0_8e;
3178 //biosA0[0x8f] = psxBios_sys_a0_8f;
dc4fa8bc 3179 biosA0[0x90] = hleExc0_1_2;
3180 biosA0[0x91] = hleExc0_0_2;
3181 biosA0[0x92] = hleExc0_1_1;
3182 biosA0[0x93] = hleExc0_0_1;
ef79bbde
P
3183 //biosA0[0x94] = psxBios_sys_a0_94;
3184 //biosA0[0x95] = psxBios_sys_a0_95;
3185 //biosA0[0x96] = psxBios_AddCDROMDevice;
3186 //biosA0[0x97] = psxBios_AddMemCardDevide;
3187 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3188 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3189 //biosA0[0x9a] = psxBios_sys_a0_9a;
3190 //biosA0[0x9b] = psxBios_sys_a0_9b;
3191 //biosA0[0x9c] = psxBios_SetConf;
3192 //biosA0[0x9d] = psxBios_GetConf;
3193 //biosA0[0x9e] = psxBios_sys_a0_9e;
3194 biosA0[0x9f] = psxBios_SetMem;
3195 //biosA0[0xa0] = psxBios__boot;
3196 //biosA0[0xa1] = psxBios_SystemError;
3197 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
dc4fa8bc 3198 biosA0[0xa3] = psxBios_DequeueCdIntr;
ef79bbde
P
3199 //biosA0[0xa4] = psxBios_sys_a0_a4;
3200 //biosA0[0xa5] = psxBios_ReadSector;
18dd7e9e 3201 biosA0[0xa6] = psxBios_get_cd_status;
ef79bbde
P
3202 //biosA0[0xa7] = psxBios_bufs_cb_0;
3203 //biosA0[0xa8] = psxBios_bufs_cb_1;
3204 //biosA0[0xa9] = psxBios_bufs_cb_2;
3205 //biosA0[0xaa] = psxBios_bufs_cb_3;
3206 biosA0[0xab] = psxBios__card_info;
3207 biosA0[0xac] = psxBios__card_load;
3208 //biosA0[0axd] = psxBios__card_auto;
3209 //biosA0[0xae] = psxBios_bufs_cd_4;
3210 //biosA0[0xaf] = psxBios_sys_a0_af;
3211 //biosA0[0xb0] = psxBios_sys_a0_b0;
3212 //biosA0[0xb1] = psxBios_sys_a0_b1;
3213 //biosA0[0xb2] = psxBios_do_a_long_jmp
3214 //biosA0[0xb3] = psxBios_sys_a0_b3;
3215 //biosA0[0xb4] = psxBios_sub_function;
3216//*******************B0 CALLS****************************
7650b754 3217 biosB0[0x00] = psxBios_SysMalloc;
ef79bbde
P
3218 //biosB0[0x01] = psxBios_sys_b0_01;
3219 biosB0[0x02] = psxBios_SetRCnt;
3220 biosB0[0x03] = psxBios_GetRCnt;
3221 biosB0[0x04] = psxBios_StartRCnt;
3222 biosB0[0x05] = psxBios_StopRCnt;
3223 biosB0[0x06] = psxBios_ResetRCnt;
3224 biosB0[0x07] = psxBios_DeliverEvent;
3225 biosB0[0x08] = psxBios_OpenEvent;
3226 biosB0[0x09] = psxBios_CloseEvent;
3227 biosB0[0x0a] = psxBios_WaitEvent;
3228 biosB0[0x0b] = psxBios_TestEvent;
3229 biosB0[0x0c] = psxBios_EnableEvent;
3230 biosB0[0x0d] = psxBios_DisableEvent;
3231 biosB0[0x0e] = psxBios_OpenTh;
3232 biosB0[0x0f] = psxBios_CloseTh;
3233 biosB0[0x10] = psxBios_ChangeTh;
3234 //biosB0[0x11] = psxBios_psxBios_b0_11;
3235 biosB0[0x12] = psxBios_InitPAD;
3236 biosB0[0x13] = psxBios_StartPAD;
3237 biosB0[0x14] = psxBios_StopPAD;
3238 biosB0[0x15] = psxBios_PAD_init;
3239 biosB0[0x16] = psxBios_PAD_dr;
3240 biosB0[0x17] = psxBios_ReturnFromException;
3241 biosB0[0x18] = psxBios_ResetEntryInt;
3242 biosB0[0x19] = psxBios_HookEntryInt;
3243 //biosB0[0x1a] = psxBios_sys_b0_1a;
3244 //biosB0[0x1b] = psxBios_sys_b0_1b;
3245 //biosB0[0x1c] = psxBios_sys_b0_1c;
3246 //biosB0[0x1d] = psxBios_sys_b0_1d;
3247 //biosB0[0x1e] = psxBios_sys_b0_1e;
3248 //biosB0[0x1f] = psxBios_sys_b0_1f;
3249 biosB0[0x20] = psxBios_UnDeliverEvent;
3250 //biosB0[0x21] = psxBios_sys_b0_21;
3251 //biosB0[0x22] = psxBios_sys_b0_22;
3252 //biosB0[0x23] = psxBios_sys_b0_23;
3253 //biosB0[0x24] = psxBios_sys_b0_24;
3254 //biosB0[0x25] = psxBios_sys_b0_25;
3255 //biosB0[0x26] = psxBios_sys_b0_26;
3256 //biosB0[0x27] = psxBios_sys_b0_27;
3257 //biosB0[0x28] = psxBios_sys_b0_28;
3258 //biosB0[0x29] = psxBios_sys_b0_29;
3259 //biosB0[0x2a] = psxBios_sys_b0_2a;
3260 //biosB0[0x2b] = psxBios_sys_b0_2b;
3261 //biosB0[0x2c] = psxBios_sys_b0_2c;
3262 //biosB0[0x2d] = psxBios_sys_b0_2d;
3263 //biosB0[0x2e] = psxBios_sys_b0_2e;
3264 //biosB0[0x2f] = psxBios_sys_b0_2f;
3265 //biosB0[0x30] = psxBios_sys_b0_30;
3266 //biosB0[0x31] = psxBios_sys_b0_31;
3267 biosB0[0x32] = psxBios_open;
3268 biosB0[0x33] = psxBios_lseek;
3269 biosB0[0x34] = psxBios_read;
3270 biosB0[0x35] = psxBios_write;
3271 biosB0[0x36] = psxBios_close;
3272 //biosB0[0x37] = psxBios_ioctl;
3273 //biosB0[0x38] = psxBios_exit;
3274 //biosB0[0x39] = psxBios_sys_b0_39;
3275 //biosB0[0x3a] = psxBios_getc;
3276 //biosB0[0x3b] = psxBios_putc;
3277 biosB0[0x3c] = psxBios_getchar;
3278 //biosB0[0x3e] = psxBios_gets;
3279 //biosB0[0x40] = psxBios_cd;
e7e1f572 3280 biosB0[0x41] = psxBios_format;
ef79bbde
P
3281 biosB0[0x42] = psxBios_firstfile;
3282 biosB0[0x43] = psxBios_nextfile;
3283 biosB0[0x44] = psxBios_rename;
3284 biosB0[0x45] = psxBios_delete;
3285 //biosB0[0x46] = psxBios_undelete;
3286 //biosB0[0x47] = psxBios_AddDevice;
3287 //biosB0[0x48] = psxBios_RemoteDevice;
3288 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3289 biosB0[0x4a] = psxBios_InitCARD;
3290 biosB0[0x4b] = psxBios_StartCARD;
3291 biosB0[0x4c] = psxBios_StopCARD;
3292 //biosB0[0x4d] = psxBios_sys_b0_4d;
3293 biosB0[0x4e] = psxBios__card_write;
3294 biosB0[0x4f] = psxBios__card_read;
3295 biosB0[0x50] = psxBios__new_card;
3296 biosB0[0x51] = psxBios_Krom2RawAdd;
3297 //biosB0[0x52] = psxBios_sys_b0_52;
3298 //biosB0[0x53] = psxBios_sys_b0_53;
3299 //biosB0[0x54] = psxBios__get_errno;
002b2f7d 3300 biosB0[0x55] = psxBios__get_error;
ef79bbde
P
3301 biosB0[0x56] = psxBios_GetC0Table;
3302 biosB0[0x57] = psxBios_GetB0Table;
e9fda093 3303 biosB0[0x58] = psxBios__card_chan;
ef79bbde
P
3304 //biosB0[0x59] = psxBios_sys_b0_59;
3305 //biosB0[0x5a] = psxBios_sys_b0_5a;
3306 biosB0[0x5b] = psxBios_ChangeClearPad;
21af3ff6 3307 biosB0[0x5c] = psxBios__card_status;
5f652aa9 3308 biosB0[0x5d] = psxBios__card_wait;
ef79bbde 3309//*******************C0 CALLS****************************
7650b754 3310 biosC0[0x00] = psxBios_InitRCnt;
3311 biosC0[0x01] = psxBios_InitException;
ef79bbde
P
3312 biosC0[0x02] = psxBios_SysEnqIntRP;
3313 biosC0[0x03] = psxBios_SysDeqIntRP;
3314 //biosC0[0x04] = psxBios_get_free_EvCB_slot;
3315 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3316 //biosC0[0x06] = psxBios_ExceptionHandler;
3317 //biosC0[0x07] = psxBios_InstallExeptionHandler;
7650b754 3318 biosC0[0x08] = psxBios_SysInitMemory;
ef79bbde 3319 //biosC0[0x09] = psxBios_SysInitKMem;
7a8d521f 3320 biosC0[0x0a] = psxBios_ChangeClearRCnt;
ef79bbde 3321 //biosC0[0x0b] = psxBios_SystemError;
7650b754 3322 biosC0[0x0c] = psxBios_InitDefInt;
ef79bbde
P
3323 //biosC0[0x0d] = psxBios_sys_c0_0d;
3324 //biosC0[0x0e] = psxBios_sys_c0_0e;
3325 //biosC0[0x0f] = psxBios_sys_c0_0f;
3326 //biosC0[0x10] = psxBios_sys_c0_10;
3327 //biosC0[0x11] = psxBios_sys_c0_11;
3328 //biosC0[0x12] = psxBios_InstallDevices;
3329 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3330 //biosC0[0x14] = psxBios_sys_c0_14;
3331 //biosC0[0x15] = psxBios__cdevinput;
3332 //biosC0[0x16] = psxBios__cdevscan;
3333 //biosC0[0x17] = psxBios__circgetc;
3334 //biosC0[0x18] = psxBios__circputc;
3335 //biosC0[0x19] = psxBios_ioabort;
3336 //biosC0[0x1a] = psxBios_sys_c0_1a
3337 //biosC0[0x1b] = psxBios_KernelRedirect;
3338 //biosC0[0x1c] = psxBios_PatchAOTable;
3339//************** THE END ***************************************
3340/**/
3341 base = 0x1000;
3342 size = sizeof(EvCB) * 32;
7a8d521f 3343 EventCB = (void *)&psxR[base]; base += size * 6;
3344 memset(EventCB, 0, size * 6);
3345 HwEV = EventCB;
3346 EvEV = EventCB + 32;
3347 RcEV = EventCB + 32 * 2;
3348 UeEV = EventCB + 32 * 3;
3349 SwEV = EventCB + 32 * 4;
3350 ThEV = EventCB + 32 * 5;
ef79bbde 3351
832f0c3c 3352 pad_stopped = 1;
c62b43c9 3353 pad_buf = NULL;
3354 pad_buf1 = NULL;
3355 pad_buf2 = NULL;
3356 pad_buf1len = pad_buf2len = 0;
3357 heap_addr = NULL;
3358 heap_end = NULL;
26b964b5 3359 heap_size = 0;
c62b43c9 3360 CardState = -1;
3361 CurThread = 0;
3362 memset(FDesc, 0, sizeof(FDesc));
832f0c3c 3363 card_active_chan = 0;
c62b43c9 3364
ef79bbde
P
3365 // initial RNG seed
3366 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3367
3368 // fonts
3369 len = 0x80000 - 0x66000;
3370 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3371 len = 0x80000 - 0x69d68;
3372 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3373
3374 // memory size 2 MB
3375 psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3376
bf643fd9 3377 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3378 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
339cc5b6 3379 Here are some examples of games not working with this fix in place :
3380 R-type won't get past the Irem logo if not implemented.
3381 Crash Team Racing will softlock after the Sony logo.
bf643fd9 3382 */
7a8d521f 3383
dc4fa8bc 3384 ram32 = (u32 *)psxM;
3385 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3386 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3387 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3388 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3389
3390 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3391 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3392
3393 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3394 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3395 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3396 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3397
3398 ram32[0x00a0/4] = HLEOP(hleop_a0);
3399 ram32[0x00b0/4] = HLEOP(hleop_b0);
3400 ram32[0x00c0/4] = HLEOP(hleop_c0);
3401
7650b754 3402 setup_tt(4, 16);
dc4fa8bc 3403
3404 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3405 strcpy((char *)&ram32[0xeff0/4], "bu");
3406
3407 // default exception handler chains
3408 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3409 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3410 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3411 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3412 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3413 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3414 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3415 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3416
3417 setup_mips_code();
3418
3419 // fill the api jumptables with fake entries as some games patch them
3420 // (or rather the funcs listed there)
3421 ptr = (u32 *)&psxM[A_A0_TABLE];
3422 for (i = 0; i < 256; i++)
3423 ptr[i] = SWAP32(0x1000);
3424
3425 ptr = (u32 *)&psxM[A_B0_TABLE];
3426 for (i = 0; i < 256; i++)
3427 ptr[i] = SWAP32(0x2000);
3428 // B(5b) is special because games patch (sometimes even jump to)
3429 // code at fixed offsets from it, nocash lists offsets:
3430 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3431 // call: +7a0=4b70, +884=4c54, +894=4c64
3432 ptr[0x5b] = SWAP32(0x43d0);
3433 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra
3434 ram32[0x4c54/4] = SWAP32(0x03e00008); // jr $ra
3435 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3436
3437 ptr = (u32 *)&psxM[A_C0_TABLE];
3438 for (i = 0; i < 256/2; i++)
3439 ptr[i] = SWAP32(0x3000);
3440 ptr[6] = SWAP32(A_EXCEPTION);
3441
3442 // more HLE traps
3443 ram32[0x1000/4] = HLEOP(hleop_dummy);
3444 ram32[0x2000/4] = HLEOP(hleop_dummy);
3445 ram32[0x3000/4] = HLEOP(hleop_dummy);
3446 ram32[0x4c54/4] = HLEOP(hleop_dummy); // for B12_InitPad?
3447 ram32[0x8000/4] = HLEOP(hleop_execret);
3448
3449 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3450 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3451 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3452 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3453 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3454 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
ef79bbde
P
3455}
3456
3457void psxBiosShutdown() {
3458}
3459
7650b754 3460void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt) {
3461 if (tcb_cnt != 4 || evcb_cnt != 16)
3462 setup_tt(tcb_cnt, evcb_cnt);
dc4fa8bc 3463}
3464
ef79bbde
P
3465#define psxBios_PADpoll(pad) { \
3466 PAD##pad##_startPoll(pad); \
3467 pad_buf##pad[0] = 0; \
3468 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3469 if (!(pad_buf##pad[1] & 0x0f)) { \
3470 bufcount = 32; \
3471 } else { \
3472 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3473 } \
3474 PAD##pad##_poll(0); \
3475 i = 2; \
3476 while (bufcount--) { \
3477 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3478 } \
3479}
3480
dc4fa8bc 3481static void biosPadHLE() {
ef79bbde
P
3482 int i, bufcount;
3483
dc4fa8bc 3484 if (pad_buf != NULL) {
3485 u32 *buf = (u32*)pad_buf;
3486
3487 PAD1_startPoll(1);
3488 if (PAD1_poll(0x42) == 0x23) {
3489 PAD1_poll(0);
3490 *buf = PAD1_poll(0) << 8;
3491 *buf |= PAD1_poll(0);
3492 PAD1_poll(0);
3493 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3494 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3495 } else {
3496 PAD1_poll(0);
3497 *buf = PAD1_poll(0) << 8;
3498 *buf|= PAD1_poll(0);
3499 }
ef79bbde 3500
dc4fa8bc 3501 PAD2_startPoll(2);
3502 if (PAD2_poll(0x42) == 0x23) {
3503 PAD2_poll(0);
3504 *buf |= PAD2_poll(0) << 24;
3505 *buf |= PAD2_poll(0) << 16;
3506 PAD2_poll(0);
3507 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3508 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3509 } else {
3510 PAD2_poll(0);
3511 *buf |= PAD2_poll(0) << 24;
3512 *buf |= PAD2_poll(0) << 16;
3513 }
3514 }
3515 if (!pad_stopped) {
3516 if (pad_buf1) {
3517 psxBios_PADpoll(1);
3518 }
ef79bbde 3519
dc4fa8bc 3520 if (pad_buf2) {
3521 psxBios_PADpoll(2);
3522 }
3523 }
3524}
3525
3526static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3527{
3528 use_cycles(10);
3529 if (enable) {
3530 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3531 psxBios_ReturnFromException();
3532 }
3533 else
3534 pc0 = ra;
3535}
ef79bbde 3536
dc4fa8bc 3537// hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3538// so this is only partially implemented
3539void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3540{
3541 u32 cdrom_dma_ack_enable = 1; // a000b93c
3542 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3543}
ef79bbde 3544
dc4fa8bc 3545void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3546{
3547 u32 ret = 0;
3548 //PSXBIOS_LOG("%s\n", __func__);
ef79bbde 3549
dc4fa8bc 3550 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3551 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3552 //if (--cdrom_irq_counter == 0) // 0xa0009180
3553 // DeliverEvent(); // 0xf0000003, 0x10
3554 use_cycles(22);
3555 ret = 1;
3556 }
3557 mips_return_c(ret, 20);
3558}
ef79bbde 3559
dc4fa8bc 3560void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3561{
3562 u32 cdrom_irq_ack_enable = 1; // a000b938
3563 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3564}
ef79bbde 3565
dc4fa8bc 3566void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3567{
3568 u32 ret = 0;
3569 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3570 PSXBIOS_LOG("%s TODO\n", __func__);
3571 ret = 1;
3572 }
3573 mips_return_c(ret, 20);
3574}
ef79bbde 3575
dc4fa8bc 3576void hleExc0_2_2_syscall() // not in any A/B/C table
3577{
3578 u32 code = (psxRegs.CP0.n.Cause & 0x3c) >> 2;
3579 u32 tcbPtr = loadRam32(A_TT_PCB);
3580 TCB *tcb = loadRam32ptr(tcbPtr);
3581
3582 if (code != R3000E_Syscall) {
3583 if (code != 0) {
3584 // DeliverEvent(); // 0xf0000010, 0x1000
3585 psxBios_SystemErrorUnresolvedException();
ef79bbde 3586 }
dc4fa8bc 3587 mips_return_c(0, 17);
3588 return;
ef79bbde
P
3589 }
3590
dc4fa8bc 3591 //printf("%s c=%d a0=%d\n", __func__, code, a0);
3592 tcb->epc += SWAP32(4);
3593 switch (a0) {
3594 case 0: // noop
3595 break;
ef79bbde 3596
dc4fa8bc 3597 case 1: { // EnterCritical - disable irqs
3598 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3599 tcb->reg[2] = SWAP32(was_enabled);
3600 tcb->sr &= SWAP32(~0x404);
3601 break;
3602 }
3603 case 2: // ExitCritical - enable irqs
3604 tcb->sr |= SWAP32(0x404);
3605 break;
3606
3607 case 3: { // ChangeThreadSubFunction
3608 u32 tcbPtr = loadRam32(A_TT_PCB);
3609 storeRam32(tcbPtr, a1);
3610 break;
ef79bbde 3611 }
dc4fa8bc 3612 default:
3613 // DeliverEvent(); // 0xf0000010, 0x4000
3614 break;
ef79bbde 3615 }
dc4fa8bc 3616 use_cycles(30);
3617 psxBios_ReturnFromException();
ef79bbde
P
3618}
3619
dc4fa8bc 3620void hleExc1_0_1(void)
3621{
3622 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3623 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3624}
ef79bbde 3625
dc4fa8bc 3626static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3627{
3628 u32 ret = 0;
3629 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3630 // DeliverEvent 0xf2000000 + ev_index, 2
3631 if (RcEV[ev_index][1].status == EvStACTIVE) {
3632 softCall(RcEV[ev_index][1].fhandler);
3633 }
3634 ret = 1;
3635 }
3636 mips_return_c(ret, 22);
3637}
ef79bbde 3638
dc4fa8bc 3639void hleExc1_0_2(void)
3640{
3641 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3642}
ef79bbde 3643
dc4fa8bc 3644void hleExc1_1_1(void)
3645{
3646 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3647 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3648}
ef79bbde 3649
dc4fa8bc 3650void hleExc1_1_2(void)
3651{
3652 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3653}
ef79bbde 3654
dc4fa8bc 3655void hleExc1_2_1(void)
3656{
3657 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3658 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3659}
ef79bbde 3660
dc4fa8bc 3661void hleExc1_2_2(void)
3662{
3663 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3664}
ef79bbde 3665
dc4fa8bc 3666void hleExc1_3_1(void)
3667{
3668 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3669 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3670}
ef79bbde 3671
dc4fa8bc 3672void hleExc1_3_2(void)
3673{
3674 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3675}
ef79bbde 3676
dc4fa8bc 3677void hleExc3_0_2_defint(void)
3678{
3679 static const struct {
3680 u8 ev, irqbit;
3681 } tab[] = {
3682 { 3, 2 }, // cdrom
3683 { 9, 9 }, // spu
3684 { 2, 1 }, // gpu
3685 { 10, 10 }, // io
3686 { 11, 8 }, // sio
3687 { 1, 0 }, // vbl
3688 { 5, 4 }, // rcnt0
3689 { 6, 5 }, // rcnt1
3690 { 6, 6 }, // rcnt2 (bug)
3691 { 8, 7 }, // sio rx
3692 { 4, 3 }, // sio
3693 };
3694 size_t i;
3695 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3696 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3697 // DeliverEvent 0xf0000000 + ev, 0x1000
3698 use_cycles(7);
3699 }
ef79bbde 3700
dc4fa8bc 3701 }
3702 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3703}
ef79bbde 3704
dc4fa8bc 3705void psxBiosException() {
3706 u32 tcbPtr = loadRam32(A_TT_PCB);
3707 u32 *chains = loadRam32ptr(A_TT_ExCB);
3708 TCB *tcb = loadRam32ptr(tcbPtr);
3709 u32 ptr, *chain;
3710 int c, lim;
3711 int i;
ef79bbde 3712
dc4fa8bc 3713 // save the regs
3714 // $at, $v0, $v1 already saved by the mips code at A_EXCEPTION
3715 for (i = 4; i < 32; i++) {
3716 if (i == 26) // $k0
3717 continue;
3718 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
3719 }
3720 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
3721 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
3722 tcb->epc = SWAP32(psxRegs.CP0.n.EPC);
3723 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
3724 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
3725 sp = fp = loadRam32(A_EXC_SP);
3726 gp = A_EXC_GP;
3727 use_cycles(46);
3728
3729 // do the chains (always 4)
3730 for (c = lim = 0; c < 4; c++) {
3731 if (chains[c * 2] == 0)
3732 continue;
3733 ptr = SWAP32(chains[c * 2]);
3734 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
3735 chain = castRam32ptr(ptr);
3736 use_cycles(14);
3737 lim++;
3738 if (chain[2] == 0)
3739 continue;
3740 softCallInException(SWAP32(chain[2]));
3741 if (returned_from_exception())
3742 return;
ef79bbde 3743
dc4fa8bc 3744 if (v0 == 0 || chain[1] == 0)
3745 continue;
3746 softCallInException(SWAP32(chain[1]));
3747 if (returned_from_exception())
3748 return;
3749 }
ef79bbde 3750 }
dc4fa8bc 3751 assert(lim < 100);
ef79bbde 3752
dc4fa8bc 3753 // TODO make this a chain entry
3754 if (psxHu32(0x1070) & 1)
3755 biosPadHLE();
ef79bbde 3756
dc4fa8bc 3757 // return from exception (custom or default)
3758 use_cycles(23);
3759 ptr = loadRam32(A_EEXIT_PTR);
3760 if (ptr != A_EEXIT_DEF) {
3761 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
3762 longjmp_load(jmp_buf);
3763 v0 = 1;
3764 pc0 = ra;
3765 return;
3766 }
3767 psxBios_ReturnFromException();
ef79bbde
P
3768}
3769
3770#define bfreeze(ptr, size) { \
3771 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3772 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3773 base += size; \
3774}
3775
3776#define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3777#define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3778
3779#define bfreezepsxMptr(ptr, type) { \
3780 if (Mode == 1) { \
3781 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3782 else psxRu32ref(base) = 0; \
3783 } else { \
3784 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3785 else (ptr) = NULL; \
3786 } \
3787 base += sizeof(u32); \
3788}
3789
3790void psxBiosFreeze(int Mode) {
3791 u32 base = 0x40000;
3792
ef79bbde
P
3793 bfreezepsxMptr(pad_buf, int);
3794 bfreezepsxMptr(pad_buf1, char);
3795 bfreezepsxMptr(pad_buf2, char);
3796 bfreezepsxMptr(heap_addr, u32);
3797 bfreezel(&pad_buf1len);
3798 bfreezel(&pad_buf2len);
3799 bfreezes(regs);
ef79bbde 3800 bfreezel(&CardState);
ef79bbde
P
3801 bfreezel(&CurThread);
3802 bfreezes(FDesc);
e9fda093 3803 bfreezel(&card_active_chan);
a15f3544 3804 bfreezel(&pad_stopped);
17b2d969 3805 bfreezel(&heap_size);
ef79bbde 3806}