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