Merge pull request #139 from retro-wertz/patch-3
[pcsx_rearmed.git] / libpcsxcore / psxbios.c
CommitLineData
ef79bbde 1/***************************************************************************
8254b5a7 2 * Copyright (C) 2019 Ryan Schultz, PCSX-df Team, PCSX team, gameblabla, *
3 * dmitrysmagin, senquack *
ef79bbde
P
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
19 ***************************************************************************/
20
8254b5a7 21/* Gameblabla 2018-2019 :
22 * Numerous changes to bios calls as well as improvements in order to conform to nocash's findings
23 * for the PSX bios calls. Thanks senquack for helping out with some of the changes
24 * and helping to spot issues and refine my patches.
25 * */
26
ef79bbde
P
27/*
28 * Internal simulated HLE BIOS.
29 */
30
31// TODO: implement all system calls, count the exact CPU cycles of system calls.
32
33#include "psxbios.h"
34#include "psxhw.h"
ddbaf678 35#include "gpu.h"
496d88d4 36#include <zlib.h>
ef79bbde 37
452b85f9 38#undef SysPrintf
39#define SysPrintf if (Config.PsxOut) printf
40
ef79bbde
P
41char *biosA0n[256] = {
42// 0x00
43 "open", "lseek", "read", "write",
44 "close", "ioctl", "exit", "sys_a0_07",
45 "getc", "putc", "todigit", "atof",
46 "strtoul", "strtol", "abs", "labs",
47// 0x10
48 "atoi", "atol", "atob", "setjmp",
49 "longjmp", "strcat", "strncat", "strcmp",
50 "strncmp", "strcpy", "strncpy", "strlen",
51 "index", "rindex", "strchr", "strrchr",
52// 0x20
53 "strpbrk", "strspn", "strcspn", "strtok",
54 "strstr", "toupper", "tolower", "bcopy",
55 "bzero", "bcmp", "memcpy", "memset",
56 "memmove", "memcmp", "memchr", "rand",
57// 0x30
58 "srand", "qsort", "strtod", "malloc",
59 "free", "lsearch", "bsearch", "calloc",
60 "realloc", "InitHeap", "_exit", "getchar",
61 "putchar", "gets", "puts", "printf",
62// 0x40
63 "sys_a0_40", "LoadTest", "Load", "Exec",
64 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
65 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
66 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
67// 0x50
68 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
69 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
70 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
71 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
72// 0x60
73 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
74 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
75 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
76 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
77// 0x70
78 "_bu_init", "_96_init", "_96_remove", "sys_a0_73",
79 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
80 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
81 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
82// 0x80
83 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
84 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
85 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
86 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
87// 0x90
88 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
89 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
90 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
91 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
92// 0xa0
93 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
94 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
95 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
96 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
97// 0xb0
98 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
99 "?? sub_function",
100};
101
102char *biosB0n[256] = {
103// 0x00
104 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
105 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
106 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
107 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
108// 0x10
109 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
110 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
111 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
112 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
113// 0x20
114 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
115 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
116 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
117 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
118// 0x30
119 "sys_b0_30", "sys_b0_31", "open", "lseek",
120 "read", "write", "close", "ioctl",
121 "exit", "sys_b0_39", "getc", "putc",
122 "getchar", "putchar", "gets", "puts",
123// 0x40
124 "cd", "format", "firstfile", "nextfile",
125 "rename", "delete", "undelete", "AddDevice",
126 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
127 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
128// 0x50
129 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
130 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
131 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
132 "_card_status", "_card_wait",
133};
134
135char *biosC0n[256] = {
136// 0x00
137 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
138 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
139 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
140 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
141// 0x10
142 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
143 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
144 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
145 "PatchAOTable",
146};
147
148//#define r0 (psxRegs.GPR.n.r0)
149#define at (psxRegs.GPR.n.at)
150#define v0 (psxRegs.GPR.n.v0)
151#define v1 (psxRegs.GPR.n.v1)
152#define a0 (psxRegs.GPR.n.a0)
153#define a1 (psxRegs.GPR.n.a1)
154#define a2 (psxRegs.GPR.n.a2)
155#define a3 (psxRegs.GPR.n.a3)
156#define t0 (psxRegs.GPR.n.t0)
157#define t1 (psxRegs.GPR.n.t1)
158#define t2 (psxRegs.GPR.n.t2)
159#define t3 (psxRegs.GPR.n.t3)
160#define t4 (psxRegs.GPR.n.t4)
161#define t5 (psxRegs.GPR.n.t5)
162#define t6 (psxRegs.GPR.n.t6)
163#define t7 (psxRegs.GPR.n.t7)
164#define t8 (psxRegs.GPR.n.t8)
165#define t9 (psxRegs.GPR.n.t9)
166#define s0 (psxRegs.GPR.n.s0)
167#define s1 (psxRegs.GPR.n.s1)
168#define s2 (psxRegs.GPR.n.s2)
169#define s3 (psxRegs.GPR.n.s3)
170#define s4 (psxRegs.GPR.n.s4)
171#define s5 (psxRegs.GPR.n.s5)
172#define s6 (psxRegs.GPR.n.s6)
173#define s7 (psxRegs.GPR.n.s7)
174#define k0 (psxRegs.GPR.n.k0)
175#define k1 (psxRegs.GPR.n.k1)
176#define gp (psxRegs.GPR.n.gp)
177#define sp (psxRegs.GPR.n.sp)
178#define fp (psxRegs.GPR.n.s8)
179#define ra (psxRegs.GPR.n.ra)
180#define pc0 (psxRegs.pc)
181
182#define Ra0 ((char *)PSXM(a0))
183#define Ra1 ((char *)PSXM(a1))
184#define Ra2 ((char *)PSXM(a2))
185#define Ra3 ((char *)PSXM(a3))
186#define Rv0 ((char *)PSXM(v0))
187#define Rsp ((char *)PSXM(sp))
188
189typedef struct {
190 u32 desc;
191 s32 status;
192 s32 mode;
193 u32 fhandler;
194} EvCB[32];
195
196#define EvStUNUSED 0x0000
197#define EvStWAIT 0x1000
198#define EvStACTIVE 0x2000
199#define EvStALREADY 0x4000
200
201#define EvMdINTR 0x1000
202#define EvMdNOINTR 0x2000
203
204/*
205typedef struct {
206 s32 next;
207 s32 func1;
208 s32 func2;
209 s32 pad;
210} SysRPst;
211*/
212
213typedef struct {
214 s32 status;
215 s32 mode;
216 u32 reg[32];
217 u32 func;
218} TCB;
219
220typedef struct {
221 u32 _pc0;
222 u32 gp0;
223 u32 t_addr;
224 u32 t_size;
225 u32 d_addr;
226 u32 d_size;
227 u32 b_addr;
228 u32 b_size;
229 u32 S_addr;
230 u32 s_size;
231 u32 _sp, _fp, _gp, ret, base;
232} EXEC;
233
234struct DIRENTRY {
235 char name[20];
236 s32 attr;
237 s32 size;
238 u32 next;
239 s32 head;
240 char system[4];
241};
242
243typedef struct {
244 char name[32];
245 u32 mode;
246 u32 offset;
247 u32 size;
248 u32 mcfile;
249} FileDesc;
250
251static u32 *jmp_int = NULL;
252static int *pad_buf = NULL;
253static char *pad_buf1 = NULL, *pad_buf2 = NULL;
254static int pad_buf1len, pad_buf2len;
f25c285b 255static int pad_stopped = 0;
ef79bbde
P
256
257static u32 regs[35];
258static EvCB *Event;
259static EvCB *HwEV; // 0xf0
260static EvCB *EvEV; // 0xf1
261static EvCB *RcEV; // 0xf2
262static EvCB *UeEV; // 0xf3
263static EvCB *SwEV; // 0xf4
264static EvCB *ThEV; // 0xff
26b964b5 265static u32 heap_size = 0;
ef79bbde
P
266static u32 *heap_addr = NULL;
267static u32 *heap_end = NULL;
268static u32 SysIntRP[8];
269static int CardState = -1;
270static TCB Thread[8];
271static int CurThread = 0;
272static FileDesc FDesc[32];
e9fda093 273static u32 card_active_chan;
ef79bbde
P
274
275boolean hleSoftCall = FALSE;
276
277static inline void softCall(u32 pc) {
278 pc0 = pc;
279 ra = 0x80001000;
280
281 hleSoftCall = TRUE;
282
283 while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
284
285 hleSoftCall = FALSE;
286}
287
288static inline void softCall2(u32 pc) {
289 u32 sra = ra;
290 pc0 = pc;
291 ra = 0x80001000;
292
293 hleSoftCall = TRUE;
294
295 while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
296 ra = sra;
297
298 hleSoftCall = FALSE;
299}
300
301static inline void DeliverEvent(u32 ev, u32 spec) {
302 if (Event[ev][spec].status != EvStACTIVE) return;
303
304// Event[ev][spec].status = EvStALREADY;
305 if (Event[ev][spec].mode == EvMdINTR) {
306 softCall2(Event[ev][spec].fhandler);
307 } else Event[ev][spec].status = EvStALREADY;
308}
309
f23c2241 310static unsigned interrupt_r26=0x8004E8B0;
311
ef79bbde
P
312static inline void SaveRegs() {
313 memcpy(regs, psxRegs.GPR.r, 32*4);
314 regs[32] = psxRegs.GPR.n.lo;
315 regs[33] = psxRegs.GPR.n.hi;
316 regs[34] = psxRegs.pc;
317}
318
319static inline void LoadRegs() {
320 memcpy(psxRegs.GPR.r, regs, 32*4);
321 psxRegs.GPR.n.lo = regs[32];
322 psxRegs.GPR.n.hi = regs[33];
323}
324
325/* *
326// *
327// *
328// System calls A0 */
329
d99f6068 330
331#define buread(Ra1, mcd, length) { \
332 SysPrintf("read %d: %x,%x (%s)\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2, Mcd##mcd##Data + 128 * FDesc[1 + mcd].mcfile + 0xa); \
333 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
334 memcpy(Ra1, ptr, length); \
f1514614 335 if (FDesc[1 + mcd].mode & 0x8000) { \
d99f6068 336 DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
337 DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
f1514614 338 v0 = 0; } \
d99f6068 339 else v0 = length; \
340 FDesc[1 + mcd].offset += v0; \
341}
342
343#define buwrite(Ra1, mcd, length) { \
344 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
345 SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
346 ptr = Mcd##mcd##Data + offset; \
347 memcpy(ptr, Ra1, length); \
f1514614 348 FDesc[1 + mcd].offset += length; \
e49ac7a5 349 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
f1514614 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 }
699
ef79bbde
P
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;
0f598f20 928
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;
1427}
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}
1467
1468void psxBios_GPU_SendPackets() { //4b:
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
1503 a1 = 0xf000;
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);
1558
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
76b81516 1578 u32 ret;
e9fda093 1579 card_active_chan = a0;
1580
76b81516 1581 switch (card_active_chan)
1582 {
1583 case 0x00: case 0x01: case 0x02: case 0x03:
1584 ret = Config.Mcd1[0] ? 0x2 : 0x8;
1585 break;
1586 case 0x10: case 0x11: case 0x12: case 0x13:
1587 ret = Config.Mcd2[0] ? 0x2 : 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
c2360853 1597 DeliverEvent(0x11, 0x2); // 0xf4000001, 0x0004
76b81516 1598 DeliverEvent(0x81, ret); // 0xf4000001, 0x0004
ef79bbde
P
1599 v0 = 1; pc0 = ra;
1600}
1601
1602void psxBios__card_load() { // ac
1603#ifdef PSXBIOS_LOG
1604 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1605#endif
1606
e9fda093 1607 card_active_chan = a0;
1608
ef79bbde
P
1609// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1610 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1611
1612 v0 = 1; pc0 = ra;
1613}
1614
1615/* System calls B0 */
1616
1617void psxBios_SetRCnt() { // 02
1618#ifdef PSXBIOS_LOG
1619 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1620#endif
1621
1622 a0&= 0x3;
1623 if (a0 != 3) {
1624 u32 mode=0;
1625
1626 psxRcntWtarget(a0, a1);
1627 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1628 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1629 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1630 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1631 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1632
1633 psxRcntWmode(a0, mode);
1634 }
1635 pc0 = ra;
1636}
1637
1638void psxBios_GetRCnt() { // 03
1639#ifdef PSXBIOS_LOG
1640 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1641#endif
1642
1643 a0&= 0x3;
1644 if (a0 != 3) v0 = psxRcntRcount(a0);
1645 else v0 = 0;
1646 pc0 = ra;
1647}
1648
1649void psxBios_StartRCnt() { // 04
1650#ifdef PSXBIOS_LOG
1651 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1652#endif
1653
1654 a0&= 0x3;
1655 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1656 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1657 v0 = 1; pc0 = ra;
1658}
1659
1660void psxBios_StopRCnt() { // 05
1661#ifdef PSXBIOS_LOG
1662 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1663#endif
1664
1665 a0&= 0x3;
1666 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1667 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1668 pc0 = ra;
1669}
1670
1671void psxBios_ResetRCnt() { // 06
1672#ifdef PSXBIOS_LOG
1673 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1674#endif
1675
1676 a0&= 0x3;
1677 if (a0 != 3) {
1678 psxRcntWmode(a0, 0);
1679 psxRcntWtarget(a0, 0);
1680 psxRcntWcount(a0, 0);
1681 }
1682 pc0 = ra;
1683}
1684
1685
1686/* gets ev for use with Event */
1687#define GetEv() \
1688 ev = (a0 >> 24) & 0xf; \
1689 if (ev == 0xf) ev = 0x5; \
1690 ev*= 32; \
1691 ev+= a0&0x1f;
1692
1693/* gets spec for use with Event */
1694#define GetSpec() \
1695 spec = 0; \
1696 switch (a1) { \
1697 case 0x0301: spec = 16; break; \
1698 case 0x0302: spec = 17; break; \
1699 default: \
1700 for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \
1701 break; \
1702 }
1703
1704void psxBios_DeliverEvent() { // 07
1705 int ev, spec;
1706 int i;
1707
1708 GetEv();
1709 GetSpec();
1710
1711#ifdef PSXBIOS_LOG
1712 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x07], ev, spec);
1713#endif
1714
1715 DeliverEvent(ev, spec);
1716
1717 pc0 = ra;
1718}
1719
1720void psxBios_OpenEvent() { // 08
1721 int ev, spec;
1722 int i;
1723
1724 GetEv();
1725 GetSpec();
1726
1727#ifdef PSXBIOS_LOG
1728 PSXBIOS_LOG("psxBios_%s %x,%x (class:%x, spec:%x, mode:%x, func:%x)\n", biosB0n[0x08], ev, spec, a0, a1, a2, a3);
1729#endif
1730
1731 Event[ev][spec].status = EvStWAIT;
1732 Event[ev][spec].mode = a2;
1733 Event[ev][spec].fhandler = a3;
1734
1735 v0 = ev | (spec << 8);
1736 pc0 = ra;
1737}
1738
1739void psxBios_CloseEvent() { // 09
1740 int ev, spec;
1741
1742 ev = a0 & 0xff;
1743 spec = (a0 >> 8) & 0xff;
1744
1745#ifdef PSXBIOS_LOG
1746 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x09], ev, spec);
1747#endif
1748
1749 Event[ev][spec].status = EvStUNUSED;
1750
1751 v0 = 1; pc0 = ra;
1752}
1753
1754void psxBios_WaitEvent() { // 0a
1755 int ev, spec;
1756
1757 ev = a0 & 0xff;
1758 spec = (a0 >> 8) & 0xff;
ef79bbde
P
1759#ifdef PSXBIOS_LOG
1760 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0a], ev, spec);
1761#endif
d95c9dcb 1762 if (Event[ev][spec].status == EvStUNUSED)
1763 {
1764 v0 = 0;
1765 pc0 = ra;
1766 return;
1767 }
ef79bbde 1768
d95c9dcb 1769 if (Event[ev][spec].status == EvStALREADY)
1770 {
1771 /* Callback events (mode=EvMdINTR) do never set the ready flag (and thus WaitEvent would hang forever). */
1772 if (!(Event[ev][spec].mode == EvMdINTR)) Event[ev][spec].status = EvStACTIVE;
1773 v0 = 1;
1774 pc0 = ra;
1775 return;
1776 }
ef79bbde 1777
d95c9dcb 1778 v0 = 0;
1779 pc0 = ra;
ef79bbde
P
1780}
1781
1782void psxBios_TestEvent() { // 0b
1783 int ev, spec;
1784
1785 ev = a0 & 0xff;
1786 spec = (a0 >> 8) & 0xff;
1787
b4ae2532 1788 if (Event[ev][spec].status == EvStALREADY)
1789 {
1790 if (!(Event[ev][spec].mode == EvMdINTR)) Event[ev][spec].status = EvStACTIVE;
1791 v0 = 1;
1792 }
1793 else
1794 {
1795 v0 = 0;
1796 }
ef79bbde
P
1797
1798#ifdef PSXBIOS_LOG
1799 PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0);
1800#endif
1801
1802 pc0 = ra;
1803}
1804
1805void psxBios_EnableEvent() { // 0c
1806 int ev, spec;
1807
1808 ev = a0 & 0xff;
1809 spec = (a0 >> 8) & 0xff;
1810
1811#ifdef PSXBIOS_LOG
1812 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0c], ev, spec);
1813#endif
1814
1815 Event[ev][spec].status = EvStACTIVE;
1816
1817 v0 = 1; pc0 = ra;
1818}
1819
1820void psxBios_DisableEvent() { // 0d
1821 int ev, spec;
1822
1823 ev = a0 & 0xff;
1824 spec = (a0 >> 8) & 0xff;
1825
1826#ifdef PSXBIOS_LOG
1827 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0d], ev, spec);
1828#endif
1829
1830 Event[ev][spec].status = EvStWAIT;
1831
1832 v0 = 1; pc0 = ra;
1833}
1834
1835/*
1836 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
1837 */
1838
1839void psxBios_OpenTh() { // 0e
1840 int th;
1841
1842 for (th=1; th<8; th++)
a66d3058 1843 {
ef79bbde
P
1844 if (Thread[th].status == 0) break;
1845
a66d3058 1846 }
1847 if (th == 8) {
1848 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
1849 // When no free TCB is found, return 0xffffffff according to Nocash doc.
1850#ifdef PSXBIOS_LOG
1851 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
1852#endif
1853 v0 = 0xffffffff;
1854 pc0 = ra;
1855 return;
1856 }
ef79bbde
P
1857#ifdef PSXBIOS_LOG
1858 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
1859#endif
1860
1861 Thread[th].status = 1;
1862 Thread[th].func = a0;
1863 Thread[th].reg[29] = a1;
1864 Thread[th].reg[28] = a2;
1865
1866 v0 = th; pc0 = ra;
1867}
1868
1869/*
1870 * int CloseTh(long thread);
1871 */
1872
1873void psxBios_CloseTh() { // 0f
1874 int th = a0 & 0xff;
1875
1876#ifdef PSXBIOS_LOG
1877 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
1878#endif
9ee77db1 1879 /* The return value is always 1 (even if the handle was already closed). */
1880 v0 = 1;
1881 if (Thread[th].status != 0) {
ef79bbde 1882 Thread[th].status = 0;
ef79bbde
P
1883 }
1884
1885 pc0 = ra;
1886}
1887
1888/*
1889 * int ChangeTh(long thread);
1890 */
1891
1892void psxBios_ChangeTh() { // 10
1893 int th = a0 & 0xff;
1894
1895#ifdef PSXBIOS_LOG
1896// PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
1897#endif
9ee77db1 1898 /* The return value is always 1. */
1899 v0 = 1;
ef79bbde 1900 if (Thread[th].status == 0 || CurThread == th) {
ef79bbde
P
1901 pc0 = ra;
1902 } else {
ef79bbde
P
1903 if (Thread[CurThread].status == 2) {
1904 Thread[CurThread].status = 1;
1905 Thread[CurThread].func = ra;
1906 memcpy(Thread[CurThread].reg, psxRegs.GPR.r, 32*4);
1907 }
1908
1909 memcpy(psxRegs.GPR.r, Thread[th].reg, 32*4);
1910 pc0 = Thread[th].func;
1911 Thread[th].status = 2;
1912 CurThread = th;
1913 }
1914}
1915
1916void psxBios_InitPAD() { // 0x12
1917#ifdef PSXBIOS_LOG
1918 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x12]);
1919#endif
1920
1921 pad_buf1 = (char*)Ra0;
1922 pad_buf1len = a1;
1923 pad_buf2 = (char*)Ra2;
1924 pad_buf2len = a3;
1925
1926 v0 = 1; pc0 = ra;
1927}
1928
1929void psxBios_StartPAD() { // 13
1930#ifdef PSXBIOS_LOG
1931 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
1932#endif
f25c285b 1933 pad_stopped = 0;
ef79bbde
P
1934 psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1));
1935 psxRegs.CP0.n.Status |= 0x401;
1936 pc0 = ra;
1937}
1938
1939void psxBios_StopPAD() { // 14
1940#ifdef PSXBIOS_LOG
1941 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
1942#endif
f25c285b 1943 pad_stopped = 1;
ef79bbde
P
1944 pad_buf1 = NULL;
1945 pad_buf2 = NULL;
1946 pc0 = ra;
1947}
1948
1949void psxBios_PAD_init() { // 15
1950#ifdef PSXBIOS_LOG
1951 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
1952#endif
a824e83d 1953 if (!(a0 == 0x20000000 || a0 == 0x20000001))
1954 {
1955 v0 = 0;
1956 pc0 = ra;
1957 return;
1958 }
ef79bbde
P
1959 psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
1960 pad_buf = (int *)Ra1;
1961 *pad_buf = -1;
1962 psxRegs.CP0.n.Status |= 0x401;
a824e83d 1963 v0 = 2;
ef79bbde
P
1964 pc0 = ra;
1965}
1966
1967void psxBios_PAD_dr() { // 16
1968#ifdef PSXBIOS_LOG
1969 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
1970#endif
1971
1972 v0 = -1; pc0 = ra;
1973}
1974
1975void psxBios_ReturnFromException() { // 17
1976 LoadRegs();
1977
1978 pc0 = psxRegs.CP0.n.EPC;
f23c2241 1979 k0 = interrupt_r26;
ef79bbde
P
1980 if (psxRegs.CP0.n.Cause & 0x80000000) pc0 += 4;
1981
1982 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
1983 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
1984}
1985
1986void psxBios_ResetEntryInt() { // 18
1987#ifdef PSXBIOS_LOG
1988 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
1989#endif
1990
1991 jmp_int = NULL;
1992 pc0 = ra;
1993}
1994
1995void psxBios_HookEntryInt() { // 19
1996#ifdef PSXBIOS_LOG
1997 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x19]);
1998#endif
1999
2000 jmp_int = (u32*)Ra0;
2001 pc0 = ra;
2002}
2003
2004void psxBios_UnDeliverEvent() { // 0x20
2005 int ev, spec;
2006 int i;
2007
2008 GetEv();
2009 GetSpec();
2010
2011#ifdef PSXBIOS_LOG
2012 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec);
2013#endif
2014
2015 if (Event[ev][spec].status == EvStALREADY &&
2016 Event[ev][spec].mode == EvMdNOINTR)
2017 Event[ev][spec].status = EvStACTIVE;
2018
2019 pc0 = ra;
2020}
2021
595a136b 2022char ffile[64], *pfile;
2023int nfile;
2024static void buopen(int mcd, u8 *ptr, u8 *cfg)
2025{
2026 int i;
2027 u8 *fptr = ptr;
2028
2029 strcpy(FDesc[1 + mcd].name, Ra0+5);
2030 FDesc[1 + mcd].offset = 0;
2031 FDesc[1 + mcd].mode = a1;
2032
2033 for (i=1; i<16; i++) {
2034 fptr += 128;
2035 if ((*fptr & 0xF0) != 0x50) continue;
2036 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2037 FDesc[1 + mcd].mcfile = i;
2038 SysPrintf("open %s\n", fptr+0xa);
2039 v0 = 1 + mcd;
2040 break;
2041 }
2042 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2043 fptr = ptr;
2044 for (i=1; i<16; i++) {
2045 int j, xor, nblk = a1 >> 16;
2046 u8 *pptr, *fptr2;
2047
2048 fptr += 128;
2049 if ((*fptr & 0xF0) != 0xa0) continue;
2050
2051 FDesc[1 + mcd].mcfile = i;
2052 fptr[0] = 0x51;
2053 fptr[4] = 0x00;
2054 fptr[5] = 0x20 * nblk;
2055 fptr[6] = 0x00;
2056 fptr[7] = 0x00;
2057 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2058 pptr = fptr2 = fptr;
2059 for(j=2; j<=nblk; j++) {
2060 int k;
2061 for(i++; i<16; i++) {
2062 fptr2 += 128;
2063
2064 memset(fptr2, 0, 128);
2065 fptr2[0] = j < nblk ? 0x52 : 0x53;
2066 pptr[8] = i - 1;
2067 pptr[9] = 0;
2068 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2069 pptr[127] = xor;
2070 pptr = fptr2;
2071 break;
2072 }
2073 /* shouldn't this return ENOSPC if i == 16? */
2074 }
2075 pptr[8] = pptr[9] = 0xff;
2076 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2077 pptr[127] = xor;
2078 SysPrintf("openC %s %d\n", ptr, nblk);
2079 v0 = 1 + mcd;
2080 /* just go ahead and resave them all */
2081 SaveMcd(cfg, ptr, 128, 128 * 15);
2082 break;
2083 }
2084 /* shouldn't this return ENOSPC if i == 16? */
2085 }
ef79bbde
P
2086}
2087
2088/*
2089 * int open(char *name , int mode);
2090 */
2091
2092void psxBios_open() { // 0x32
2093 int i;
2094 char *ptr;
02949f79 2095 void *pa0 = Ra0;
ef79bbde
P
2096
2097#ifdef PSXBIOS_LOG
2098 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2099#endif
2100
2101 v0 = -1;
2102
02949f79 2103 if (pa0) {
2104 if (!strncmp(pa0, "bu00", 4)) {
595a136b 2105 buopen(1, Mcd1Data, Config.Mcd1);
02949f79 2106 }
ef79bbde 2107
02949f79 2108 if (!strncmp(pa0, "bu10", 4)) {
595a136b 2109 buopen(2, Mcd2Data, Config.Mcd2);
02949f79 2110 }
ef79bbde
P
2111 }
2112
2113 pc0 = ra;
2114}
2115
2116/*
2117 * int lseek(int fd , int offset , int whence);
2118 */
2119
2120void psxBios_lseek() { // 0x33
2121#ifdef PSXBIOS_LOG
2122 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2123#endif
2124
2125 switch (a2) {
2126 case 0: // SEEK_SET
2127 FDesc[a0].offset = a1;
2128 v0 = a1;
2129// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2130// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2131 break;
2132
2133 case 1: // SEEK_CUR
2134 FDesc[a0].offset+= a1;
2135 v0 = FDesc[a0].offset;
2136 break;
2137 }
2138
2139 pc0 = ra;
2140}
2141
595a136b 2142
ef79bbde
P
2143/*
2144 * int read(int fd , void *buf , int nbytes);
2145 */
2146
2147void psxBios_read() { // 0x34
2148 char *ptr;
02949f79 2149 void *pa1 = Ra1;
ef79bbde
P
2150
2151#ifdef PSXBIOS_LOG
2152 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2153#endif
2154
2155 v0 = -1;
2156
02949f79 2157 if (pa1) {
2158 switch (a0) {
595a136b 2159 case 2: buread(pa1, 1, a2); break;
2160 case 3: buread(pa1, 2, a2); break;
02949f79 2161 }
ef79bbde
P
2162 }
2163
2164 pc0 = ra;
2165}
2166
ef79bbde
P
2167/*
2168 * int write(int fd , void *buf , int nbytes);
2169 */
2170
2171void psxBios_write() { // 0x35/0x03
2172 char *ptr;
02949f79 2173 void *pa1 = Ra1;
2174
2175#ifdef PSXBIOS_LOG
2176 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2177#endif
2178
2179 v0 = -1;
2180 if (!pa1) {
2181 pc0 = ra;
2182 return;
2183 }
ef79bbde
P
2184
2185 if (a0 == 1) { // stdout
02949f79 2186 char *ptr = pa1;
ef79bbde 2187
02949f79 2188 v0 = a2;
ef79bbde
P
2189 while (a2 > 0) {
2190 SysPrintf("%c", *ptr++); a2--;
2191 }
2192 pc0 = ra; return;
2193 }
ef79bbde
P
2194
2195 switch (a0) {
595a136b 2196 case 2: buwrite(pa1, 1, a2); break;
2197 case 3: buwrite(pa1, 2, a2); break;
ef79bbde
P
2198 }
2199
2200 pc0 = ra;
2201}
2202
2203/*
2204 * int close(int fd);
2205 */
2206
2207void psxBios_close() { // 0x36
2208#ifdef PSXBIOS_LOG
2209 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2210#endif
2211
2212 v0 = a0;
2213 pc0 = ra;
2214}
2215
2216void psxBios_putchar() { // 3d
2217 SysPrintf("%c", (char)a0);
2218 pc0 = ra;
2219}
2220
2221void psxBios_puts() { // 3e/3f
808a13bd 2222 SysPrintf("%s", Ra0);
ef79bbde
P
2223 pc0 = ra;
2224}
2225
f1514614 2226
2227/* To avoid any issues with different behaviour when using the libc's own strlen instead.
2228 * We want to mimic the PSX's behaviour in this case for bufile. */
2229static size_t strlen_internal(char* p)
2230{
2231 size_t size_of_array = 0;
2232 while (*p++) size_of_array++;
2233 return size_of_array;
2234}
2235
ef79bbde 2236#define bufile(mcd) { \
f1514614 2237 size_t size_of_name = strlen_internal(dir->name); \
ef79bbde
P
2238 while (nfile < 16) { \
2239 int match=1; \
2240 \
595a136b 2241 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
ef79bbde
P
2242 nfile++; \
2243 if ((*ptr & 0xF0) != 0x50) continue; \
595a136b 2244 /* Bug link files show up as free block. */ \
2245 if (!ptr[0xa]) continue; \
ef79bbde
P
2246 ptr+= 0xa; \
2247 if (pfile[0] == 0) { \
f1514614 2248 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2249 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
ef79bbde
P
2250 } else for (i=0; i<20; i++) { \
2251 if (pfile[i] == ptr[i]) { \
595a136b 2252 dir->name[i] = ptr[i]; continue; } \
ef79bbde
P
2253 if (pfile[i] == '?') { \
2254 dir->name[i] = ptr[i]; continue; } \
2255 if (pfile[i] == '*') { \
2256 strcpy(dir->name+i, ptr+i); break; } \
2257 match = 0; break; \
2258 } \
2259 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
595a136b 2260 if (match == 0) { continue; } \
ef79bbde
P
2261 dir->size = 8192; \
2262 v0 = _dir; \
2263 break; \
2264 } \
2265}
2266
2267/*
2268 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2269 */
2270
2271void psxBios_firstfile() { // 42
2272 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
02949f79 2273 void *pa0 = Ra0;
ef79bbde
P
2274 u32 _dir = a1;
2275 char *ptr;
2276 int i;
2277
2278#ifdef PSXBIOS_LOG
2279 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2280#endif
2281
2282 v0 = 0;
2283
02949f79 2284 if (pa0) {
2285 strcpy(ffile, pa0);
2286 pfile = ffile+5;
8f3b2bd3 2287 nfile = 0;
02949f79 2288 if (!strncmp(pa0, "bu00", 4)) {
857fabea 2289 // firstfile() calls _card_read() internally, so deliver it's event
2290 DeliverEvent(0x11, 0x2);
02949f79 2291 bufile(1);
2292 } else if (!strncmp(pa0, "bu10", 4)) {
857fabea 2293 // firstfile() calls _card_read() internally, so deliver it's event
2294 DeliverEvent(0x11, 0x2);
02949f79 2295 bufile(2);
2296 }
ef79bbde
P
2297 }
2298
2299 pc0 = ra;
2300}
2301
2302/*
2303 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2304 */
2305
2306void psxBios_nextfile() { // 43
2307 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2308 u32 _dir = a0;
2309 char *ptr;
2310 int i;
2311
2312#ifdef PSXBIOS_LOG
2313 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2314#endif
2315
2316 v0 = 0;
2317
2318 if (!strncmp(ffile, "bu00", 4)) {
2319 bufile(1);
2320 }
2321
2322 if (!strncmp(ffile, "bu10", 4)) {
2323 bufile(2);
2324 }
2325
2326 pc0 = ra;
2327}
2328
2329#define burename(mcd) { \
2330 for (i=1; i<16; i++) { \
2331 int namelen, j, xor = 0; \
2332 ptr = Mcd##mcd##Data + 128 * i; \
2333 if ((*ptr & 0xF0) != 0x50) continue; \
2334 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2335 namelen = strlen(Ra1+5); \
2336 memcpy(ptr+0xa, Ra1+5, namelen); \
2337 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2338 for (j=0; j<127; j++) xor^= ptr[j]; \
2339 ptr[127] = xor; \
2340 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2341 v0 = 1; \
2342 break; \
2343 } \
2344}
2345
2346/*
2347 * int rename(char *old, char *new);
2348 */
2349
2350void psxBios_rename() { // 44
02949f79 2351 void *pa0 = Ra0;
2352 void *pa1 = Ra1;
ef79bbde
P
2353 char *ptr;
2354 int i;
2355
2356#ifdef PSXBIOS_LOG
2357 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2358#endif
2359
2360 v0 = 0;
2361
02949f79 2362 if (pa0 && pa1) {
2363 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2364 burename(1);
2365 }
ef79bbde 2366
02949f79 2367 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2368 burename(2);
2369 }
ef79bbde
P
2370 }
2371
2372 pc0 = ra;
2373}
2374
2375
2376#define budelete(mcd) { \
2377 for (i=1; i<16; i++) { \
2378 ptr = Mcd##mcd##Data + 128 * i; \
2379 if ((*ptr & 0xF0) != 0x50) continue; \
2380 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2381 *ptr = (*ptr & 0xf) | 0xA0; \
2382 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2383 SysPrintf("delete %s\n", ptr+0xa); \
2384 v0 = 1; \
2385 break; \
2386 } \
2387}
2388
2389/*
2390 * int delete(char *name);
2391 */
2392
2393void psxBios_delete() { // 45
02949f79 2394 void *pa0 = Ra0;
ef79bbde
P
2395 char *ptr;
2396 int i;
2397
2398#ifdef PSXBIOS_LOG
2399 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2400#endif
2401
2402 v0 = 0;
2403
02949f79 2404 if (pa0) {
2405 if (!strncmp(pa0, "bu00", 4)) {
2406 budelete(1);
2407 }
ef79bbde 2408
02949f79 2409 if (!strncmp(pa0, "bu10", 4)) {
2410 budelete(2);
2411 }
ef79bbde
P
2412 }
2413
2414 pc0 = ra;
2415}
2416
2417void psxBios_InitCARD() { // 4a
2418#ifdef PSXBIOS_LOG
2419 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2420#endif
2421
2422 CardState = 0;
2423
2424 pc0 = ra;
2425}
2426
2427void psxBios_StartCARD() { // 4b
2428#ifdef PSXBIOS_LOG
2429 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2430#endif
2431
2432 if (CardState == 0) CardState = 1;
2433
2434 pc0 = ra;
2435}
2436
2437void psxBios_StopCARD() { // 4c
2438#ifdef PSXBIOS_LOG
2439 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2440#endif
2441
2442 if (CardState == 1) CardState = 0;
2443
2444 pc0 = ra;
2445}
2446
2447void psxBios__card_write() { // 0x4e
02949f79 2448 void *pa2 = Ra2;
ef79bbde
P
2449 int port;
2450
2451#ifdef PSXBIOS_LOG
2452 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2453#endif
1059caaf 2454 /*
2455 Function also accepts sector 400h (a bug).
2456 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2457 */
2458 if (!(a1 <= 0x3FF))
bd48ba5e 2459 {
2460 /* Invalid sectors */
2461 v0 = 0; pc0 = ra;
2462 return;
2463 }
e9fda093 2464 card_active_chan = a0;
ef79bbde
P
2465 port = a0 >> 4;
2466
02949f79 2467 if (pa2) {
2468 if (port == 0) {
2469 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2470 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2471 } else {
2472 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2473 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2474 }
ef79bbde
P
2475 }
2476
2477 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2478// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2479
2480 v0 = 1; pc0 = ra;
2481}
2482
2483void psxBios__card_read() { // 0x4f
02949f79 2484 void *pa2 = Ra2;
ef79bbde
P
2485 int port;
2486
2487#ifdef PSXBIOS_LOG
2488 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2489#endif
1059caaf 2490 /*
2491 Function also accepts sector 400h (a bug).
2492 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2493 */
2494 if (!(a1 <= 0x3FF))
bd48ba5e 2495 {
2496 /* Invalid sectors */
2497 v0 = 0; pc0 = ra;
2498 return;
2499 }
e9fda093 2500 card_active_chan = a0;
ef79bbde
P
2501 port = a0 >> 4;
2502
02949f79 2503 if (pa2) {
2504 if (port == 0) {
2505 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2506 } else {
2507 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2508 }
ef79bbde
P
2509 }
2510
2511 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2512// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2513
2514 v0 = 1; pc0 = ra;
2515}
2516
2517void psxBios__new_card() { // 0x50
2518#ifdef PSXBIOS_LOG
2519 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2520#endif
2521
2522 pc0 = ra;
2523}
2524
002b2f7d 2525/* According to a user, this allows Final Fantasy Tactics to save/load properly */
2526void psxBios__get_error(void) // 55
2527{
2528 v0 = 0;
2529 pc0 = ra;
2530}
2531
ef79bbde
P
2532void psxBios_Krom2RawAdd() { // 0x51
2533 int i = 0;
2534
2535 const u32 table_8140[][2] = {
2536 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2537 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2538 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2539 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2540 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2541 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2542 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2543 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2544 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2545 {0xffff, 0}
2546 };
2547
2548 const u32 table_889f[][2] = {
2549 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2550 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2551 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2552 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2553 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2554 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2555 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2556 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2557 {0xffff, 0}
2558 };
2559
2560 if (a0 >= 0x8140 && a0 <= 0x84be) {
2561 while (table_8140[i][0] <= a0) i++;
2562 a0 -= table_8140[i - 1][0];
2563 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2564 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2565 while (table_889f[i][0] <= a0) i++;
2566 a0 -= table_889f[i - 1][0];
2567 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2568 } else {
2569 v0 = 0xffffffff;
2570 }
2571
2572 pc0 = ra;
2573}
2574
2575void psxBios_GetC0Table() { // 56
2576#ifdef PSXBIOS_LOG
2577 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2578#endif
2579
2580 v0 = 0x674; pc0 = ra;
2581}
2582
2583void psxBios_GetB0Table() { // 57
2584#ifdef PSXBIOS_LOG
2585 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2586#endif
2587
2588 v0 = 0x874; pc0 = ra;
2589}
2590
e9fda093 2591void psxBios__card_chan() { // 0x58
2592#ifdef PSXBIOS_LOG
2593 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2594#endif
2595
2596 v0 = card_active_chan;
2597 pc0 = ra;
2598}
2599
ef79bbde
P
2600void psxBios_ChangeClearPad() { // 5b
2601#ifdef PSXBIOS_LOG
2602 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2603#endif
2604
2605 pc0 = ra;
2606}
2607
21af3ff6 2608void psxBios__card_status() { // 5c
2609#ifdef PSXBIOS_LOG
2610 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2611#endif
2612
cf1af0ed 2613 v0 = card_active_chan;
21af3ff6 2614 pc0 = ra;
2615}
2616
5f652aa9 2617void psxBios__card_wait() { // 5d
2618#ifdef PSXBIOS_LOG
2619 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2620#endif
2621
2622 v0 = 1;
2623 pc0 = ra;
2624}
2625
ef79bbde
P
2626/* System calls C0 */
2627
2628/*
2629 * int SysEnqIntRP(int index , long *queue);
2630 */
2631
2632void psxBios_SysEnqIntRP() { // 02
2633#ifdef PSXBIOS_LOG
2634 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x02] ,a0);
2635#endif
2636
2637 SysIntRP[a0] = a1;
2638
2639 v0 = 0; pc0 = ra;
2640}
2641
2642/*
2643 * int SysDeqIntRP(int index , long *queue);
2644 */
2645
2646void psxBios_SysDeqIntRP() { // 03
2647#ifdef PSXBIOS_LOG
2648 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x03], a0);
2649#endif
2650
2651 SysIntRP[a0] = 0;
2652
2653 v0 = 0; pc0 = ra;
2654}
2655
2656void psxBios_ChangeClearRCnt() { // 0a
2657 u32 *ptr;
2658
2659#ifdef PSXBIOS_LOG
2660 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2661#endif
2662
2663 ptr = (u32*)PSXM((a0 << 2) + 0x8600);
2664 v0 = *ptr;
2665 *ptr = a1;
2666
2667// psxRegs.CP0.n.Status|= 0x404;
2668 pc0 = ra;
2669}
2670
2671void psxBios_dummy() {
2672#ifdef PSXBIOS_LOG
2673 PSXBIOS_LOG("unk %x call: %x\n", pc0 & 0x1fffff, t1);
2674#endif
2675 pc0 = ra;
2676}
2677
2678void (*biosA0[256])();
2679void (*biosB0[256])();
2680void (*biosC0[256])();
2681
2682#include "sjisfont.h"
2683
2684void psxBiosInit() {
2685 u32 base, size;
2686 u32 *ptr;
2687 int i;
2688 uLongf len;
2689
2690 for(i = 0; i < 256; i++) {
2691 biosA0[i] = NULL;
2692 biosB0[i] = NULL;
2693 biosC0[i] = NULL;
2694 }
2695 biosA0[0x3e] = psxBios_puts;
2696 biosA0[0x3f] = psxBios_printf;
2697
2698 biosB0[0x3d] = psxBios_putchar;
2699 biosB0[0x3f] = psxBios_puts;
2700
2701 if (!Config.HLE) return;
2702
2703 for(i = 0; i < 256; i++) {
2704 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
2705 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
2706 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
2707 }
2708
2709 biosA0[0x00] = psxBios_open;
2710 biosA0[0x01] = psxBios_lseek;
2711 biosA0[0x02] = psxBios_read;
2712 biosA0[0x03] = psxBios_write;
2713 biosA0[0x04] = psxBios_close;
2714 //biosA0[0x05] = psxBios_ioctl;
2715 //biosA0[0x06] = psxBios_exit;
2716 //biosA0[0x07] = psxBios_sys_a0_07;
324cec89 2717 biosA0[0x08] = psxBios_getc;
2718 biosA0[0x09] = psxBios_putc;
ba11675c 2719 biosA0[0x0a] = psxBios_todigit;
ef79bbde
P
2720 //biosA0[0x0b] = psxBios_atof;
2721 //biosA0[0x0c] = psxBios_strtoul;
2722 //biosA0[0x0d] = psxBios_strtol;
2723 biosA0[0x0e] = psxBios_abs;
2724 biosA0[0x0f] = psxBios_labs;
2725 biosA0[0x10] = psxBios_atoi;
2726 biosA0[0x11] = psxBios_atol;
2727 //biosA0[0x12] = psxBios_atob;
2728 biosA0[0x13] = psxBios_setjmp;
2729 biosA0[0x14] = psxBios_longjmp;
2730 biosA0[0x15] = psxBios_strcat;
2731 biosA0[0x16] = psxBios_strncat;
2732 biosA0[0x17] = psxBios_strcmp;
2733 biosA0[0x18] = psxBios_strncmp;
2734 biosA0[0x19] = psxBios_strcpy;
2735 biosA0[0x1a] = psxBios_strncpy;
2736 biosA0[0x1b] = psxBios_strlen;
2737 biosA0[0x1c] = psxBios_index;
2738 biosA0[0x1d] = psxBios_rindex;
2739 biosA0[0x1e] = psxBios_strchr;
2740 biosA0[0x1f] = psxBios_strrchr;
2741 biosA0[0x20] = psxBios_strpbrk;
2742 biosA0[0x21] = psxBios_strspn;
2743 biosA0[0x22] = psxBios_strcspn;
2744 biosA0[0x23] = psxBios_strtok;
2745 biosA0[0x24] = psxBios_strstr;
2746 biosA0[0x25] = psxBios_toupper;
2747 biosA0[0x26] = psxBios_tolower;
2748 biosA0[0x27] = psxBios_bcopy;
2749 biosA0[0x28] = psxBios_bzero;
2750 biosA0[0x29] = psxBios_bcmp;
2751 biosA0[0x2a] = psxBios_memcpy;
2752 biosA0[0x2b] = psxBios_memset;
2753 biosA0[0x2c] = psxBios_memmove;
2754 biosA0[0x2d] = psxBios_memcmp;
2755 biosA0[0x2e] = psxBios_memchr;
2756 biosA0[0x2f] = psxBios_rand;
2757 biosA0[0x30] = psxBios_srand;
2758 biosA0[0x31] = psxBios_qsort;
2759 //biosA0[0x32] = psxBios_strtod;
2760 biosA0[0x33] = psxBios_malloc;
2761 biosA0[0x34] = psxBios_free;
2762 //biosA0[0x35] = psxBios_lsearch;
2763 //biosA0[0x36] = psxBios_bsearch;
2764 biosA0[0x37] = psxBios_calloc;
2765 biosA0[0x38] = psxBios_realloc;
2766 biosA0[0x39] = psxBios_InitHeap;
2767 //biosA0[0x3a] = psxBios__exit;
2768 biosA0[0x3b] = psxBios_getchar;
2769 biosA0[0x3c] = psxBios_putchar;
2770 //biosA0[0x3d] = psxBios_gets;
2771 //biosA0[0x40] = psxBios_sys_a0_40;
2772 //biosA0[0x41] = psxBios_LoadTest;
2773 biosA0[0x42] = psxBios_Load;
2774 biosA0[0x43] = psxBios_Exec;
2775 biosA0[0x44] = psxBios_FlushCache;
2776 //biosA0[0x45] = psxBios_InstallInterruptHandler;
2777 biosA0[0x46] = psxBios_GPU_dw;
2778 biosA0[0x47] = psxBios_mem2vram;
2779 biosA0[0x48] = psxBios_SendGPU;
2780 biosA0[0x49] = psxBios_GPU_cw;
2781 biosA0[0x4a] = psxBios_GPU_cwb;
2782 biosA0[0x4b] = psxBios_GPU_SendPackets;
2783 biosA0[0x4c] = psxBios_sys_a0_4c;
2784 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
2785 //biosA0[0x4e] = psxBios_GPU_sync;
2786 //biosA0[0x4f] = psxBios_sys_a0_4f;
2787 //biosA0[0x50] = psxBios_sys_a0_50;
2788 biosA0[0x51] = psxBios_LoadExec;
2789 //biosA0[0x52] = psxBios_GetSysSp;
2790 //biosA0[0x53] = psxBios_sys_a0_53;
2791 //biosA0[0x54] = psxBios__96_init_a54;
2792 //biosA0[0x55] = psxBios__bu_init_a55;
2793 //biosA0[0x56] = psxBios__96_remove_a56;
2794 //biosA0[0x57] = psxBios_sys_a0_57;
2795 //biosA0[0x58] = psxBios_sys_a0_58;
2796 //biosA0[0x59] = psxBios_sys_a0_59;
2797 //biosA0[0x5a] = psxBios_sys_a0_5a;
2798 //biosA0[0x5b] = psxBios_dev_tty_init;
2799 //biosA0[0x5c] = psxBios_dev_tty_open;
2800 //biosA0[0x5d] = psxBios_sys_a0_5d;
2801 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
2802 //biosA0[0x5f] = psxBios_dev_cd_open;
2803 //biosA0[0x60] = psxBios_dev_cd_read;
2804 //biosA0[0x61] = psxBios_dev_cd_close;
2805 //biosA0[0x62] = psxBios_dev_cd_firstfile;
2806 //biosA0[0x63] = psxBios_dev_cd_nextfile;
2807 //biosA0[0x64] = psxBios_dev_cd_chdir;
2808 //biosA0[0x65] = psxBios_dev_card_open;
2809 //biosA0[0x66] = psxBios_dev_card_read;
2810 //biosA0[0x67] = psxBios_dev_card_write;
2811 //biosA0[0x68] = psxBios_dev_card_close;
2812 //biosA0[0x69] = psxBios_dev_card_firstfile;
2813 //biosA0[0x6a] = psxBios_dev_card_nextfile;
2814 //biosA0[0x6b] = psxBios_dev_card_erase;
2815 //biosA0[0x6c] = psxBios_dev_card_undelete;
2816 //biosA0[0x6d] = psxBios_dev_card_format;
2817 //biosA0[0x6e] = psxBios_dev_card_rename;
2818 //biosA0[0x6f] = psxBios_dev_card_6f;
2819 biosA0[0x70] = psxBios__bu_init;
2820 biosA0[0x71] = psxBios__96_init;
2821 biosA0[0x72] = psxBios__96_remove;
2822 //biosA0[0x73] = psxBios_sys_a0_73;
2823 //biosA0[0x74] = psxBios_sys_a0_74;
2824 //biosA0[0x75] = psxBios_sys_a0_75;
2825 //biosA0[0x76] = psxBios_sys_a0_76;
2826 //biosA0[0x77] = psxBios_sys_a0_77;
2827 //biosA0[0x78] = psxBios__96_CdSeekL;
2828 //biosA0[0x79] = psxBios_sys_a0_79;
2829 //biosA0[0x7a] = psxBios_sys_a0_7a;
2830 //biosA0[0x7b] = psxBios_sys_a0_7b;
2831 //biosA0[0x7c] = psxBios__96_CdGetStatus;
2832 //biosA0[0x7d] = psxBios_sys_a0_7d;
2833 //biosA0[0x7e] = psxBios__96_CdRead;
2834 //biosA0[0x7f] = psxBios_sys_a0_7f;
2835 //biosA0[0x80] = psxBios_sys_a0_80;
2836 //biosA0[0x81] = psxBios_sys_a0_81;
2837 //biosA0[0x82] = psxBios_sys_a0_82;
2838 //biosA0[0x83] = psxBios_sys_a0_83;
2839 //biosA0[0x84] = psxBios_sys_a0_84;
2840 //biosA0[0x85] = psxBios__96_CdStop;
2841 //biosA0[0x86] = psxBios_sys_a0_86;
2842 //biosA0[0x87] = psxBios_sys_a0_87;
2843 //biosA0[0x88] = psxBios_sys_a0_88;
2844 //biosA0[0x89] = psxBios_sys_a0_89;
2845 //biosA0[0x8a] = psxBios_sys_a0_8a;
2846 //biosA0[0x8b] = psxBios_sys_a0_8b;
2847 //biosA0[0x8c] = psxBios_sys_a0_8c;
2848 //biosA0[0x8d] = psxBios_sys_a0_8d;
2849 //biosA0[0x8e] = psxBios_sys_a0_8e;
2850 //biosA0[0x8f] = psxBios_sys_a0_8f;
2851 //biosA0[0x90] = psxBios_sys_a0_90;
2852 //biosA0[0x91] = psxBios_sys_a0_91;
2853 //biosA0[0x92] = psxBios_sys_a0_92;
2854 //biosA0[0x93] = psxBios_sys_a0_93;
2855 //biosA0[0x94] = psxBios_sys_a0_94;
2856 //biosA0[0x95] = psxBios_sys_a0_95;
2857 //biosA0[0x96] = psxBios_AddCDROMDevice;
2858 //biosA0[0x97] = psxBios_AddMemCardDevide;
2859 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
2860 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
2861 //biosA0[0x9a] = psxBios_sys_a0_9a;
2862 //biosA0[0x9b] = psxBios_sys_a0_9b;
2863 //biosA0[0x9c] = psxBios_SetConf;
2864 //biosA0[0x9d] = psxBios_GetConf;
2865 //biosA0[0x9e] = psxBios_sys_a0_9e;
2866 biosA0[0x9f] = psxBios_SetMem;
2867 //biosA0[0xa0] = psxBios__boot;
2868 //biosA0[0xa1] = psxBios_SystemError;
2869 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
2870 //biosA0[0xa3] = psxBios_DequeueCdIntr;
2871 //biosA0[0xa4] = psxBios_sys_a0_a4;
2872 //biosA0[0xa5] = psxBios_ReadSector;
18dd7e9e 2873 biosA0[0xa6] = psxBios_get_cd_status;
ef79bbde
P
2874 //biosA0[0xa7] = psxBios_bufs_cb_0;
2875 //biosA0[0xa8] = psxBios_bufs_cb_1;
2876 //biosA0[0xa9] = psxBios_bufs_cb_2;
2877 //biosA0[0xaa] = psxBios_bufs_cb_3;
2878 biosA0[0xab] = psxBios__card_info;
2879 biosA0[0xac] = psxBios__card_load;
2880 //biosA0[0axd] = psxBios__card_auto;
2881 //biosA0[0xae] = psxBios_bufs_cd_4;
2882 //biosA0[0xaf] = psxBios_sys_a0_af;
2883 //biosA0[0xb0] = psxBios_sys_a0_b0;
2884 //biosA0[0xb1] = psxBios_sys_a0_b1;
2885 //biosA0[0xb2] = psxBios_do_a_long_jmp
2886 //biosA0[0xb3] = psxBios_sys_a0_b3;
2887 //biosA0[0xb4] = psxBios_sub_function;
2888//*******************B0 CALLS****************************
2889 //biosB0[0x00] = psxBios_SysMalloc;
2890 //biosB0[0x01] = psxBios_sys_b0_01;
2891 biosB0[0x02] = psxBios_SetRCnt;
2892 biosB0[0x03] = psxBios_GetRCnt;
2893 biosB0[0x04] = psxBios_StartRCnt;
2894 biosB0[0x05] = psxBios_StopRCnt;
2895 biosB0[0x06] = psxBios_ResetRCnt;
2896 biosB0[0x07] = psxBios_DeliverEvent;
2897 biosB0[0x08] = psxBios_OpenEvent;
2898 biosB0[0x09] = psxBios_CloseEvent;
2899 biosB0[0x0a] = psxBios_WaitEvent;
2900 biosB0[0x0b] = psxBios_TestEvent;
2901 biosB0[0x0c] = psxBios_EnableEvent;
2902 biosB0[0x0d] = psxBios_DisableEvent;
2903 biosB0[0x0e] = psxBios_OpenTh;
2904 biosB0[0x0f] = psxBios_CloseTh;
2905 biosB0[0x10] = psxBios_ChangeTh;
2906 //biosB0[0x11] = psxBios_psxBios_b0_11;
2907 biosB0[0x12] = psxBios_InitPAD;
2908 biosB0[0x13] = psxBios_StartPAD;
2909 biosB0[0x14] = psxBios_StopPAD;
2910 biosB0[0x15] = psxBios_PAD_init;
2911 biosB0[0x16] = psxBios_PAD_dr;
2912 biosB0[0x17] = psxBios_ReturnFromException;
2913 biosB0[0x18] = psxBios_ResetEntryInt;
2914 biosB0[0x19] = psxBios_HookEntryInt;
2915 //biosB0[0x1a] = psxBios_sys_b0_1a;
2916 //biosB0[0x1b] = psxBios_sys_b0_1b;
2917 //biosB0[0x1c] = psxBios_sys_b0_1c;
2918 //biosB0[0x1d] = psxBios_sys_b0_1d;
2919 //biosB0[0x1e] = psxBios_sys_b0_1e;
2920 //biosB0[0x1f] = psxBios_sys_b0_1f;
2921 biosB0[0x20] = psxBios_UnDeliverEvent;
2922 //biosB0[0x21] = psxBios_sys_b0_21;
2923 //biosB0[0x22] = psxBios_sys_b0_22;
2924 //biosB0[0x23] = psxBios_sys_b0_23;
2925 //biosB0[0x24] = psxBios_sys_b0_24;
2926 //biosB0[0x25] = psxBios_sys_b0_25;
2927 //biosB0[0x26] = psxBios_sys_b0_26;
2928 //biosB0[0x27] = psxBios_sys_b0_27;
2929 //biosB0[0x28] = psxBios_sys_b0_28;
2930 //biosB0[0x29] = psxBios_sys_b0_29;
2931 //biosB0[0x2a] = psxBios_sys_b0_2a;
2932 //biosB0[0x2b] = psxBios_sys_b0_2b;
2933 //biosB0[0x2c] = psxBios_sys_b0_2c;
2934 //biosB0[0x2d] = psxBios_sys_b0_2d;
2935 //biosB0[0x2e] = psxBios_sys_b0_2e;
2936 //biosB0[0x2f] = psxBios_sys_b0_2f;
2937 //biosB0[0x30] = psxBios_sys_b0_30;
2938 //biosB0[0x31] = psxBios_sys_b0_31;
2939 biosB0[0x32] = psxBios_open;
2940 biosB0[0x33] = psxBios_lseek;
2941 biosB0[0x34] = psxBios_read;
2942 biosB0[0x35] = psxBios_write;
2943 biosB0[0x36] = psxBios_close;
2944 //biosB0[0x37] = psxBios_ioctl;
2945 //biosB0[0x38] = psxBios_exit;
2946 //biosB0[0x39] = psxBios_sys_b0_39;
2947 //biosB0[0x3a] = psxBios_getc;
2948 //biosB0[0x3b] = psxBios_putc;
2949 biosB0[0x3c] = psxBios_getchar;
2950 //biosB0[0x3e] = psxBios_gets;
2951 //biosB0[0x40] = psxBios_cd;
e7e1f572 2952 biosB0[0x41] = psxBios_format;
ef79bbde
P
2953 biosB0[0x42] = psxBios_firstfile;
2954 biosB0[0x43] = psxBios_nextfile;
2955 biosB0[0x44] = psxBios_rename;
2956 biosB0[0x45] = psxBios_delete;
2957 //biosB0[0x46] = psxBios_undelete;
2958 //biosB0[0x47] = psxBios_AddDevice;
2959 //biosB0[0x48] = psxBios_RemoteDevice;
2960 //biosB0[0x49] = psxBios_PrintInstalledDevices;
2961 biosB0[0x4a] = psxBios_InitCARD;
2962 biosB0[0x4b] = psxBios_StartCARD;
2963 biosB0[0x4c] = psxBios_StopCARD;
2964 //biosB0[0x4d] = psxBios_sys_b0_4d;
2965 biosB0[0x4e] = psxBios__card_write;
2966 biosB0[0x4f] = psxBios__card_read;
2967 biosB0[0x50] = psxBios__new_card;
2968 biosB0[0x51] = psxBios_Krom2RawAdd;
2969 //biosB0[0x52] = psxBios_sys_b0_52;
2970 //biosB0[0x53] = psxBios_sys_b0_53;
2971 //biosB0[0x54] = psxBios__get_errno;
002b2f7d 2972 biosB0[0x55] = psxBios__get_error;
ef79bbde
P
2973 biosB0[0x56] = psxBios_GetC0Table;
2974 biosB0[0x57] = psxBios_GetB0Table;
e9fda093 2975 biosB0[0x58] = psxBios__card_chan;
ef79bbde
P
2976 //biosB0[0x59] = psxBios_sys_b0_59;
2977 //biosB0[0x5a] = psxBios_sys_b0_5a;
2978 biosB0[0x5b] = psxBios_ChangeClearPad;
21af3ff6 2979 biosB0[0x5c] = psxBios__card_status;
5f652aa9 2980 biosB0[0x5d] = psxBios__card_wait;
ef79bbde
P
2981//*******************C0 CALLS****************************
2982 //biosC0[0x00] = psxBios_InitRCnt;
2983 //biosC0[0x01] = psxBios_InitException;
2984 biosC0[0x02] = psxBios_SysEnqIntRP;
2985 biosC0[0x03] = psxBios_SysDeqIntRP;
2986 //biosC0[0x04] = psxBios_get_free_EvCB_slot;
2987 //biosC0[0x05] = psxBios_get_free_TCB_slot;
2988 //biosC0[0x06] = psxBios_ExceptionHandler;
2989 //biosC0[0x07] = psxBios_InstallExeptionHandler;
2990 //biosC0[0x08] = psxBios_SysInitMemory;
2991 //biosC0[0x09] = psxBios_SysInitKMem;
2992 biosC0[0x0a] = psxBios_ChangeClearRCnt;
2993 //biosC0[0x0b] = psxBios_SystemError;
2994 //biosC0[0x0c] = psxBios_InitDefInt;
2995 //biosC0[0x0d] = psxBios_sys_c0_0d;
2996 //biosC0[0x0e] = psxBios_sys_c0_0e;
2997 //biosC0[0x0f] = psxBios_sys_c0_0f;
2998 //biosC0[0x10] = psxBios_sys_c0_10;
2999 //biosC0[0x11] = psxBios_sys_c0_11;
3000 //biosC0[0x12] = psxBios_InstallDevices;
3001 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3002 //biosC0[0x14] = psxBios_sys_c0_14;
3003 //biosC0[0x15] = psxBios__cdevinput;
3004 //biosC0[0x16] = psxBios__cdevscan;
3005 //biosC0[0x17] = psxBios__circgetc;
3006 //biosC0[0x18] = psxBios__circputc;
3007 //biosC0[0x19] = psxBios_ioabort;
3008 //biosC0[0x1a] = psxBios_sys_c0_1a
3009 //biosC0[0x1b] = psxBios_KernelRedirect;
3010 //biosC0[0x1c] = psxBios_PatchAOTable;
3011//************** THE END ***************************************
3012/**/
3013 base = 0x1000;
3014 size = sizeof(EvCB) * 32;
3015 Event = (void *)&psxR[base]; base += size * 6;
3016 memset(Event, 0, size * 6);
3017 HwEV = Event;
3018 EvEV = Event + 32;
3019 RcEV = Event + 32 * 2;
3020 UeEV = Event + 32 * 3;
3021 SwEV = Event + 32 * 4;
3022 ThEV = Event + 32 * 5;
3023
3024 ptr = (u32 *)&psxM[0x0874]; // b0 table
3025 ptr[0] = SWAPu32(0x4c54 - 0x884);
3026
3027 ptr = (u32 *)&psxM[0x0674]; // c0 table
3028 ptr[6] = SWAPu32(0xc80);
3029
3030 memset(SysIntRP, 0, sizeof(SysIntRP));
3031 memset(Thread, 0, sizeof(Thread));
3032 Thread[0].status = 2; // main thread
3033
832f0c3c 3034 pad_stopped = 1;
c62b43c9 3035 jmp_int = NULL;
3036 pad_buf = NULL;
3037 pad_buf1 = NULL;
3038 pad_buf2 = NULL;
3039 pad_buf1len = pad_buf2len = 0;
3040 heap_addr = NULL;
3041 heap_end = NULL;
26b964b5 3042 heap_size = 0;
c62b43c9 3043 CardState = -1;
3044 CurThread = 0;
3045 memset(FDesc, 0, sizeof(FDesc));
832f0c3c 3046 card_active_chan = 0;
c62b43c9 3047
ef79bbde
P
3048 psxMu32ref(0x0150) = SWAPu32(0x160);
3049 psxMu32ref(0x0154) = SWAPu32(0x320);
3050 psxMu32ref(0x0160) = SWAPu32(0x248);
3051 strcpy((char *)&psxM[0x248], "bu");
3052/* psxMu32ref(0x0ca8) = SWAPu32(0x1f410004);
3053 psxMu32ref(0x0cf0) = SWAPu32(0x3c020000);
3054 psxMu32ref(0x0cf4) = SWAPu32(0x2442641c);
3055 psxMu32ref(0x09e0) = SWAPu32(0x43d0);
3056 psxMu32ref(0x4d98) = SWAPu32(0x946f000a);
3057*/
3058 // opcode HLE
3059 psxRu32ref(0x0000) = SWAPu32((0x3b << 26) | 4);
bf643fd9 3060 /* Whatever this does, it actually breaks CTR, even without the uninitiliazed memory patch.
3061 Normally games shouldn't read from address 0 yet they do. See explanation below in details. */
3062 //psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0);
ef79bbde
P
3063 psxMu32ref(0x00a0) = SWAPu32((0x3b << 26) | 1);
3064 psxMu32ref(0x00b0) = SWAPu32((0x3b << 26) | 2);
3065 psxMu32ref(0x00c0) = SWAPu32((0x3b << 26) | 3);
3066 psxMu32ref(0x4c54) = SWAPu32((0x3b << 26) | 0);
3067 psxMu32ref(0x8000) = SWAPu32((0x3b << 26) | 5);
3068 psxMu32ref(0x07a0) = SWAPu32((0x3b << 26) | 0);
3069 psxMu32ref(0x0884) = SWAPu32((0x3b << 26) | 0);
3070 psxMu32ref(0x0894) = SWAPu32((0x3b << 26) | 0);
3071
3072 // initial stack pointer for BIOS interrupt
3073 psxMu32ref(0x6c80) = SWAPu32(0x000085c8);
3074
3075 // initial RNG seed
3076 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3077
3078 // fonts
3079 len = 0x80000 - 0x66000;
3080 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3081 len = 0x80000 - 0x69d68;
3082 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3083
3084 // memory size 2 MB
3085 psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3086
3087 hleSoftCall = FALSE;
bf643fd9 3088
3089 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3090 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
339cc5b6 3091 Here are some examples of games not working with this fix in place :
3092 R-type won't get past the Irem logo if not implemented.
3093 Crash Team Racing will softlock after the Sony logo.
bf643fd9 3094 */
339cc5b6 3095
3096 psxMu32ref(0x0000) = SWAPu32(0x00000003);
3097 /*
3098 But overwritten by 00000003h after soon.
3099 psxMu32ref(0x0000) = SWAPu32(0x00001A3C);
3100 */
3101 psxMu32ref(0x0004) = SWAPu32(0x800C5A27);
3102 psxMu32ref(0x0008) = SWAPu32(0x08000403);
3103 psxMu32ref(0x000C) = SWAPu32(0x00000000);
ef79bbde
P
3104}
3105
3106void psxBiosShutdown() {
3107}
3108
3109#define psxBios_PADpoll(pad) { \
3110 PAD##pad##_startPoll(pad); \
3111 pad_buf##pad[0] = 0; \
3112 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3113 if (!(pad_buf##pad[1] & 0x0f)) { \
3114 bufcount = 32; \
3115 } else { \
3116 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3117 } \
3118 PAD##pad##_poll(0); \
3119 i = 2; \
3120 while (bufcount--) { \
3121 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3122 } \
3123}
3124
3125void biosInterrupt() {
3126 int i, bufcount;
3127
3128// if (psxHu32(0x1070) & 0x1) { // Vsync
3129 if (pad_buf != NULL) {
3130 u32 *buf = (u32*)pad_buf;
3131
3132 if (!Config.UseNet) {
3133 PAD1_startPoll(1);
3134 if (PAD1_poll(0x42) == 0x23) {
3135 PAD1_poll(0);
3136 *buf = PAD1_poll(0) << 8;
3137 *buf |= PAD1_poll(0);
3138 PAD1_poll(0);
3139 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3140 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3141 } else {
3142 PAD1_poll(0);
3143 *buf = PAD1_poll(0) << 8;
3144 *buf|= PAD1_poll(0);
3145 }
3146
3147 PAD2_startPoll(2);
3148 if (PAD2_poll(0x42) == 0x23) {
3149 PAD2_poll(0);
3150 *buf |= PAD2_poll(0) << 24;
3151 *buf |= PAD2_poll(0) << 16;
3152 PAD2_poll(0);
3153 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3154 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3155 } else {
3156 PAD2_poll(0);
3157 *buf |= PAD2_poll(0) << 24;
3158 *buf |= PAD2_poll(0) << 16;
3159 }
3160 } else {
3161 u16 data;
3162
3163 PAD1_startPoll(1);
3164 PAD1_poll(0x42);
3165 PAD1_poll(0);
3166 data = PAD1_poll(0) << 8;
3167 data |= PAD1_poll(0);
3168
3169 if (NET_sendPadData(&data, 2) == -1)
3170 netError();
3171
3172 if (NET_recvPadData(&((u16*)buf)[0], 1) == -1)
3173 netError();
3174 if (NET_recvPadData(&((u16*)buf)[1], 2) == -1)
3175 netError();
3176 }
3177 }
3178 if (Config.UseNet && pad_buf1 != NULL && pad_buf2 != NULL) {
3179 psxBios_PADpoll(1);
3180
3181 if (NET_sendPadData(pad_buf1, i) == -1)
3182 netError();
3183
3184 if (NET_recvPadData(pad_buf1, 1) == -1)
3185 netError();
3186 if (NET_recvPadData(pad_buf2, 2) == -1)
3187 netError();
3188 } else {
f25c285b 3189 if (!pad_stopped) {
3190 if (pad_buf1) {
3191 psxBios_PADpoll(1);
3192 }
ef79bbde 3193
f25c285b 3194 if (pad_buf2) {
3195 psxBios_PADpoll(2);
3196 }
ef79bbde
P
3197 }
3198 }
3199
3200 if (psxHu32(0x1070) & 0x1) { // Vsync
3201 if (RcEV[3][1].status == EvStACTIVE) {
3202 softCall(RcEV[3][1].fhandler);
3203// hwWrite32(0x1f801070, ~(1));
3204 }
3205 }
3206
3207 if (psxHu32(0x1070) & 0x70) { // Rcnt 0,1,2
3208 int i;
3209
3210 for (i = 0; i < 3; i++) {
3211 if (psxHu32(0x1070) & (1 << (i + 4))) {
3212 if (RcEV[i][1].status == EvStACTIVE) {
3213 softCall(RcEV[i][1].fhandler);
3214 }
3215 psxHwWrite32(0x1f801070, ~(1 << (i + 4)));
3216 }
3217 }
3218 }
3219}
3220
3221void psxBiosException() {
3222 int i;
3223
3224 switch (psxRegs.CP0.n.Cause & 0x3c) {
3225 case 0x00: // Interrupt
f23c2241 3226 interrupt_r26=psxRegs.CP0.n.EPC;
ef79bbde
P
3227#ifdef PSXCPU_LOG
3228// PSXCPU_LOG("interrupt\n");
3229#endif
3230 SaveRegs();
3231
3232 sp = psxMu32(0x6c80); // create new stack for interrupt handlers
3233
3234 biosInterrupt();
3235
3236 for (i = 0; i < 8; i++) {
3237 if (SysIntRP[i]) {
3238 u32 *queue = (u32 *)PSXM(SysIntRP[i]);
3239
3240 s0 = queue[2];
3241 softCall(queue[1]);
3242 }
3243 }
3244
3245 if (jmp_int != NULL) {
3246 int i;
3247
3248 psxHwWrite32(0x1f801070, 0xffffffff);
3249
3250 ra = jmp_int[0];
3251 sp = jmp_int[1];
3252 fp = jmp_int[2];
3253 for (i = 0; i < 8; i++) // s0-s7
3254 psxRegs.GPR.r[16 + i] = jmp_int[3 + i];
3255 gp = jmp_int[11];
3256
3257 v0 = 1;
3258 pc0 = ra;
3259 return;
3260 }
3261 psxHwWrite16(0x1f801070, 0);
3262 break;
3263
3264 case 0x20: // Syscall
3265#ifdef PSXCPU_LOG
3266 PSXCPU_LOG("syscall exp %x\n", a0);
3267#endif
3268 switch (a0) {
3269 case 1: // EnterCritical - disable irq's
79dad1b3 3270 /* Fixes Medievil 2 not loading up new game, Digimon World not booting up and possibly others */
3271 v0 = (psxRegs.CP0.n.Status & 0x404) == 0x404;
3272 psxRegs.CP0.n.Status &= ~0x404;
ef79bbde
P
3273 break;
3274
3275 case 2: // ExitCritical - enable irq's
3276 psxRegs.CP0.n.Status |= 0x404;
3277 break;
a946d159 3278 /* Normally this should cover SYS(00h, SYS(04h but they don't do anything relevant so... */
3279 default:
3280 break;
ef79bbde
P
3281 }
3282 pc0 = psxRegs.CP0.n.EPC + 4;
3283
3284 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3285 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3286 return;
3287
3288 default:
3289#ifdef PSXCPU_LOG
3290 PSXCPU_LOG("unknown bios exception!\n");
3291#endif
3292 break;
3293 }
3294
3295 pc0 = psxRegs.CP0.n.EPC;
3296 if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;
3297
3298 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3299 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3300}
3301
3302#define bfreeze(ptr, size) { \
3303 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3304 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3305 base += size; \
3306}
3307
3308#define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3309#define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3310
3311#define bfreezepsxMptr(ptr, type) { \
3312 if (Mode == 1) { \
3313 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3314 else psxRu32ref(base) = 0; \
3315 } else { \
3316 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3317 else (ptr) = NULL; \
3318 } \
3319 base += sizeof(u32); \
3320}
3321
3322void psxBiosFreeze(int Mode) {
3323 u32 base = 0x40000;
3324
3325 bfreezepsxMptr(jmp_int, u32);
3326 bfreezepsxMptr(pad_buf, int);
3327 bfreezepsxMptr(pad_buf1, char);
3328 bfreezepsxMptr(pad_buf2, char);
3329 bfreezepsxMptr(heap_addr, u32);
3330 bfreezel(&pad_buf1len);
3331 bfreezel(&pad_buf2len);
3332 bfreezes(regs);
3333 bfreezes(SysIntRP);
3334 bfreezel(&CardState);
3335 bfreezes(Thread);
3336 bfreezel(&CurThread);
3337 bfreezes(FDesc);
e9fda093 3338 bfreezel(&card_active_chan);
a15f3544 3339 bfreezel(&pad_stopped);
17b2d969 3340 bfreezel(&heap_size);
ef79bbde 3341}