libretro: add (psx) exe and iso to valid_extensions
[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 1951 psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1));
bc7c5acb 1952 psxRegs.CP0.n.SR |= 0x401;
ef79bbde
P
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;
bc7c5acb 1979 psxRegs.CP0.n.SR |= 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
bc7c5acb 1999 psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
ef79bbde
P
2000}
2001
2002void psxBios_ResetEntryInt() { // 18
2003#ifdef PSXBIOS_LOG
2004 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2005#endif
2006
2007 jmp_int = NULL;
2008 pc0 = ra;
2009}
2010
2011void psxBios_HookEntryInt() { // 19
2012#ifdef PSXBIOS_LOG
2013 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x19]);
2014#endif
2015
2016 jmp_int = (u32*)Ra0;
2017 pc0 = ra;
2018}
2019
2020void psxBios_UnDeliverEvent() { // 0x20
2021 int ev, spec;
2022 int i;
2023
2024 GetEv();
2025 GetSpec();
2026
2027#ifdef PSXBIOS_LOG
2028 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec);
2029#endif
2030
7a8d521f 2031 if (EventCB[ev][spec].status == EvStALREADY &&
2032 EventCB[ev][spec].mode == EvMdNOINTR)
2033 EventCB[ev][spec].status = EvStACTIVE;
ef79bbde
P
2034
2035 pc0 = ra;
2036}
2037
595a136b 2038char ffile[64], *pfile;
2039int nfile;
7a8d521f 2040
857275a9 2041static void buopen(int mcd, char *ptr, char *cfg)
595a136b 2042{
2043 int i;
7a8d521f 2044 char *mcd_data = ptr;
595a136b 2045
2046 strcpy(FDesc[1 + mcd].name, Ra0+5);
2047 FDesc[1 + mcd].offset = 0;
2048 FDesc[1 + mcd].mode = a1;
2049
2050 for (i=1; i<16; i++) {
7a8d521f 2051 const char *fptr = mcd_data + 128 * i;
595a136b 2052 if ((*fptr & 0xF0) != 0x50) continue;
2053 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2054 FDesc[1 + mcd].mcfile = i;
2055 SysPrintf("open %s\n", fptr+0xa);
2056 v0 = 1 + mcd;
2057 break;
2058 }
2059 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
595a136b 2060 for (i=1; i<16; i++) {
2061 int j, xor, nblk = a1 >> 16;
7a8d521f 2062 char *pptr, *fptr2;
2063 char *fptr = mcd_data + 128 * i;
595a136b 2064
595a136b 2065 if ((*fptr & 0xF0) != 0xa0) continue;
2066
2067 FDesc[1 + mcd].mcfile = i;
2068 fptr[0] = 0x51;
2069 fptr[4] = 0x00;
2070 fptr[5] = 0x20 * nblk;
2071 fptr[6] = 0x00;
2072 fptr[7] = 0x00;
2073 strcpy(fptr+0xa, FDesc[1 + mcd].name);
7a8d521f 2074 pptr = fptr2 = fptr;
595a136b 2075 for(j=2; j<=nblk; j++) {
2076 int k;
2077 for(i++; i<16; i++) {
2078 fptr2 += 128;
7a8d521f 2079
595a136b 2080 memset(fptr2, 0, 128);
2081 fptr2[0] = j < nblk ? 0x52 : 0x53;
2082 pptr[8] = i - 1;
2083 pptr[9] = 0;
2084 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2085 pptr[127] = xor;
2086 pptr = fptr2;
2087 break;
2088 }
2089 /* shouldn't this return ENOSPC if i == 16? */
2090 }
2091 pptr[8] = pptr[9] = 0xff;
2092 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2093 pptr[127] = xor;
2094 SysPrintf("openC %s %d\n", ptr, nblk);
2095 v0 = 1 + mcd;
2096 /* just go ahead and resave them all */
2097 SaveMcd(cfg, ptr, 128, 128 * 15);
2098 break;
2099 }
2100 /* shouldn't this return ENOSPC if i == 16? */
2101 }
ef79bbde
P
2102}
2103
2104/*
2105 * int open(char *name , int mode);
2106 */
2107
2108void psxBios_open() { // 0x32
02949f79 2109 void *pa0 = Ra0;
ef79bbde
P
2110
2111#ifdef PSXBIOS_LOG
2112 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2113#endif
2114
2115 v0 = -1;
2116
7a8d521f 2117 if (pa0 != INVALID_PTR) {
02949f79 2118 if (!strncmp(pa0, "bu00", 4)) {
595a136b 2119 buopen(1, Mcd1Data, Config.Mcd1);
02949f79 2120 }
ef79bbde 2121
02949f79 2122 if (!strncmp(pa0, "bu10", 4)) {
595a136b 2123 buopen(2, Mcd2Data, Config.Mcd2);
02949f79 2124 }
ef79bbde
P
2125 }
2126
2127 pc0 = ra;
2128}
2129
2130/*
2131 * int lseek(int fd , int offset , int whence);
2132 */
2133
2134void psxBios_lseek() { // 0x33
2135#ifdef PSXBIOS_LOG
2136 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2137#endif
2138
2139 switch (a2) {
2140 case 0: // SEEK_SET
2141 FDesc[a0].offset = a1;
2142 v0 = a1;
2143// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2144// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2145 break;
2146
2147 case 1: // SEEK_CUR
2148 FDesc[a0].offset+= a1;
2149 v0 = FDesc[a0].offset;
2150 break;
2151 }
2152
2153 pc0 = ra;
2154}
2155
595a136b 2156
ef79bbde
P
2157/*
2158 * int read(int fd , void *buf , int nbytes);
2159 */
2160
2161void psxBios_read() { // 0x34
2162 char *ptr;
02949f79 2163 void *pa1 = Ra1;
ef79bbde
P
2164
2165#ifdef PSXBIOS_LOG
2166 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2167#endif
2168
2169 v0 = -1;
2170
7a8d521f 2171 if (pa1 != INVALID_PTR) {
02949f79 2172 switch (a0) {
595a136b 2173 case 2: buread(pa1, 1, a2); break;
2174 case 3: buread(pa1, 2, a2); break;
02949f79 2175 }
ef79bbde 2176 }
7a8d521f 2177
ef79bbde
P
2178 pc0 = ra;
2179}
2180
ef79bbde
P
2181/*
2182 * int write(int fd , void *buf , int nbytes);
2183 */
2184
2185void psxBios_write() { // 0x35/0x03
2186 char *ptr;
02949f79 2187 void *pa1 = Ra1;
2188
2189#ifdef PSXBIOS_LOG
2190 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2191#endif
2192
2193 v0 = -1;
7a8d521f 2194 if (pa1 == INVALID_PTR) {
02949f79 2195 pc0 = ra;
2196 return;
2197 }
ef79bbde
P
2198
2199 if (a0 == 1) { // stdout
02949f79 2200 char *ptr = pa1;
ef79bbde 2201
02949f79 2202 v0 = a2;
ef79bbde
P
2203 while (a2 > 0) {
2204 SysPrintf("%c", *ptr++); a2--;
2205 }
2206 pc0 = ra; return;
2207 }
ef79bbde
P
2208
2209 switch (a0) {
595a136b 2210 case 2: buwrite(pa1, 1, a2); break;
2211 case 3: buwrite(pa1, 2, a2); break;
ef79bbde
P
2212 }
2213
2214 pc0 = ra;
2215}
2216
a94ccc7f 2217static void psxBios_write_psxout() {
2218 if (a0 == 1) { // stdout
2219 const char *ptr = Ra1;
2220 int len = a2;
2221
2222 if (ptr != INVALID_PTR)
2223 while (len-- > 0)
2224 SysPrintf("%c", *ptr++);
2225 }
2226}
2227
2228static void psxBios_putchar_psxout() { // 3d
2229 SysPrintf("%c", (char)a0);
2230}
2231
2232static void psxBios_puts_psxout() { // 3e/3f
2233 SysPrintf("%s", Ra0);
2234}
2235
ef79bbde
P
2236/*
2237 * int close(int fd);
2238 */
2239
2240void psxBios_close() { // 0x36
2241#ifdef PSXBIOS_LOG
2242 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2243#endif
2244
2245 v0 = a0;
2246 pc0 = ra;
2247}
2248
2249void psxBios_putchar() { // 3d
2250 SysPrintf("%c", (char)a0);
2251 pc0 = ra;
2252}
2253
2254void psxBios_puts() { // 3e/3f
808a13bd 2255 SysPrintf("%s", Ra0);
ef79bbde
P
2256 pc0 = ra;
2257}
2258
f1514614 2259
2260/* To avoid any issues with different behaviour when using the libc's own strlen instead.
2261 * We want to mimic the PSX's behaviour in this case for bufile. */
7a8d521f 2262static size_t strlen_internal(char* p)
f1514614 2263{
2264 size_t size_of_array = 0;
2265 while (*p++) size_of_array++;
2266 return size_of_array;
2267}
2268
ef79bbde 2269#define bufile(mcd) { \
f1514614 2270 size_t size_of_name = strlen_internal(dir->name); \
ef79bbde
P
2271 while (nfile < 16) { \
2272 int match=1; \
2273 \
595a136b 2274 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
ef79bbde
P
2275 nfile++; \
2276 if ((*ptr & 0xF0) != 0x50) continue; \
595a136b 2277 /* Bug link files show up as free block. */ \
2278 if (!ptr[0xa]) continue; \
ef79bbde
P
2279 ptr+= 0xa; \
2280 if (pfile[0] == 0) { \
f1514614 2281 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2282 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
ef79bbde
P
2283 } else for (i=0; i<20; i++) { \
2284 if (pfile[i] == ptr[i]) { \
595a136b 2285 dir->name[i] = ptr[i]; continue; } \
ef79bbde
P
2286 if (pfile[i] == '?') { \
2287 dir->name[i] = ptr[i]; continue; } \
2288 if (pfile[i] == '*') { \
2289 strcpy(dir->name+i, ptr+i); break; } \
2290 match = 0; break; \
2291 } \
2292 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
595a136b 2293 if (match == 0) { continue; } \
ef79bbde
P
2294 dir->size = 8192; \
2295 v0 = _dir; \
2296 break; \
2297 } \
2298}
2299
2300/*
2301 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2302 */
7a8d521f 2303
ef79bbde
P
2304void psxBios_firstfile() { // 42
2305 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
02949f79 2306 void *pa0 = Ra0;
ef79bbde
P
2307 u32 _dir = a1;
2308 char *ptr;
2309 int i;
2310
2311#ifdef PSXBIOS_LOG
2312 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2313#endif
2314
2315 v0 = 0;
2316
7a8d521f 2317 if (pa0 != INVALID_PTR) {
02949f79 2318 strcpy(ffile, pa0);
2319 pfile = ffile+5;
8f3b2bd3 2320 nfile = 0;
02949f79 2321 if (!strncmp(pa0, "bu00", 4)) {
857fabea 2322 // firstfile() calls _card_read() internally, so deliver it's event
2323 DeliverEvent(0x11, 0x2);
02949f79 2324 bufile(1);
2325 } else if (!strncmp(pa0, "bu10", 4)) {
857fabea 2326 // firstfile() calls _card_read() internally, so deliver it's event
2327 DeliverEvent(0x11, 0x2);
02949f79 2328 bufile(2);
2329 }
ef79bbde
P
2330 }
2331
2332 pc0 = ra;
2333}
2334
2335/*
2336 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2337 */
2338
2339void psxBios_nextfile() { // 43
2340 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2341 u32 _dir = a0;
2342 char *ptr;
2343 int i;
2344
2345#ifdef PSXBIOS_LOG
2346 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2347#endif
2348
2349 v0 = 0;
2350
2351 if (!strncmp(ffile, "bu00", 4)) {
2352 bufile(1);
2353 }
2354
2355 if (!strncmp(ffile, "bu10", 4)) {
2356 bufile(2);
2357 }
2358
2359 pc0 = ra;
2360}
2361
2362#define burename(mcd) { \
2363 for (i=1; i<16; i++) { \
2364 int namelen, j, xor = 0; \
2365 ptr = Mcd##mcd##Data + 128 * i; \
2366 if ((*ptr & 0xF0) != 0x50) continue; \
2367 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2368 namelen = strlen(Ra1+5); \
2369 memcpy(ptr+0xa, Ra1+5, namelen); \
2370 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2371 for (j=0; j<127; j++) xor^= ptr[j]; \
2372 ptr[127] = xor; \
2373 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2374 v0 = 1; \
2375 break; \
2376 } \
2377}
2378
2379/*
2380 * int rename(char *old, char *new);
2381 */
2382
2383void psxBios_rename() { // 44
02949f79 2384 void *pa0 = Ra0;
2385 void *pa1 = Ra1;
ef79bbde
P
2386 char *ptr;
2387 int i;
2388
2389#ifdef PSXBIOS_LOG
2390 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2391#endif
2392
2393 v0 = 0;
2394
7a8d521f 2395 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
02949f79 2396 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2397 burename(1);
2398 }
ef79bbde 2399
02949f79 2400 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2401 burename(2);
2402 }
ef79bbde
P
2403 }
2404
2405 pc0 = ra;
2406}
2407
2408
2409#define budelete(mcd) { \
2410 for (i=1; i<16; i++) { \
2411 ptr = Mcd##mcd##Data + 128 * i; \
2412 if ((*ptr & 0xF0) != 0x50) continue; \
2413 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2414 *ptr = (*ptr & 0xf) | 0xA0; \
2415 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2416 SysPrintf("delete %s\n", ptr+0xa); \
2417 v0 = 1; \
2418 break; \
2419 } \
2420}
2421
2422/*
2423 * int delete(char *name);
2424 */
2425
2426void psxBios_delete() { // 45
02949f79 2427 void *pa0 = Ra0;
ef79bbde
P
2428 char *ptr;
2429 int i;
2430
2431#ifdef PSXBIOS_LOG
2432 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2433#endif
2434
2435 v0 = 0;
2436
7a8d521f 2437 if (pa0 != INVALID_PTR) {
02949f79 2438 if (!strncmp(pa0, "bu00", 4)) {
2439 budelete(1);
2440 }
ef79bbde 2441
02949f79 2442 if (!strncmp(pa0, "bu10", 4)) {
2443 budelete(2);
2444 }
ef79bbde
P
2445 }
2446
2447 pc0 = ra;
2448}
2449
2450void psxBios_InitCARD() { // 4a
2451#ifdef PSXBIOS_LOG
2452 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2453#endif
2454
2455 CardState = 0;
2456
2457 pc0 = ra;
2458}
2459
2460void psxBios_StartCARD() { // 4b
2461#ifdef PSXBIOS_LOG
2462 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2463#endif
2464
2465 if (CardState == 0) CardState = 1;
2466
2467 pc0 = ra;
2468}
2469
2470void psxBios_StopCARD() { // 4c
2471#ifdef PSXBIOS_LOG
2472 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2473#endif
2474
2475 if (CardState == 1) CardState = 0;
2476
2477 pc0 = ra;
2478}
2479
2480void psxBios__card_write() { // 0x4e
02949f79 2481 void *pa2 = Ra2;
ef79bbde
P
2482 int port;
2483
2484#ifdef PSXBIOS_LOG
2485 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2486#endif
1059caaf 2487 /*
2488 Function also accepts sector 400h (a bug).
2489 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2490 */
2491 if (!(a1 <= 0x3FF))
bd48ba5e 2492 {
2493 /* Invalid sectors */
2494 v0 = 0; pc0 = ra;
2495 return;
2496 }
e9fda093 2497 card_active_chan = a0;
ef79bbde
P
2498 port = a0 >> 4;
2499
7a8d521f 2500 if (pa2 != INVALID_PTR) {
02949f79 2501 if (port == 0) {
2502 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2503 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2504 } else {
2505 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2506 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2507 }
ef79bbde
P
2508 }
2509
2510 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2511// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2512
2513 v0 = 1; pc0 = ra;
2514}
2515
2516void psxBios__card_read() { // 0x4f
02949f79 2517 void *pa2 = Ra2;
ef79bbde
P
2518 int port;
2519
2520#ifdef PSXBIOS_LOG
2521 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2522#endif
1059caaf 2523 /*
2524 Function also accepts sector 400h (a bug).
2525 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2526 */
2527 if (!(a1 <= 0x3FF))
bd48ba5e 2528 {
2529 /* Invalid sectors */
2530 v0 = 0; pc0 = ra;
2531 return;
2532 }
e9fda093 2533 card_active_chan = a0;
ef79bbde
P
2534 port = a0 >> 4;
2535
7a8d521f 2536 if (pa2 != INVALID_PTR) {
02949f79 2537 if (port == 0) {
2538 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2539 } else {
2540 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2541 }
ef79bbde
P
2542 }
2543
2544 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2545// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2546
2547 v0 = 1; pc0 = ra;
2548}
2549
2550void psxBios__new_card() { // 0x50
2551#ifdef PSXBIOS_LOG
2552 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2553#endif
2554
2555 pc0 = ra;
2556}
2557
002b2f7d 2558/* According to a user, this allows Final Fantasy Tactics to save/load properly */
2559void psxBios__get_error(void) // 55
7a8d521f 2560{
002b2f7d 2561 v0 = 0;
2562 pc0 = ra;
2563}
2564
ef79bbde
P
2565void psxBios_Krom2RawAdd() { // 0x51
2566 int i = 0;
2567
2568 const u32 table_8140[][2] = {
2569 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2570 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2571 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2572 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2573 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2574 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2575 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2576 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2577 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2578 {0xffff, 0}
2579 };
2580
2581 const u32 table_889f[][2] = {
2582 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2583 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2584 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2585 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2586 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2587 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2588 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2589 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2590 {0xffff, 0}
2591 };
2592
2593 if (a0 >= 0x8140 && a0 <= 0x84be) {
2594 while (table_8140[i][0] <= a0) i++;
2595 a0 -= table_8140[i - 1][0];
2596 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2597 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2598 while (table_889f[i][0] <= a0) i++;
2599 a0 -= table_889f[i - 1][0];
2600 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2601 } else {
2602 v0 = 0xffffffff;
2603 }
2604
2605 pc0 = ra;
2606}
2607
2608void psxBios_GetC0Table() { // 56
2609#ifdef PSXBIOS_LOG
2610 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2611#endif
2612
2613 v0 = 0x674; pc0 = ra;
2614}
2615
2616void psxBios_GetB0Table() { // 57
2617#ifdef PSXBIOS_LOG
2618 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2619#endif
2620
2621 v0 = 0x874; pc0 = ra;
2622}
2623
e9fda093 2624void psxBios__card_chan() { // 0x58
2625#ifdef PSXBIOS_LOG
2626 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2627#endif
2628
2629 v0 = card_active_chan;
2630 pc0 = ra;
2631}
2632
ef79bbde
P
2633void psxBios_ChangeClearPad() { // 5b
2634#ifdef PSXBIOS_LOG
2635 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
7a8d521f 2636#endif
ef79bbde
P
2637
2638 pc0 = ra;
2639}
2640
21af3ff6 2641void psxBios__card_status() { // 5c
2642#ifdef PSXBIOS_LOG
2643 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2644#endif
2645
cf1af0ed 2646 v0 = card_active_chan;
21af3ff6 2647 pc0 = ra;
2648}
2649
5f652aa9 2650void psxBios__card_wait() { // 5d
2651#ifdef PSXBIOS_LOG
2652 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2653#endif
2654
2655 v0 = 1;
2656 pc0 = ra;
2657}
2658
ef79bbde
P
2659/* System calls C0 */
2660
2661/*
2662 * int SysEnqIntRP(int index , long *queue);
2663 */
2664
2665void psxBios_SysEnqIntRP() { // 02
2666#ifdef PSXBIOS_LOG
2667 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x02] ,a0);
2668#endif
2669
2670 SysIntRP[a0] = a1;
2671
2672 v0 = 0; pc0 = ra;
2673}
2674
2675/*
2676 * int SysDeqIntRP(int index , long *queue);
2677 */
2678
2679void psxBios_SysDeqIntRP() { // 03
2680#ifdef PSXBIOS_LOG
2681 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x03], a0);
2682#endif
2683
2684 SysIntRP[a0] = 0;
2685
2686 v0 = 0; pc0 = ra;
2687}
2688
2689void psxBios_ChangeClearRCnt() { // 0a
2690 u32 *ptr;
2691
2692#ifdef PSXBIOS_LOG
2693 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2694#endif
2695
2696 ptr = (u32*)PSXM((a0 << 2) + 0x8600);
2697 v0 = *ptr;
2698 *ptr = a1;
2699
bc7c5acb 2700// psxRegs.CP0.n.SR|= 0x404;
ef79bbde
P
2701 pc0 = ra;
2702}
2703
7a8d521f 2704void psxBios_dummy() {
ef79bbde
P
2705#ifdef PSXBIOS_LOG
2706 PSXBIOS_LOG("unk %x call: %x\n", pc0 & 0x1fffff, t1);
2707#endif
7a8d521f 2708 pc0 = ra;
ef79bbde
P
2709}
2710
2711void (*biosA0[256])();
2712void (*biosB0[256])();
2713void (*biosC0[256])();
2714
2715#include "sjisfont.h"
2716
2717void psxBiosInit() {
2718 u32 base, size;
7a8d521f 2719 u32 *ptr;
ef79bbde
P
2720 int i;
2721 uLongf len;
2722
2723 for(i = 0; i < 256; i++) {
2724 biosA0[i] = NULL;
2725 biosB0[i] = NULL;
2726 biosC0[i] = NULL;
2727 }
a94ccc7f 2728 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
2729 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
2730 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
2731 biosA0[0x3f] = psxBios_printf_psxout;
ef79bbde
P
2732
2733 if (!Config.HLE) return;
2734
2735 for(i = 0; i < 256; i++) {
2736 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
2737 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
2738 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
2739 }
2740
2741 biosA0[0x00] = psxBios_open;
2742 biosA0[0x01] = psxBios_lseek;
2743 biosA0[0x02] = psxBios_read;
2744 biosA0[0x03] = psxBios_write;
2745 biosA0[0x04] = psxBios_close;
2746 //biosA0[0x05] = psxBios_ioctl;
2747 //biosA0[0x06] = psxBios_exit;
2748 //biosA0[0x07] = psxBios_sys_a0_07;
324cec89 2749 biosA0[0x08] = psxBios_getc;
2750 biosA0[0x09] = psxBios_putc;
ba11675c 2751 biosA0[0x0a] = psxBios_todigit;
ef79bbde
P
2752 //biosA0[0x0b] = psxBios_atof;
2753 //biosA0[0x0c] = psxBios_strtoul;
2754 //biosA0[0x0d] = psxBios_strtol;
2755 biosA0[0x0e] = psxBios_abs;
2756 biosA0[0x0f] = psxBios_labs;
2757 biosA0[0x10] = psxBios_atoi;
2758 biosA0[0x11] = psxBios_atol;
2759 //biosA0[0x12] = psxBios_atob;
2760 biosA0[0x13] = psxBios_setjmp;
2761 biosA0[0x14] = psxBios_longjmp;
2762 biosA0[0x15] = psxBios_strcat;
2763 biosA0[0x16] = psxBios_strncat;
2764 biosA0[0x17] = psxBios_strcmp;
2765 biosA0[0x18] = psxBios_strncmp;
2766 biosA0[0x19] = psxBios_strcpy;
2767 biosA0[0x1a] = psxBios_strncpy;
2768 biosA0[0x1b] = psxBios_strlen;
2769 biosA0[0x1c] = psxBios_index;
2770 biosA0[0x1d] = psxBios_rindex;
2771 biosA0[0x1e] = psxBios_strchr;
2772 biosA0[0x1f] = psxBios_strrchr;
2773 biosA0[0x20] = psxBios_strpbrk;
2774 biosA0[0x21] = psxBios_strspn;
2775 biosA0[0x22] = psxBios_strcspn;
2776 biosA0[0x23] = psxBios_strtok;
2777 biosA0[0x24] = psxBios_strstr;
2778 biosA0[0x25] = psxBios_toupper;
2779 biosA0[0x26] = psxBios_tolower;
2780 biosA0[0x27] = psxBios_bcopy;
2781 biosA0[0x28] = psxBios_bzero;
2782 biosA0[0x29] = psxBios_bcmp;
2783 biosA0[0x2a] = psxBios_memcpy;
2784 biosA0[0x2b] = psxBios_memset;
2785 biosA0[0x2c] = psxBios_memmove;
2786 biosA0[0x2d] = psxBios_memcmp;
2787 biosA0[0x2e] = psxBios_memchr;
2788 biosA0[0x2f] = psxBios_rand;
2789 biosA0[0x30] = psxBios_srand;
2790 biosA0[0x31] = psxBios_qsort;
2791 //biosA0[0x32] = psxBios_strtod;
2792 biosA0[0x33] = psxBios_malloc;
2793 biosA0[0x34] = psxBios_free;
2794 //biosA0[0x35] = psxBios_lsearch;
2795 //biosA0[0x36] = psxBios_bsearch;
2796 biosA0[0x37] = psxBios_calloc;
2797 biosA0[0x38] = psxBios_realloc;
2798 biosA0[0x39] = psxBios_InitHeap;
2799 //biosA0[0x3a] = psxBios__exit;
2800 biosA0[0x3b] = psxBios_getchar;
7a8d521f 2801 biosA0[0x3c] = psxBios_putchar;
ef79bbde
P
2802 //biosA0[0x3d] = psxBios_gets;
2803 //biosA0[0x40] = psxBios_sys_a0_40;
2804 //biosA0[0x41] = psxBios_LoadTest;
2805 biosA0[0x42] = psxBios_Load;
2806 biosA0[0x43] = psxBios_Exec;
2807 biosA0[0x44] = psxBios_FlushCache;
2808 //biosA0[0x45] = psxBios_InstallInterruptHandler;
2809 biosA0[0x46] = psxBios_GPU_dw;
2810 biosA0[0x47] = psxBios_mem2vram;
2811 biosA0[0x48] = psxBios_SendGPU;
2812 biosA0[0x49] = psxBios_GPU_cw;
2813 biosA0[0x4a] = psxBios_GPU_cwb;
2814 biosA0[0x4b] = psxBios_GPU_SendPackets;
2815 biosA0[0x4c] = psxBios_sys_a0_4c;
2816 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
7a8d521f 2817 //biosA0[0x4e] = psxBios_GPU_sync;
ef79bbde
P
2818 //biosA0[0x4f] = psxBios_sys_a0_4f;
2819 //biosA0[0x50] = psxBios_sys_a0_50;
2820 biosA0[0x51] = psxBios_LoadExec;
2821 //biosA0[0x52] = psxBios_GetSysSp;
2822 //biosA0[0x53] = psxBios_sys_a0_53;
2823 //biosA0[0x54] = psxBios__96_init_a54;
2824 //biosA0[0x55] = psxBios__bu_init_a55;
2825 //biosA0[0x56] = psxBios__96_remove_a56;
2826 //biosA0[0x57] = psxBios_sys_a0_57;
2827 //biosA0[0x58] = psxBios_sys_a0_58;
2828 //biosA0[0x59] = psxBios_sys_a0_59;
2829 //biosA0[0x5a] = psxBios_sys_a0_5a;
2830 //biosA0[0x5b] = psxBios_dev_tty_init;
2831 //biosA0[0x5c] = psxBios_dev_tty_open;
2832 //biosA0[0x5d] = psxBios_sys_a0_5d;
2833 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
2834 //biosA0[0x5f] = psxBios_dev_cd_open;
2835 //biosA0[0x60] = psxBios_dev_cd_read;
2836 //biosA0[0x61] = psxBios_dev_cd_close;
2837 //biosA0[0x62] = psxBios_dev_cd_firstfile;
2838 //biosA0[0x63] = psxBios_dev_cd_nextfile;
2839 //biosA0[0x64] = psxBios_dev_cd_chdir;
2840 //biosA0[0x65] = psxBios_dev_card_open;
2841 //biosA0[0x66] = psxBios_dev_card_read;
2842 //biosA0[0x67] = psxBios_dev_card_write;
2843 //biosA0[0x68] = psxBios_dev_card_close;
2844 //biosA0[0x69] = psxBios_dev_card_firstfile;
2845 //biosA0[0x6a] = psxBios_dev_card_nextfile;
2846 //biosA0[0x6b] = psxBios_dev_card_erase;
2847 //biosA0[0x6c] = psxBios_dev_card_undelete;
2848 //biosA0[0x6d] = psxBios_dev_card_format;
2849 //biosA0[0x6e] = psxBios_dev_card_rename;
2850 //biosA0[0x6f] = psxBios_dev_card_6f;
2851 biosA0[0x70] = psxBios__bu_init;
2852 biosA0[0x71] = psxBios__96_init;
2853 biosA0[0x72] = psxBios__96_remove;
2854 //biosA0[0x73] = psxBios_sys_a0_73;
2855 //biosA0[0x74] = psxBios_sys_a0_74;
2856 //biosA0[0x75] = psxBios_sys_a0_75;
2857 //biosA0[0x76] = psxBios_sys_a0_76;
2858 //biosA0[0x77] = psxBios_sys_a0_77;
2859 //biosA0[0x78] = psxBios__96_CdSeekL;
2860 //biosA0[0x79] = psxBios_sys_a0_79;
2861 //biosA0[0x7a] = psxBios_sys_a0_7a;
2862 //biosA0[0x7b] = psxBios_sys_a0_7b;
2863 //biosA0[0x7c] = psxBios__96_CdGetStatus;
2864 //biosA0[0x7d] = psxBios_sys_a0_7d;
2865 //biosA0[0x7e] = psxBios__96_CdRead;
2866 //biosA0[0x7f] = psxBios_sys_a0_7f;
2867 //biosA0[0x80] = psxBios_sys_a0_80;
2868 //biosA0[0x81] = psxBios_sys_a0_81;
7a8d521f 2869 //biosA0[0x82] = psxBios_sys_a0_82;
ef79bbde
P
2870 //biosA0[0x83] = psxBios_sys_a0_83;
2871 //biosA0[0x84] = psxBios_sys_a0_84;
7a8d521f 2872 //biosA0[0x85] = psxBios__96_CdStop;
ef79bbde
P
2873 //biosA0[0x86] = psxBios_sys_a0_86;
2874 //biosA0[0x87] = psxBios_sys_a0_87;
2875 //biosA0[0x88] = psxBios_sys_a0_88;
2876 //biosA0[0x89] = psxBios_sys_a0_89;
2877 //biosA0[0x8a] = psxBios_sys_a0_8a;
2878 //biosA0[0x8b] = psxBios_sys_a0_8b;
2879 //biosA0[0x8c] = psxBios_sys_a0_8c;
2880 //biosA0[0x8d] = psxBios_sys_a0_8d;
2881 //biosA0[0x8e] = psxBios_sys_a0_8e;
2882 //biosA0[0x8f] = psxBios_sys_a0_8f;
2883 //biosA0[0x90] = psxBios_sys_a0_90;
2884 //biosA0[0x91] = psxBios_sys_a0_91;
2885 //biosA0[0x92] = psxBios_sys_a0_92;
2886 //biosA0[0x93] = psxBios_sys_a0_93;
2887 //biosA0[0x94] = psxBios_sys_a0_94;
2888 //biosA0[0x95] = psxBios_sys_a0_95;
2889 //biosA0[0x96] = psxBios_AddCDROMDevice;
2890 //biosA0[0x97] = psxBios_AddMemCardDevide;
2891 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
2892 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
2893 //biosA0[0x9a] = psxBios_sys_a0_9a;
2894 //biosA0[0x9b] = psxBios_sys_a0_9b;
2895 //biosA0[0x9c] = psxBios_SetConf;
2896 //biosA0[0x9d] = psxBios_GetConf;
2897 //biosA0[0x9e] = psxBios_sys_a0_9e;
2898 biosA0[0x9f] = psxBios_SetMem;
2899 //biosA0[0xa0] = psxBios__boot;
2900 //biosA0[0xa1] = psxBios_SystemError;
2901 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
2902 //biosA0[0xa3] = psxBios_DequeueCdIntr;
2903 //biosA0[0xa4] = psxBios_sys_a0_a4;
2904 //biosA0[0xa5] = psxBios_ReadSector;
18dd7e9e 2905 biosA0[0xa6] = psxBios_get_cd_status;
ef79bbde
P
2906 //biosA0[0xa7] = psxBios_bufs_cb_0;
2907 //biosA0[0xa8] = psxBios_bufs_cb_1;
2908 //biosA0[0xa9] = psxBios_bufs_cb_2;
2909 //biosA0[0xaa] = psxBios_bufs_cb_3;
2910 biosA0[0xab] = psxBios__card_info;
2911 biosA0[0xac] = psxBios__card_load;
2912 //biosA0[0axd] = psxBios__card_auto;
2913 //biosA0[0xae] = psxBios_bufs_cd_4;
2914 //biosA0[0xaf] = psxBios_sys_a0_af;
2915 //biosA0[0xb0] = psxBios_sys_a0_b0;
2916 //biosA0[0xb1] = psxBios_sys_a0_b1;
2917 //biosA0[0xb2] = psxBios_do_a_long_jmp
2918 //biosA0[0xb3] = psxBios_sys_a0_b3;
2919 //biosA0[0xb4] = psxBios_sub_function;
2920//*******************B0 CALLS****************************
2921 //biosB0[0x00] = psxBios_SysMalloc;
2922 //biosB0[0x01] = psxBios_sys_b0_01;
2923 biosB0[0x02] = psxBios_SetRCnt;
2924 biosB0[0x03] = psxBios_GetRCnt;
2925 biosB0[0x04] = psxBios_StartRCnt;
2926 biosB0[0x05] = psxBios_StopRCnt;
2927 biosB0[0x06] = psxBios_ResetRCnt;
2928 biosB0[0x07] = psxBios_DeliverEvent;
2929 biosB0[0x08] = psxBios_OpenEvent;
2930 biosB0[0x09] = psxBios_CloseEvent;
2931 biosB0[0x0a] = psxBios_WaitEvent;
2932 biosB0[0x0b] = psxBios_TestEvent;
2933 biosB0[0x0c] = psxBios_EnableEvent;
2934 biosB0[0x0d] = psxBios_DisableEvent;
2935 biosB0[0x0e] = psxBios_OpenTh;
2936 biosB0[0x0f] = psxBios_CloseTh;
2937 biosB0[0x10] = psxBios_ChangeTh;
2938 //biosB0[0x11] = psxBios_psxBios_b0_11;
2939 biosB0[0x12] = psxBios_InitPAD;
2940 biosB0[0x13] = psxBios_StartPAD;
2941 biosB0[0x14] = psxBios_StopPAD;
2942 biosB0[0x15] = psxBios_PAD_init;
2943 biosB0[0x16] = psxBios_PAD_dr;
2944 biosB0[0x17] = psxBios_ReturnFromException;
2945 biosB0[0x18] = psxBios_ResetEntryInt;
2946 biosB0[0x19] = psxBios_HookEntryInt;
2947 //biosB0[0x1a] = psxBios_sys_b0_1a;
2948 //biosB0[0x1b] = psxBios_sys_b0_1b;
2949 //biosB0[0x1c] = psxBios_sys_b0_1c;
2950 //biosB0[0x1d] = psxBios_sys_b0_1d;
2951 //biosB0[0x1e] = psxBios_sys_b0_1e;
2952 //biosB0[0x1f] = psxBios_sys_b0_1f;
2953 biosB0[0x20] = psxBios_UnDeliverEvent;
2954 //biosB0[0x21] = psxBios_sys_b0_21;
2955 //biosB0[0x22] = psxBios_sys_b0_22;
2956 //biosB0[0x23] = psxBios_sys_b0_23;
2957 //biosB0[0x24] = psxBios_sys_b0_24;
2958 //biosB0[0x25] = psxBios_sys_b0_25;
2959 //biosB0[0x26] = psxBios_sys_b0_26;
2960 //biosB0[0x27] = psxBios_sys_b0_27;
2961 //biosB0[0x28] = psxBios_sys_b0_28;
2962 //biosB0[0x29] = psxBios_sys_b0_29;
2963 //biosB0[0x2a] = psxBios_sys_b0_2a;
2964 //biosB0[0x2b] = psxBios_sys_b0_2b;
2965 //biosB0[0x2c] = psxBios_sys_b0_2c;
2966 //biosB0[0x2d] = psxBios_sys_b0_2d;
2967 //biosB0[0x2e] = psxBios_sys_b0_2e;
2968 //biosB0[0x2f] = psxBios_sys_b0_2f;
2969 //biosB0[0x30] = psxBios_sys_b0_30;
2970 //biosB0[0x31] = psxBios_sys_b0_31;
2971 biosB0[0x32] = psxBios_open;
2972 biosB0[0x33] = psxBios_lseek;
2973 biosB0[0x34] = psxBios_read;
2974 biosB0[0x35] = psxBios_write;
2975 biosB0[0x36] = psxBios_close;
2976 //biosB0[0x37] = psxBios_ioctl;
2977 //biosB0[0x38] = psxBios_exit;
2978 //biosB0[0x39] = psxBios_sys_b0_39;
2979 //biosB0[0x3a] = psxBios_getc;
2980 //biosB0[0x3b] = psxBios_putc;
2981 biosB0[0x3c] = psxBios_getchar;
2982 //biosB0[0x3e] = psxBios_gets;
2983 //biosB0[0x40] = psxBios_cd;
e7e1f572 2984 biosB0[0x41] = psxBios_format;
ef79bbde
P
2985 biosB0[0x42] = psxBios_firstfile;
2986 biosB0[0x43] = psxBios_nextfile;
2987 biosB0[0x44] = psxBios_rename;
2988 biosB0[0x45] = psxBios_delete;
2989 //biosB0[0x46] = psxBios_undelete;
2990 //biosB0[0x47] = psxBios_AddDevice;
2991 //biosB0[0x48] = psxBios_RemoteDevice;
2992 //biosB0[0x49] = psxBios_PrintInstalledDevices;
2993 biosB0[0x4a] = psxBios_InitCARD;
2994 biosB0[0x4b] = psxBios_StartCARD;
2995 biosB0[0x4c] = psxBios_StopCARD;
2996 //biosB0[0x4d] = psxBios_sys_b0_4d;
2997 biosB0[0x4e] = psxBios__card_write;
2998 biosB0[0x4f] = psxBios__card_read;
2999 biosB0[0x50] = psxBios__new_card;
3000 biosB0[0x51] = psxBios_Krom2RawAdd;
3001 //biosB0[0x52] = psxBios_sys_b0_52;
3002 //biosB0[0x53] = psxBios_sys_b0_53;
3003 //biosB0[0x54] = psxBios__get_errno;
002b2f7d 3004 biosB0[0x55] = psxBios__get_error;
ef79bbde
P
3005 biosB0[0x56] = psxBios_GetC0Table;
3006 biosB0[0x57] = psxBios_GetB0Table;
e9fda093 3007 biosB0[0x58] = psxBios__card_chan;
ef79bbde
P
3008 //biosB0[0x59] = psxBios_sys_b0_59;
3009 //biosB0[0x5a] = psxBios_sys_b0_5a;
3010 biosB0[0x5b] = psxBios_ChangeClearPad;
21af3ff6 3011 biosB0[0x5c] = psxBios__card_status;
5f652aa9 3012 biosB0[0x5d] = psxBios__card_wait;
ef79bbde
P
3013//*******************C0 CALLS****************************
3014 //biosC0[0x00] = psxBios_InitRCnt;
3015 //biosC0[0x01] = psxBios_InitException;
3016 biosC0[0x02] = psxBios_SysEnqIntRP;
3017 biosC0[0x03] = psxBios_SysDeqIntRP;
3018 //biosC0[0x04] = psxBios_get_free_EvCB_slot;
3019 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3020 //biosC0[0x06] = psxBios_ExceptionHandler;
3021 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3022 //biosC0[0x08] = psxBios_SysInitMemory;
3023 //biosC0[0x09] = psxBios_SysInitKMem;
7a8d521f 3024 biosC0[0x0a] = psxBios_ChangeClearRCnt;
ef79bbde
P
3025 //biosC0[0x0b] = psxBios_SystemError;
3026 //biosC0[0x0c] = psxBios_InitDefInt;
3027 //biosC0[0x0d] = psxBios_sys_c0_0d;
3028 //biosC0[0x0e] = psxBios_sys_c0_0e;
3029 //biosC0[0x0f] = psxBios_sys_c0_0f;
3030 //biosC0[0x10] = psxBios_sys_c0_10;
3031 //biosC0[0x11] = psxBios_sys_c0_11;
3032 //biosC0[0x12] = psxBios_InstallDevices;
3033 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3034 //biosC0[0x14] = psxBios_sys_c0_14;
3035 //biosC0[0x15] = psxBios__cdevinput;
3036 //biosC0[0x16] = psxBios__cdevscan;
3037 //biosC0[0x17] = psxBios__circgetc;
3038 //biosC0[0x18] = psxBios__circputc;
3039 //biosC0[0x19] = psxBios_ioabort;
3040 //biosC0[0x1a] = psxBios_sys_c0_1a
3041 //biosC0[0x1b] = psxBios_KernelRedirect;
3042 //biosC0[0x1c] = psxBios_PatchAOTable;
3043//************** THE END ***************************************
3044/**/
3045 base = 0x1000;
3046 size = sizeof(EvCB) * 32;
7a8d521f 3047 EventCB = (void *)&psxR[base]; base += size * 6;
3048 memset(EventCB, 0, size * 6);
3049 HwEV = EventCB;
3050 EvEV = EventCB + 32;
3051 RcEV = EventCB + 32 * 2;
3052 UeEV = EventCB + 32 * 3;
3053 SwEV = EventCB + 32 * 4;
3054 ThEV = EventCB + 32 * 5;
ef79bbde
P
3055
3056 ptr = (u32 *)&psxM[0x0874]; // b0 table
3057 ptr[0] = SWAPu32(0x4c54 - 0x884);
3058
3059 ptr = (u32 *)&psxM[0x0674]; // c0 table
3060 ptr[6] = SWAPu32(0xc80);
3061
3062 memset(SysIntRP, 0, sizeof(SysIntRP));
7a8d521f 3063 memset(ThreadCB, 0, sizeof(ThreadCB));
3064 ThreadCB[0].status = 2; // main thread
ef79bbde 3065
832f0c3c 3066 pad_stopped = 1;
c62b43c9 3067 jmp_int = NULL;
3068 pad_buf = NULL;
3069 pad_buf1 = NULL;
3070 pad_buf2 = NULL;
3071 pad_buf1len = pad_buf2len = 0;
3072 heap_addr = NULL;
3073 heap_end = NULL;
26b964b5 3074 heap_size = 0;
c62b43c9 3075 CardState = -1;
3076 CurThread = 0;
3077 memset(FDesc, 0, sizeof(FDesc));
832f0c3c 3078 card_active_chan = 0;
c62b43c9 3079
ef79bbde
P
3080 psxMu32ref(0x0150) = SWAPu32(0x160);
3081 psxMu32ref(0x0154) = SWAPu32(0x320);
3082 psxMu32ref(0x0160) = SWAPu32(0x248);
3083 strcpy((char *)&psxM[0x248], "bu");
3084/* psxMu32ref(0x0ca8) = SWAPu32(0x1f410004);
3085 psxMu32ref(0x0cf0) = SWAPu32(0x3c020000);
3086 psxMu32ref(0x0cf4) = SWAPu32(0x2442641c);
3087 psxMu32ref(0x09e0) = SWAPu32(0x43d0);
3088 psxMu32ref(0x4d98) = SWAPu32(0x946f000a);
3089*/
3090 // opcode HLE
3091 psxRu32ref(0x0000) = SWAPu32((0x3b << 26) | 4);
7a8d521f 3092 /* Whatever this does, it actually breaks CTR, even without the uninitiliazed memory patch.
bf643fd9 3093 Normally games shouldn't read from address 0 yet they do. See explanation below in details. */
3094 //psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0);
ef79bbde
P
3095 psxMu32ref(0x00a0) = SWAPu32((0x3b << 26) | 1);
3096 psxMu32ref(0x00b0) = SWAPu32((0x3b << 26) | 2);
3097 psxMu32ref(0x00c0) = SWAPu32((0x3b << 26) | 3);
3098 psxMu32ref(0x4c54) = SWAPu32((0x3b << 26) | 0);
3099 psxMu32ref(0x8000) = SWAPu32((0x3b << 26) | 5);
3100 psxMu32ref(0x07a0) = SWAPu32((0x3b << 26) | 0);
3101 psxMu32ref(0x0884) = SWAPu32((0x3b << 26) | 0);
3102 psxMu32ref(0x0894) = SWAPu32((0x3b << 26) | 0);
3103
3104 // initial stack pointer for BIOS interrupt
3105 psxMu32ref(0x6c80) = SWAPu32(0x000085c8);
3106
3107 // initial RNG seed
3108 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3109
3110 // fonts
3111 len = 0x80000 - 0x66000;
3112 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3113 len = 0x80000 - 0x69d68;
3114 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3115
3116 // memory size 2 MB
3117 psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3118
3119 hleSoftCall = FALSE;
7a8d521f 3120
bf643fd9 3121 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3122 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
339cc5b6 3123 Here are some examples of games not working with this fix in place :
3124 R-type won't get past the Irem logo if not implemented.
3125 Crash Team Racing will softlock after the Sony logo.
bf643fd9 3126 */
7a8d521f 3127
339cc5b6 3128 psxMu32ref(0x0000) = SWAPu32(0x00000003);
3129 /*
3130 But overwritten by 00000003h after soon.
3131 psxMu32ref(0x0000) = SWAPu32(0x00001A3C);
3132 */
3133 psxMu32ref(0x0004) = SWAPu32(0x800C5A27);
3134 psxMu32ref(0x0008) = SWAPu32(0x08000403);
3135 psxMu32ref(0x000C) = SWAPu32(0x00000000);
ef79bbde
P
3136}
3137
3138void psxBiosShutdown() {
3139}
3140
3141#define psxBios_PADpoll(pad) { \
3142 PAD##pad##_startPoll(pad); \
3143 pad_buf##pad[0] = 0; \
3144 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3145 if (!(pad_buf##pad[1] & 0x0f)) { \
3146 bufcount = 32; \
3147 } else { \
3148 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3149 } \
3150 PAD##pad##_poll(0); \
3151 i = 2; \
3152 while (bufcount--) { \
3153 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3154 } \
3155}
3156
3157void biosInterrupt() {
3158 int i, bufcount;
3159
3160// if (psxHu32(0x1070) & 0x1) { // Vsync
3161 if (pad_buf != NULL) {
3162 u32 *buf = (u32*)pad_buf;
3163
3164 if (!Config.UseNet) {
3165 PAD1_startPoll(1);
3166 if (PAD1_poll(0x42) == 0x23) {
3167 PAD1_poll(0);
3168 *buf = PAD1_poll(0) << 8;
3169 *buf |= PAD1_poll(0);
3170 PAD1_poll(0);
3171 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3172 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3173 } else {
3174 PAD1_poll(0);
3175 *buf = PAD1_poll(0) << 8;
3176 *buf|= PAD1_poll(0);
3177 }
3178
3179 PAD2_startPoll(2);
3180 if (PAD2_poll(0x42) == 0x23) {
3181 PAD2_poll(0);
3182 *buf |= PAD2_poll(0) << 24;
3183 *buf |= PAD2_poll(0) << 16;
3184 PAD2_poll(0);
3185 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3186 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3187 } else {
3188 PAD2_poll(0);
3189 *buf |= PAD2_poll(0) << 24;
3190 *buf |= PAD2_poll(0) << 16;
3191 }
3192 } else {
3193 u16 data;
3194
3195 PAD1_startPoll(1);
3196 PAD1_poll(0x42);
3197 PAD1_poll(0);
3198 data = PAD1_poll(0) << 8;
3199 data |= PAD1_poll(0);
3200
3201 if (NET_sendPadData(&data, 2) == -1)
3202 netError();
3203
3204 if (NET_recvPadData(&((u16*)buf)[0], 1) == -1)
3205 netError();
3206 if (NET_recvPadData(&((u16*)buf)[1], 2) == -1)
3207 netError();
3208 }
3209 }
3210 if (Config.UseNet && pad_buf1 != NULL && pad_buf2 != NULL) {
3211 psxBios_PADpoll(1);
3212
3213 if (NET_sendPadData(pad_buf1, i) == -1)
3214 netError();
3215
3216 if (NET_recvPadData(pad_buf1, 1) == -1)
3217 netError();
3218 if (NET_recvPadData(pad_buf2, 2) == -1)
3219 netError();
3220 } else {
f25c285b 3221 if (!pad_stopped) {
3222 if (pad_buf1) {
3223 psxBios_PADpoll(1);
3224 }
ef79bbde 3225
f25c285b 3226 if (pad_buf2) {
3227 psxBios_PADpoll(2);
3228 }
ef79bbde
P
3229 }
3230 }
3231
3232 if (psxHu32(0x1070) & 0x1) { // Vsync
3233 if (RcEV[3][1].status == EvStACTIVE) {
3234 softCall(RcEV[3][1].fhandler);
3235// hwWrite32(0x1f801070, ~(1));
3236 }
3237 }
3238
3239 if (psxHu32(0x1070) & 0x70) { // Rcnt 0,1,2
3240 int i;
3241
3242 for (i = 0; i < 3; i++) {
3243 if (psxHu32(0x1070) & (1 << (i + 4))) {
3244 if (RcEV[i][1].status == EvStACTIVE) {
3245 softCall(RcEV[i][1].fhandler);
3246 }
3247 psxHwWrite32(0x1f801070, ~(1 << (i + 4)));
3248 }
3249 }
3250 }
3251}
3252
3253void psxBiosException() {
3254 int i;
3255
3256 switch (psxRegs.CP0.n.Cause & 0x3c) {
3257 case 0x00: // Interrupt
f23c2241 3258 interrupt_r26=psxRegs.CP0.n.EPC;
ef79bbde
P
3259#ifdef PSXCPU_LOG
3260// PSXCPU_LOG("interrupt\n");
3261#endif
3262 SaveRegs();
3263
3264 sp = psxMu32(0x6c80); // create new stack for interrupt handlers
3265
3266 biosInterrupt();
3267
3268 for (i = 0; i < 8; i++) {
3269 if (SysIntRP[i]) {
3270 u32 *queue = (u32 *)PSXM(SysIntRP[i]);
3271
3272 s0 = queue[2];
3273 softCall(queue[1]);
3274 }
3275 }
3276
3277 if (jmp_int != NULL) {
3278 int i;
3279
3280 psxHwWrite32(0x1f801070, 0xffffffff);
3281
3282 ra = jmp_int[0];
3283 sp = jmp_int[1];
3284 fp = jmp_int[2];
3285 for (i = 0; i < 8; i++) // s0-s7
3286 psxRegs.GPR.r[16 + i] = jmp_int[3 + i];
3287 gp = jmp_int[11];
3288
3289 v0 = 1;
3290 pc0 = ra;
3291 return;
3292 }
3293 psxHwWrite16(0x1f801070, 0);
3294 break;
3295
3296 case 0x20: // Syscall
3297#ifdef PSXCPU_LOG
3298 PSXCPU_LOG("syscall exp %x\n", a0);
3299#endif
3300 switch (a0) {
3301 case 1: // EnterCritical - disable irq's
79dad1b3 3302 /* Fixes Medievil 2 not loading up new game, Digimon World not booting up and possibly others */
bc7c5acb 3303 v0 = (psxRegs.CP0.n.SR & 0x404) == 0x404;
3304 psxRegs.CP0.n.SR &= ~0x404;
ef79bbde
P
3305 break;
3306
3307 case 2: // ExitCritical - enable irq's
bc7c5acb 3308 psxRegs.CP0.n.SR |= 0x404;
ef79bbde 3309 break;
a946d159 3310 /* Normally this should cover SYS(00h, SYS(04h but they don't do anything relevant so... */
3311 default:
3312 break;
ef79bbde
P
3313 }
3314 pc0 = psxRegs.CP0.n.EPC + 4;
3315
bc7c5acb 3316 psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
ef79bbde
P
3317 return;
3318
3319 default:
3320#ifdef PSXCPU_LOG
3321 PSXCPU_LOG("unknown bios exception!\n");
3322#endif
3323 break;
3324 }
3325
3326 pc0 = psxRegs.CP0.n.EPC;
3327 if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;
3328
bc7c5acb 3329 psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
ef79bbde
P
3330}
3331
3332#define bfreeze(ptr, size) { \
3333 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3334 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3335 base += size; \
3336}
3337
3338#define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3339#define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3340
3341#define bfreezepsxMptr(ptr, type) { \
3342 if (Mode == 1) { \
3343 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3344 else psxRu32ref(base) = 0; \
3345 } else { \
3346 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3347 else (ptr) = NULL; \
3348 } \
3349 base += sizeof(u32); \
3350}
3351
3352void psxBiosFreeze(int Mode) {
3353 u32 base = 0x40000;
3354
3355 bfreezepsxMptr(jmp_int, u32);
3356 bfreezepsxMptr(pad_buf, int);
3357 bfreezepsxMptr(pad_buf1, char);
3358 bfreezepsxMptr(pad_buf2, char);
3359 bfreezepsxMptr(heap_addr, u32);
3360 bfreezel(&pad_buf1len);
3361 bfreezel(&pad_buf2len);
3362 bfreezes(regs);
3363 bfreezes(SysIntRP);
3364 bfreezel(&CardState);
7a8d521f 3365 bfreezes(ThreadCB);
ef79bbde
P
3366 bfreezel(&CurThread);
3367 bfreezes(FDesc);
e9fda093 3368 bfreezel(&card_active_chan);
a15f3544 3369 bfreezel(&pad_stopped);
17b2d969 3370 bfreezel(&heap_size);
ef79bbde 3371}