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