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