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