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