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