gpulib: update gpuinfo
[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
288 while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
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
300 while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
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
1255void psxBios_printf() { // 0x3f
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
02949f79 1320 if (psp)
1321 memcpy(psp, save, 4 * 4);
ef79bbde 1322
808a13bd 1323 SysPrintf("%s", tmp);
ef79bbde
P
1324
1325 pc0 = ra;
1326}
1327
e7e1f572 1328void psxBios_format() { // 0x41
1329 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1330 {
1331 CreateMcd(Config.Mcd1);
1332 LoadMcd(1, Config.Mcd1);
1333 v0 = 1;
1334 }
1335 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1336 {
1337 CreateMcd(Config.Mcd2);
1338 LoadMcd(2, Config.Mcd2);
1339 v0 = 1;
1340 }
1341 else
1342 {
1343 v0 = 0;
1344 }
1345 pc0 = ra;
1346}
1347
ef79bbde
P
1348/*
1349 * long Load(char *name, struct EXEC *header);
1350 */
1351
1352void psxBios_Load() { // 0x42
1353 EXE_HEADER eheader;
02949f79 1354 void *pa1;
ef79bbde
P
1355
1356#ifdef PSXBIOS_LOG
1357 PSXBIOS_LOG("psxBios_%s: %s, %x\n", biosA0n[0x42], Ra0, a1);
1358#endif
1359
02949f79 1360 pa1 = Ra1;
1361 if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
1362 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
ef79bbde
P
1363 v0 = 1;
1364 } else v0 = 0;
1365
1366 pc0 = ra;
1367}
1368
1369/*
1370 * int Exec(struct EXEC *header , int argc , char **argv);
1371 */
1372
1373void psxBios_Exec() { // 43
1374 EXEC *header = (EXEC*)Ra0;
1375 u32 tmp;
1376
1377#ifdef PSXBIOS_LOG
1378 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1379#endif
1380
1381 header->_sp = sp;
1382 header->_fp = fp;
1383 header->_sp = sp;
1384 header->_gp = gp;
1385 header->ret = ra;
1386 header->base = s0;
1387
1388 if (header->S_addr != 0) {
1389 tmp = header->S_addr + header->s_size;
1390 sp = tmp;
1391 fp = sp;
1392 }
1393
1394 gp = header->gp0;
1395
1396 s0 = a0;
1397
1398 a0 = a1;
1399 a1 = a2;
1400
1401 ra = 0x8000;
1402 pc0 = header->_pc0;
1403}
1404
1405void psxBios_FlushCache() { // 44
1406#ifdef PSXBIOS_LOG
1407 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1408#endif
943a507a 1409 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1410 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
ef79bbde
P
1411 pc0 = ra;
1412}
1413
1414void psxBios_GPU_dw() { // 0x46
1415 int size;
3a284665 1416 u32 *ptr;
ef79bbde
P
1417
1418#ifdef PSXBIOS_LOG
1419 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1420#endif
1421
1422 GPU_writeData(0xa0000000);
3a284665 1423 GPU_writeData((a1<<0x10)|(a0&0xffff));
1424 GPU_writeData((a3<<0x10)|(a2&0xffff));
1425 size = (a2*a3)/2;
1426 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1427 while(size--)
1428 {
1429 GPU_writeData(SWAPu32(*ptr++));
1430 }
ef79bbde
P
1431
1432 pc0 = ra;
7a8d521f 1433}
ef79bbde
P
1434
1435void psxBios_mem2vram() { // 0x47
1436 int size;
3a284665 1437 gpuSyncPluginSR();
ef79bbde 1438 GPU_writeData(0xa0000000);
3a284665 1439 GPU_writeData((a1<<0x10)|(a0&0xffff));
1440 GPU_writeData((a3<<0x10)|(a2&0xffff));
1441 size = ((((a2 * a3) / 2) >> 4) << 16);
ef79bbde
P
1442 GPU_writeStatus(0x04000002);
1443 psxHwWrite32(0x1f8010f4,0);
1444 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1445 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
3a284665 1446 psxHwWrite32(0x1f8010a4, size | 0x10);
ef79bbde
P
1447 psxHwWrite32(0x1f8010a8,0x01000201);
1448
1449 pc0 = ra;
1450}
1451
1452void psxBios_SendGPU() { // 0x48
1453 GPU_writeStatus(a0);
ddbaf678 1454 gpuSyncPluginSR();
ef79bbde
P
1455 pc0 = ra;
1456}
1457
1458void psxBios_GPU_cw() { // 0x49
3a284665 1459 gpuSyncPluginSR();
ef79bbde 1460 GPU_writeData(a0);
3a284665 1461 v0 = HW_GPU_STATUS;
7a8d521f 1462 pc0 = ra;
ef79bbde
P
1463}
1464
1465void psxBios_GPU_cwb() { // 0x4a
3a284665 1466 u32 *ptr = (u32*)Ra0;
ef79bbde 1467 int size = a1;
3a284665 1468 gpuSyncPluginSR();
1469 while(size--)
1470 {
1471 GPU_writeData(SWAPu32(*ptr++));
ef79bbde
P
1472 }
1473
1474 pc0 = ra;
1475}
1476
1477void psxBios_GPU_SendPackets() { //4b:
3a284665 1478 gpuSyncPluginSR();
ef79bbde
P
1479 GPU_writeStatus(0x04000002);
1480 psxHwWrite32(0x1f8010f4,0);
1481 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1482 psxHwWrite32(0x1f8010a0,a0);
1483 psxHwWrite32(0x1f8010a4,0);
1484 psxHwWrite32(0x1f8010a8,0x010000401);
1485 pc0 = ra;
1486}
1487
1488void psxBios_sys_a0_4c() { // 0x4c GPU relate
1489 psxHwWrite32(0x1f8010a8,0x00000401);
1490 GPU_writeData(0x0400000);
1491 GPU_writeData(0x0200000);
1492 GPU_writeData(0x0100000);
cd1ea245 1493 v0 = 0x1f801814;
ef79bbde
P
1494 pc0 = ra;
1495}
1496
1497void psxBios_GPU_GetGPUStatus() { // 0x4d
1498 v0 = GPU_readStatus();
1499 pc0 = ra;
1500}
1501
1502#undef s_addr
1503
1504void psxBios_LoadExec() { // 51
1505 EXEC *header = (EXEC*)PSXM(0xf000);
1506 u32 s_addr, s_size;
1507
1508#ifdef PSXBIOS_LOG
1509 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1510#endif
1511 s_addr = a1; s_size = a2;
1512
7a8d521f 1513 a1 = 0xf000;
ef79bbde
P
1514 psxBios_Load();
1515
1516 header->S_addr = s_addr;
1517 header->s_size = s_size;
1518
1519 a0 = 0xf000; a1 = 0; a2 = 0;
1520 psxBios_Exec();
1521}
1522
1523void psxBios__bu_init() { // 70
1524#ifdef PSXBIOS_LOG
1525 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1526#endif
1527
1528 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1529 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1530
1531 pc0 = ra;
1532}
1533
1534void psxBios__96_init() { // 71
1535#ifdef PSXBIOS_LOG
1536 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1537#endif
1538
1539 pc0 = ra;
1540}
1541
1542void psxBios__96_remove() { // 72
1543#ifdef PSXBIOS_LOG
1544 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1545#endif
1546
1547 pc0 = ra;
1548}
1549
1550void psxBios_SetMem() { // 9f
1551 u32 new = psxHu32(0x1060);
1552
1553#ifdef PSXBIOS_LOG
1554 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1555#endif
1556
1557 switch(a0) {
1558 case 2:
1559 psxHu32ref(0x1060) = SWAP32(new);
1560 psxMu32ref(0x060) = a0;
1561 SysPrintf("Change effective memory : %d MBytes\n",a0);
1562 break;
1563
1564 case 8:
1565 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1566 psxMu32ref(0x060) = a0;
1567 SysPrintf("Change effective memory : %d MBytes\n",a0);
7a8d521f 1568
ef79bbde
P
1569 default:
1570 SysPrintf("Effective memory must be 2/8 MBytes\n");
1571 break;
1572 }
1573
1574 pc0 = ra;
1575}
1576
18dd7e9e 1577/* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1578void psxBios_get_cd_status(void) //a6
1579{
1580 v0 = 1;
1581 pc0 = ra;
1582}
1583
ef79bbde
P
1584void psxBios__card_info() { // ab
1585#ifdef PSXBIOS_LOG
1586 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1587#endif
7a8d521f 1588 u32 ret, port;
e9fda093 1589 card_active_chan = a0;
7a8d521f 1590 port = card_active_chan >> 4;
1591
1592 switch (port) {
1593 case 0x0:
1594 case 0x1:
1595 ret = 0x2;
1596 if (McdDisable[port & 1])
1597 ret = 0x8;
76b81516 1598 break;
1599 default:
1600#ifdef PSXBIOS_LOG
1601 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
1602#endif
1603 ret = 0x11;
1604 break;
1605 }
7a8d521f 1606
1607 if (McdDisable[0] && McdDisable[1])
1608 ret = 0x8;
1609
1610 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1611// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
76b81516 1612 DeliverEvent(0x81, ret); // 0xf4000001, 0x0004
ef79bbde
P
1613 v0 = 1; pc0 = ra;
1614}
1615
1616void psxBios__card_load() { // ac
1617#ifdef PSXBIOS_LOG
1618 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1619#endif
1620
e9fda093 1621 card_active_chan = a0;
1622
ef79bbde
P
1623// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1624 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1625
1626 v0 = 1; pc0 = ra;
1627}
1628
1629/* System calls B0 */
1630
1631void psxBios_SetRCnt() { // 02
1632#ifdef PSXBIOS_LOG
1633 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1634#endif
1635
1636 a0&= 0x3;
1637 if (a0 != 3) {
1638 u32 mode=0;
1639
1640 psxRcntWtarget(a0, a1);
1641 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1642 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1643 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1644 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1645 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1646
1647 psxRcntWmode(a0, mode);
1648 }
1649 pc0 = ra;
1650}
1651
1652void psxBios_GetRCnt() { // 03
1653#ifdef PSXBIOS_LOG
1654 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1655#endif
1656
1657 a0&= 0x3;
1658 if (a0 != 3) v0 = psxRcntRcount(a0);
1659 else v0 = 0;
1660 pc0 = ra;
1661}
1662
1663void psxBios_StartRCnt() { // 04
1664#ifdef PSXBIOS_LOG
1665 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1666#endif
1667
1668 a0&= 0x3;
1669 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1670 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1671 v0 = 1; pc0 = ra;
1672}
1673
1674void psxBios_StopRCnt() { // 05
1675#ifdef PSXBIOS_LOG
1676 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1677#endif
1678
1679 a0&= 0x3;
1680 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1681 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1682 pc0 = ra;
1683}
1684
1685void psxBios_ResetRCnt() { // 06
1686#ifdef PSXBIOS_LOG
1687 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1688#endif
1689
1690 a0&= 0x3;
1691 if (a0 != 3) {
1692 psxRcntWmode(a0, 0);
1693 psxRcntWtarget(a0, 0);
1694 psxRcntWcount(a0, 0);
1695 }
1696 pc0 = ra;
1697}
1698
1699
7a8d521f 1700/* gets ev for use with EventCB */
ef79bbde
P
1701#define GetEv() \
1702 ev = (a0 >> 24) & 0xf; \
1703 if (ev == 0xf) ev = 0x5; \
1704 ev*= 32; \
1705 ev+= a0&0x1f;
1706
7a8d521f 1707/* gets spec for use with EventCB */
ef79bbde
P
1708#define GetSpec() \
1709 spec = 0; \
1710 switch (a1) { \
1711 case 0x0301: spec = 16; break; \
1712 case 0x0302: spec = 17; break; \
1713 default: \
1714 for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \
1715 break; \
1716 }
1717
1718void psxBios_DeliverEvent() { // 07
1719 int ev, spec;
1720 int i;
1721
1722 GetEv();
1723 GetSpec();
1724
1725#ifdef PSXBIOS_LOG
1726 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x07], ev, spec);
1727#endif
1728
1729 DeliverEvent(ev, spec);
1730
1731 pc0 = ra;
1732}
1733
1734void psxBios_OpenEvent() { // 08
1735 int ev, spec;
1736 int i;
1737
1738 GetEv();
1739 GetSpec();
1740
1741#ifdef PSXBIOS_LOG
1742 PSXBIOS_LOG("psxBios_%s %x,%x (class:%x, spec:%x, mode:%x, func:%x)\n", biosB0n[0x08], ev, spec, a0, a1, a2, a3);
1743#endif
1744
7a8d521f 1745 EventCB[ev][spec].status = EvStWAIT;
1746 EventCB[ev][spec].mode = a2;
1747 EventCB[ev][spec].fhandler = a3;
ef79bbde
P
1748
1749 v0 = ev | (spec << 8);
1750 pc0 = ra;
1751}
1752
1753void psxBios_CloseEvent() { // 09
1754 int ev, spec;
1755
1756 ev = a0 & 0xff;
1757 spec = (a0 >> 8) & 0xff;
1758
1759#ifdef PSXBIOS_LOG
1760 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x09], ev, spec);
1761#endif
1762
7a8d521f 1763 EventCB[ev][spec].status = EvStUNUSED;
ef79bbde
P
1764
1765 v0 = 1; pc0 = ra;
1766}
1767
1768void psxBios_WaitEvent() { // 0a
1769 int ev, spec;
1770
1771 ev = a0 & 0xff;
1772 spec = (a0 >> 8) & 0xff;
ef79bbde
P
1773#ifdef PSXBIOS_LOG
1774 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0a], ev, spec);
1775#endif
7a8d521f 1776 if (EventCB[ev][spec].status == EvStUNUSED)
d95c9dcb 1777 {
1778 v0 = 0;
7a8d521f 1779 pc0 = ra;
d95c9dcb 1780 return;
1781 }
ef79bbde 1782
7a8d521f 1783 if (EventCB[ev][spec].status == EvStALREADY)
d95c9dcb 1784 {
1785 /* Callback events (mode=EvMdINTR) do never set the ready flag (and thus WaitEvent would hang forever). */
7a8d521f 1786 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
d95c9dcb 1787 v0 = 1;
1788 pc0 = ra;
1789 return;
1790 }
ef79bbde 1791
d95c9dcb 1792 v0 = 0;
1793 pc0 = ra;
ef79bbde
P
1794}
1795
1796void psxBios_TestEvent() { // 0b
1797 int ev, spec;
1798
1799 ev = a0 & 0xff;
1800 spec = (a0 >> 8) & 0xff;
1801
7a8d521f 1802 if (EventCB[ev][spec].status == EvStALREADY)
b4ae2532 1803 {
7a8d521f 1804 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
b4ae2532 1805 v0 = 1;
7a8d521f 1806 }
1807 else
b4ae2532 1808 {
1809 v0 = 0;
1810 }
ef79bbde
P
1811
1812#ifdef PSXBIOS_LOG
1813 PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0);
1814#endif
1815
1816 pc0 = ra;
1817}
1818
1819void psxBios_EnableEvent() { // 0c
1820 int ev, spec;
1821
1822 ev = a0 & 0xff;
1823 spec = (a0 >> 8) & 0xff;
1824
1825#ifdef PSXBIOS_LOG
1826 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0c], ev, spec);
1827#endif
1828
7a8d521f 1829 EventCB[ev][spec].status = EvStACTIVE;
ef79bbde
P
1830
1831 v0 = 1; pc0 = ra;
1832}
1833
1834void psxBios_DisableEvent() { // 0d
1835 int ev, spec;
1836
1837 ev = a0 & 0xff;
1838 spec = (a0 >> 8) & 0xff;
1839
1840#ifdef PSXBIOS_LOG
1841 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0d], ev, spec);
1842#endif
1843
7a8d521f 1844 EventCB[ev][spec].status = EvStWAIT;
ef79bbde
P
1845
1846 v0 = 1; pc0 = ra;
1847}
1848
1849/*
1850 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
1851 */
1852
1853void psxBios_OpenTh() { // 0e
1854 int th;
1855
1856 for (th=1; th<8; th++)
a66d3058 1857 {
7a8d521f 1858 if (ThreadCB[th].status == 0) break;
ef79bbde 1859
a66d3058 1860 }
1861 if (th == 8) {
1862 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
1863 // When no free TCB is found, return 0xffffffff according to Nocash doc.
1864#ifdef PSXBIOS_LOG
1865 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
1866#endif
1867 v0 = 0xffffffff;
1868 pc0 = ra;
1869 return;
1870 }
ef79bbde
P
1871#ifdef PSXBIOS_LOG
1872 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
1873#endif
1874
7a8d521f 1875 ThreadCB[th].status = 1;
1876 ThreadCB[th].func = a0;
1877 ThreadCB[th].reg[29] = a1;
1878 ThreadCB[th].reg[28] = a2;
ef79bbde
P
1879
1880 v0 = th; pc0 = ra;
1881}
1882
1883/*
1884 * int CloseTh(long thread);
1885 */
1886
1887void psxBios_CloseTh() { // 0f
1888 int th = a0 & 0xff;
1889
1890#ifdef PSXBIOS_LOG
1891 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
1892#endif
9ee77db1 1893 /* The return value is always 1 (even if the handle was already closed). */
1894 v0 = 1;
7a8d521f 1895 if (ThreadCB[th].status != 0) {
1896 ThreadCB[th].status = 0;
ef79bbde
P
1897 }
1898
1899 pc0 = ra;
1900}
1901
1902/*
1903 * int ChangeTh(long thread);
1904 */
1905
1906void psxBios_ChangeTh() { // 10
1907 int th = a0 & 0xff;
1908
1909#ifdef PSXBIOS_LOG
1910// PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
1911#endif
9ee77db1 1912 /* The return value is always 1. */
1913 v0 = 1;
7a8d521f 1914 if (ThreadCB[th].status == 0 || CurThread == th) {
ef79bbde
P
1915 pc0 = ra;
1916 } else {
7a8d521f 1917 if (ThreadCB[CurThread].status == 2) {
1918 ThreadCB[CurThread].status = 1;
1919 ThreadCB[CurThread].func = ra;
1920 memcpy(ThreadCB[CurThread].reg, psxRegs.GPR.r, 32*4);
ef79bbde
P
1921 }
1922
7a8d521f 1923 memcpy(psxRegs.GPR.r, ThreadCB[th].reg, 32*4);
1924 pc0 = ThreadCB[th].func;
1925 ThreadCB[th].status = 2;
ef79bbde
P
1926 CurThread = th;
1927 }
1928}
1929
1930void psxBios_InitPAD() { // 0x12
1931#ifdef PSXBIOS_LOG
1932 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x12]);
1933#endif
1934
1935 pad_buf1 = (char*)Ra0;
1936 pad_buf1len = a1;
1937 pad_buf2 = (char*)Ra2;
1938 pad_buf2len = a3;
1939
1940 v0 = 1; pc0 = ra;
1941}
1942
1943void psxBios_StartPAD() { // 13
1944#ifdef PSXBIOS_LOG
1945 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
1946#endif
f25c285b 1947 pad_stopped = 0;
ef79bbde
P
1948 psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1));
1949 psxRegs.CP0.n.Status |= 0x401;
1950 pc0 = ra;
1951}
1952
1953void psxBios_StopPAD() { // 14
1954#ifdef PSXBIOS_LOG
1955 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
1956#endif
f25c285b 1957 pad_stopped = 1;
ef79bbde
P
1958 pad_buf1 = NULL;
1959 pad_buf2 = NULL;
1960 pc0 = ra;
1961}
1962
1963void psxBios_PAD_init() { // 15
1964#ifdef PSXBIOS_LOG
1965 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
1966#endif
a824e83d 1967 if (!(a0 == 0x20000000 || a0 == 0x20000001))
1968 {
1969 v0 = 0;
1970 pc0 = ra;
1971 return;
1972 }
ef79bbde
P
1973 psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
1974 pad_buf = (int *)Ra1;
1975 *pad_buf = -1;
1976 psxRegs.CP0.n.Status |= 0x401;
a824e83d 1977 v0 = 2;
ef79bbde
P
1978 pc0 = ra;
1979}
1980
1981void psxBios_PAD_dr() { // 16
1982#ifdef PSXBIOS_LOG
1983 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
1984#endif
1985
1986 v0 = -1; pc0 = ra;
1987}
1988
1989void psxBios_ReturnFromException() { // 17
1990 LoadRegs();
1991
1992 pc0 = psxRegs.CP0.n.EPC;
f23c2241 1993 k0 = interrupt_r26;
ef79bbde
P
1994 if (psxRegs.CP0.n.Cause & 0x80000000) pc0 += 4;
1995
1996 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
1997 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
1998}
1999
2000void psxBios_ResetEntryInt() { // 18
2001#ifdef PSXBIOS_LOG
2002 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2003#endif
2004
2005 jmp_int = NULL;
2006 pc0 = ra;
2007}
2008
2009void psxBios_HookEntryInt() { // 19
2010#ifdef PSXBIOS_LOG
2011 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x19]);
2012#endif
2013
2014 jmp_int = (u32*)Ra0;
2015 pc0 = ra;
2016}
2017
2018void psxBios_UnDeliverEvent() { // 0x20
2019 int ev, spec;
2020 int i;
2021
2022 GetEv();
2023 GetSpec();
2024
2025#ifdef PSXBIOS_LOG
2026 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec);
2027#endif
2028
7a8d521f 2029 if (EventCB[ev][spec].status == EvStALREADY &&
2030 EventCB[ev][spec].mode == EvMdNOINTR)
2031 EventCB[ev][spec].status = EvStACTIVE;
ef79bbde
P
2032
2033 pc0 = ra;
2034}
2035
595a136b 2036char ffile[64], *pfile;
2037int nfile;
7a8d521f 2038
857275a9 2039static void buopen(int mcd, char *ptr, char *cfg)
595a136b 2040{
2041 int i;
7a8d521f 2042 char *mcd_data = ptr;
595a136b 2043
2044 strcpy(FDesc[1 + mcd].name, Ra0+5);
2045 FDesc[1 + mcd].offset = 0;
2046 FDesc[1 + mcd].mode = a1;
2047
2048 for (i=1; i<16; i++) {
7a8d521f 2049 const char *fptr = mcd_data + 128 * i;
595a136b 2050 if ((*fptr & 0xF0) != 0x50) continue;
2051 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2052 FDesc[1 + mcd].mcfile = i;
2053 SysPrintf("open %s\n", fptr+0xa);
2054 v0 = 1 + mcd;
2055 break;
2056 }
2057 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
595a136b 2058 for (i=1; i<16; i++) {
2059 int j, xor, nblk = a1 >> 16;
7a8d521f 2060 char *pptr, *fptr2;
2061 char *fptr = mcd_data + 128 * i;
595a136b 2062
595a136b 2063 if ((*fptr & 0xF0) != 0xa0) continue;
2064
2065 FDesc[1 + mcd].mcfile = i;
2066 fptr[0] = 0x51;
2067 fptr[4] = 0x00;
2068 fptr[5] = 0x20 * nblk;
2069 fptr[6] = 0x00;
2070 fptr[7] = 0x00;
2071 strcpy(fptr+0xa, FDesc[1 + mcd].name);
7a8d521f 2072 pptr = fptr2 = fptr;
595a136b 2073 for(j=2; j<=nblk; j++) {
2074 int k;
2075 for(i++; i<16; i++) {
2076 fptr2 += 128;
7a8d521f 2077
595a136b 2078 memset(fptr2, 0, 128);
2079 fptr2[0] = j < nblk ? 0x52 : 0x53;
2080 pptr[8] = i - 1;
2081 pptr[9] = 0;
2082 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2083 pptr[127] = xor;
2084 pptr = fptr2;
2085 break;
2086 }
2087 /* shouldn't this return ENOSPC if i == 16? */
2088 }
2089 pptr[8] = pptr[9] = 0xff;
2090 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2091 pptr[127] = xor;
2092 SysPrintf("openC %s %d\n", ptr, nblk);
2093 v0 = 1 + mcd;
2094 /* just go ahead and resave them all */
2095 SaveMcd(cfg, ptr, 128, 128 * 15);
2096 break;
2097 }
2098 /* shouldn't this return ENOSPC if i == 16? */
2099 }
ef79bbde
P
2100}
2101
2102/*
2103 * int open(char *name , int mode);
2104 */
2105
2106void psxBios_open() { // 0x32
02949f79 2107 void *pa0 = Ra0;
ef79bbde
P
2108
2109#ifdef PSXBIOS_LOG
2110 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2111#endif
2112
2113 v0 = -1;
2114
7a8d521f 2115 if (pa0 != INVALID_PTR) {
02949f79 2116 if (!strncmp(pa0, "bu00", 4)) {
595a136b 2117 buopen(1, Mcd1Data, Config.Mcd1);
02949f79 2118 }
ef79bbde 2119
02949f79 2120 if (!strncmp(pa0, "bu10", 4)) {
595a136b 2121 buopen(2, Mcd2Data, Config.Mcd2);
02949f79 2122 }
ef79bbde
P
2123 }
2124
2125 pc0 = ra;
2126}
2127
2128/*
2129 * int lseek(int fd , int offset , int whence);
2130 */
2131
2132void psxBios_lseek() { // 0x33
2133#ifdef PSXBIOS_LOG
2134 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2135#endif
2136
2137 switch (a2) {
2138 case 0: // SEEK_SET
2139 FDesc[a0].offset = a1;
2140 v0 = a1;
2141// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2142// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2143 break;
2144
2145 case 1: // SEEK_CUR
2146 FDesc[a0].offset+= a1;
2147 v0 = FDesc[a0].offset;
2148 break;
2149 }
2150
2151 pc0 = ra;
2152}
2153
595a136b 2154
ef79bbde
P
2155/*
2156 * int read(int fd , void *buf , int nbytes);
2157 */
2158
2159void psxBios_read() { // 0x34
2160 char *ptr;
02949f79 2161 void *pa1 = Ra1;
ef79bbde
P
2162
2163#ifdef PSXBIOS_LOG
2164 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2165#endif
2166
2167 v0 = -1;
2168
7a8d521f 2169 if (pa1 != INVALID_PTR) {
02949f79 2170 switch (a0) {
595a136b 2171 case 2: buread(pa1, 1, a2); break;
2172 case 3: buread(pa1, 2, a2); break;
02949f79 2173 }
ef79bbde 2174 }
7a8d521f 2175
ef79bbde
P
2176 pc0 = ra;
2177}
2178
ef79bbde
P
2179/*
2180 * int write(int fd , void *buf , int nbytes);
2181 */
2182
2183void psxBios_write() { // 0x35/0x03
2184 char *ptr;
02949f79 2185 void *pa1 = Ra1;
2186
2187#ifdef PSXBIOS_LOG
2188 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2189#endif
2190
2191 v0 = -1;
7a8d521f 2192 if (pa1 == INVALID_PTR) {
02949f79 2193 pc0 = ra;
2194 return;
2195 }
ef79bbde
P
2196
2197 if (a0 == 1) { // stdout
02949f79 2198 char *ptr = pa1;
ef79bbde 2199
02949f79 2200 v0 = a2;
ef79bbde
P
2201 while (a2 > 0) {
2202 SysPrintf("%c", *ptr++); a2--;
2203 }
2204 pc0 = ra; return;
2205 }
ef79bbde
P
2206
2207 switch (a0) {
595a136b 2208 case 2: buwrite(pa1, 1, a2); break;
2209 case 3: buwrite(pa1, 2, a2); break;
ef79bbde
P
2210 }
2211
2212 pc0 = ra;
2213}
2214
2215/*
2216 * int close(int fd);
2217 */
2218
2219void psxBios_close() { // 0x36
2220#ifdef PSXBIOS_LOG
2221 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2222#endif
2223
2224 v0 = a0;
2225 pc0 = ra;
2226}
2227
2228void psxBios_putchar() { // 3d
2229 SysPrintf("%c", (char)a0);
2230 pc0 = ra;
2231}
2232
2233void psxBios_puts() { // 3e/3f
808a13bd 2234 SysPrintf("%s", Ra0);
ef79bbde
P
2235 pc0 = ra;
2236}
2237
f1514614 2238
2239/* To avoid any issues with different behaviour when using the libc's own strlen instead.
2240 * We want to mimic the PSX's behaviour in this case for bufile. */
7a8d521f 2241static size_t strlen_internal(char* p)
f1514614 2242{
2243 size_t size_of_array = 0;
2244 while (*p++) size_of_array++;
2245 return size_of_array;
2246}
2247
ef79bbde 2248#define bufile(mcd) { \
f1514614 2249 size_t size_of_name = strlen_internal(dir->name); \
ef79bbde
P
2250 while (nfile < 16) { \
2251 int match=1; \
2252 \
595a136b 2253 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
ef79bbde
P
2254 nfile++; \
2255 if ((*ptr & 0xF0) != 0x50) continue; \
595a136b 2256 /* Bug link files show up as free block. */ \
2257 if (!ptr[0xa]) continue; \
ef79bbde
P
2258 ptr+= 0xa; \
2259 if (pfile[0] == 0) { \
f1514614 2260 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2261 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
ef79bbde
P
2262 } else for (i=0; i<20; i++) { \
2263 if (pfile[i] == ptr[i]) { \
595a136b 2264 dir->name[i] = ptr[i]; continue; } \
ef79bbde
P
2265 if (pfile[i] == '?') { \
2266 dir->name[i] = ptr[i]; continue; } \
2267 if (pfile[i] == '*') { \
2268 strcpy(dir->name+i, ptr+i); break; } \
2269 match = 0; break; \
2270 } \
2271 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
595a136b 2272 if (match == 0) { continue; } \
ef79bbde
P
2273 dir->size = 8192; \
2274 v0 = _dir; \
2275 break; \
2276 } \
2277}
2278
2279/*
2280 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2281 */
7a8d521f 2282
ef79bbde
P
2283void psxBios_firstfile() { // 42
2284 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
02949f79 2285 void *pa0 = Ra0;
ef79bbde
P
2286 u32 _dir = a1;
2287 char *ptr;
2288 int i;
2289
2290#ifdef PSXBIOS_LOG
2291 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2292#endif
2293
2294 v0 = 0;
2295
7a8d521f 2296 if (pa0 != INVALID_PTR) {
02949f79 2297 strcpy(ffile, pa0);
2298 pfile = ffile+5;
8f3b2bd3 2299 nfile = 0;
02949f79 2300 if (!strncmp(pa0, "bu00", 4)) {
857fabea 2301 // firstfile() calls _card_read() internally, so deliver it's event
2302 DeliverEvent(0x11, 0x2);
02949f79 2303 bufile(1);
2304 } else if (!strncmp(pa0, "bu10", 4)) {
857fabea 2305 // firstfile() calls _card_read() internally, so deliver it's event
2306 DeliverEvent(0x11, 0x2);
02949f79 2307 bufile(2);
2308 }
ef79bbde
P
2309 }
2310
2311 pc0 = ra;
2312}
2313
2314/*
2315 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2316 */
2317
2318void psxBios_nextfile() { // 43
2319 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2320 u32 _dir = a0;
2321 char *ptr;
2322 int i;
2323
2324#ifdef PSXBIOS_LOG
2325 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2326#endif
2327
2328 v0 = 0;
2329
2330 if (!strncmp(ffile, "bu00", 4)) {
2331 bufile(1);
2332 }
2333
2334 if (!strncmp(ffile, "bu10", 4)) {
2335 bufile(2);
2336 }
2337
2338 pc0 = ra;
2339}
2340
2341#define burename(mcd) { \
2342 for (i=1; i<16; i++) { \
2343 int namelen, j, xor = 0; \
2344 ptr = Mcd##mcd##Data + 128 * i; \
2345 if ((*ptr & 0xF0) != 0x50) continue; \
2346 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2347 namelen = strlen(Ra1+5); \
2348 memcpy(ptr+0xa, Ra1+5, namelen); \
2349 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2350 for (j=0; j<127; j++) xor^= ptr[j]; \
2351 ptr[127] = xor; \
2352 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2353 v0 = 1; \
2354 break; \
2355 } \
2356}
2357
2358/*
2359 * int rename(char *old, char *new);
2360 */
2361
2362void psxBios_rename() { // 44
02949f79 2363 void *pa0 = Ra0;
2364 void *pa1 = Ra1;
ef79bbde
P
2365 char *ptr;
2366 int i;
2367
2368#ifdef PSXBIOS_LOG
2369 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2370#endif
2371
2372 v0 = 0;
2373
7a8d521f 2374 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
02949f79 2375 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2376 burename(1);
2377 }
ef79bbde 2378
02949f79 2379 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2380 burename(2);
2381 }
ef79bbde
P
2382 }
2383
2384 pc0 = ra;
2385}
2386
2387
2388#define budelete(mcd) { \
2389 for (i=1; i<16; i++) { \
2390 ptr = Mcd##mcd##Data + 128 * i; \
2391 if ((*ptr & 0xF0) != 0x50) continue; \
2392 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2393 *ptr = (*ptr & 0xf) | 0xA0; \
2394 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2395 SysPrintf("delete %s\n", ptr+0xa); \
2396 v0 = 1; \
2397 break; \
2398 } \
2399}
2400
2401/*
2402 * int delete(char *name);
2403 */
2404
2405void psxBios_delete() { // 45
02949f79 2406 void *pa0 = Ra0;
ef79bbde
P
2407 char *ptr;
2408 int i;
2409
2410#ifdef PSXBIOS_LOG
2411 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2412#endif
2413
2414 v0 = 0;
2415
7a8d521f 2416 if (pa0 != INVALID_PTR) {
02949f79 2417 if (!strncmp(pa0, "bu00", 4)) {
2418 budelete(1);
2419 }
ef79bbde 2420
02949f79 2421 if (!strncmp(pa0, "bu10", 4)) {
2422 budelete(2);
2423 }
ef79bbde
P
2424 }
2425
2426 pc0 = ra;
2427}
2428
2429void psxBios_InitCARD() { // 4a
2430#ifdef PSXBIOS_LOG
2431 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2432#endif
2433
2434 CardState = 0;
2435
2436 pc0 = ra;
2437}
2438
2439void psxBios_StartCARD() { // 4b
2440#ifdef PSXBIOS_LOG
2441 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2442#endif
2443
2444 if (CardState == 0) CardState = 1;
2445
2446 pc0 = ra;
2447}
2448
2449void psxBios_StopCARD() { // 4c
2450#ifdef PSXBIOS_LOG
2451 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2452#endif
2453
2454 if (CardState == 1) CardState = 0;
2455
2456 pc0 = ra;
2457}
2458
2459void psxBios__card_write() { // 0x4e
02949f79 2460 void *pa2 = Ra2;
ef79bbde
P
2461 int port;
2462
2463#ifdef PSXBIOS_LOG
2464 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2465#endif
1059caaf 2466 /*
2467 Function also accepts sector 400h (a bug).
2468 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2469 */
2470 if (!(a1 <= 0x3FF))
bd48ba5e 2471 {
2472 /* Invalid sectors */
2473 v0 = 0; pc0 = ra;
2474 return;
2475 }
e9fda093 2476 card_active_chan = a0;
ef79bbde
P
2477 port = a0 >> 4;
2478
7a8d521f 2479 if (pa2 != INVALID_PTR) {
02949f79 2480 if (port == 0) {
2481 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2482 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2483 } else {
2484 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2485 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2486 }
ef79bbde
P
2487 }
2488
2489 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2490// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2491
2492 v0 = 1; pc0 = ra;
2493}
2494
2495void psxBios__card_read() { // 0x4f
02949f79 2496 void *pa2 = Ra2;
ef79bbde
P
2497 int port;
2498
2499#ifdef PSXBIOS_LOG
2500 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2501#endif
1059caaf 2502 /*
2503 Function also accepts sector 400h (a bug).
2504 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2505 */
2506 if (!(a1 <= 0x3FF))
bd48ba5e 2507 {
2508 /* Invalid sectors */
2509 v0 = 0; pc0 = ra;
2510 return;
2511 }
e9fda093 2512 card_active_chan = a0;
ef79bbde
P
2513 port = a0 >> 4;
2514
7a8d521f 2515 if (pa2 != INVALID_PTR) {
02949f79 2516 if (port == 0) {
2517 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2518 } else {
2519 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2520 }
ef79bbde
P
2521 }
2522
2523 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2524// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2525
2526 v0 = 1; pc0 = ra;
2527}
2528
2529void psxBios__new_card() { // 0x50
2530#ifdef PSXBIOS_LOG
2531 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2532#endif
2533
2534 pc0 = ra;
2535}
2536
002b2f7d 2537/* According to a user, this allows Final Fantasy Tactics to save/load properly */
2538void psxBios__get_error(void) // 55
7a8d521f 2539{
002b2f7d 2540 v0 = 0;
2541 pc0 = ra;
2542}
2543
ef79bbde
P
2544void psxBios_Krom2RawAdd() { // 0x51
2545 int i = 0;
2546
2547 const u32 table_8140[][2] = {
2548 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2549 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2550 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2551 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2552 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2553 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2554 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2555 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2556 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2557 {0xffff, 0}
2558 };
2559
2560 const u32 table_889f[][2] = {
2561 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2562 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2563 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2564 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2565 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2566 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2567 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2568 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2569 {0xffff, 0}
2570 };
2571
2572 if (a0 >= 0x8140 && a0 <= 0x84be) {
2573 while (table_8140[i][0] <= a0) i++;
2574 a0 -= table_8140[i - 1][0];
2575 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2576 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2577 while (table_889f[i][0] <= a0) i++;
2578 a0 -= table_889f[i - 1][0];
2579 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2580 } else {
2581 v0 = 0xffffffff;
2582 }
2583
2584 pc0 = ra;
2585}
2586
2587void psxBios_GetC0Table() { // 56
2588#ifdef PSXBIOS_LOG
2589 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2590#endif
2591
2592 v0 = 0x674; pc0 = ra;
2593}
2594
2595void psxBios_GetB0Table() { // 57
2596#ifdef PSXBIOS_LOG
2597 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2598#endif
2599
2600 v0 = 0x874; pc0 = ra;
2601}
2602
e9fda093 2603void psxBios__card_chan() { // 0x58
2604#ifdef PSXBIOS_LOG
2605 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2606#endif
2607
2608 v0 = card_active_chan;
2609 pc0 = ra;
2610}
2611
ef79bbde
P
2612void psxBios_ChangeClearPad() { // 5b
2613#ifdef PSXBIOS_LOG
2614 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
7a8d521f 2615#endif
ef79bbde
P
2616
2617 pc0 = ra;
2618}
2619
21af3ff6 2620void psxBios__card_status() { // 5c
2621#ifdef PSXBIOS_LOG
2622 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2623#endif
2624
cf1af0ed 2625 v0 = card_active_chan;
21af3ff6 2626 pc0 = ra;
2627}
2628
5f652aa9 2629void psxBios__card_wait() { // 5d
2630#ifdef PSXBIOS_LOG
2631 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2632#endif
2633
2634 v0 = 1;
2635 pc0 = ra;
2636}
2637
ef79bbde
P
2638/* System calls C0 */
2639
2640/*
2641 * int SysEnqIntRP(int index , long *queue);
2642 */
2643
2644void psxBios_SysEnqIntRP() { // 02
2645#ifdef PSXBIOS_LOG
2646 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x02] ,a0);
2647#endif
2648
2649 SysIntRP[a0] = a1;
2650
2651 v0 = 0; pc0 = ra;
2652}
2653
2654/*
2655 * int SysDeqIntRP(int index , long *queue);
2656 */
2657
2658void psxBios_SysDeqIntRP() { // 03
2659#ifdef PSXBIOS_LOG
2660 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x03], a0);
2661#endif
2662
2663 SysIntRP[a0] = 0;
2664
2665 v0 = 0; pc0 = ra;
2666}
2667
2668void psxBios_ChangeClearRCnt() { // 0a
2669 u32 *ptr;
2670
2671#ifdef PSXBIOS_LOG
2672 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2673#endif
2674
2675 ptr = (u32*)PSXM((a0 << 2) + 0x8600);
2676 v0 = *ptr;
2677 *ptr = a1;
2678
2679// psxRegs.CP0.n.Status|= 0x404;
2680 pc0 = ra;
2681}
2682
7a8d521f 2683void psxBios_dummy() {
ef79bbde
P
2684#ifdef PSXBIOS_LOG
2685 PSXBIOS_LOG("unk %x call: %x\n", pc0 & 0x1fffff, t1);
2686#endif
7a8d521f 2687 pc0 = ra;
ef79bbde
P
2688}
2689
2690void (*biosA0[256])();
2691void (*biosB0[256])();
2692void (*biosC0[256])();
2693
2694#include "sjisfont.h"
2695
2696void psxBiosInit() {
2697 u32 base, size;
7a8d521f 2698 u32 *ptr;
ef79bbde
P
2699 int i;
2700 uLongf len;
2701
2702 for(i = 0; i < 256; i++) {
2703 biosA0[i] = NULL;
2704 biosB0[i] = NULL;
2705 biosC0[i] = NULL;
2706 }
2707 biosA0[0x3e] = psxBios_puts;
2708 biosA0[0x3f] = psxBios_printf;
2709
2710 biosB0[0x3d] = psxBios_putchar;
2711 biosB0[0x3f] = psxBios_puts;
2712
2713 if (!Config.HLE) return;
2714
2715 for(i = 0; i < 256; i++) {
2716 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
2717 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
2718 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
2719 }
2720
2721 biosA0[0x00] = psxBios_open;
2722 biosA0[0x01] = psxBios_lseek;
2723 biosA0[0x02] = psxBios_read;
2724 biosA0[0x03] = psxBios_write;
2725 biosA0[0x04] = psxBios_close;
2726 //biosA0[0x05] = psxBios_ioctl;
2727 //biosA0[0x06] = psxBios_exit;
2728 //biosA0[0x07] = psxBios_sys_a0_07;
324cec89 2729 biosA0[0x08] = psxBios_getc;
2730 biosA0[0x09] = psxBios_putc;
ba11675c 2731 biosA0[0x0a] = psxBios_todigit;
ef79bbde
P
2732 //biosA0[0x0b] = psxBios_atof;
2733 //biosA0[0x0c] = psxBios_strtoul;
2734 //biosA0[0x0d] = psxBios_strtol;
2735 biosA0[0x0e] = psxBios_abs;
2736 biosA0[0x0f] = psxBios_labs;
2737 biosA0[0x10] = psxBios_atoi;
2738 biosA0[0x11] = psxBios_atol;
2739 //biosA0[0x12] = psxBios_atob;
2740 biosA0[0x13] = psxBios_setjmp;
2741 biosA0[0x14] = psxBios_longjmp;
2742 biosA0[0x15] = psxBios_strcat;
2743 biosA0[0x16] = psxBios_strncat;
2744 biosA0[0x17] = psxBios_strcmp;
2745 biosA0[0x18] = psxBios_strncmp;
2746 biosA0[0x19] = psxBios_strcpy;
2747 biosA0[0x1a] = psxBios_strncpy;
2748 biosA0[0x1b] = psxBios_strlen;
2749 biosA0[0x1c] = psxBios_index;
2750 biosA0[0x1d] = psxBios_rindex;
2751 biosA0[0x1e] = psxBios_strchr;
2752 biosA0[0x1f] = psxBios_strrchr;
2753 biosA0[0x20] = psxBios_strpbrk;
2754 biosA0[0x21] = psxBios_strspn;
2755 biosA0[0x22] = psxBios_strcspn;
2756 biosA0[0x23] = psxBios_strtok;
2757 biosA0[0x24] = psxBios_strstr;
2758 biosA0[0x25] = psxBios_toupper;
2759 biosA0[0x26] = psxBios_tolower;
2760 biosA0[0x27] = psxBios_bcopy;
2761 biosA0[0x28] = psxBios_bzero;
2762 biosA0[0x29] = psxBios_bcmp;
2763 biosA0[0x2a] = psxBios_memcpy;
2764 biosA0[0x2b] = psxBios_memset;
2765 biosA0[0x2c] = psxBios_memmove;
2766 biosA0[0x2d] = psxBios_memcmp;
2767 biosA0[0x2e] = psxBios_memchr;
2768 biosA0[0x2f] = psxBios_rand;
2769 biosA0[0x30] = psxBios_srand;
2770 biosA0[0x31] = psxBios_qsort;
2771 //biosA0[0x32] = psxBios_strtod;
2772 biosA0[0x33] = psxBios_malloc;
2773 biosA0[0x34] = psxBios_free;
2774 //biosA0[0x35] = psxBios_lsearch;
2775 //biosA0[0x36] = psxBios_bsearch;
2776 biosA0[0x37] = psxBios_calloc;
2777 biosA0[0x38] = psxBios_realloc;
2778 biosA0[0x39] = psxBios_InitHeap;
2779 //biosA0[0x3a] = psxBios__exit;
2780 biosA0[0x3b] = psxBios_getchar;
7a8d521f 2781 biosA0[0x3c] = psxBios_putchar;
ef79bbde
P
2782 //biosA0[0x3d] = psxBios_gets;
2783 //biosA0[0x40] = psxBios_sys_a0_40;
2784 //biosA0[0x41] = psxBios_LoadTest;
2785 biosA0[0x42] = psxBios_Load;
2786 biosA0[0x43] = psxBios_Exec;
2787 biosA0[0x44] = psxBios_FlushCache;
2788 //biosA0[0x45] = psxBios_InstallInterruptHandler;
2789 biosA0[0x46] = psxBios_GPU_dw;
2790 biosA0[0x47] = psxBios_mem2vram;
2791 biosA0[0x48] = psxBios_SendGPU;
2792 biosA0[0x49] = psxBios_GPU_cw;
2793 biosA0[0x4a] = psxBios_GPU_cwb;
2794 biosA0[0x4b] = psxBios_GPU_SendPackets;
2795 biosA0[0x4c] = psxBios_sys_a0_4c;
2796 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
7a8d521f 2797 //biosA0[0x4e] = psxBios_GPU_sync;
ef79bbde
P
2798 //biosA0[0x4f] = psxBios_sys_a0_4f;
2799 //biosA0[0x50] = psxBios_sys_a0_50;
2800 biosA0[0x51] = psxBios_LoadExec;
2801 //biosA0[0x52] = psxBios_GetSysSp;
2802 //biosA0[0x53] = psxBios_sys_a0_53;
2803 //biosA0[0x54] = psxBios__96_init_a54;
2804 //biosA0[0x55] = psxBios__bu_init_a55;
2805 //biosA0[0x56] = psxBios__96_remove_a56;
2806 //biosA0[0x57] = psxBios_sys_a0_57;
2807 //biosA0[0x58] = psxBios_sys_a0_58;
2808 //biosA0[0x59] = psxBios_sys_a0_59;
2809 //biosA0[0x5a] = psxBios_sys_a0_5a;
2810 //biosA0[0x5b] = psxBios_dev_tty_init;
2811 //biosA0[0x5c] = psxBios_dev_tty_open;
2812 //biosA0[0x5d] = psxBios_sys_a0_5d;
2813 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
2814 //biosA0[0x5f] = psxBios_dev_cd_open;
2815 //biosA0[0x60] = psxBios_dev_cd_read;
2816 //biosA0[0x61] = psxBios_dev_cd_close;
2817 //biosA0[0x62] = psxBios_dev_cd_firstfile;
2818 //biosA0[0x63] = psxBios_dev_cd_nextfile;
2819 //biosA0[0x64] = psxBios_dev_cd_chdir;
2820 //biosA0[0x65] = psxBios_dev_card_open;
2821 //biosA0[0x66] = psxBios_dev_card_read;
2822 //biosA0[0x67] = psxBios_dev_card_write;
2823 //biosA0[0x68] = psxBios_dev_card_close;
2824 //biosA0[0x69] = psxBios_dev_card_firstfile;
2825 //biosA0[0x6a] = psxBios_dev_card_nextfile;
2826 //biosA0[0x6b] = psxBios_dev_card_erase;
2827 //biosA0[0x6c] = psxBios_dev_card_undelete;
2828 //biosA0[0x6d] = psxBios_dev_card_format;
2829 //biosA0[0x6e] = psxBios_dev_card_rename;
2830 //biosA0[0x6f] = psxBios_dev_card_6f;
2831 biosA0[0x70] = psxBios__bu_init;
2832 biosA0[0x71] = psxBios__96_init;
2833 biosA0[0x72] = psxBios__96_remove;
2834 //biosA0[0x73] = psxBios_sys_a0_73;
2835 //biosA0[0x74] = psxBios_sys_a0_74;
2836 //biosA0[0x75] = psxBios_sys_a0_75;
2837 //biosA0[0x76] = psxBios_sys_a0_76;
2838 //biosA0[0x77] = psxBios_sys_a0_77;
2839 //biosA0[0x78] = psxBios__96_CdSeekL;
2840 //biosA0[0x79] = psxBios_sys_a0_79;
2841 //biosA0[0x7a] = psxBios_sys_a0_7a;
2842 //biosA0[0x7b] = psxBios_sys_a0_7b;
2843 //biosA0[0x7c] = psxBios__96_CdGetStatus;
2844 //biosA0[0x7d] = psxBios_sys_a0_7d;
2845 //biosA0[0x7e] = psxBios__96_CdRead;
2846 //biosA0[0x7f] = psxBios_sys_a0_7f;
2847 //biosA0[0x80] = psxBios_sys_a0_80;
2848 //biosA0[0x81] = psxBios_sys_a0_81;
7a8d521f 2849 //biosA0[0x82] = psxBios_sys_a0_82;
ef79bbde
P
2850 //biosA0[0x83] = psxBios_sys_a0_83;
2851 //biosA0[0x84] = psxBios_sys_a0_84;
7a8d521f 2852 //biosA0[0x85] = psxBios__96_CdStop;
ef79bbde
P
2853 //biosA0[0x86] = psxBios_sys_a0_86;
2854 //biosA0[0x87] = psxBios_sys_a0_87;
2855 //biosA0[0x88] = psxBios_sys_a0_88;
2856 //biosA0[0x89] = psxBios_sys_a0_89;
2857 //biosA0[0x8a] = psxBios_sys_a0_8a;
2858 //biosA0[0x8b] = psxBios_sys_a0_8b;
2859 //biosA0[0x8c] = psxBios_sys_a0_8c;
2860 //biosA0[0x8d] = psxBios_sys_a0_8d;
2861 //biosA0[0x8e] = psxBios_sys_a0_8e;
2862 //biosA0[0x8f] = psxBios_sys_a0_8f;
2863 //biosA0[0x90] = psxBios_sys_a0_90;
2864 //biosA0[0x91] = psxBios_sys_a0_91;
2865 //biosA0[0x92] = psxBios_sys_a0_92;
2866 //biosA0[0x93] = psxBios_sys_a0_93;
2867 //biosA0[0x94] = psxBios_sys_a0_94;
2868 //biosA0[0x95] = psxBios_sys_a0_95;
2869 //biosA0[0x96] = psxBios_AddCDROMDevice;
2870 //biosA0[0x97] = psxBios_AddMemCardDevide;
2871 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
2872 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
2873 //biosA0[0x9a] = psxBios_sys_a0_9a;
2874 //biosA0[0x9b] = psxBios_sys_a0_9b;
2875 //biosA0[0x9c] = psxBios_SetConf;
2876 //biosA0[0x9d] = psxBios_GetConf;
2877 //biosA0[0x9e] = psxBios_sys_a0_9e;
2878 biosA0[0x9f] = psxBios_SetMem;
2879 //biosA0[0xa0] = psxBios__boot;
2880 //biosA0[0xa1] = psxBios_SystemError;
2881 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
2882 //biosA0[0xa3] = psxBios_DequeueCdIntr;
2883 //biosA0[0xa4] = psxBios_sys_a0_a4;
2884 //biosA0[0xa5] = psxBios_ReadSector;
18dd7e9e 2885 biosA0[0xa6] = psxBios_get_cd_status;
ef79bbde
P
2886 //biosA0[0xa7] = psxBios_bufs_cb_0;
2887 //biosA0[0xa8] = psxBios_bufs_cb_1;
2888 //biosA0[0xa9] = psxBios_bufs_cb_2;
2889 //biosA0[0xaa] = psxBios_bufs_cb_3;
2890 biosA0[0xab] = psxBios__card_info;
2891 biosA0[0xac] = psxBios__card_load;
2892 //biosA0[0axd] = psxBios__card_auto;
2893 //biosA0[0xae] = psxBios_bufs_cd_4;
2894 //biosA0[0xaf] = psxBios_sys_a0_af;
2895 //biosA0[0xb0] = psxBios_sys_a0_b0;
2896 //biosA0[0xb1] = psxBios_sys_a0_b1;
2897 //biosA0[0xb2] = psxBios_do_a_long_jmp
2898 //biosA0[0xb3] = psxBios_sys_a0_b3;
2899 //biosA0[0xb4] = psxBios_sub_function;
2900//*******************B0 CALLS****************************
2901 //biosB0[0x00] = psxBios_SysMalloc;
2902 //biosB0[0x01] = psxBios_sys_b0_01;
2903 biosB0[0x02] = psxBios_SetRCnt;
2904 biosB0[0x03] = psxBios_GetRCnt;
2905 biosB0[0x04] = psxBios_StartRCnt;
2906 biosB0[0x05] = psxBios_StopRCnt;
2907 biosB0[0x06] = psxBios_ResetRCnt;
2908 biosB0[0x07] = psxBios_DeliverEvent;
2909 biosB0[0x08] = psxBios_OpenEvent;
2910 biosB0[0x09] = psxBios_CloseEvent;
2911 biosB0[0x0a] = psxBios_WaitEvent;
2912 biosB0[0x0b] = psxBios_TestEvent;
2913 biosB0[0x0c] = psxBios_EnableEvent;
2914 biosB0[0x0d] = psxBios_DisableEvent;
2915 biosB0[0x0e] = psxBios_OpenTh;
2916 biosB0[0x0f] = psxBios_CloseTh;
2917 biosB0[0x10] = psxBios_ChangeTh;
2918 //biosB0[0x11] = psxBios_psxBios_b0_11;
2919 biosB0[0x12] = psxBios_InitPAD;
2920 biosB0[0x13] = psxBios_StartPAD;
2921 biosB0[0x14] = psxBios_StopPAD;
2922 biosB0[0x15] = psxBios_PAD_init;
2923 biosB0[0x16] = psxBios_PAD_dr;
2924 biosB0[0x17] = psxBios_ReturnFromException;
2925 biosB0[0x18] = psxBios_ResetEntryInt;
2926 biosB0[0x19] = psxBios_HookEntryInt;
2927 //biosB0[0x1a] = psxBios_sys_b0_1a;
2928 //biosB0[0x1b] = psxBios_sys_b0_1b;
2929 //biosB0[0x1c] = psxBios_sys_b0_1c;
2930 //biosB0[0x1d] = psxBios_sys_b0_1d;
2931 //biosB0[0x1e] = psxBios_sys_b0_1e;
2932 //biosB0[0x1f] = psxBios_sys_b0_1f;
2933 biosB0[0x20] = psxBios_UnDeliverEvent;
2934 //biosB0[0x21] = psxBios_sys_b0_21;
2935 //biosB0[0x22] = psxBios_sys_b0_22;
2936 //biosB0[0x23] = psxBios_sys_b0_23;
2937 //biosB0[0x24] = psxBios_sys_b0_24;
2938 //biosB0[0x25] = psxBios_sys_b0_25;
2939 //biosB0[0x26] = psxBios_sys_b0_26;
2940 //biosB0[0x27] = psxBios_sys_b0_27;
2941 //biosB0[0x28] = psxBios_sys_b0_28;
2942 //biosB0[0x29] = psxBios_sys_b0_29;
2943 //biosB0[0x2a] = psxBios_sys_b0_2a;
2944 //biosB0[0x2b] = psxBios_sys_b0_2b;
2945 //biosB0[0x2c] = psxBios_sys_b0_2c;
2946 //biosB0[0x2d] = psxBios_sys_b0_2d;
2947 //biosB0[0x2e] = psxBios_sys_b0_2e;
2948 //biosB0[0x2f] = psxBios_sys_b0_2f;
2949 //biosB0[0x30] = psxBios_sys_b0_30;
2950 //biosB0[0x31] = psxBios_sys_b0_31;
2951 biosB0[0x32] = psxBios_open;
2952 biosB0[0x33] = psxBios_lseek;
2953 biosB0[0x34] = psxBios_read;
2954 biosB0[0x35] = psxBios_write;
2955 biosB0[0x36] = psxBios_close;
2956 //biosB0[0x37] = psxBios_ioctl;
2957 //biosB0[0x38] = psxBios_exit;
2958 //biosB0[0x39] = psxBios_sys_b0_39;
2959 //biosB0[0x3a] = psxBios_getc;
2960 //biosB0[0x3b] = psxBios_putc;
2961 biosB0[0x3c] = psxBios_getchar;
2962 //biosB0[0x3e] = psxBios_gets;
2963 //biosB0[0x40] = psxBios_cd;
e7e1f572 2964 biosB0[0x41] = psxBios_format;
ef79bbde
P
2965 biosB0[0x42] = psxBios_firstfile;
2966 biosB0[0x43] = psxBios_nextfile;
2967 biosB0[0x44] = psxBios_rename;
2968 biosB0[0x45] = psxBios_delete;
2969 //biosB0[0x46] = psxBios_undelete;
2970 //biosB0[0x47] = psxBios_AddDevice;
2971 //biosB0[0x48] = psxBios_RemoteDevice;
2972 //biosB0[0x49] = psxBios_PrintInstalledDevices;
2973 biosB0[0x4a] = psxBios_InitCARD;
2974 biosB0[0x4b] = psxBios_StartCARD;
2975 biosB0[0x4c] = psxBios_StopCARD;
2976 //biosB0[0x4d] = psxBios_sys_b0_4d;
2977 biosB0[0x4e] = psxBios__card_write;
2978 biosB0[0x4f] = psxBios__card_read;
2979 biosB0[0x50] = psxBios__new_card;
2980 biosB0[0x51] = psxBios_Krom2RawAdd;
2981 //biosB0[0x52] = psxBios_sys_b0_52;
2982 //biosB0[0x53] = psxBios_sys_b0_53;
2983 //biosB0[0x54] = psxBios__get_errno;
002b2f7d 2984 biosB0[0x55] = psxBios__get_error;
ef79bbde
P
2985 biosB0[0x56] = psxBios_GetC0Table;
2986 biosB0[0x57] = psxBios_GetB0Table;
e9fda093 2987 biosB0[0x58] = psxBios__card_chan;
ef79bbde
P
2988 //biosB0[0x59] = psxBios_sys_b0_59;
2989 //biosB0[0x5a] = psxBios_sys_b0_5a;
2990 biosB0[0x5b] = psxBios_ChangeClearPad;
21af3ff6 2991 biosB0[0x5c] = psxBios__card_status;
5f652aa9 2992 biosB0[0x5d] = psxBios__card_wait;
ef79bbde
P
2993//*******************C0 CALLS****************************
2994 //biosC0[0x00] = psxBios_InitRCnt;
2995 //biosC0[0x01] = psxBios_InitException;
2996 biosC0[0x02] = psxBios_SysEnqIntRP;
2997 biosC0[0x03] = psxBios_SysDeqIntRP;
2998 //biosC0[0x04] = psxBios_get_free_EvCB_slot;
2999 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3000 //biosC0[0x06] = psxBios_ExceptionHandler;
3001 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3002 //biosC0[0x08] = psxBios_SysInitMemory;
3003 //biosC0[0x09] = psxBios_SysInitKMem;
7a8d521f 3004 biosC0[0x0a] = psxBios_ChangeClearRCnt;
ef79bbde
P
3005 //biosC0[0x0b] = psxBios_SystemError;
3006 //biosC0[0x0c] = psxBios_InitDefInt;
3007 //biosC0[0x0d] = psxBios_sys_c0_0d;
3008 //biosC0[0x0e] = psxBios_sys_c0_0e;
3009 //biosC0[0x0f] = psxBios_sys_c0_0f;
3010 //biosC0[0x10] = psxBios_sys_c0_10;
3011 //biosC0[0x11] = psxBios_sys_c0_11;
3012 //biosC0[0x12] = psxBios_InstallDevices;
3013 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3014 //biosC0[0x14] = psxBios_sys_c0_14;
3015 //biosC0[0x15] = psxBios__cdevinput;
3016 //biosC0[0x16] = psxBios__cdevscan;
3017 //biosC0[0x17] = psxBios__circgetc;
3018 //biosC0[0x18] = psxBios__circputc;
3019 //biosC0[0x19] = psxBios_ioabort;
3020 //biosC0[0x1a] = psxBios_sys_c0_1a
3021 //biosC0[0x1b] = psxBios_KernelRedirect;
3022 //biosC0[0x1c] = psxBios_PatchAOTable;
3023//************** THE END ***************************************
3024/**/
3025 base = 0x1000;
3026 size = sizeof(EvCB) * 32;
7a8d521f 3027 EventCB = (void *)&psxR[base]; base += size * 6;
3028 memset(EventCB, 0, size * 6);
3029 HwEV = EventCB;
3030 EvEV = EventCB + 32;
3031 RcEV = EventCB + 32 * 2;
3032 UeEV = EventCB + 32 * 3;
3033 SwEV = EventCB + 32 * 4;
3034 ThEV = EventCB + 32 * 5;
ef79bbde
P
3035
3036 ptr = (u32 *)&psxM[0x0874]; // b0 table
3037 ptr[0] = SWAPu32(0x4c54 - 0x884);
3038
3039 ptr = (u32 *)&psxM[0x0674]; // c0 table
3040 ptr[6] = SWAPu32(0xc80);
3041
3042 memset(SysIntRP, 0, sizeof(SysIntRP));
7a8d521f 3043 memset(ThreadCB, 0, sizeof(ThreadCB));
3044 ThreadCB[0].status = 2; // main thread
ef79bbde 3045
832f0c3c 3046 pad_stopped = 1;
c62b43c9 3047 jmp_int = NULL;
3048 pad_buf = NULL;
3049 pad_buf1 = NULL;
3050 pad_buf2 = NULL;
3051 pad_buf1len = pad_buf2len = 0;
3052 heap_addr = NULL;
3053 heap_end = NULL;
26b964b5 3054 heap_size = 0;
c62b43c9 3055 CardState = -1;
3056 CurThread = 0;
3057 memset(FDesc, 0, sizeof(FDesc));
832f0c3c 3058 card_active_chan = 0;
c62b43c9 3059
ef79bbde
P
3060 psxMu32ref(0x0150) = SWAPu32(0x160);
3061 psxMu32ref(0x0154) = SWAPu32(0x320);
3062 psxMu32ref(0x0160) = SWAPu32(0x248);
3063 strcpy((char *)&psxM[0x248], "bu");
3064/* psxMu32ref(0x0ca8) = SWAPu32(0x1f410004);
3065 psxMu32ref(0x0cf0) = SWAPu32(0x3c020000);
3066 psxMu32ref(0x0cf4) = SWAPu32(0x2442641c);
3067 psxMu32ref(0x09e0) = SWAPu32(0x43d0);
3068 psxMu32ref(0x4d98) = SWAPu32(0x946f000a);
3069*/
3070 // opcode HLE
3071 psxRu32ref(0x0000) = SWAPu32((0x3b << 26) | 4);
7a8d521f 3072 /* Whatever this does, it actually breaks CTR, even without the uninitiliazed memory patch.
bf643fd9 3073 Normally games shouldn't read from address 0 yet they do. See explanation below in details. */
3074 //psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0);
ef79bbde
P
3075 psxMu32ref(0x00a0) = SWAPu32((0x3b << 26) | 1);
3076 psxMu32ref(0x00b0) = SWAPu32((0x3b << 26) | 2);
3077 psxMu32ref(0x00c0) = SWAPu32((0x3b << 26) | 3);
3078 psxMu32ref(0x4c54) = SWAPu32((0x3b << 26) | 0);
3079 psxMu32ref(0x8000) = SWAPu32((0x3b << 26) | 5);
3080 psxMu32ref(0x07a0) = SWAPu32((0x3b << 26) | 0);
3081 psxMu32ref(0x0884) = SWAPu32((0x3b << 26) | 0);
3082 psxMu32ref(0x0894) = SWAPu32((0x3b << 26) | 0);
3083
3084 // initial stack pointer for BIOS interrupt
3085 psxMu32ref(0x6c80) = SWAPu32(0x000085c8);
3086
3087 // initial RNG seed
3088 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3089
3090 // fonts
3091 len = 0x80000 - 0x66000;
3092 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3093 len = 0x80000 - 0x69d68;
3094 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3095
3096 // memory size 2 MB
3097 psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3098
3099 hleSoftCall = FALSE;
7a8d521f 3100
bf643fd9 3101 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3102 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
339cc5b6 3103 Here are some examples of games not working with this fix in place :
3104 R-type won't get past the Irem logo if not implemented.
3105 Crash Team Racing will softlock after the Sony logo.
bf643fd9 3106 */
7a8d521f 3107
339cc5b6 3108 psxMu32ref(0x0000) = SWAPu32(0x00000003);
3109 /*
3110 But overwritten by 00000003h after soon.
3111 psxMu32ref(0x0000) = SWAPu32(0x00001A3C);
3112 */
3113 psxMu32ref(0x0004) = SWAPu32(0x800C5A27);
3114 psxMu32ref(0x0008) = SWAPu32(0x08000403);
3115 psxMu32ref(0x000C) = SWAPu32(0x00000000);
ef79bbde
P
3116}
3117
3118void psxBiosShutdown() {
3119}
3120
3121#define psxBios_PADpoll(pad) { \
3122 PAD##pad##_startPoll(pad); \
3123 pad_buf##pad[0] = 0; \
3124 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3125 if (!(pad_buf##pad[1] & 0x0f)) { \
3126 bufcount = 32; \
3127 } else { \
3128 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3129 } \
3130 PAD##pad##_poll(0); \
3131 i = 2; \
3132 while (bufcount--) { \
3133 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3134 } \
3135}
3136
3137void biosInterrupt() {
3138 int i, bufcount;
3139
3140// if (psxHu32(0x1070) & 0x1) { // Vsync
3141 if (pad_buf != NULL) {
3142 u32 *buf = (u32*)pad_buf;
3143
3144 if (!Config.UseNet) {
3145 PAD1_startPoll(1);
3146 if (PAD1_poll(0x42) == 0x23) {
3147 PAD1_poll(0);
3148 *buf = PAD1_poll(0) << 8;
3149 *buf |= PAD1_poll(0);
3150 PAD1_poll(0);
3151 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3152 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3153 } else {
3154 PAD1_poll(0);
3155 *buf = PAD1_poll(0) << 8;
3156 *buf|= PAD1_poll(0);
3157 }
3158
3159 PAD2_startPoll(2);
3160 if (PAD2_poll(0x42) == 0x23) {
3161 PAD2_poll(0);
3162 *buf |= PAD2_poll(0) << 24;
3163 *buf |= PAD2_poll(0) << 16;
3164 PAD2_poll(0);
3165 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3166 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3167 } else {
3168 PAD2_poll(0);
3169 *buf |= PAD2_poll(0) << 24;
3170 *buf |= PAD2_poll(0) << 16;
3171 }
3172 } else {
3173 u16 data;
3174
3175 PAD1_startPoll(1);
3176 PAD1_poll(0x42);
3177 PAD1_poll(0);
3178 data = PAD1_poll(0) << 8;
3179 data |= PAD1_poll(0);
3180
3181 if (NET_sendPadData(&data, 2) == -1)
3182 netError();
3183
3184 if (NET_recvPadData(&((u16*)buf)[0], 1) == -1)
3185 netError();
3186 if (NET_recvPadData(&((u16*)buf)[1], 2) == -1)
3187 netError();
3188 }
3189 }
3190 if (Config.UseNet && pad_buf1 != NULL && pad_buf2 != NULL) {
3191 psxBios_PADpoll(1);
3192
3193 if (NET_sendPadData(pad_buf1, i) == -1)
3194 netError();
3195
3196 if (NET_recvPadData(pad_buf1, 1) == -1)
3197 netError();
3198 if (NET_recvPadData(pad_buf2, 2) == -1)
3199 netError();
3200 } else {
f25c285b 3201 if (!pad_stopped) {
3202 if (pad_buf1) {
3203 psxBios_PADpoll(1);
3204 }
ef79bbde 3205
f25c285b 3206 if (pad_buf2) {
3207 psxBios_PADpoll(2);
3208 }
ef79bbde
P
3209 }
3210 }
3211
3212 if (psxHu32(0x1070) & 0x1) { // Vsync
3213 if (RcEV[3][1].status == EvStACTIVE) {
3214 softCall(RcEV[3][1].fhandler);
3215// hwWrite32(0x1f801070, ~(1));
3216 }
3217 }
3218
3219 if (psxHu32(0x1070) & 0x70) { // Rcnt 0,1,2
3220 int i;
3221
3222 for (i = 0; i < 3; i++) {
3223 if (psxHu32(0x1070) & (1 << (i + 4))) {
3224 if (RcEV[i][1].status == EvStACTIVE) {
3225 softCall(RcEV[i][1].fhandler);
3226 }
3227 psxHwWrite32(0x1f801070, ~(1 << (i + 4)));
3228 }
3229 }
3230 }
3231}
3232
3233void psxBiosException() {
3234 int i;
3235
3236 switch (psxRegs.CP0.n.Cause & 0x3c) {
3237 case 0x00: // Interrupt
f23c2241 3238 interrupt_r26=psxRegs.CP0.n.EPC;
ef79bbde
P
3239#ifdef PSXCPU_LOG
3240// PSXCPU_LOG("interrupt\n");
3241#endif
3242 SaveRegs();
3243
3244 sp = psxMu32(0x6c80); // create new stack for interrupt handlers
3245
3246 biosInterrupt();
3247
3248 for (i = 0; i < 8; i++) {
3249 if (SysIntRP[i]) {
3250 u32 *queue = (u32 *)PSXM(SysIntRP[i]);
3251
3252 s0 = queue[2];
3253 softCall(queue[1]);
3254 }
3255 }
3256
3257 if (jmp_int != NULL) {
3258 int i;
3259
3260 psxHwWrite32(0x1f801070, 0xffffffff);
3261
3262 ra = jmp_int[0];
3263 sp = jmp_int[1];
3264 fp = jmp_int[2];
3265 for (i = 0; i < 8; i++) // s0-s7
3266 psxRegs.GPR.r[16 + i] = jmp_int[3 + i];
3267 gp = jmp_int[11];
3268
3269 v0 = 1;
3270 pc0 = ra;
3271 return;
3272 }
3273 psxHwWrite16(0x1f801070, 0);
3274 break;
3275
3276 case 0x20: // Syscall
3277#ifdef PSXCPU_LOG
3278 PSXCPU_LOG("syscall exp %x\n", a0);
3279#endif
3280 switch (a0) {
3281 case 1: // EnterCritical - disable irq's
79dad1b3 3282 /* Fixes Medievil 2 not loading up new game, Digimon World not booting up and possibly others */
3283 v0 = (psxRegs.CP0.n.Status & 0x404) == 0x404;
3284 psxRegs.CP0.n.Status &= ~0x404;
ef79bbde
P
3285 break;
3286
3287 case 2: // ExitCritical - enable irq's
7a8d521f 3288 psxRegs.CP0.n.Status |= 0x404;
ef79bbde 3289 break;
a946d159 3290 /* Normally this should cover SYS(00h, SYS(04h but they don't do anything relevant so... */
3291 default:
3292 break;
ef79bbde
P
3293 }
3294 pc0 = psxRegs.CP0.n.EPC + 4;
3295
3296 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3297 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3298 return;
3299
3300 default:
3301#ifdef PSXCPU_LOG
3302 PSXCPU_LOG("unknown bios exception!\n");
3303#endif
3304 break;
3305 }
3306
3307 pc0 = psxRegs.CP0.n.EPC;
3308 if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;
3309
3310 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3311 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3312}
3313
3314#define bfreeze(ptr, size) { \
3315 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3316 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3317 base += size; \
3318}
3319
3320#define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3321#define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3322
3323#define bfreezepsxMptr(ptr, type) { \
3324 if (Mode == 1) { \
3325 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3326 else psxRu32ref(base) = 0; \
3327 } else { \
3328 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3329 else (ptr) = NULL; \
3330 } \
3331 base += sizeof(u32); \
3332}
3333
3334void psxBiosFreeze(int Mode) {
3335 u32 base = 0x40000;
3336
3337 bfreezepsxMptr(jmp_int, u32);
3338 bfreezepsxMptr(pad_buf, int);
3339 bfreezepsxMptr(pad_buf1, char);
3340 bfreezepsxMptr(pad_buf2, char);
3341 bfreezepsxMptr(heap_addr, u32);
3342 bfreezel(&pad_buf1len);
3343 bfreezel(&pad_buf2len);
3344 bfreezes(regs);
3345 bfreezes(SysIntRP);
3346 bfreezel(&CardState);
7a8d521f 3347 bfreezes(ThreadCB);
ef79bbde
P
3348 bfreezel(&CurThread);
3349 bfreezes(FDesc);
e9fda093 3350 bfreezel(&card_active_chan);
a15f3544 3351 bfreezel(&pad_stopped);
17b2d969 3352 bfreezel(&heap_size);
ef79bbde 3353}