psxbios.c: Cleanup buopen()
[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;
a6a44e96 2028
2029static void buopen(int mcd, char *ptr, char *cfg)
595a136b 2030{
2031 int i;
a6a44e96 2032 char *mcd_data = ptr;
595a136b 2033
2034 strcpy(FDesc[1 + mcd].name, Ra0+5);
2035 FDesc[1 + mcd].offset = 0;
2036 FDesc[1 + mcd].mode = a1;
2037
2038 for (i=1; i<16; i++) {
a6a44e96 2039 const char *fptr = mcd_data + 128 * i;
595a136b 2040 if ((*fptr & 0xF0) != 0x50) continue;
2041 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2042 FDesc[1 + mcd].mcfile = i;
2043 SysPrintf("open %s\n", fptr+0xa);
2044 v0 = 1 + mcd;
2045 break;
2046 }
2047 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
595a136b 2048 for (i=1; i<16; i++) {
2049 int j, xor, nblk = a1 >> 16;
a6a44e96 2050 char *pptr, *fptr2;
2051 char *fptr = mcd_data + 128 * i;
595a136b 2052
595a136b 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
02949f79 2097 void *pa0 = Ra0;
ef79bbde
P
2098
2099#ifdef PSXBIOS_LOG
2100 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2101#endif
2102
2103 v0 = -1;
2104
02949f79 2105 if (pa0) {
2106 if (!strncmp(pa0, "bu00", 4)) {
595a136b 2107 buopen(1, Mcd1Data, Config.Mcd1);
02949f79 2108 }
ef79bbde 2109
02949f79 2110 if (!strncmp(pa0, "bu10", 4)) {
595a136b 2111 buopen(2, Mcd2Data, Config.Mcd2);
02949f79 2112 }
ef79bbde
P
2113 }
2114
2115 pc0 = ra;
2116}
2117
2118/*
2119 * int lseek(int fd , int offset , int whence);
2120 */
2121
2122void psxBios_lseek() { // 0x33
2123#ifdef PSXBIOS_LOG
2124 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2125#endif
2126
2127 switch (a2) {
2128 case 0: // SEEK_SET
2129 FDesc[a0].offset = a1;
2130 v0 = a1;
2131// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2132// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2133 break;
2134
2135 case 1: // SEEK_CUR
2136 FDesc[a0].offset+= a1;
2137 v0 = FDesc[a0].offset;
2138 break;
2139 }
2140
2141 pc0 = ra;
2142}
2143
ef79bbde
P
2144
2145/*
2146 * int read(int fd , void *buf , int nbytes);
2147 */
2148
2149void psxBios_read() { // 0x34
2150 char *ptr;
02949f79 2151 void *pa1 = Ra1;
ef79bbde
P
2152
2153#ifdef PSXBIOS_LOG
2154 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2155#endif
2156
2157 v0 = -1;
2158
02949f79 2159 if (pa1) {
2160 switch (a0) {
595a136b 2161 case 2: buread(pa1, 1, a2); break;
2162 case 3: buread(pa1, 2, a2); break;
02949f79 2163 }
ef79bbde 2164 }
ef79bbde 2165
ef79bbde 2166 pc0 = ra;
ef79bbde
P
2167}
2168
2169/*
2170 * int write(int fd , void *buf , int nbytes);
2171 */
2172
2173void psxBios_write() { // 0x35/0x03
2174 char *ptr;
02949f79 2175 void *pa1 = Ra1;
2176
2177#ifdef PSXBIOS_LOG
2178 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2179#endif
2180
2181 v0 = -1;
2182 if (!pa1) {
2183 pc0 = ra;
2184 return;
2185 }
ef79bbde
P
2186
2187 if (a0 == 1) { // stdout
02949f79 2188 char *ptr = pa1;
ef79bbde 2189
02949f79 2190 v0 = a2;
ef79bbde
P
2191 while (a2 > 0) {
2192 SysPrintf("%c", *ptr++); a2--;
2193 }
2194 pc0 = ra; return;
2195 }
ef79bbde
P
2196
2197 switch (a0) {
595a136b 2198 case 2: buwrite(pa1, 1, a2); break;
2199 case 3: buwrite(pa1, 2, a2); break;
ef79bbde
P
2200 }
2201
2202 pc0 = ra;
2203}
2204
2205/*
2206 * int close(int fd);
2207 */
2208
2209void psxBios_close() { // 0x36
2210#ifdef PSXBIOS_LOG
2211 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2212#endif
2213
2214 v0 = a0;
2215 pc0 = ra;
2216}
2217
2218void psxBios_putchar() { // 3d
2219 SysPrintf("%c", (char)a0);
2220 pc0 = ra;
2221}
2222
2223void psxBios_puts() { // 3e/3f
808a13bd 2224 SysPrintf("%s", Ra0);
ef79bbde
P
2225 pc0 = ra;
2226}
2227
f1514614 2228
2229/* To avoid any issues with different behaviour when using the libc's own strlen instead.
2230 * We want to mimic the PSX's behaviour in this case for bufile. */
8ec1e4de 2231static size_t strlen_internal(char* p)
f1514614 2232{
2233 size_t size_of_array = 0;
2234 while (*p++) size_of_array++;
2235 return size_of_array;
2236}
ef79bbde
P
2237
2238#define bufile(mcd) { \
f1514614 2239 size_t size_of_name = strlen_internal(dir->name); \
ef79bbde
P
2240 while (nfile < 16) { \
2241 int match=1; \
2242 \
595a136b 2243 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
ef79bbde
P
2244 nfile++; \
2245 if ((*ptr & 0xF0) != 0x50) continue; \
595a136b 2246 /* Bug link files show up as free block. */ \
2247 if (!ptr[0xa]) continue; \
ef79bbde
P
2248 ptr+= 0xa; \
2249 if (pfile[0] == 0) { \
f1514614 2250 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2251 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
ef79bbde
P
2252 } else for (i=0; i<20; i++) { \
2253 if (pfile[i] == ptr[i]) { \
595a136b 2254 dir->name[i] = ptr[i]; continue; } \
ef79bbde
P
2255 if (pfile[i] == '?') { \
2256 dir->name[i] = ptr[i]; continue; } \
2257 if (pfile[i] == '*') { \
2258 strcpy(dir->name+i, ptr+i); break; } \
2259 match = 0; break; \
2260 } \
2261 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
595a136b 2262 if (match == 0) { continue; } \
ef79bbde
P
2263 dir->size = 8192; \
2264 v0 = _dir; \
2265 break; \
2266 } \
2267}
2268
2269/*
2270 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2271 */
8ec1e4de 2272
ef79bbde
P
2273void psxBios_firstfile() { // 42
2274 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
02949f79 2275 void *pa0 = Ra0;
ef79bbde
P
2276 u32 _dir = a1;
2277 char *ptr;
2278 int i;
2279
2280#ifdef PSXBIOS_LOG
2281 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2282#endif
2283
2284 v0 = 0;
2285
02949f79 2286 if (pa0) {
2287 strcpy(ffile, pa0);
2288 pfile = ffile+5;
8f3b2bd3 2289 nfile = 0;
02949f79 2290 if (!strncmp(pa0, "bu00", 4)) {
857fabea 2291 // firstfile() calls _card_read() internally, so deliver it's event
2292 DeliverEvent(0x11, 0x2);
02949f79 2293 bufile(1);
2294 } else if (!strncmp(pa0, "bu10", 4)) {
857fabea 2295 // firstfile() calls _card_read() internally, so deliver it's event
2296 DeliverEvent(0x11, 0x2);
02949f79 2297 bufile(2);
2298 }
ef79bbde
P
2299 }
2300
2301 pc0 = ra;
2302}
2303
2304/*
2305 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2306 */
2307
2308void psxBios_nextfile() { // 43
2309 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2310 u32 _dir = a0;
2311 char *ptr;
2312 int i;
2313
2314#ifdef PSXBIOS_LOG
2315 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2316#endif
2317
2318 v0 = 0;
2319
2320 if (!strncmp(ffile, "bu00", 4)) {
2321 bufile(1);
2322 }
2323
2324 if (!strncmp(ffile, "bu10", 4)) {
2325 bufile(2);
2326 }
2327
2328 pc0 = ra;
2329}
2330
2331#define burename(mcd) { \
2332 for (i=1; i<16; i++) { \
2333 int namelen, j, xor = 0; \
2334 ptr = Mcd##mcd##Data + 128 * i; \
2335 if ((*ptr & 0xF0) != 0x50) continue; \
2336 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2337 namelen = strlen(Ra1+5); \
2338 memcpy(ptr+0xa, Ra1+5, namelen); \
2339 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2340 for (j=0; j<127; j++) xor^= ptr[j]; \
2341 ptr[127] = xor; \
2342 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2343 v0 = 1; \
2344 break; \
2345 } \
2346}
2347
2348/*
2349 * int rename(char *old, char *new);
2350 */
2351
2352void psxBios_rename() { // 44
02949f79 2353 void *pa0 = Ra0;
2354 void *pa1 = Ra1;
ef79bbde
P
2355 char *ptr;
2356 int i;
2357
2358#ifdef PSXBIOS_LOG
2359 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2360#endif
2361
2362 v0 = 0;
2363
02949f79 2364 if (pa0 && pa1) {
2365 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2366 burename(1);
2367 }
ef79bbde 2368
02949f79 2369 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2370 burename(2);
2371 }
ef79bbde
P
2372 }
2373
2374 pc0 = ra;
2375}
2376
2377
2378#define budelete(mcd) { \
2379 for (i=1; i<16; i++) { \
2380 ptr = Mcd##mcd##Data + 128 * i; \
2381 if ((*ptr & 0xF0) != 0x50) continue; \
2382 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2383 *ptr = (*ptr & 0xf) | 0xA0; \
2384 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2385 SysPrintf("delete %s\n", ptr+0xa); \
2386 v0 = 1; \
2387 break; \
2388 } \
2389}
2390
2391/*
2392 * int delete(char *name);
2393 */
2394
2395void psxBios_delete() { // 45
02949f79 2396 void *pa0 = Ra0;
ef79bbde
P
2397 char *ptr;
2398 int i;
2399
2400#ifdef PSXBIOS_LOG
2401 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2402#endif
2403
2404 v0 = 0;
2405
02949f79 2406 if (pa0) {
2407 if (!strncmp(pa0, "bu00", 4)) {
2408 budelete(1);
2409 }
ef79bbde 2410
02949f79 2411 if (!strncmp(pa0, "bu10", 4)) {
2412 budelete(2);
2413 }
ef79bbde
P
2414 }
2415
2416 pc0 = ra;
2417}
2418
2419void psxBios_InitCARD() { // 4a
2420#ifdef PSXBIOS_LOG
2421 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2422#endif
2423
2424 CardState = 0;
2425
2426 pc0 = ra;
2427}
2428
2429void psxBios_StartCARD() { // 4b
2430#ifdef PSXBIOS_LOG
2431 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2432#endif
2433
2434 if (CardState == 0) CardState = 1;
2435
2436 pc0 = ra;
2437}
2438
2439void psxBios_StopCARD() { // 4c
2440#ifdef PSXBIOS_LOG
2441 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2442#endif
2443
2444 if (CardState == 1) CardState = 0;
2445
2446 pc0 = ra;
2447}
2448
2449void psxBios__card_write() { // 0x4e
02949f79 2450 void *pa2 = Ra2;
ef79bbde
P
2451 int port;
2452
2453#ifdef PSXBIOS_LOG
2454 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2455#endif
1059caaf 2456 /*
2457 Function also accepts sector 400h (a bug).
2458 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2459 */
2460 if (!(a1 <= 0x3FF))
bd48ba5e 2461 {
2462 /* Invalid sectors */
2463 v0 = 0; pc0 = ra;
2464 return;
2465 }
e9fda093 2466 card_active_chan = a0;
ef79bbde
P
2467 port = a0 >> 4;
2468
02949f79 2469 if (pa2) {
2470 if (port == 0) {
2471 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2472 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2473 } else {
2474 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2475 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2476 }
ef79bbde
P
2477 }
2478
2479 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2480// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2481
2482 v0 = 1; pc0 = ra;
2483}
2484
2485void psxBios__card_read() { // 0x4f
02949f79 2486 void *pa2 = Ra2;
ef79bbde
P
2487 int port;
2488
2489#ifdef PSXBIOS_LOG
2490 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2491#endif
1059caaf 2492 /*
2493 Function also accepts sector 400h (a bug).
2494 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2495 */
2496 if (!(a1 <= 0x3FF))
bd48ba5e 2497 {
2498 /* Invalid sectors */
2499 v0 = 0; pc0 = ra;
2500 return;
2501 }
e9fda093 2502 card_active_chan = a0;
ef79bbde
P
2503 port = a0 >> 4;
2504
02949f79 2505 if (pa2) {
2506 if (port == 0) {
2507 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2508 } else {
2509 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2510 }
ef79bbde
P
2511 }
2512
2513 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2514// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2515
2516 v0 = 1; pc0 = ra;
2517}
2518
2519void psxBios__new_card() { // 0x50
2520#ifdef PSXBIOS_LOG
2521 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2522#endif
2523
2524 pc0 = ra;
2525}
2526
002b2f7d 2527/* According to a user, this allows Final Fantasy Tactics to save/load properly */
2528void psxBios__get_error(void) // 55
8ec1e4de 2529{
002b2f7d 2530 v0 = 0;
2531 pc0 = ra;
2532}
2533
ef79bbde
P
2534void psxBios_Krom2RawAdd() { // 0x51
2535 int i = 0;
2536
2537 const u32 table_8140[][2] = {
2538 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2539 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2540 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2541 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2542 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2543 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2544 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2545 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2546 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2547 {0xffff, 0}
2548 };
2549
2550 const u32 table_889f[][2] = {
2551 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2552 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2553 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2554 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2555 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2556 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2557 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2558 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2559 {0xffff, 0}
2560 };
2561
2562 if (a0 >= 0x8140 && a0 <= 0x84be) {
2563 while (table_8140[i][0] <= a0) i++;
2564 a0 -= table_8140[i - 1][0];
2565 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2566 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2567 while (table_889f[i][0] <= a0) i++;
2568 a0 -= table_889f[i - 1][0];
2569 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2570 } else {
2571 v0 = 0xffffffff;
2572 }
2573
2574 pc0 = ra;
2575}
2576
2577void psxBios_GetC0Table() { // 56
2578#ifdef PSXBIOS_LOG
2579 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2580#endif
2581
2582 v0 = 0x674; pc0 = ra;
2583}
2584
2585void psxBios_GetB0Table() { // 57
2586#ifdef PSXBIOS_LOG
2587 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2588#endif
2589
2590 v0 = 0x874; pc0 = ra;
2591}
2592
e9fda093 2593void psxBios__card_chan() { // 0x58
2594#ifdef PSXBIOS_LOG
2595 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2596#endif
2597
2598 v0 = card_active_chan;
2599 pc0 = ra;
2600}
2601
ef79bbde
P
2602void psxBios_ChangeClearPad() { // 5b
2603#ifdef PSXBIOS_LOG
2604 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
8ec1e4de 2605#endif
ef79bbde
P
2606
2607 pc0 = ra;
2608}
2609
872515f9 2610void psxBios__card_status() { // 5c
2611#ifdef PSXBIOS_LOG
21af3ff6 2612 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
872515f9 2613#endif
2614
cf1af0ed 2615 v0 = card_active_chan;
21af3ff6 2616 pc0 = ra;
2617}
2618
5f652aa9 2619void psxBios__card_wait() { // 5d
2620#ifdef PSXBIOS_LOG
2621 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2622#endif
2623
2624 v0 = 1;
2625 pc0 = ra;
872515f9 2626}
2627
ef79bbde
P
2628/* System calls C0 */
2629
2630/*
2631 * int SysEnqIntRP(int index , long *queue);
2632 */
2633
2634void psxBios_SysEnqIntRP() { // 02
2635#ifdef PSXBIOS_LOG
2636 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x02] ,a0);
2637#endif
2638
2639 SysIntRP[a0] = a1;
2640
2641 v0 = 0; pc0 = ra;
2642}
2643
2644/*
2645 * int SysDeqIntRP(int index , long *queue);
2646 */
2647
2648void psxBios_SysDeqIntRP() { // 03
2649#ifdef PSXBIOS_LOG
2650 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x03], a0);
2651#endif
2652
2653 SysIntRP[a0] = 0;
2654
2655 v0 = 0; pc0 = ra;
2656}
2657
2658void psxBios_ChangeClearRCnt() { // 0a
2659 u32 *ptr;
2660
2661#ifdef PSXBIOS_LOG
2662 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2663#endif
2664
2665 ptr = (u32*)PSXM((a0 << 2) + 0x8600);
2666 v0 = *ptr;
2667 *ptr = a1;
2668
2669// psxRegs.CP0.n.Status|= 0x404;
2670 pc0 = ra;
2671}
2672
8ec1e4de 2673void psxBios_dummy() {
ef79bbde
P
2674#ifdef PSXBIOS_LOG
2675 PSXBIOS_LOG("unk %x call: %x\n", pc0 & 0x1fffff, t1);
2676#endif
8ec1e4de 2677 pc0 = ra;
ef79bbde
P
2678}
2679
2680void (*biosA0[256])();
2681void (*biosB0[256])();
2682void (*biosC0[256])();
2683
2684#include "sjisfont.h"
2685
2686void psxBiosInit() {
2687 u32 base, size;
8ec1e4de 2688 u32 *ptr;
ef79bbde
P
2689 int i;
2690 uLongf len;
2691
2692 for(i = 0; i < 256; i++) {
2693 biosA0[i] = NULL;
2694 biosB0[i] = NULL;
2695 biosC0[i] = NULL;
2696 }
2697 biosA0[0x3e] = psxBios_puts;
2698 biosA0[0x3f] = psxBios_printf;
2699
2700 biosB0[0x3d] = psxBios_putchar;
2701 biosB0[0x3f] = psxBios_puts;
2702
2703 if (!Config.HLE) return;
2704
2705 for(i = 0; i < 256; i++) {
2706 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
2707 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
2708 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
2709 }
2710
2711 biosA0[0x00] = psxBios_open;
2712 biosA0[0x01] = psxBios_lseek;
2713 biosA0[0x02] = psxBios_read;
2714 biosA0[0x03] = psxBios_write;
2715 biosA0[0x04] = psxBios_close;
2716 //biosA0[0x05] = psxBios_ioctl;
2717 //biosA0[0x06] = psxBios_exit;
2718 //biosA0[0x07] = psxBios_sys_a0_07;
324cec89 2719 biosA0[0x08] = psxBios_getc;
2720 biosA0[0x09] = psxBios_putc;
ba11675c 2721 biosA0[0x0a] = psxBios_todigit;
ef79bbde
P
2722 //biosA0[0x0b] = psxBios_atof;
2723 //biosA0[0x0c] = psxBios_strtoul;
2724 //biosA0[0x0d] = psxBios_strtol;
2725 biosA0[0x0e] = psxBios_abs;
2726 biosA0[0x0f] = psxBios_labs;
2727 biosA0[0x10] = psxBios_atoi;
2728 biosA0[0x11] = psxBios_atol;
2729 //biosA0[0x12] = psxBios_atob;
2730 biosA0[0x13] = psxBios_setjmp;
2731 biosA0[0x14] = psxBios_longjmp;
2732 biosA0[0x15] = psxBios_strcat;
2733 biosA0[0x16] = psxBios_strncat;
2734 biosA0[0x17] = psxBios_strcmp;
2735 biosA0[0x18] = psxBios_strncmp;
2736 biosA0[0x19] = psxBios_strcpy;
2737 biosA0[0x1a] = psxBios_strncpy;
2738 biosA0[0x1b] = psxBios_strlen;
2739 biosA0[0x1c] = psxBios_index;
2740 biosA0[0x1d] = psxBios_rindex;
2741 biosA0[0x1e] = psxBios_strchr;
2742 biosA0[0x1f] = psxBios_strrchr;
2743 biosA0[0x20] = psxBios_strpbrk;
2744 biosA0[0x21] = psxBios_strspn;
2745 biosA0[0x22] = psxBios_strcspn;
2746 biosA0[0x23] = psxBios_strtok;
2747 biosA0[0x24] = psxBios_strstr;
2748 biosA0[0x25] = psxBios_toupper;
2749 biosA0[0x26] = psxBios_tolower;
2750 biosA0[0x27] = psxBios_bcopy;
2751 biosA0[0x28] = psxBios_bzero;
2752 biosA0[0x29] = psxBios_bcmp;
2753 biosA0[0x2a] = psxBios_memcpy;
2754 biosA0[0x2b] = psxBios_memset;
2755 biosA0[0x2c] = psxBios_memmove;
2756 biosA0[0x2d] = psxBios_memcmp;
2757 biosA0[0x2e] = psxBios_memchr;
2758 biosA0[0x2f] = psxBios_rand;
2759 biosA0[0x30] = psxBios_srand;
2760 biosA0[0x31] = psxBios_qsort;
2761 //biosA0[0x32] = psxBios_strtod;
2762 biosA0[0x33] = psxBios_malloc;
2763 biosA0[0x34] = psxBios_free;
2764 //biosA0[0x35] = psxBios_lsearch;
2765 //biosA0[0x36] = psxBios_bsearch;
2766 biosA0[0x37] = psxBios_calloc;
2767 biosA0[0x38] = psxBios_realloc;
2768 biosA0[0x39] = psxBios_InitHeap;
2769 //biosA0[0x3a] = psxBios__exit;
2770 biosA0[0x3b] = psxBios_getchar;
8ec1e4de 2771 biosA0[0x3c] = psxBios_putchar;
ef79bbde
P
2772 //biosA0[0x3d] = psxBios_gets;
2773 //biosA0[0x40] = psxBios_sys_a0_40;
2774 //biosA0[0x41] = psxBios_LoadTest;
2775 biosA0[0x42] = psxBios_Load;
2776 biosA0[0x43] = psxBios_Exec;
2777 biosA0[0x44] = psxBios_FlushCache;
2778 //biosA0[0x45] = psxBios_InstallInterruptHandler;
2779 biosA0[0x46] = psxBios_GPU_dw;
2780 biosA0[0x47] = psxBios_mem2vram;
2781 biosA0[0x48] = psxBios_SendGPU;
2782 biosA0[0x49] = psxBios_GPU_cw;
2783 biosA0[0x4a] = psxBios_GPU_cwb;
2784 biosA0[0x4b] = psxBios_GPU_SendPackets;
2785 biosA0[0x4c] = psxBios_sys_a0_4c;
2786 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
8ec1e4de 2787 //biosA0[0x4e] = psxBios_GPU_sync;
ef79bbde
P
2788 //biosA0[0x4f] = psxBios_sys_a0_4f;
2789 //biosA0[0x50] = psxBios_sys_a0_50;
2790 biosA0[0x51] = psxBios_LoadExec;
2791 //biosA0[0x52] = psxBios_GetSysSp;
2792 //biosA0[0x53] = psxBios_sys_a0_53;
2793 //biosA0[0x54] = psxBios__96_init_a54;
2794 //biosA0[0x55] = psxBios__bu_init_a55;
2795 //biosA0[0x56] = psxBios__96_remove_a56;
2796 //biosA0[0x57] = psxBios_sys_a0_57;
2797 //biosA0[0x58] = psxBios_sys_a0_58;
2798 //biosA0[0x59] = psxBios_sys_a0_59;
2799 //biosA0[0x5a] = psxBios_sys_a0_5a;
2800 //biosA0[0x5b] = psxBios_dev_tty_init;
2801 //biosA0[0x5c] = psxBios_dev_tty_open;
2802 //biosA0[0x5d] = psxBios_sys_a0_5d;
2803 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
2804 //biosA0[0x5f] = psxBios_dev_cd_open;
2805 //biosA0[0x60] = psxBios_dev_cd_read;
2806 //biosA0[0x61] = psxBios_dev_cd_close;
2807 //biosA0[0x62] = psxBios_dev_cd_firstfile;
2808 //biosA0[0x63] = psxBios_dev_cd_nextfile;
2809 //biosA0[0x64] = psxBios_dev_cd_chdir;
2810 //biosA0[0x65] = psxBios_dev_card_open;
2811 //biosA0[0x66] = psxBios_dev_card_read;
2812 //biosA0[0x67] = psxBios_dev_card_write;
2813 //biosA0[0x68] = psxBios_dev_card_close;
2814 //biosA0[0x69] = psxBios_dev_card_firstfile;
2815 //biosA0[0x6a] = psxBios_dev_card_nextfile;
2816 //biosA0[0x6b] = psxBios_dev_card_erase;
2817 //biosA0[0x6c] = psxBios_dev_card_undelete;
2818 //biosA0[0x6d] = psxBios_dev_card_format;
2819 //biosA0[0x6e] = psxBios_dev_card_rename;
2820 //biosA0[0x6f] = psxBios_dev_card_6f;
2821 biosA0[0x70] = psxBios__bu_init;
2822 biosA0[0x71] = psxBios__96_init;
2823 biosA0[0x72] = psxBios__96_remove;
2824 //biosA0[0x73] = psxBios_sys_a0_73;
2825 //biosA0[0x74] = psxBios_sys_a0_74;
2826 //biosA0[0x75] = psxBios_sys_a0_75;
2827 //biosA0[0x76] = psxBios_sys_a0_76;
2828 //biosA0[0x77] = psxBios_sys_a0_77;
2829 //biosA0[0x78] = psxBios__96_CdSeekL;
2830 //biosA0[0x79] = psxBios_sys_a0_79;
2831 //biosA0[0x7a] = psxBios_sys_a0_7a;
2832 //biosA0[0x7b] = psxBios_sys_a0_7b;
2833 //biosA0[0x7c] = psxBios__96_CdGetStatus;
2834 //biosA0[0x7d] = psxBios_sys_a0_7d;
2835 //biosA0[0x7e] = psxBios__96_CdRead;
2836 //biosA0[0x7f] = psxBios_sys_a0_7f;
2837 //biosA0[0x80] = psxBios_sys_a0_80;
2838 //biosA0[0x81] = psxBios_sys_a0_81;
8ec1e4de 2839 //biosA0[0x82] = psxBios_sys_a0_82;
ef79bbde
P
2840 //biosA0[0x83] = psxBios_sys_a0_83;
2841 //biosA0[0x84] = psxBios_sys_a0_84;
8ec1e4de 2842 //biosA0[0x85] = psxBios__96_CdStop;
ef79bbde
P
2843 //biosA0[0x86] = psxBios_sys_a0_86;
2844 //biosA0[0x87] = psxBios_sys_a0_87;
2845 //biosA0[0x88] = psxBios_sys_a0_88;
2846 //biosA0[0x89] = psxBios_sys_a0_89;
2847 //biosA0[0x8a] = psxBios_sys_a0_8a;
2848 //biosA0[0x8b] = psxBios_sys_a0_8b;
2849 //biosA0[0x8c] = psxBios_sys_a0_8c;
2850 //biosA0[0x8d] = psxBios_sys_a0_8d;
2851 //biosA0[0x8e] = psxBios_sys_a0_8e;
2852 //biosA0[0x8f] = psxBios_sys_a0_8f;
2853 //biosA0[0x90] = psxBios_sys_a0_90;
2854 //biosA0[0x91] = psxBios_sys_a0_91;
2855 //biosA0[0x92] = psxBios_sys_a0_92;
2856 //biosA0[0x93] = psxBios_sys_a0_93;
2857 //biosA0[0x94] = psxBios_sys_a0_94;
2858 //biosA0[0x95] = psxBios_sys_a0_95;
2859 //biosA0[0x96] = psxBios_AddCDROMDevice;
2860 //biosA0[0x97] = psxBios_AddMemCardDevide;
2861 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
2862 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
2863 //biosA0[0x9a] = psxBios_sys_a0_9a;
2864 //biosA0[0x9b] = psxBios_sys_a0_9b;
2865 //biosA0[0x9c] = psxBios_SetConf;
2866 //biosA0[0x9d] = psxBios_GetConf;
2867 //biosA0[0x9e] = psxBios_sys_a0_9e;
2868 biosA0[0x9f] = psxBios_SetMem;
2869 //biosA0[0xa0] = psxBios__boot;
2870 //biosA0[0xa1] = psxBios_SystemError;
2871 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
2872 //biosA0[0xa3] = psxBios_DequeueCdIntr;
2873 //biosA0[0xa4] = psxBios_sys_a0_a4;
2874 //biosA0[0xa5] = psxBios_ReadSector;
18dd7e9e 2875 biosA0[0xa6] = psxBios_get_cd_status;
ef79bbde
P
2876 //biosA0[0xa7] = psxBios_bufs_cb_0;
2877 //biosA0[0xa8] = psxBios_bufs_cb_1;
2878 //biosA0[0xa9] = psxBios_bufs_cb_2;
2879 //biosA0[0xaa] = psxBios_bufs_cb_3;
2880 biosA0[0xab] = psxBios__card_info;
2881 biosA0[0xac] = psxBios__card_load;
2882 //biosA0[0axd] = psxBios__card_auto;
2883 //biosA0[0xae] = psxBios_bufs_cd_4;
2884 //biosA0[0xaf] = psxBios_sys_a0_af;
2885 //biosA0[0xb0] = psxBios_sys_a0_b0;
2886 //biosA0[0xb1] = psxBios_sys_a0_b1;
2887 //biosA0[0xb2] = psxBios_do_a_long_jmp
2888 //biosA0[0xb3] = psxBios_sys_a0_b3;
2889 //biosA0[0xb4] = psxBios_sub_function;
2890//*******************B0 CALLS****************************
2891 //biosB0[0x00] = psxBios_SysMalloc;
2892 //biosB0[0x01] = psxBios_sys_b0_01;
2893 biosB0[0x02] = psxBios_SetRCnt;
2894 biosB0[0x03] = psxBios_GetRCnt;
2895 biosB0[0x04] = psxBios_StartRCnt;
2896 biosB0[0x05] = psxBios_StopRCnt;
2897 biosB0[0x06] = psxBios_ResetRCnt;
2898 biosB0[0x07] = psxBios_DeliverEvent;
2899 biosB0[0x08] = psxBios_OpenEvent;
2900 biosB0[0x09] = psxBios_CloseEvent;
2901 biosB0[0x0a] = psxBios_WaitEvent;
2902 biosB0[0x0b] = psxBios_TestEvent;
2903 biosB0[0x0c] = psxBios_EnableEvent;
2904 biosB0[0x0d] = psxBios_DisableEvent;
2905 biosB0[0x0e] = psxBios_OpenTh;
2906 biosB0[0x0f] = psxBios_CloseTh;
2907 biosB0[0x10] = psxBios_ChangeTh;
2908 //biosB0[0x11] = psxBios_psxBios_b0_11;
2909 biosB0[0x12] = psxBios_InitPAD;
2910 biosB0[0x13] = psxBios_StartPAD;
2911 biosB0[0x14] = psxBios_StopPAD;
2912 biosB0[0x15] = psxBios_PAD_init;
2913 biosB0[0x16] = psxBios_PAD_dr;
2914 biosB0[0x17] = psxBios_ReturnFromException;
2915 biosB0[0x18] = psxBios_ResetEntryInt;
2916 biosB0[0x19] = psxBios_HookEntryInt;
2917 //biosB0[0x1a] = psxBios_sys_b0_1a;
2918 //biosB0[0x1b] = psxBios_sys_b0_1b;
2919 //biosB0[0x1c] = psxBios_sys_b0_1c;
2920 //biosB0[0x1d] = psxBios_sys_b0_1d;
2921 //biosB0[0x1e] = psxBios_sys_b0_1e;
2922 //biosB0[0x1f] = psxBios_sys_b0_1f;
2923 biosB0[0x20] = psxBios_UnDeliverEvent;
2924 //biosB0[0x21] = psxBios_sys_b0_21;
2925 //biosB0[0x22] = psxBios_sys_b0_22;
2926 //biosB0[0x23] = psxBios_sys_b0_23;
2927 //biosB0[0x24] = psxBios_sys_b0_24;
2928 //biosB0[0x25] = psxBios_sys_b0_25;
2929 //biosB0[0x26] = psxBios_sys_b0_26;
2930 //biosB0[0x27] = psxBios_sys_b0_27;
2931 //biosB0[0x28] = psxBios_sys_b0_28;
2932 //biosB0[0x29] = psxBios_sys_b0_29;
2933 //biosB0[0x2a] = psxBios_sys_b0_2a;
2934 //biosB0[0x2b] = psxBios_sys_b0_2b;
2935 //biosB0[0x2c] = psxBios_sys_b0_2c;
2936 //biosB0[0x2d] = psxBios_sys_b0_2d;
2937 //biosB0[0x2e] = psxBios_sys_b0_2e;
2938 //biosB0[0x2f] = psxBios_sys_b0_2f;
2939 //biosB0[0x30] = psxBios_sys_b0_30;
2940 //biosB0[0x31] = psxBios_sys_b0_31;
2941 biosB0[0x32] = psxBios_open;
2942 biosB0[0x33] = psxBios_lseek;
2943 biosB0[0x34] = psxBios_read;
2944 biosB0[0x35] = psxBios_write;
2945 biosB0[0x36] = psxBios_close;
2946 //biosB0[0x37] = psxBios_ioctl;
2947 //biosB0[0x38] = psxBios_exit;
2948 //biosB0[0x39] = psxBios_sys_b0_39;
2949 //biosB0[0x3a] = psxBios_getc;
2950 //biosB0[0x3b] = psxBios_putc;
2951 biosB0[0x3c] = psxBios_getchar;
2952 //biosB0[0x3e] = psxBios_gets;
2953 //biosB0[0x40] = psxBios_cd;
e7e1f572 2954 biosB0[0x41] = psxBios_format;
ef79bbde
P
2955 biosB0[0x42] = psxBios_firstfile;
2956 biosB0[0x43] = psxBios_nextfile;
2957 biosB0[0x44] = psxBios_rename;
2958 biosB0[0x45] = psxBios_delete;
2959 //biosB0[0x46] = psxBios_undelete;
2960 //biosB0[0x47] = psxBios_AddDevice;
2961 //biosB0[0x48] = psxBios_RemoteDevice;
2962 //biosB0[0x49] = psxBios_PrintInstalledDevices;
2963 biosB0[0x4a] = psxBios_InitCARD;
2964 biosB0[0x4b] = psxBios_StartCARD;
2965 biosB0[0x4c] = psxBios_StopCARD;
2966 //biosB0[0x4d] = psxBios_sys_b0_4d;
2967 biosB0[0x4e] = psxBios__card_write;
2968 biosB0[0x4f] = psxBios__card_read;
2969 biosB0[0x50] = psxBios__new_card;
2970 biosB0[0x51] = psxBios_Krom2RawAdd;
2971 //biosB0[0x52] = psxBios_sys_b0_52;
2972 //biosB0[0x53] = psxBios_sys_b0_53;
2973 //biosB0[0x54] = psxBios__get_errno;
002b2f7d 2974 biosB0[0x55] = psxBios__get_error;
ef79bbde
P
2975 biosB0[0x56] = psxBios_GetC0Table;
2976 biosB0[0x57] = psxBios_GetB0Table;
e9fda093 2977 biosB0[0x58] = psxBios__card_chan;
ef79bbde
P
2978 //biosB0[0x59] = psxBios_sys_b0_59;
2979 //biosB0[0x5a] = psxBios_sys_b0_5a;
2980 biosB0[0x5b] = psxBios_ChangeClearPad;
872515f9 2981 biosB0[0x5c] = psxBios__card_status;
5f652aa9 2982 biosB0[0x5d] = psxBios__card_wait;
ef79bbde
P
2983//*******************C0 CALLS****************************
2984 //biosC0[0x00] = psxBios_InitRCnt;
2985 //biosC0[0x01] = psxBios_InitException;
2986 biosC0[0x02] = psxBios_SysEnqIntRP;
2987 biosC0[0x03] = psxBios_SysDeqIntRP;
2988 //biosC0[0x04] = psxBios_get_free_EvCB_slot;
2989 //biosC0[0x05] = psxBios_get_free_TCB_slot;
2990 //biosC0[0x06] = psxBios_ExceptionHandler;
2991 //biosC0[0x07] = psxBios_InstallExeptionHandler;
2992 //biosC0[0x08] = psxBios_SysInitMemory;
2993 //biosC0[0x09] = psxBios_SysInitKMem;
8ec1e4de 2994 biosC0[0x0a] = psxBios_ChangeClearRCnt;
ef79bbde
P
2995 //biosC0[0x0b] = psxBios_SystemError;
2996 //biosC0[0x0c] = psxBios_InitDefInt;
2997 //biosC0[0x0d] = psxBios_sys_c0_0d;
2998 //biosC0[0x0e] = psxBios_sys_c0_0e;
2999 //biosC0[0x0f] = psxBios_sys_c0_0f;
3000 //biosC0[0x10] = psxBios_sys_c0_10;
3001 //biosC0[0x11] = psxBios_sys_c0_11;
3002 //biosC0[0x12] = psxBios_InstallDevices;
3003 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3004 //biosC0[0x14] = psxBios_sys_c0_14;
3005 //biosC0[0x15] = psxBios__cdevinput;
3006 //biosC0[0x16] = psxBios__cdevscan;
3007 //biosC0[0x17] = psxBios__circgetc;
3008 //biosC0[0x18] = psxBios__circputc;
3009 //biosC0[0x19] = psxBios_ioabort;
3010 //biosC0[0x1a] = psxBios_sys_c0_1a
3011 //biosC0[0x1b] = psxBios_KernelRedirect;
3012 //biosC0[0x1c] = psxBios_PatchAOTable;
3013//************** THE END ***************************************
3014/**/
3015 base = 0x1000;
3016 size = sizeof(EvCB) * 32;
3017 Event = (void *)&psxR[base]; base += size * 6;
3018 memset(Event, 0, size * 6);
3019 HwEV = Event;
3020 EvEV = Event + 32;
3021 RcEV = Event + 32 * 2;
3022 UeEV = Event + 32 * 3;
3023 SwEV = Event + 32 * 4;
3024 ThEV = Event + 32 * 5;
3025
3026 ptr = (u32 *)&psxM[0x0874]; // b0 table
3027 ptr[0] = SWAPu32(0x4c54 - 0x884);
3028
3029 ptr = (u32 *)&psxM[0x0674]; // c0 table
3030 ptr[6] = SWAPu32(0xc80);
3031
3032 memset(SysIntRP, 0, sizeof(SysIntRP));
3033 memset(Thread, 0, sizeof(Thread));
3034 Thread[0].status = 2; // main thread
3035
832f0c3c 3036 pad_stopped = 1;
c62b43c9 3037 jmp_int = NULL;
3038 pad_buf = NULL;
3039 pad_buf1 = NULL;
3040 pad_buf2 = NULL;
3041 pad_buf1len = pad_buf2len = 0;
3042 heap_addr = NULL;
3043 heap_end = NULL;
26b964b5 3044 heap_size = 0;
c62b43c9 3045 CardState = -1;
3046 CurThread = 0;
3047 memset(FDesc, 0, sizeof(FDesc));
5bf56268 3048 card_active_chan = 0;
c62b43c9 3049
ef79bbde
P
3050 psxMu32ref(0x0150) = SWAPu32(0x160);
3051 psxMu32ref(0x0154) = SWAPu32(0x320);
3052 psxMu32ref(0x0160) = SWAPu32(0x248);
3053 strcpy((char *)&psxM[0x248], "bu");
3054/* psxMu32ref(0x0ca8) = SWAPu32(0x1f410004);
3055 psxMu32ref(0x0cf0) = SWAPu32(0x3c020000);
3056 psxMu32ref(0x0cf4) = SWAPu32(0x2442641c);
3057 psxMu32ref(0x09e0) = SWAPu32(0x43d0);
3058 psxMu32ref(0x4d98) = SWAPu32(0x946f000a);
3059*/
3060 // opcode HLE
3061 psxRu32ref(0x0000) = SWAPu32((0x3b << 26) | 4);
8ec1e4de 3062 /* Whatever this does, it actually breaks CTR, even without the uninitiliazed memory patch.
bf643fd9 3063 Normally games shouldn't read from address 0 yet they do. See explanation below in details. */
3064 //psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0);
ef79bbde
P
3065 psxMu32ref(0x00a0) = SWAPu32((0x3b << 26) | 1);
3066 psxMu32ref(0x00b0) = SWAPu32((0x3b << 26) | 2);
3067 psxMu32ref(0x00c0) = SWAPu32((0x3b << 26) | 3);
3068 psxMu32ref(0x4c54) = SWAPu32((0x3b << 26) | 0);
3069 psxMu32ref(0x8000) = SWAPu32((0x3b << 26) | 5);
3070 psxMu32ref(0x07a0) = SWAPu32((0x3b << 26) | 0);
3071 psxMu32ref(0x0884) = SWAPu32((0x3b << 26) | 0);
3072 psxMu32ref(0x0894) = SWAPu32((0x3b << 26) | 0);
3073
3074 // initial stack pointer for BIOS interrupt
3075 psxMu32ref(0x6c80) = SWAPu32(0x000085c8);
3076
3077 // initial RNG seed
3078 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3079
3080 // fonts
3081 len = 0x80000 - 0x66000;
3082 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3083 len = 0x80000 - 0x69d68;
3084 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3085
3086 // memory size 2 MB
3087 psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3088
3089 hleSoftCall = FALSE;
8ec1e4de 3090
bf643fd9 3091 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3092 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
339cc5b6 3093 Here are some examples of games not working with this fix in place :
3094 R-type won't get past the Irem logo if not implemented.
3095 Crash Team Racing will softlock after the Sony logo.
bf643fd9 3096 */
8ec1e4de 3097
339cc5b6 3098 psxMu32ref(0x0000) = SWAPu32(0x00000003);
3099 /*
3100 But overwritten by 00000003h after soon.
3101 psxMu32ref(0x0000) = SWAPu32(0x00001A3C);
3102 */
3103 psxMu32ref(0x0004) = SWAPu32(0x800C5A27);
3104 psxMu32ref(0x0008) = SWAPu32(0x08000403);
3105 psxMu32ref(0x000C) = SWAPu32(0x00000000);
ef79bbde
P
3106}
3107
3108void psxBiosShutdown() {
3109}
3110
3111#define psxBios_PADpoll(pad) { \
3112 PAD##pad##_startPoll(pad); \
3113 pad_buf##pad[0] = 0; \
3114 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3115 if (!(pad_buf##pad[1] & 0x0f)) { \
3116 bufcount = 32; \
3117 } else { \
3118 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3119 } \
3120 PAD##pad##_poll(0); \
3121 i = 2; \
3122 while (bufcount--) { \
3123 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3124 } \
3125}
3126
3127void biosInterrupt() {
3128 int i, bufcount;
3129
3130// if (psxHu32(0x1070) & 0x1) { // Vsync
3131 if (pad_buf != NULL) {
3132 u32 *buf = (u32*)pad_buf;
3133
3134 if (!Config.UseNet) {
3135 PAD1_startPoll(1);
3136 if (PAD1_poll(0x42) == 0x23) {
3137 PAD1_poll(0);
3138 *buf = PAD1_poll(0) << 8;
3139 *buf |= PAD1_poll(0);
3140 PAD1_poll(0);
3141 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3142 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3143 } else {
3144 PAD1_poll(0);
3145 *buf = PAD1_poll(0) << 8;
3146 *buf|= PAD1_poll(0);
3147 }
3148
3149 PAD2_startPoll(2);
3150 if (PAD2_poll(0x42) == 0x23) {
3151 PAD2_poll(0);
3152 *buf |= PAD2_poll(0) << 24;
3153 *buf |= PAD2_poll(0) << 16;
3154 PAD2_poll(0);
3155 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3156 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3157 } else {
3158 PAD2_poll(0);
3159 *buf |= PAD2_poll(0) << 24;
3160 *buf |= PAD2_poll(0) << 16;
3161 }
3162 } else {
3163 u16 data;
3164
3165 PAD1_startPoll(1);
3166 PAD1_poll(0x42);
3167 PAD1_poll(0);
3168 data = PAD1_poll(0) << 8;
3169 data |= PAD1_poll(0);
3170
3171 if (NET_sendPadData(&data, 2) == -1)
3172 netError();
3173
3174 if (NET_recvPadData(&((u16*)buf)[0], 1) == -1)
3175 netError();
3176 if (NET_recvPadData(&((u16*)buf)[1], 2) == -1)
3177 netError();
3178 }
3179 }
3180 if (Config.UseNet && pad_buf1 != NULL && pad_buf2 != NULL) {
3181 psxBios_PADpoll(1);
3182
3183 if (NET_sendPadData(pad_buf1, i) == -1)
3184 netError();
3185
3186 if (NET_recvPadData(pad_buf1, 1) == -1)
3187 netError();
3188 if (NET_recvPadData(pad_buf2, 2) == -1)
3189 netError();
3190 } else {
f25c285b 3191 if (!pad_stopped) {
3192 if (pad_buf1) {
3193 psxBios_PADpoll(1);
3194 }
ef79bbde 3195
f25c285b 3196 if (pad_buf2) {
3197 psxBios_PADpoll(2);
3198 }
ef79bbde
P
3199 }
3200 }
3201
3202 if (psxHu32(0x1070) & 0x1) { // Vsync
3203 if (RcEV[3][1].status == EvStACTIVE) {
3204 softCall(RcEV[3][1].fhandler);
3205// hwWrite32(0x1f801070, ~(1));
3206 }
3207 }
3208
3209 if (psxHu32(0x1070) & 0x70) { // Rcnt 0,1,2
3210 int i;
3211
3212 for (i = 0; i < 3; i++) {
3213 if (psxHu32(0x1070) & (1 << (i + 4))) {
3214 if (RcEV[i][1].status == EvStACTIVE) {
3215 softCall(RcEV[i][1].fhandler);
3216 }
3217 psxHwWrite32(0x1f801070, ~(1 << (i + 4)));
3218 }
3219 }
3220 }
3221}
3222
3223void psxBiosException() {
3224 int i;
3225
3226 switch (psxRegs.CP0.n.Cause & 0x3c) {
3227 case 0x00: // Interrupt
f23c2241 3228 interrupt_r26=psxRegs.CP0.n.EPC;
ef79bbde
P
3229#ifdef PSXCPU_LOG
3230// PSXCPU_LOG("interrupt\n");
3231#endif
3232 SaveRegs();
3233
3234 sp = psxMu32(0x6c80); // create new stack for interrupt handlers
3235
3236 biosInterrupt();
3237
3238 for (i = 0; i < 8; i++) {
3239 if (SysIntRP[i]) {
3240 u32 *queue = (u32 *)PSXM(SysIntRP[i]);
3241
3242 s0 = queue[2];
3243 softCall(queue[1]);
3244 }
3245 }
3246
3247 if (jmp_int != NULL) {
3248 int i;
3249
3250 psxHwWrite32(0x1f801070, 0xffffffff);
3251
3252 ra = jmp_int[0];
3253 sp = jmp_int[1];
3254 fp = jmp_int[2];
3255 for (i = 0; i < 8; i++) // s0-s7
3256 psxRegs.GPR.r[16 + i] = jmp_int[3 + i];
3257 gp = jmp_int[11];
3258
3259 v0 = 1;
3260 pc0 = ra;
3261 return;
3262 }
3263 psxHwWrite16(0x1f801070, 0);
3264 break;
3265
3266 case 0x20: // Syscall
3267#ifdef PSXCPU_LOG
3268 PSXCPU_LOG("syscall exp %x\n", a0);
3269#endif
3270 switch (a0) {
3271 case 1: // EnterCritical - disable irq's
79dad1b3 3272 /* Fixes Medievil 2 not loading up new game, Digimon World not booting up and possibly others */
3273 v0 = (psxRegs.CP0.n.Status & 0x404) == 0x404;
3274 psxRegs.CP0.n.Status &= ~0x404;
ef79bbde
P
3275 break;
3276
3277 case 2: // ExitCritical - enable irq's
8ec1e4de 3278 psxRegs.CP0.n.Status |= 0x404;
ef79bbde 3279 break;
a946d159 3280 /* Normally this should cover SYS(00h, SYS(04h but they don't do anything relevant so... */
3281 default:
ef79bbde
P
3282 break;
3283 }
3284 pc0 = psxRegs.CP0.n.EPC + 4;
3285
3286 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3287 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3288 return;
3289
3290 default:
3291#ifdef PSXCPU_LOG
3292 PSXCPU_LOG("unknown bios exception!\n");
3293#endif
3294 break;
3295 }
3296
3297 pc0 = psxRegs.CP0.n.EPC;
3298 if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;
3299
3300 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3301 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3302}
3303
3304#define bfreeze(ptr, size) { \
3305 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3306 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3307 base += size; \
3308}
3309
3310#define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3311#define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3312
3313#define bfreezepsxMptr(ptr, type) { \
3314 if (Mode == 1) { \
3315 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3316 else psxRu32ref(base) = 0; \
3317 } else { \
3318 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3319 else (ptr) = NULL; \
3320 } \
3321 base += sizeof(u32); \
3322}
3323
3324void psxBiosFreeze(int Mode) {
3325 u32 base = 0x40000;
3326
3327 bfreezepsxMptr(jmp_int, u32);
3328 bfreezepsxMptr(pad_buf, int);
3329 bfreezepsxMptr(pad_buf1, char);
3330 bfreezepsxMptr(pad_buf2, char);
3331 bfreezepsxMptr(heap_addr, u32);
3332 bfreezel(&pad_buf1len);
3333 bfreezel(&pad_buf2len);
3334 bfreezes(regs);
3335 bfreezes(SysIntRP);
3336 bfreezel(&CardState);
3337 bfreezes(Thread);
3338 bfreezel(&CurThread);
3339 bfreezes(FDesc);
e9fda093 3340 bfreezel(&card_active_chan);
a15f3544 3341 bfreezel(&pad_stopped);
17b2d969 3342 bfreezel(&heap_size);
ef79bbde 3343}