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