configure: rm some leftover
[pcsx_rearmed.git] / libpcsxcore / psxbios.c
... / ...
CommitLineData
1/***************************************************************************
2 * Copyright (C) 2019 Ryan Schultz, PCSX-df Team, PCSX team, gameblabla, *
3 * dmitrysmagin, senquack *
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
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
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"
35#include "gpu.h"
36#include "sio.h"
37#include "psxhle.h"
38#include <zlib.h>
39
40#if (defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)
41#pragma GCC diagnostic ignored "-Wpointer-sign"
42#endif
43
44#undef SysPrintf
45#define SysPrintf if (Config.PsxOut) printf
46
47char *biosA0n[256] = {
48// 0x00
49 "open", "lseek", "read", "write",
50 "close", "ioctl", "exit", "sys_a0_07",
51 "getc", "putc", "todigit", "atof",
52 "strtoul", "strtol", "abs", "labs",
53// 0x10
54 "atoi", "atol", "atob", "setjmp",
55 "longjmp", "strcat", "strncat", "strcmp",
56 "strncmp", "strcpy", "strncpy", "strlen",
57 "index", "rindex", "strchr", "strrchr",
58// 0x20
59 "strpbrk", "strspn", "strcspn", "strtok",
60 "strstr", "toupper", "tolower", "bcopy",
61 "bzero", "bcmp", "memcpy", "memset",
62 "memmove", "memcmp", "memchr", "rand",
63// 0x30
64 "srand", "qsort", "strtod", "malloc",
65 "free", "lsearch", "bsearch", "calloc",
66 "realloc", "InitHeap", "_exit", "getchar",
67 "putchar", "gets", "puts", "printf",
68// 0x40
69 "sys_a0_40", "LoadTest", "Load", "Exec",
70 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
71 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
72 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
73// 0x50
74 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
75 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
76 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
77 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
78// 0x60
79 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
80 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
81 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
82 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
83// 0x70
84 "_bu_init", "_96_init", "CdRemove", "sys_a0_73",
85 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
86 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
87 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
88// 0x80
89 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
90 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
91 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
92 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
93// 0x90
94 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
95 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
96 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
97 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
98// 0xa0
99 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
100 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
101 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
102 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
103// 0xb0
104 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
105 "?? sub_function",
106};
107
108char *biosB0n[256] = {
109// 0x00
110 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
111 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
112 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
113 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
114// 0x10
115 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
116 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
117 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
118 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
119// 0x20
120 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
121 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
122 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
123 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
124// 0x30
125 "sys_b0_30", "sys_b0_31", "open", "lseek",
126 "read", "write", "close", "ioctl",
127 "exit", "sys_b0_39", "getc", "putc",
128 "getchar", "putchar", "gets", "puts",
129// 0x40
130 "cd", "format", "firstfile", "nextfile",
131 "rename", "delete", "undelete", "AddDevice",
132 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
133 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
134// 0x50
135 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
136 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
137 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
138 "_card_status", "_card_wait",
139};
140
141char *biosC0n[256] = {
142// 0x00
143 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
144 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
145 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
146 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
147// 0x10
148 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
149 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
150 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
151 "PatchAOTable",
152};
153
154//#define r0 (psxRegs.GPR.n.r0)
155#define at (psxRegs.GPR.n.at)
156#define v0 (psxRegs.GPR.n.v0)
157#define v1 (psxRegs.GPR.n.v1)
158#define a0 (psxRegs.GPR.n.a0)
159#define a1 (psxRegs.GPR.n.a1)
160#define a2 (psxRegs.GPR.n.a2)
161#define a3 (psxRegs.GPR.n.a3)
162#define t0 (psxRegs.GPR.n.t0)
163#define t1 (psxRegs.GPR.n.t1)
164#define t2 (psxRegs.GPR.n.t2)
165#define t3 (psxRegs.GPR.n.t3)
166#define t4 (psxRegs.GPR.n.t4)
167#define t5 (psxRegs.GPR.n.t5)
168#define t6 (psxRegs.GPR.n.t6)
169#define t7 (psxRegs.GPR.n.t7)
170#define t8 (psxRegs.GPR.n.t8)
171#define t9 (psxRegs.GPR.n.t9)
172#define s0 (psxRegs.GPR.n.s0)
173#define s1 (psxRegs.GPR.n.s1)
174#define s2 (psxRegs.GPR.n.s2)
175#define s3 (psxRegs.GPR.n.s3)
176#define s4 (psxRegs.GPR.n.s4)
177#define s5 (psxRegs.GPR.n.s5)
178#define s6 (psxRegs.GPR.n.s6)
179#define s7 (psxRegs.GPR.n.s7)
180#define k0 (psxRegs.GPR.n.k0)
181#define k1 (psxRegs.GPR.n.k1)
182#define gp (psxRegs.GPR.n.gp)
183#define sp (psxRegs.GPR.n.sp)
184#define fp (psxRegs.GPR.n.s8)
185#define ra (psxRegs.GPR.n.ra)
186#define pc0 (psxRegs.pc)
187
188#define Ra0 ((char *)PSXM(a0))
189#define Ra1 ((char *)PSXM(a1))
190#define Ra2 ((char *)PSXM(a2))
191#define Ra3 ((char *)PSXM(a3))
192#define Rv0 ((char *)PSXM(v0))
193#define Rsp ((char *)PSXM(sp))
194
195typedef struct {
196 u32 class;
197 u32 status;
198 u32 spec;
199 u32 mode;
200 u32 fhandler;
201 u32 unused[2];
202} EvCB;
203
204#define EvStUNUSED 0x0000
205#define EvStDISABLED 0x1000
206#define EvStACTIVE 0x2000
207#define EvStALREADY 0x4000
208
209#define EvMdCALL 0x1000
210#define EvMdMARK 0x2000
211
212typedef struct {
213 u32 status;
214 u32 mode;
215 u32 reg[32];
216 u32 epc;
217 u32 hi, lo;
218 u32 sr, cause;
219 u32 unused[9];
220} TCB;
221
222typedef struct {
223 u32 _pc0;
224 u32 gp0;
225 u32 t_addr;
226 u32 t_size;
227 u32 d_addr;
228 u32 d_size;
229 u32 b_addr;
230 u32 b_size;
231 u32 S_addr;
232 u32 s_size;
233 u32 _sp, _fp, _gp, ret, base;
234} EXEC;
235
236struct DIRENTRY {
237 char name[20];
238 s32 attr;
239 s32 size;
240 u32 next;
241 s32 head;
242 char system[4];
243};
244
245typedef struct {
246 char name[32];
247 u32 mode;
248 u32 offset;
249 u32 size;
250 u32 mcfile;
251} FileDesc;
252
253static int *pad_buf = NULL;
254static u32 heap_size = 0;
255static u32 *heap_addr = NULL;
256static u32 *heap_end = NULL;
257static FileDesc FDesc[32];
258static u32 card_active_chan = 0;
259
260// fixed RAM offsets, SCPH1001 compatible
261#define A_TT_ExCB 0x0100
262#define A_TT_PCB 0x0108
263#define A_TT_TCB 0x0110
264#define A_TT_EvCB 0x0120
265#define A_A0_TABLE 0x0200
266#define A_B0_TABLE 0x0874
267#define A_C0_TABLE 0x0674
268#define A_SYSCALL 0x0650
269#define A_EXCEPTION 0x0c80
270#define A_EXC_SP 0x6cf0
271#define A_EEXIT_DEF 0x6cf4
272#define A_KMALLOC_PTR 0x7460
273#define A_KMALLOC_SIZE 0x7464
274#define A_KMALLOC_END 0x7468
275#define A_PADCRD_CHN_E 0x74a8 // pad/card irq chain entry
276#define A_PAD_IRQR_ENA 0x74b8 // pad read on vint irq (nocash 'pad_enable_flag')
277#define A_CARD_IRQR_ENA 0x74bc // same for card
278#define A_PAD_INBUF 0x74c8 // 2x buffers for rx pad data
279#define A_PAD_OUTBUF 0x74d0 // 2x buffers for tx pad data
280#define A_PAD_IN_LEN 0x74d8
281#define A_PAD_OUT_LEN 0x74e0
282#define A_EEXIT_PTR 0x75d0
283#define A_EXC_STACK 0x85d8 // exception stack top
284#define A_RCNT_VBL_ACK 0x8600
285#define A_PAD_ACK_VBL 0x8914 // enable vint ack by pad reading code
286#define A_CD_EVENTS 0xb9b8
287#define A_EXC_GP 0xf450
288
289#define HLEOP(n) SWAPu32((0x3b << 26) | (n));
290
291static u32 loadRam32(u32 addr)
292{
293 assert(!(addr & 0x5f800000));
294 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
295}
296
297static void *castRam8ptr(u32 addr)
298{
299 assert(!(addr & 0x5f800000));
300 return psxM + (addr & 0x1fffff);
301}
302
303static void *castRam32ptr(u32 addr)
304{
305 assert(!(addr & 0x5f800003));
306 return psxM + (addr & 0x1ffffc);
307}
308
309static void *loadRam8ptr(u32 addr)
310{
311 return castRam8ptr(loadRam32(addr));
312}
313
314static void *loadRam32ptr(u32 addr)
315{
316 return castRam32ptr(loadRam32(addr));
317}
318
319static void storeRam8(u32 addr, u8 d)
320{
321 assert(!(addr & 0x5f800000));
322 *((u8 *)psxM + (addr & 0x1fffff)) = d;
323}
324
325static void storeRam32(u32 addr, u32 d)
326{
327 assert(!(addr & 0x5f800000));
328 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
329}
330
331static void mips_return(u32 val)
332{
333 v0 = val;
334 pc0 = ra;
335}
336
337static void use_cycles(u32 cycle)
338{
339 psxRegs.cycle += cycle * 2;
340}
341
342static void mips_return_c(u32 val, u32 cycle)
343{
344 use_cycles(cycle);
345 mips_return(val);
346}
347
348static void mips_return_void_c(u32 cycle)
349{
350 use_cycles(cycle);
351 pc0 = ra;
352}
353
354static int returned_from_exception(void)
355{
356 // 0x80000080 means it took another exception just after return
357 return pc0 == k0 || pc0 == 0x80000080;
358}
359
360static inline void softCall(u32 pc) {
361 u32 sra = ra;
362 u32 ssr = psxRegs.CP0.n.SR;
363 pc0 = pc;
364 ra = 0x80001000;
365 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
366
367 while (pc0 != 0x80001000)
368 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
369
370 ra = sra;
371 psxRegs.CP0.n.SR = ssr;
372}
373
374static inline void softCallInException(u32 pc) {
375 u32 sra = ra;
376 pc0 = pc;
377 ra = 0x80001000;
378
379 while (!returned_from_exception() && pc0 != 0x80001000)
380 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
381
382 if (pc0 == 0x80001000)
383 ra = sra;
384}
385
386static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
387static u32 DeliverEvent(u32 class, u32 spec);
388static u32 UnDeliverEvent(u32 class, u32 spec);
389static void CloseEvent(u32 ev);
390
391/* *
392// *
393// *
394// System calls A0 */
395
396
397#define buread(Ra1, mcd, length) { \
398 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); \
399 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
400 memcpy(Ra1, ptr, length); \
401 if (FDesc[1 + mcd].mode & 0x8000) { \
402 DeliverEvent(0xf0000011, 0x0004); \
403 DeliverEvent(0xf4000001, 0x0004); \
404 v0 = 0; } \
405 else v0 = length; \
406 FDesc[1 + mcd].offset += v0; \
407}
408
409#define buwrite(Ra1, mcd, length) { \
410 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
411 SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
412 ptr = Mcd##mcd##Data + offset; \
413 memcpy(ptr, Ra1, length); \
414 FDesc[1 + mcd].offset += length; \
415 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
416 if (FDesc[1 + mcd].mode & 0x8000) { \
417 DeliverEvent(0xf0000011, 0x0004); \
418 DeliverEvent(0xf4000001, 0x0004); \
419 v0 = 0; } \
420 else v0 = length; \
421}
422
423#ifndef PSXBIOS_LOG
424//#define PSXBIOS_LOG printf
425#define PSXBIOS_LOG(...)
426#endif
427
428/* Internally redirects to "FileRead(fd,tempbuf,1)".*/
429/* For some strange reason, the returned character is sign-expanded; */
430/* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
431/* TODO FIX ME : Properly implement this behaviour */
432void psxBios_getc(void) // 0x03, 0x35
433{
434 char *ptr;
435 void *pa1 = Ra1;
436#ifdef PSXBIOS_LOG
437 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
438#endif
439 v0 = -1;
440
441 if (pa1 != INVALID_PTR) {
442 switch (a0) {
443 case 2: buread(pa1, 1, 1); break;
444 case 3: buread(pa1, 2, 1); break;
445 }
446 }
447
448 pc0 = ra;
449}
450
451/* Copy of psxBios_write, except size is 1. */
452void psxBios_putc(void) // 0x09, 0x3B
453{
454 char *ptr;
455 void *pa1 = Ra1;
456#ifdef PSXBIOS_LOG
457 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
458#endif
459 v0 = -1;
460 if (pa1 == INVALID_PTR) {
461 pc0 = ra;
462 return;
463 }
464
465 if (a0 == 1) { // stdout
466 char *ptr = (char *)pa1;
467
468 v0 = a2;
469 while (a2 > 0) {
470 printf("%c", *ptr++); a2--;
471 }
472 pc0 = ra; return;
473 }
474
475 switch (a0) {
476 case 2: buwrite(pa1, 1, 1); break;
477 case 3: buwrite(pa1, 2, 1); break;
478 }
479
480 pc0 = ra;
481}
482
483void psxBios_todigit(void) // 0x0a
484{
485 int c = a0;
486#ifdef PSXBIOS_LOG
487 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
488#endif
489 c &= 0xFF;
490 if (c >= 0x30 && c < 0x3A) {
491 c -= 0x30;
492 }
493 else if (c > 0x60 && c < 0x7B) {
494 c -= 0x20;
495 }
496 else if (c > 0x40 && c < 0x5B) {
497 c = c - 0x41 + 10;
498 }
499 else if (c >= 0x80) {
500 c = -1;
501 }
502 else
503 {
504 c = 0x0098967F;
505 }
506 v0 = c;
507 pc0 = ra;
508}
509
510void psxBios_abs() { // 0x0e
511 if ((s32)a0 < 0) v0 = -(s32)a0;
512 else v0 = a0;
513 pc0 = ra;
514}
515
516void psxBios_labs() { // 0x0f
517 psxBios_abs();
518}
519
520void psxBios_atoi() { // 0x10
521 s32 n = 0, f = 0;
522 char *p = (char *)Ra0;
523
524 for (;;p++) {
525 switch (*p) {
526 case ' ': case '\t': continue;
527 case '-': f++;
528 case '+': p++;
529 }
530 break;
531 }
532
533 while (*p >= '0' && *p <= '9') {
534 n = n * 10 + *p++ - '0';
535 }
536
537 v0 = (f ? -n : n);
538 pc0 = ra;
539}
540
541void psxBios_atol() { // 0x11
542 psxBios_atoi();
543}
544
545struct jmp_buf_ {
546 u32 ra_, sp_, fp_;
547 u32 s[8];
548 u32 gp_;
549};
550
551static void psxBios_setjmp() { // 0x13
552 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
553 int i;
554
555 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
556
557 jmp_buf->ra_ = SWAP32(ra);
558 jmp_buf->sp_ = SWAP32(sp);
559 jmp_buf->fp_ = SWAP32(fp);
560 for (i = 0; i < 8; i++) // s0-s7
561 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
562 jmp_buf->gp_ = SWAP32(gp);
563
564 mips_return_c(0, 15);
565}
566
567static void longjmp_load(const struct jmp_buf_ *jmp_buf)
568{
569 int i;
570
571 ra = SWAP32(jmp_buf->ra_);
572 sp = SWAP32(jmp_buf->sp_);
573 fp = SWAP32(jmp_buf->fp_);
574 for (i = 0; i < 8; i++) // s0-s7
575 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
576 gp = SWAP32(jmp_buf->gp_);;
577}
578
579void psxBios_longjmp() { // 0x14
580 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
581
582 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
583 longjmp_load(jmp_buf);
584 mips_return_c(a1, 15);
585}
586
587void psxBios_strcat() { // 0x15
588 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
589
590#ifdef PSXBIOS_LOG
591 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
592#endif
593 if (a0 == 0 || a1 == 0)
594 {
595 v0 = 0;
596 pc0 = ra;
597 return;
598 }
599 while (*p1++);
600 --p1;
601 while ((*p1++ = *p2++) != '\0');
602
603 v0 = a0; pc0 = ra;
604}
605
606void psxBios_strncat() { // 0x16
607 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
608 s32 n = a2;
609
610#ifdef PSXBIOS_LOG
611 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
612#endif
613 if (a0 == 0 || a1 == 0)
614 {
615 v0 = 0;
616 pc0 = ra;
617 return;
618 }
619 while (*p1++);
620 --p1;
621 while ((*p1++ = *p2++) != '\0') {
622 if (--n < 0) {
623 *--p1 = '\0';
624 break;
625 }
626 }
627
628 v0 = a0; pc0 = ra;
629}
630
631void psxBios_strcmp() { // 0x17
632 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
633 s32 n=0;
634 if (a0 == 0 && a1 == 0)
635 {
636 v0 = 0;
637 pc0 = ra;
638 return;
639 }
640 else if (a0 == 0 && a1 != 0)
641 {
642 v0 = -1;
643 pc0 = ra;
644 return;
645 }
646 else if (a0 != 0 && a1 == 0)
647 {
648 v0 = 1;
649 pc0 = ra;
650 return;
651 }
652#ifdef PSXBIOS_LOG
653 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
654#endif
655
656 while (*p1 == *p2++) {
657 n++;
658 if (*p1++ == '\0') {
659 v1=n-1;
660 a0+=n;
661 a1+=n;
662 v0 = 0;
663 pc0 = ra;
664 return;
665 }
666 }
667
668 v0 = (*p1 - *--p2);
669 v1 = n;
670 a0+=n;
671 a1+=n;
672 pc0 = ra;
673}
674
675void psxBios_strncmp() { // 0x18
676 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
677 s32 n = a2;
678 if (a0 == 0 && a1 == 0)
679 {
680 v0 = 0;
681 pc0 = ra;
682 return;
683 }
684 else if (a0 == 0 && a1 != 0)
685 {
686 v0 = -1;
687 pc0 = ra;
688 return;
689 }
690 else if (a0 != 0 && a1 == 0)
691 {
692 v0 = 1;
693 pc0 = ra;
694 return;
695 }
696#ifdef PSXBIOS_LOG
697 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
698#endif
699
700 while (--n >= 0 && *p1 == *p2++) {
701 if (*p1++ == '\0') {
702 v0 = 0;
703 pc0 = ra;
704 v1 = a2 - ((a2-n) - 1);
705 a0 += (a2-n) - 1;
706 a1 += (a2-n) - 1;
707 a2 = n;
708 return;
709 }
710 }
711
712 v0 = (n < 0 ? 0 : *p1 - *--p2);
713 pc0 = ra;
714 v1 = a2 - ((a2-n) - 1);
715 a0 += (a2-n) - 1;
716 a1 += (a2-n) - 1;
717 a2 = n;
718}
719
720void psxBios_strcpy() { // 0x19
721 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
722 if (a0 == 0 || a1 == 0)
723 {
724 v0 = 0;
725 pc0 = ra;
726 return;
727 }
728 while ((*p1++ = *p2++) != '\0');
729
730 v0 = a0; pc0 = ra;
731}
732
733void psxBios_strncpy() { // 0x1a
734 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
735 s32 n = a2, i;
736 if (a0 == 0 || a1 == 0)
737 {
738 v0 = 0;
739 pc0 = ra;
740 return;
741 }
742 for (i = 0; i < n; i++) {
743 if ((*p1++ = *p2++) == '\0') {
744 while (++i < n) {
745 *p1++ = '\0';
746 }
747 v0 = a0; pc0 = ra;
748 return;
749 }
750 }
751
752 v0 = a0; pc0 = ra;
753}
754
755void psxBios_strlen() { // 0x1b
756 char *p = (char *)Ra0;
757 v0 = 0;
758 if (a0 == 0)
759 {
760 pc0 = ra;
761 return;
762 }
763 while (*p++) v0++;
764 pc0 = ra;
765}
766
767void psxBios_index() { // 0x1c
768 char *p = (char *)Ra0;
769 if (a0 == 0)
770 {
771 v0 = 0;
772 pc0 = ra;
773 return;
774 }
775
776 do {
777 if (*p == a1) {
778 v0 = a0 + (p - (char *)Ra0);
779 pc0 = ra;
780 return;
781 }
782 } while (*p++ != '\0');
783
784 v0 = 0; pc0 = ra;
785}
786
787void psxBios_rindex() { // 0x1d
788 char *p = (char *)Ra0;
789
790 v0 = 0;
791 if (a0 == 0)
792 {
793 pc0 = ra;
794 return;
795 }
796 do {
797 if (*p == a1)
798 v0 = a0 + (p - (char *)Ra0);
799 } while (*p++ != '\0');
800
801 pc0 = ra;
802}
803
804void psxBios_strchr() { // 0x1e
805 psxBios_index();
806}
807
808void psxBios_strrchr() { // 0x1f
809 psxBios_rindex();
810}
811
812void psxBios_strpbrk() { // 0x20
813 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
814
815 while ((c = *p1++) != '\0') {
816 for (scanp = p2; (sc = *scanp++) != '\0';) {
817 if (sc == c) {
818 v0 = a0 + (p1 - 1 - (char *)Ra0);
819 pc0 = ra;
820 return;
821 }
822 }
823 }
824
825 // BUG: return a0 instead of NULL if not found
826 v0 = a0; pc0 = ra;
827}
828
829void psxBios_strspn() { // 0x21
830 char *p1, *p2;
831
832 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
833 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
834 if (*p2 == '\0') break;
835 }
836
837 v0 = p1 - (char *)Ra0; pc0 = ra;
838}
839
840void psxBios_strcspn() { // 0x22
841 char *p1, *p2;
842
843 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
844 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
845 if (*p2 != '\0') break;
846 }
847
848 v0 = p1 - (char *)Ra0; pc0 = ra;
849}
850
851void psxBios_strtok() { // 0x23
852 char *pcA0 = (char *)Ra0;
853 char *pcRet = strtok(pcA0, (char *)Ra1);
854 if (pcRet)
855 v0 = a0 + pcRet - pcA0;
856 else
857 v0 = 0;
858 pc0 = ra;
859}
860
861void psxBios_strstr() { // 0x24
862 char *p = (char *)Ra0, *p1, *p2;
863
864 while (*p != '\0') {
865 p1 = p;
866 p2 = (char *)Ra1;
867
868 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
869 p1++; p2++;
870 }
871
872 if (*p2 == '\0') {
873 v0 = a0 + (p - (char *)Ra0);
874 pc0 = ra;
875 return;
876 }
877
878 p++;
879 }
880
881 v0 = 0; pc0 = ra;
882}
883
884void psxBios_toupper() { // 0x25
885 v0 = (s8)(a0 & 0xff);
886 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
887 pc0 = ra;
888}
889
890void psxBios_tolower() { // 0x26
891 v0 = (s8)(a0 & 0xff);
892 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
893 pc0 = ra;
894}
895
896void psxBios_bcopy() { // 0x27
897 char *p1 = (char *)Ra1, *p2 = (char *)Ra0;
898 v0 = a0;
899 if (a0 == 0 || a2 > 0x7FFFFFFF)
900 {
901 pc0 = ra;
902 return;
903 }
904 while ((s32)a2-- > 0) *p1++ = *p2++;
905 a2 = 0;
906 pc0 = ra;
907}
908
909void psxBios_bzero() { // 0x28
910 char *p = (char *)Ra0;
911 v0 = a0;
912 /* Same as memset here (See memset below) */
913 if (a1 > 0x7FFFFFFF || a1 == 0)
914 {
915 v0 = 0;
916 pc0 = ra;
917 return;
918 }
919 else if (a0 == 0)
920 {
921 pc0 = ra;
922 return;
923 }
924 while ((s32)a1-- > 0) *p++ = '\0';
925 a1 = 0;
926 pc0 = ra;
927}
928
929void psxBios_bcmp() { // 0x29
930 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
931
932 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
933
934 while ((s32)a2-- > 0) {
935 if (*p1++ != *p2++) {
936 v0 = *p1 - *p2; // BUG: compare the NEXT byte
937 pc0 = ra;
938 return;
939 }
940 }
941
942 v0 = 0; pc0 = ra;
943}
944
945void psxBios_memcpy() { // 0x2a
946 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
947 v0 = a0;
948 if (a0 == 0 || a2 > 0x7FFFFFFF)
949 {
950 pc0 = ra;
951 return;
952 }
953 while ((s32)a2-- > 0) {
954 *p1++ = *p2++;
955 }
956 a2 = 0;
957 pc0 = ra;
958}
959
960void psxBios_memset() { // 0x2b
961 char *p = (char *)Ra0;
962 v0 = a0;
963 if (a2 > 0x7FFFFFFF || a2 == 0)
964 {
965 v0 = 0;
966 pc0 = ra;
967 return;
968 }
969 if (a0 == 0)
970 {
971 pc0 = ra;
972 return;
973 }
974 while ((s32)a2-- > 0) *p++ = (char)a1;
975 a2 = 0;
976 v0 = a0; pc0 = ra;
977}
978
979void psxBios_memmove() { // 0x2c
980 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
981 v0 = a0;
982 if (a0 == 0 || a2 > 0x7FFFFFFF)
983 {
984 pc0 = ra;
985 return;
986 }
987 if (p2 <= p1 && p2 + a2 > p1) {
988 a2++; // BUG: copy one more byte here
989 p1 += a2;
990 p2 += a2;
991 while ((s32)a2-- > 0) *--p1 = *--p2;
992 } else {
993 while ((s32)a2-- > 0) *p1++ = *p2++;
994 }
995 pc0 = ra;
996}
997
998void psxBios_memcmp() { // 0x2d
999 psxBios_bcmp();
1000}
1001
1002void psxBios_memchr() { // 0x2e
1003 char *p = (char *)Ra0;
1004
1005 if (a0 == 0 || a2 > 0x7FFFFFFF)
1006 {
1007 pc0 = ra;
1008 return;
1009 }
1010
1011 while ((s32)a2-- > 0) {
1012 if (*p++ != (s8)a1) continue;
1013 v0 = a0 + (p - (char *)Ra0 - 1);
1014 pc0 = ra;
1015 return;
1016 }
1017
1018 v0 = 0; pc0 = ra;
1019}
1020
1021void psxBios_rand() { // 0x2f
1022 u32 s = psxMu32(0x9010) * 1103515245 + 12345;
1023 v0 = (s >> 16) & 0x7fff;
1024 psxMu32ref(0x9010) = SWAPu32(s);
1025 pc0 = ra;
1026}
1027
1028void psxBios_srand() { // 0x30
1029 psxMu32ref(0x9010) = SWAPu32(a0);
1030 pc0 = ra;
1031}
1032
1033static u32 qscmpfunc, qswidth;
1034
1035static inline int qscmp(char *a, char *b) {
1036 u32 sa0 = a0;
1037
1038 a0 = sa0 + (a - (char *)PSXM(sa0));
1039 a1 = sa0 + (b - (char *)PSXM(sa0));
1040
1041 softCall(qscmpfunc);
1042
1043 a0 = sa0;
1044 return (s32)v0;
1045}
1046
1047static inline void qexchange(char *i, char *j) {
1048 char t;
1049 int n = qswidth;
1050
1051 do {
1052 t = *i;
1053 *i++ = *j;
1054 *j++ = t;
1055 } while (--n);
1056}
1057
1058static inline void q3exchange(char *i, char *j, char *k) {
1059 char t;
1060 int n = qswidth;
1061
1062 do {
1063 t = *i;
1064 *i++ = *k;
1065 *k++ = *j;
1066 *j++ = t;
1067 } while (--n);
1068}
1069
1070static void qsort_main(char *a, char *l) {
1071 char *i, *j, *lp, *hp;
1072 int c;
1073 unsigned int n;
1074
1075start:
1076 if ((n = l - a) <= qswidth)
1077 return;
1078 n = qswidth * (n / (2 * qswidth));
1079 hp = lp = a + n;
1080 i = a;
1081 j = l - qswidth;
1082 while (TRUE) {
1083 if (i < lp) {
1084 if ((c = qscmp(i, lp)) == 0) {
1085 qexchange(i, lp -= qswidth);
1086 continue;
1087 }
1088 if (c < 0) {
1089 i += qswidth;
1090 continue;
1091 }
1092 }
1093
1094loop:
1095 if (j > hp) {
1096 if ((c = qscmp(hp, j)) == 0) {
1097 qexchange(hp += qswidth, j);
1098 goto loop;
1099 }
1100 if (c > 0) {
1101 if (i == lp) {
1102 q3exchange(i, hp += qswidth, j);
1103 i = lp += qswidth;
1104 goto loop;
1105 }
1106 qexchange(i, j);
1107 j -= qswidth;
1108 i += qswidth;
1109 continue;
1110 }
1111 j -= qswidth;
1112 goto loop;
1113 }
1114
1115 if (i == lp) {
1116 if (lp - a >= l - hp) {
1117 qsort_main(hp + qswidth, l);
1118 l = lp;
1119 } else {
1120 qsort_main(a, lp);
1121 a = hp + qswidth;
1122 }
1123 goto start;
1124 }
1125
1126 q3exchange(j, lp -= qswidth, i);
1127 j = hp -= qswidth;
1128 }
1129}
1130
1131void psxBios_qsort() { // 0x31
1132 qswidth = a2;
1133 qscmpfunc = a3;
1134 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1135
1136 pc0 = ra;
1137}
1138
1139void psxBios_malloc() { // 0x33
1140 u32 *chunk, *newchunk = NULL;
1141 unsigned int dsize = 0, csize, cstat;
1142 int colflag;
1143#ifdef PSXBIOS_LOG
1144 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]);
1145#endif
1146 if (!a0 || (!heap_size || !heap_addr)) {
1147 v0 = 0;
1148 pc0 = ra;
1149 return;
1150 }
1151
1152 // scan through heap and combine free chunks of space
1153 chunk = heap_addr;
1154 colflag = 0;
1155 while(chunk < heap_end) {
1156 // get size and status of actual chunk
1157 csize = ((u32)*chunk) & 0xfffffffc;
1158 cstat = ((u32)*chunk) & 1;
1159
1160 // most probably broken heap descriptor
1161 // this fixes Burning Road
1162 if (*chunk == 0) {
1163 newchunk = chunk;
1164 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1165 colflag = 1;
1166 break;
1167 }
1168
1169 // it's a free chunk
1170 if(cstat == 1) {
1171 if(colflag == 0) {
1172 newchunk = chunk;
1173 dsize = csize;
1174 colflag = 1; // let's begin a new collection of free memory
1175 }
1176 else dsize += (csize+4); // add the new size including header
1177 }
1178 // not a free chunk: did we start a collection ?
1179 else {
1180 if(colflag == 1) { // collection is over
1181 colflag = 0;
1182 *newchunk = SWAP32(dsize | 1);
1183 }
1184 }
1185
1186 // next chunk
1187 chunk = (u32*)((uptr)chunk + csize + 4);
1188 }
1189 // if neccessary free memory on end of heap
1190 if (colflag == 1)
1191 *newchunk = SWAP32(dsize | 1);
1192
1193 chunk = heap_addr;
1194 csize = ((u32)*chunk) & 0xfffffffc;
1195 cstat = ((u32)*chunk) & 1;
1196 dsize = (a0 + 3) & 0xfffffffc;
1197
1198 // exit on uninitialized heap
1199 if (chunk == NULL) {
1200 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1201 v0 = 0;
1202 pc0 = ra;
1203 return;
1204 }
1205
1206 // search an unused chunk that is big enough until the end of the heap
1207 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1208 chunk = (u32*)((uptr)chunk + csize + 4);
1209
1210 // catch out of memory
1211 if(chunk >= heap_end) {
1212 printf("malloc %x,%x: Out of memory error!\n",
1213 v0, a0);
1214 v0 = 0; pc0 = ra;
1215 return;
1216 }
1217
1218 csize = ((u32)*chunk) & 0xfffffffc;
1219 cstat = ((u32)*chunk) & 1;
1220 }
1221
1222 // allocate memory
1223 if(dsize == csize) {
1224 // chunk has same size
1225 *chunk &= 0xfffffffc;
1226 } else if (dsize > csize) {
1227 v0 = 0; pc0 = ra;
1228 return;
1229 } else {
1230 // split free chunk
1231 *chunk = SWAP32(dsize);
1232 newchunk = (u32*)((uptr)chunk + dsize + 4);
1233 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1234 }
1235
1236 // return pointer to allocated memory
1237 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1238 v0|= 0x80000000;
1239 //printf ("malloc %x,%x\n", v0, a0);
1240 pc0 = ra;
1241}
1242
1243void psxBios_free() { // 0x34
1244
1245#ifdef PSXBIOS_LOG
1246 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x34]);
1247#endif
1248
1249 SysPrintf("free %x: %x bytes\n", a0, *(u32*)(Ra0-4));
1250
1251 if (a0)
1252 *(u32*)(Ra0-4) |= 1; // set chunk to free
1253 pc0 = ra;
1254}
1255
1256void psxBios_calloc() { // 0x37
1257 void *pv0;
1258#ifdef PSXBIOS_LOG
1259 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]);
1260#endif
1261
1262 a0 = a0 * a1;
1263 psxBios_malloc();
1264 pv0 = Rv0;
1265 if (pv0)
1266 memset(pv0, 0, a0);
1267}
1268
1269void psxBios_realloc() { // 0x38
1270 u32 block = a0;
1271 u32 size = a1;
1272#ifdef PSXBIOS_LOG
1273 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1274#endif
1275
1276 a0 = block;
1277 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1278 if (block == 0)
1279 {
1280 psxBios_malloc();
1281 }
1282 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1283 else if (size == 0)
1284 {
1285 psxBios_free();
1286 }
1287 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1288 /* Note that it is not quite implemented this way here. */
1289 else
1290 {
1291 psxBios_free();
1292 a0 = size;
1293 psxBios_malloc();
1294 }
1295}
1296
1297
1298/* InitHeap(void *block , int n) */
1299void psxBios_InitHeap() { // 0x39
1300 unsigned int size;
1301
1302#ifdef PSXBIOS_LOG
1303 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x39]);
1304#endif
1305
1306 if (((a0 & 0x1fffff) + a1)>= 0x200000) size = 0x1ffffc - (a0 & 0x1fffff);
1307 else size = a1;
1308
1309 size &= 0xfffffffc;
1310
1311 heap_addr = (u32 *)Ra0;
1312 heap_size = size;
1313 heap_end = (u32 *)((u8 *)heap_addr + heap_size);
1314 /* HACKFIX: Commenting out this line fixes GTA2 crash */
1315 //*heap_addr = SWAP32(size | 1);
1316
1317 SysPrintf("InitHeap %x,%x : %x %x\n",a0,a1, (int)((uptr)heap_addr-(uptr)psxM), size);
1318
1319 pc0 = ra;
1320}
1321
1322void psxBios_getchar() { //0x3b
1323 v0 = getchar(); pc0 = ra;
1324}
1325
1326static void psxBios_printf_psxout() { // 0x3f
1327 char tmp[1024];
1328 char tmp2[1024];
1329 u32 save[4];
1330 char *ptmp = tmp;
1331 int n=1, i=0, j;
1332 void *psp;
1333
1334 psp = PSXM(sp);
1335 if (psp != INVALID_PTR) {
1336 memcpy(save, psp, 4 * 4);
1337 psxMu32ref(sp) = SWAP32((u32)a0);
1338 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1339 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1340 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1341 }
1342
1343 while (Ra0[i]) {
1344 switch (Ra0[i]) {
1345 case '%':
1346 j = 0;
1347 tmp2[j++] = '%';
1348_start:
1349 switch (Ra0[++i]) {
1350 case '.':
1351 case 'l':
1352 tmp2[j++] = Ra0[i]; goto _start;
1353 default:
1354 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1355 tmp2[j++] = Ra0[i];
1356 goto _start;
1357 }
1358 break;
1359 }
1360 tmp2[j++] = Ra0[i];
1361 tmp2[j] = 0;
1362
1363 switch (Ra0[i]) {
1364 case 'f': case 'F':
1365 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1366 case 'a': case 'A':
1367 case 'e': case 'E':
1368 case 'g': case 'G':
1369 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1370 case 'p':
1371 case 'i': case 'u':
1372 case 'd': case 'D':
1373 case 'o': case 'O':
1374 case 'x': case 'X':
1375 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1376 case 'c':
1377 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1378 case 's':
1379 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1380 case '%':
1381 *ptmp++ = Ra0[i]; break;
1382 }
1383 i++;
1384 break;
1385 default:
1386 *ptmp++ = Ra0[i++];
1387 }
1388 }
1389 *ptmp = 0;
1390
1391 if (psp != INVALID_PTR)
1392 memcpy(psp, save, 4 * 4);
1393
1394 SysPrintf("%s", tmp);
1395}
1396
1397void psxBios_printf() { // 0x3f
1398 psxBios_printf_psxout();
1399 pc0 = ra;
1400}
1401
1402void psxBios_format() { // 0x41
1403 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1404 {
1405 CreateMcd(Config.Mcd1);
1406 LoadMcd(1, Config.Mcd1);
1407 v0 = 1;
1408 }
1409 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1410 {
1411 CreateMcd(Config.Mcd2);
1412 LoadMcd(2, Config.Mcd2);
1413 v0 = 1;
1414 }
1415 else
1416 {
1417 v0 = 0;
1418 }
1419 pc0 = ra;
1420}
1421
1422static void psxBios_SystemErrorUnresolvedException() {
1423 if (loadRam32(0xfffc) != 0x12345678) { // prevent log flood
1424 SysPrintf("psxBios_%s\n", biosA0n[0x40]);
1425 storeRam32(0xfffc, 0x12345678);
1426 }
1427 mips_return_void_c(1000);
1428}
1429
1430/*
1431 * long Load(char *name, struct EXEC *header);
1432 */
1433
1434void psxBios_Load() { // 0x42
1435 EXE_HEADER eheader;
1436 void *pa1;
1437
1438 pa1 = Ra1;
1439 if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
1440 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1441 v0 = 1;
1442 } else v0 = 0;
1443 PSXBIOS_LOG("psxBios_%s: %s, %d -> %d\n", biosA0n[0x42], Ra0, a1, v0);
1444
1445 pc0 = ra;
1446}
1447
1448/*
1449 * int Exec(struct EXEC *header , int argc , char **argv);
1450 */
1451
1452void psxBios_Exec() { // 43
1453 EXEC *header = (EXEC*)Ra0;
1454 u32 tmp;
1455
1456#ifdef PSXBIOS_LOG
1457 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1458#endif
1459
1460 header->_sp = sp;
1461 header->_fp = fp;
1462 header->_sp = sp;
1463 header->_gp = gp;
1464 header->ret = ra;
1465 header->base = s0;
1466
1467 if (header->S_addr != 0) {
1468 tmp = header->S_addr + header->s_size;
1469 sp = tmp;
1470 fp = sp;
1471 }
1472
1473 gp = header->gp0;
1474
1475 s0 = a0;
1476
1477 a0 = a1;
1478 a1 = a2;
1479
1480 ra = 0x8000;
1481 pc0 = header->_pc0;
1482}
1483
1484void psxBios_FlushCache() { // 44
1485#ifdef PSXBIOS_LOG
1486 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1487#endif
1488 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1489 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1490 pc0 = ra;
1491}
1492
1493void psxBios_GPU_dw() { // 0x46
1494 int size;
1495 u32 *ptr;
1496
1497#ifdef PSXBIOS_LOG
1498 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1499#endif
1500
1501 GPU_writeData(0xa0000000);
1502 GPU_writeData((a1<<0x10)|(a0&0xffff));
1503 GPU_writeData((a3<<0x10)|(a2&0xffff));
1504 size = (a2*a3)/2;
1505 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1506 while(size--)
1507 {
1508 GPU_writeData(SWAPu32(*ptr++));
1509 }
1510
1511 pc0 = ra;
1512}
1513
1514void psxBios_mem2vram() { // 0x47
1515 int size;
1516 gpuSyncPluginSR();
1517 GPU_writeData(0xa0000000);
1518 GPU_writeData((a1<<0x10)|(a0&0xffff));
1519 GPU_writeData((a3<<0x10)|(a2&0xffff));
1520 size = ((((a2 * a3) / 2) >> 4) << 16);
1521 GPU_writeStatus(0x04000002);
1522 psxHwWrite32(0x1f8010f4,0);
1523 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1524 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1525 psxHwWrite32(0x1f8010a4, size | 0x10);
1526 psxHwWrite32(0x1f8010a8,0x01000201);
1527
1528 pc0 = ra;
1529}
1530
1531void psxBios_SendGPU() { // 0x48
1532 GPU_writeStatus(a0);
1533 gpuSyncPluginSR();
1534 pc0 = ra;
1535}
1536
1537void psxBios_GPU_cw() { // 0x49
1538 gpuSyncPluginSR();
1539 GPU_writeData(a0);
1540 v0 = HW_GPU_STATUS;
1541 pc0 = ra;
1542}
1543
1544void psxBios_GPU_cwb() { // 0x4a
1545 u32 *ptr = (u32*)Ra0;
1546 int size = a1;
1547 gpuSyncPluginSR();
1548 while(size--)
1549 {
1550 GPU_writeData(SWAPu32(*ptr++));
1551 }
1552
1553 pc0 = ra;
1554}
1555
1556void psxBios_GPU_SendPackets() { //4b:
1557 gpuSyncPluginSR();
1558 GPU_writeStatus(0x04000002);
1559 psxHwWrite32(0x1f8010f4,0);
1560 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1561 psxHwWrite32(0x1f8010a0,a0);
1562 psxHwWrite32(0x1f8010a4,0);
1563 psxHwWrite32(0x1f8010a8,0x010000401);
1564 pc0 = ra;
1565}
1566
1567void psxBios_sys_a0_4c() { // 0x4c GPU relate
1568 psxHwWrite32(0x1f8010a8,0x00000401);
1569 GPU_writeData(0x0400000);
1570 GPU_writeData(0x0200000);
1571 GPU_writeData(0x0100000);
1572 v0 = 0x1f801814;
1573 pc0 = ra;
1574}
1575
1576void psxBios_GPU_GetGPUStatus() { // 0x4d
1577 v0 = GPU_readStatus();
1578 pc0 = ra;
1579}
1580
1581#undef s_addr
1582
1583void psxBios_LoadExec() { // 51
1584 EXEC *header = (EXEC*)PSXM(0xf000);
1585 u32 s_addr, s_size;
1586
1587#ifdef PSXBIOS_LOG
1588 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1589#endif
1590 s_addr = a1; s_size = a2;
1591
1592 a1 = 0xf000;
1593 psxBios_Load();
1594
1595 header->S_addr = s_addr;
1596 header->s_size = s_size;
1597
1598 a0 = 0xf000; a1 = 0; a2 = 0;
1599 psxBios_Exec();
1600}
1601
1602void psxBios__bu_init() { // 70
1603#ifdef PSXBIOS_LOG
1604 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1605#endif
1606
1607 DeliverEvent(0xf0000011, 0x0004);
1608 DeliverEvent(0xf4000001, 0x0004);
1609
1610 pc0 = ra;
1611}
1612
1613void psxBios__96_init() { // 71
1614#ifdef PSXBIOS_LOG
1615 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1616#endif
1617
1618 pc0 = ra;
1619}
1620
1621static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1622static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1623static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1624
1625static void psxBios_DequeueCdIntr_() {
1626 psxBios_SysDeqIntRP_(0, 0x91d0);
1627 psxBios_SysDeqIntRP_(0, 0x91e0);
1628 use_cycles(16);
1629}
1630
1631static void psxBios_DequeueCdIntr() { // a3
1632 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1633 psxBios_DequeueCdIntr_();
1634}
1635
1636static void psxBios_CdRemove() { // 56, 72
1637 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1638
1639 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1640 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1641 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1642 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1643 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1644 psxBios_DequeueCdIntr_();
1645
1646 // EnterCriticalSection - should be done at the beginning,
1647 // but this way is much easier to implement
1648 a0 = 1;
1649 pc0 = A_SYSCALL;
1650 use_cycles(30);
1651}
1652
1653void psxBios_SetMem() { // 9f
1654 u32 new = psxHu32(0x1060);
1655
1656#ifdef PSXBIOS_LOG
1657 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1658#endif
1659
1660 switch(a0) {
1661 case 2:
1662 psxHu32ref(0x1060) = SWAP32(new);
1663 psxMu32ref(0x060) = a0;
1664 SysPrintf("Change effective memory : %d MBytes\n",a0);
1665 break;
1666
1667 case 8:
1668 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1669 psxMu32ref(0x060) = a0;
1670 SysPrintf("Change effective memory : %d MBytes\n",a0);
1671
1672 default:
1673 SysPrintf("Effective memory must be 2/8 MBytes\n");
1674 break;
1675 }
1676
1677 pc0 = ra;
1678}
1679
1680/* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1681void psxBios_get_cd_status(void) //a6
1682{
1683 v0 = 1;
1684 pc0 = ra;
1685}
1686
1687void psxBios__card_info() { // ab
1688#ifdef PSXBIOS_LOG
1689 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1690#endif
1691 u32 ret, port;
1692 card_active_chan = a0;
1693 port = card_active_chan >> 4;
1694
1695 switch (port) {
1696 case 0x0:
1697 case 0x1:
1698 ret = 0x0004;
1699 if (McdDisable[port & 1])
1700 ret = 0x0100;
1701 break;
1702 default:
1703#ifdef PSXBIOS_LOG
1704 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
1705#endif
1706 ret = 0x0302;
1707 break;
1708 }
1709
1710 if (McdDisable[0] && McdDisable[1])
1711 ret = 0x0100;
1712
1713 DeliverEvent(0xf0000011, 0x0004);
1714// DeliverEvent(0xf4000001, 0x0004);
1715 DeliverEvent(0xf4000001, ret);
1716 v0 = 1; pc0 = ra;
1717}
1718
1719void psxBios__card_load() { // ac
1720#ifdef PSXBIOS_LOG
1721 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1722#endif
1723
1724 card_active_chan = a0;
1725
1726// DeliverEvent(0xf0000011, 0x0004);
1727 DeliverEvent(0xf4000001, 0x0004);
1728
1729 v0 = 1; pc0 = ra;
1730}
1731
1732/* System calls B0 */
1733
1734static u32 psxBios_SysMalloc_(u32 size);
1735
1736static void psxBios_SysMalloc() { // B 00
1737 u32 ret = psxBios_SysMalloc_(a0);
1738
1739 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1740 mips_return_c(ret, 33);
1741}
1742
1743void psxBios_SetRCnt() { // 02
1744#ifdef PSXBIOS_LOG
1745 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1746#endif
1747
1748 a0&= 0x3;
1749 if (a0 != 3) {
1750 u32 mode=0;
1751
1752 psxRcntWtarget(a0, a1);
1753 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1754 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1755 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1756 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1757 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1758
1759 psxRcntWmode(a0, mode);
1760 }
1761 pc0 = ra;
1762}
1763
1764void psxBios_GetRCnt() { // 03
1765#ifdef PSXBIOS_LOG
1766 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1767#endif
1768
1769 a0&= 0x3;
1770 if (a0 != 3) v0 = psxRcntRcount(a0);
1771 else v0 = 0;
1772 pc0 = ra;
1773}
1774
1775void psxBios_StartRCnt() { // 04
1776#ifdef PSXBIOS_LOG
1777 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1778#endif
1779
1780 a0&= 0x3;
1781 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1782 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1783 v0 = 1; pc0 = ra;
1784}
1785
1786void psxBios_StopRCnt() { // 05
1787#ifdef PSXBIOS_LOG
1788 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1789#endif
1790
1791 a0&= 0x3;
1792 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1793 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1794 pc0 = ra;
1795}
1796
1797void psxBios_ResetRCnt() { // 06
1798#ifdef PSXBIOS_LOG
1799 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1800#endif
1801
1802 a0&= 0x3;
1803 if (a0 != 3) {
1804 psxRcntWmode(a0, 0);
1805 psxRcntWtarget(a0, 0);
1806 psxRcntWcount(a0, 0);
1807 }
1808 pc0 = ra;
1809}
1810
1811static u32 DeliverEvent(u32 class, u32 spec) {
1812 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1813 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1814 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1815 u32 i, lim = evcb_len / 0x1c;
1816
1817 for (i = 0; i < lim; i++, ev++) {
1818 use_cycles(8);
1819 if (SWAP32(ev->status) != EvStACTIVE)
1820 continue;
1821 use_cycles(4);
1822 if (SWAP32(ev->class) != class)
1823 continue;
1824 use_cycles(4);
1825 if (SWAP32(ev->spec) != spec)
1826 continue;
1827 use_cycles(6);
1828 ret = SWAP32(ev->mode);
1829 if (ret == EvMdMARK) {
1830 ev->status = SWAP32(EvStALREADY);
1831 continue;
1832 }
1833 use_cycles(8);
1834 if (ret == EvMdCALL) {
1835 ret = SWAP32(ev->fhandler);
1836 if (ret) {
1837 v0 = ret;
1838 softCall(ret);
1839 ret = v0;
1840 }
1841 }
1842 }
1843 use_cycles(29);
1844 return ret;
1845}
1846
1847static u32 UnDeliverEvent(u32 class, u32 spec) {
1848 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1849 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1850 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1851 u32 i, lim = evcb_len / 0x1c;
1852
1853 for (i = 0; i < lim; i++, ev++) {
1854 use_cycles(8);
1855 if (SWAP32(ev->status) != EvStALREADY)
1856 continue;
1857 use_cycles(4);
1858 if (SWAP32(ev->class) != class)
1859 continue;
1860 use_cycles(4);
1861 if (SWAP32(ev->spec) != spec)
1862 continue;
1863 use_cycles(6);
1864 if (SWAP32(ev->mode) == EvMdMARK)
1865 ev->status = SWAP32(EvStACTIVE);
1866 }
1867 use_cycles(28);
1868 return ret;
1869}
1870
1871static void psxBios_DeliverEvent() { // 07
1872 u32 ret;
1873 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
1874
1875 ret = DeliverEvent(a0, a1);
1876 mips_return(ret);
1877}
1878
1879static s32 get_free_EvCB_slot() {
1880 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1881 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
1882
1883 use_cycles(19);
1884 for (i = 0; i < lim; i++, ev++) {
1885 use_cycles(8);
1886 if (ev->status == SWAP32(EvStUNUSED))
1887 return i;
1888 }
1889 return -1;
1890}
1891
1892static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
1893 u32 ret = get_free_EvCB_slot();
1894 if ((s32)ret >= 0) {
1895 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
1896 ev->class = SWAP32(class);
1897 ev->status = SWAP32(EvStDISABLED);
1898 ev->spec = SWAP32(spec);
1899 ev->mode = SWAP32(mode);
1900 ev->fhandler = SWAP32(func);
1901 ret |= 0xf1000000u;
1902 }
1903 return ret;
1904}
1905
1906static void psxBios_OpenEvent() { // 08
1907 u32 ret = OpenEvent(a0, a1, a2, a3);
1908 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
1909 biosB0n[0x08], a0, a1, a2, a3, ret);
1910 mips_return_c(ret, 36);
1911}
1912
1913static void CloseEvent(u32 ev)
1914{
1915 u32 base = loadRam32(A_TT_EvCB);
1916 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
1917}
1918
1919static void psxBios_CloseEvent() { // 09
1920 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
1921 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
1922 CloseEvent(a0);
1923 mips_return_c(1, 10);
1924}
1925
1926static void psxBios_WaitEvent() { // 0a
1927 u32 base = loadRam32(A_TT_EvCB);
1928 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1929 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
1930
1931 use_cycles(15);
1932 if (status == EvStALREADY) {
1933 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
1934 mips_return(1);
1935 return;
1936 }
1937 if (status != EvStACTIVE)
1938 {
1939 mips_return_c(0, 2);
1940 return;
1941 }
1942
1943 // retrigger this hlecall after the next emulation event
1944 pc0 -= 4;
1945 if ((s32)(next_interupt - psxRegs.cycle) > 0)
1946 psxRegs.cycle = next_interupt;
1947 psxBranchTest();
1948}
1949
1950static void psxBios_TestEvent() { // 0b
1951 u32 base = loadRam32(A_TT_EvCB);
1952 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1953 u32 ret = 0;
1954 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
1955 if (status == EvStALREADY) {
1956 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
1957 ret = 1;
1958 }
1959
1960 mips_return_c(ret, 15);
1961}
1962
1963static void psxBios_EnableEvent() { // 0c
1964 u32 base = loadRam32(A_TT_EvCB);
1965 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1966 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
1967 if (status != EvStUNUSED)
1968 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
1969
1970 mips_return_c(1, 15);
1971}
1972
1973static void psxBios_DisableEvent() { // 0d
1974 u32 base = loadRam32(A_TT_EvCB);
1975 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1976 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
1977 if (status != EvStUNUSED)
1978 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
1979
1980 mips_return_c(1, 15);
1981}
1982
1983/*
1984 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
1985 */
1986
1987void psxBios_OpenTh() { // 0e
1988 TCB *tcb = loadRam32ptr(A_TT_TCB);
1989 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
1990 int th;
1991
1992 for (th = 1; th < limit; th++)
1993 {
1994 if (tcb[th].status != SWAP32(0x4000)) break;
1995
1996 }
1997 if (th == limit) {
1998 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
1999 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2000#ifdef PSXBIOS_LOG
2001 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2002#endif
2003 mips_return_c(0xffffffff, 20);
2004 return;
2005 }
2006 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
2007
2008 tcb[th].status = SWAP32(0x4000);
2009 tcb[th].mode = SWAP32(0x1000);
2010 tcb[th].epc = SWAP32(a0);
2011 tcb[th].reg[30] = SWAP32(a1); // fp
2012 tcb[th].reg[29] = SWAP32(a1); // sp
2013 tcb[th].reg[28] = SWAP32(a2); // gp
2014
2015 mips_return_c(0xff000000 + th, 34);
2016}
2017
2018/*
2019 * int CloseTh(long thread);
2020 */
2021
2022void psxBios_CloseTh() { // 0f
2023 TCB *tcb = loadRam32ptr(A_TT_TCB);
2024 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2025 u32 th = a0 & 0xff;
2026
2027#ifdef PSXBIOS_LOG
2028 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
2029#endif
2030 /* The return value is always 1 (even if the handle was already closed). */
2031 v0 = 1;
2032 if (th < limit && tcb[th].status == SWAP32(0x4000)) {
2033 tcb[th].status = SWAP32(0x1000);
2034 }
2035
2036 pc0 = ra;
2037}
2038
2039/*
2040 * int ChangeTh(long thread);
2041 */
2042
2043void psxBios_ChangeTh() { // 10
2044 u32 tcbBase = loadRam32(A_TT_TCB);
2045 u32 th = a0 & 0xffff;
2046
2047#ifdef PSXBIOS_LOG
2048// PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
2049#endif
2050 // without doing any argument checks, just issue a syscall
2051 // (like the real bios does)
2052 a0 = 3;
2053 a1 = tcbBase + th * sizeof(TCB);
2054 pc0 = A_SYSCALL;
2055 use_cycles(15);
2056}
2057
2058void psxBios_InitPAD() { // 0x12
2059 u32 i, *ram32 = (u32 *)psxM;
2060 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2061
2062 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2063 // PAD_dr_enable = 0;
2064 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2065 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2066 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2067 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2068 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2069 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2070 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2071 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2072
2073 for (i = 0; i < a1; i++) {
2074 use_cycles(4);
2075 storeRam8(a0 + i, 0);
2076 }
2077 for (i = 0; i < a3; i++) {
2078 use_cycles(4);
2079 storeRam8(a2 + i, 0);
2080 }
2081 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2082
2083 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2084
2085 mips_return_c(1, 200);
2086}
2087
2088void psxBios_StartPAD() { // 13
2089 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2090
2091 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2092 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2093 psxHwWrite16(0x1f801070, ~1);
2094 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2095 storeRam32(A_PAD_ACK_VBL, 1);
2096 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2097 psxRegs.CP0.n.SR |= 0x401;
2098
2099 mips_return_c(1, 300);
2100}
2101
2102void psxBios_StopPAD() { // 14
2103 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2104 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2105 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2106 psxRegs.CP0.n.SR |= 0x401;
2107 mips_return_void_c(200);
2108}
2109
2110void psxBios_PAD_init() { // 15
2111#ifdef PSXBIOS_LOG
2112 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2113#endif
2114 if (!(a0 == 0x20000000 || a0 == 0x20000001))
2115 {
2116 v0 = 0;
2117 pc0 = ra;
2118 return;
2119 }
2120 psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
2121 pad_buf = (int *)Ra1;
2122 *pad_buf = -1;
2123 psxRegs.CP0.n.SR |= 0x401;
2124 v0 = 2;
2125 pc0 = ra;
2126}
2127
2128void psxBios_PAD_dr() { // 16
2129#ifdef PSXBIOS_LOG
2130 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2131#endif
2132
2133 v0 = -1; pc0 = ra;
2134}
2135
2136static void psxBios_ReturnFromException() { // 17
2137 u32 tcbPtr = loadRam32(A_TT_PCB);
2138 const TCB *tcb = loadRam32ptr(tcbPtr);
2139 int i;
2140
2141 for (i = 1; i < 32; i++)
2142 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2143 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2144 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2145 psxRegs.CP0.n.SR = SWAP32(tcb->sr);
2146
2147 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2148 pc0 = k0 = SWAP32(tcb->epc);
2149
2150 psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
2151 use_cycles(53);
2152 psxBranchTest();
2153}
2154
2155void psxBios_ResetEntryInt() { // 18
2156 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2157
2158 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2159 mips_return_void_c(5);
2160}
2161
2162void psxBios_HookEntryInt() { // 19
2163 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2164
2165 storeRam32(A_EEXIT_PTR, a0);
2166 mips_return_void_c(3);
2167}
2168
2169static void psxBios_UnDeliverEvent() { // 0x20
2170 u32 ret;
2171 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2172
2173 ret = UnDeliverEvent(a0, a1);
2174 mips_return(ret);
2175}
2176
2177char ffile[64], *pfile;
2178int nfile;
2179
2180static void buopen(int mcd, char *ptr, char *cfg)
2181{
2182 int i;
2183 char *mcd_data = ptr;
2184
2185 strcpy(FDesc[1 + mcd].name, Ra0+5);
2186 FDesc[1 + mcd].offset = 0;
2187 FDesc[1 + mcd].mode = a1;
2188
2189 for (i=1; i<16; i++) {
2190 const char *fptr = mcd_data + 128 * i;
2191 if ((*fptr & 0xF0) != 0x50) continue;
2192 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2193 FDesc[1 + mcd].mcfile = i;
2194 SysPrintf("open %s\n", fptr+0xa);
2195 v0 = 1 + mcd;
2196 break;
2197 }
2198 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2199 for (i=1; i<16; i++) {
2200 int j, xor, nblk = a1 >> 16;
2201 char *pptr, *fptr2;
2202 char *fptr = mcd_data + 128 * i;
2203
2204 if ((*fptr & 0xF0) != 0xa0) continue;
2205
2206 FDesc[1 + mcd].mcfile = i;
2207 fptr[0] = 0x51;
2208 fptr[4] = 0x00;
2209 fptr[5] = 0x20 * nblk;
2210 fptr[6] = 0x00;
2211 fptr[7] = 0x00;
2212 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2213 pptr = fptr2 = fptr;
2214 for(j=2; j<=nblk; j++) {
2215 int k;
2216 for(i++; i<16; i++) {
2217 fptr2 += 128;
2218
2219 memset(fptr2, 0, 128);
2220 fptr2[0] = j < nblk ? 0x52 : 0x53;
2221 pptr[8] = i - 1;
2222 pptr[9] = 0;
2223 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2224 pptr[127] = xor;
2225 pptr = fptr2;
2226 break;
2227 }
2228 /* shouldn't this return ENOSPC if i == 16? */
2229 }
2230 pptr[8] = pptr[9] = 0xff;
2231 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2232 pptr[127] = xor;
2233 SysPrintf("openC %s %d\n", ptr, nblk);
2234 v0 = 1 + mcd;
2235 /* just go ahead and resave them all */
2236 SaveMcd(cfg, ptr, 128, 128 * 15);
2237 break;
2238 }
2239 /* shouldn't this return ENOSPC if i == 16? */
2240 }
2241}
2242
2243/*
2244 * int open(char *name , int mode);
2245 */
2246
2247void psxBios_open() { // 0x32
2248 void *pa0 = Ra0;
2249
2250#ifdef PSXBIOS_LOG
2251 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2252#endif
2253
2254 v0 = -1;
2255
2256 if (pa0 != INVALID_PTR) {
2257 if (!strncmp(pa0, "bu00", 4)) {
2258 buopen(1, Mcd1Data, Config.Mcd1);
2259 }
2260
2261 if (!strncmp(pa0, "bu10", 4)) {
2262 buopen(2, Mcd2Data, Config.Mcd2);
2263 }
2264 }
2265
2266 pc0 = ra;
2267}
2268
2269/*
2270 * int lseek(int fd , int offset , int whence);
2271 */
2272
2273void psxBios_lseek() { // 0x33
2274#ifdef PSXBIOS_LOG
2275 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2276#endif
2277
2278 switch (a2) {
2279 case 0: // SEEK_SET
2280 FDesc[a0].offset = a1;
2281 v0 = a1;
2282// DeliverEvent(0xf0000011, 0x0004);
2283// DeliverEvent(0xf4000001, 0x0004);
2284 break;
2285
2286 case 1: // SEEK_CUR
2287 FDesc[a0].offset+= a1;
2288 v0 = FDesc[a0].offset;
2289 break;
2290 }
2291
2292 pc0 = ra;
2293}
2294
2295
2296/*
2297 * int read(int fd , void *buf , int nbytes);
2298 */
2299
2300void psxBios_read() { // 0x34
2301 char *ptr;
2302 void *pa1 = Ra1;
2303
2304#ifdef PSXBIOS_LOG
2305 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2306#endif
2307
2308 v0 = -1;
2309
2310 if (pa1 != INVALID_PTR) {
2311 switch (a0) {
2312 case 2: buread(pa1, 1, a2); break;
2313 case 3: buread(pa1, 2, a2); break;
2314 }
2315 }
2316
2317 pc0 = ra;
2318}
2319
2320/*
2321 * int write(int fd , void *buf , int nbytes);
2322 */
2323
2324void psxBios_write() { // 0x35/0x03
2325 char *ptr;
2326 void *pa1 = Ra1;
2327
2328#ifdef PSXBIOS_LOG
2329 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2330#endif
2331
2332 v0 = -1;
2333 if (pa1 == INVALID_PTR) {
2334 pc0 = ra;
2335 return;
2336 }
2337
2338 if (a0 == 1) { // stdout
2339 char *ptr = pa1;
2340
2341 v0 = a2;
2342 while (a2 > 0) {
2343 SysPrintf("%c", *ptr++); a2--;
2344 }
2345 pc0 = ra; return;
2346 }
2347
2348 switch (a0) {
2349 case 2: buwrite(pa1, 1, a2); break;
2350 case 3: buwrite(pa1, 2, a2); break;
2351 }
2352
2353 pc0 = ra;
2354}
2355
2356static void psxBios_write_psxout() {
2357 if (a0 == 1) { // stdout
2358 const char *ptr = Ra1;
2359 int len = a2;
2360
2361 if (ptr != INVALID_PTR)
2362 while (len-- > 0)
2363 SysPrintf("%c", *ptr++);
2364 }
2365}
2366
2367static void psxBios_putchar_psxout() { // 3d
2368 SysPrintf("%c", (char)a0);
2369}
2370
2371static void psxBios_puts_psxout() { // 3e/3f
2372 SysPrintf("%s", Ra0);
2373}
2374
2375/*
2376 * int close(int fd);
2377 */
2378
2379void psxBios_close() { // 0x36
2380#ifdef PSXBIOS_LOG
2381 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2382#endif
2383
2384 v0 = a0;
2385 pc0 = ra;
2386}
2387
2388void psxBios_putchar() { // 3d
2389 SysPrintf("%c", (char)a0);
2390 pc0 = ra;
2391}
2392
2393void psxBios_puts() { // 3e/3f
2394 SysPrintf("%s", Ra0);
2395 pc0 = ra;
2396}
2397
2398
2399/* To avoid any issues with different behaviour when using the libc's own strlen instead.
2400 * We want to mimic the PSX's behaviour in this case for bufile. */
2401static size_t strlen_internal(char* p)
2402{
2403 size_t size_of_array = 0;
2404 while (*p++) size_of_array++;
2405 return size_of_array;
2406}
2407
2408#define bufile(mcd) { \
2409 size_t size_of_name = strlen_internal(dir->name); \
2410 while (nfile < 16) { \
2411 int match=1; \
2412 \
2413 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2414 nfile++; \
2415 if ((*ptr & 0xF0) != 0x50) continue; \
2416 /* Bug link files show up as free block. */ \
2417 if (!ptr[0xa]) continue; \
2418 ptr+= 0xa; \
2419 if (pfile[0] == 0) { \
2420 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2421 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2422 } else for (i=0; i<20; i++) { \
2423 if (pfile[i] == ptr[i]) { \
2424 dir->name[i] = ptr[i]; continue; } \
2425 if (pfile[i] == '?') { \
2426 dir->name[i] = ptr[i]; continue; } \
2427 if (pfile[i] == '*') { \
2428 strcpy(dir->name+i, ptr+i); break; } \
2429 match = 0; break; \
2430 } \
2431 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2432 if (match == 0) { continue; } \
2433 dir->size = 8192; \
2434 v0 = _dir; \
2435 break; \
2436 } \
2437}
2438
2439/*
2440 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2441 */
2442
2443void psxBios_firstfile() { // 42
2444 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2445 void *pa0 = Ra0;
2446 u32 _dir = a1;
2447 char *ptr;
2448 int i;
2449
2450#ifdef PSXBIOS_LOG
2451 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2452#endif
2453
2454 v0 = 0;
2455
2456 if (pa0 != INVALID_PTR) {
2457 strcpy(ffile, pa0);
2458 pfile = ffile+5;
2459 nfile = 0;
2460 if (!strncmp(pa0, "bu00", 4)) {
2461 // firstfile() calls _card_read() internally, so deliver it's event
2462 DeliverEvent(0xf0000011, 0x0004);
2463 bufile(1);
2464 } else if (!strncmp(pa0, "bu10", 4)) {
2465 // firstfile() calls _card_read() internally, so deliver it's event
2466 DeliverEvent(0xf0000011, 0x0004);
2467 bufile(2);
2468 }
2469 }
2470
2471 pc0 = ra;
2472}
2473
2474/*
2475 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2476 */
2477
2478void psxBios_nextfile() { // 43
2479 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2480 u32 _dir = a0;
2481 char *ptr;
2482 int i;
2483
2484#ifdef PSXBIOS_LOG
2485 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2486#endif
2487
2488 v0 = 0;
2489
2490 if (!strncmp(ffile, "bu00", 4)) {
2491 bufile(1);
2492 }
2493
2494 if (!strncmp(ffile, "bu10", 4)) {
2495 bufile(2);
2496 }
2497
2498 pc0 = ra;
2499}
2500
2501#define burename(mcd) { \
2502 for (i=1; i<16; i++) { \
2503 int namelen, j, xor = 0; \
2504 ptr = Mcd##mcd##Data + 128 * i; \
2505 if ((*ptr & 0xF0) != 0x50) continue; \
2506 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2507 namelen = strlen(Ra1+5); \
2508 memcpy(ptr+0xa, Ra1+5, namelen); \
2509 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2510 for (j=0; j<127; j++) xor^= ptr[j]; \
2511 ptr[127] = xor; \
2512 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2513 v0 = 1; \
2514 break; \
2515 } \
2516}
2517
2518/*
2519 * int rename(char *old, char *new);
2520 */
2521
2522void psxBios_rename() { // 44
2523 void *pa0 = Ra0;
2524 void *pa1 = Ra1;
2525 char *ptr;
2526 int i;
2527
2528#ifdef PSXBIOS_LOG
2529 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2530#endif
2531
2532 v0 = 0;
2533
2534 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2535 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2536 burename(1);
2537 }
2538
2539 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2540 burename(2);
2541 }
2542 }
2543
2544 pc0 = ra;
2545}
2546
2547
2548#define budelete(mcd) { \
2549 for (i=1; i<16; i++) { \
2550 ptr = Mcd##mcd##Data + 128 * i; \
2551 if ((*ptr & 0xF0) != 0x50) continue; \
2552 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2553 *ptr = (*ptr & 0xf) | 0xA0; \
2554 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2555 SysPrintf("delete %s\n", ptr+0xa); \
2556 v0 = 1; \
2557 break; \
2558 } \
2559}
2560
2561/*
2562 * int delete(char *name);
2563 */
2564
2565void psxBios_delete() { // 45
2566 void *pa0 = Ra0;
2567 char *ptr;
2568 int i;
2569
2570#ifdef PSXBIOS_LOG
2571 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2572#endif
2573
2574 v0 = 0;
2575
2576 if (pa0 != INVALID_PTR) {
2577 if (!strncmp(pa0, "bu00", 4)) {
2578 budelete(1);
2579 }
2580
2581 if (!strncmp(pa0, "bu10", 4)) {
2582 budelete(2);
2583 }
2584 }
2585
2586 pc0 = ra;
2587}
2588
2589void psxBios_InitCARD() { // 4a
2590 u32 *ram32 = (u32 *)psxM;
2591 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2592 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2593 // (maybe) todo: early_card_irq, FlushCache etc
2594
2595 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2596
2597 mips_return_c(0, 300);
2598}
2599
2600void psxBios_StartCARD() { // 4b
2601 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2602 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2603 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2604
2605 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2606 storeRam32(A_PAD_ACK_VBL, 1);
2607 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2608 storeRam32(A_CARD_IRQR_ENA, 1);
2609 psxRegs.CP0.n.SR |= 0x401;
2610
2611 mips_return_c(1, 200);
2612}
2613
2614void psxBios_StopCARD() { // 4c
2615 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2616 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2617 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2618 storeRam32(A_CARD_IRQR_ENA, 0);
2619 psxRegs.CP0.n.SR |= 0x401;
2620 mips_return_void_c(200);
2621}
2622
2623void psxBios__card_write() { // 0x4e
2624 void *pa2 = Ra2;
2625 int port;
2626
2627#ifdef PSXBIOS_LOG
2628 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2629#endif
2630 /*
2631 Function also accepts sector 400h (a bug).
2632 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2633 */
2634 if (!(a1 <= 0x3FF))
2635 {
2636 /* Invalid sectors */
2637 v0 = 0; pc0 = ra;
2638 return;
2639 }
2640 card_active_chan = a0;
2641 port = a0 >> 4;
2642
2643 if (pa2 != INVALID_PTR) {
2644 if (port == 0) {
2645 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2646 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2647 } else {
2648 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2649 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2650 }
2651 }
2652
2653 DeliverEvent(0xf0000011, 0x0004);
2654// DeliverEvent(0xf4000001, 0x0004);
2655
2656 v0 = 1; pc0 = ra;
2657}
2658
2659void psxBios__card_read() { // 0x4f
2660 void *pa2 = Ra2;
2661 int port;
2662
2663#ifdef PSXBIOS_LOG
2664 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2665#endif
2666 /*
2667 Function also accepts sector 400h (a bug).
2668 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2669 */
2670 if (!(a1 <= 0x3FF))
2671 {
2672 /* Invalid sectors */
2673 v0 = 0; pc0 = ra;
2674 return;
2675 }
2676 card_active_chan = a0;
2677 port = a0 >> 4;
2678
2679 if (pa2 != INVALID_PTR) {
2680 if (port == 0) {
2681 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2682 } else {
2683 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2684 }
2685 }
2686
2687 DeliverEvent(0xf0000011, 0x0004);
2688// DeliverEvent(0xf4000001, 0x0004);
2689
2690 v0 = 1; pc0 = ra;
2691}
2692
2693void psxBios__new_card() { // 0x50
2694#ifdef PSXBIOS_LOG
2695 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2696#endif
2697
2698 pc0 = ra;
2699}
2700
2701/* According to a user, this allows Final Fantasy Tactics to save/load properly */
2702void psxBios__get_error(void) // 55
2703{
2704 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2705 v0 = 0;
2706 pc0 = ra;
2707}
2708
2709void psxBios_Krom2RawAdd() { // 0x51
2710 int i = 0;
2711
2712 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2713 const u32 table_8140[][2] = {
2714 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2715 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2716 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2717 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2718 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2719 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2720 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2721 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2722 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2723 {0xffff, 0}
2724 };
2725
2726 const u32 table_889f[][2] = {
2727 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2728 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2729 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2730 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2731 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2732 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2733 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2734 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2735 {0xffff, 0}
2736 };
2737
2738 if (a0 >= 0x8140 && a0 <= 0x84be) {
2739 while (table_8140[i][0] <= a0) i++;
2740 a0 -= table_8140[i - 1][0];
2741 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2742 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2743 while (table_889f[i][0] <= a0) i++;
2744 a0 -= table_889f[i - 1][0];
2745 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2746 } else {
2747 v0 = 0xffffffff;
2748 }
2749
2750 pc0 = ra;
2751}
2752
2753void psxBios_GetC0Table() { // 56
2754 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2755 log_unhandled("GetC0Table @%08x\n", ra);
2756
2757 mips_return_c(A_C0_TABLE, 3);
2758}
2759
2760void psxBios_GetB0Table() { // 57
2761 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2762 log_unhandled("GetB0Table @%08x\n", ra);
2763
2764 mips_return_c(A_B0_TABLE, 3);
2765}
2766
2767void psxBios__card_chan() { // 0x58
2768#ifdef PSXBIOS_LOG
2769 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2770#endif
2771
2772 v0 = card_active_chan;
2773 pc0 = ra;
2774}
2775
2776static void psxBios_ChangeClearPad() { // 5b
2777 u32 ret;
2778 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2779 ret = loadRam32(A_PAD_ACK_VBL);
2780 storeRam32(A_PAD_ACK_VBL, a0);
2781
2782 mips_return_c(ret, 6);
2783}
2784
2785void psxBios__card_status() { // 5c
2786#ifdef PSXBIOS_LOG
2787 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2788#endif
2789
2790 v0 = card_active_chan;
2791 pc0 = ra;
2792}
2793
2794void psxBios__card_wait() { // 5d
2795#ifdef PSXBIOS_LOG
2796 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2797#endif
2798
2799 v0 = 1;
2800 pc0 = ra;
2801}
2802
2803/* System calls C0 */
2804
2805static void psxBios_InitRCnt() { // 00
2806 int i;
2807 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2808 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2809 for (i = 0; i < 3; i++) {
2810 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2811 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2812 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2813 }
2814 psxBios_SysEnqIntRP_(a0, 0x6d88);
2815 mips_return_c(0, 9);
2816}
2817
2818static void psxBios_InitException() { // 01
2819 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2820 psxBios_SysEnqIntRP_(a0, 0x6da8);
2821 mips_return_c(0, 9);
2822}
2823
2824/*
2825 * int SysEnqIntRP(int index , long *queue);
2826 */
2827
2828static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2829 u32 old, base = loadRam32(A_TT_ExCB);
2830
2831 old = loadRam32(base + (priority << 3));
2832 storeRam32(base + (priority << 3), chain_eptr);
2833 storeRam32(chain_eptr, old);
2834 mips_return_c(0, 9);
2835}
2836
2837static void psxBios_SysEnqIntRP() { // 02
2838 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2839 psxBios_SysEnqIntRP_(a0, a1);
2840}
2841
2842/*
2843 * int SysDeqIntRP(int index , long *queue);
2844 */
2845
2846static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
2847 u32 ptr, next, base = loadRam32(A_TT_ExCB);
2848 u32 lim = 0, ret = 0;
2849
2850 // as in original: no arg checks of any kind, bug if a1 == 0
2851 ptr = loadRam32(base + (priority << 3));
2852 while (ptr) {
2853 next = loadRam32(ptr);
2854 if (ptr == chain_rm_eptr) {
2855 storeRam32(base + (priority << 3), next);
2856 ret = ptr;
2857 use_cycles(6);
2858 break;
2859 }
2860 while (next && next != chain_rm_eptr && lim++ < 100) {
2861 ptr = next;
2862 next = loadRam32(ptr);
2863 use_cycles(8);
2864 }
2865 if (next == chain_rm_eptr) {
2866 next = loadRam32(next);
2867 storeRam32(ptr, next);
2868 ret = ptr;
2869 use_cycles(6);
2870 }
2871 break;
2872 }
2873 if (lim == 100)
2874 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
2875
2876 mips_return_c(ret, 12);
2877}
2878
2879static void psxBios_SysDeqIntRP() { // 03
2880 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
2881 psxBios_SysDeqIntRP_(a0, a1);
2882}
2883
2884static void psxBios_get_free_EvCB_slot() { // 04
2885 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
2886 s32 ret = get_free_EvCB_slot();
2887 mips_return_c(ret, 0);
2888}
2889
2890static void psxBios_SysInitMemory_(u32 base, u32 size) {
2891 storeRam32(base, 0);
2892 storeRam32(A_KMALLOC_PTR, base);
2893 storeRam32(A_KMALLOC_SIZE, size);
2894 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
2895}
2896
2897// this should be much more complicated, but maybe that'll be enough
2898static u32 psxBios_SysMalloc_(u32 size) {
2899 u32 ptr = loadRam32(A_KMALLOC_PTR);
2900
2901 size = (size + 3) & ~3;
2902 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
2903 storeRam32(ptr, size);
2904 return ptr + 4;
2905}
2906
2907static void psxBios_SysInitMemory() { // 08
2908 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
2909
2910 psxBios_SysInitMemory_(a0, a1);
2911 mips_return_void_c(12);
2912}
2913
2914static void psxBios_ChangeClearRCnt() { // 0a
2915 u32 ret;
2916
2917 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2918
2919 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
2920 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
2921 mips_return_c(ret, 8);
2922}
2923
2924static void psxBios_InitDefInt() { // 0c
2925 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
2926 // should also clear the autoack table
2927 psxBios_SysEnqIntRP_(a0, 0x6d98);
2928 mips_return_c(0, 20 + 6*2);
2929}
2930
2931void psxBios_dummy() {
2932 u32 pc = (pc0 & 0x1fffff) - 4;
2933 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
2934 : pc == 0xc0 ? biosC0n : NULL;
2935 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
2936 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
2937 (void)pc; (void)ntab;
2938 mips_return_c(0, 100);
2939}
2940
2941void (*biosA0[256])();
2942// C0 and B0 overlap (end of C0 is start of B0)
2943void (*biosC0[256+128])();
2944void (**biosB0)() = biosC0 + 128;
2945
2946#include "sjisfont.h"
2947
2948void setup_mips_code()
2949{
2950 u32 *ptr;
2951 ptr = (u32 *)&psxM[A_SYSCALL];
2952 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
2953 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
2954 ptr[0x08/4] = SWAPu32(0x00000000); // nop
2955
2956 ptr = (u32 *)&psxM[A_EXCEPTION];
2957 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
2958 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
2959 ptr[0x14/4] = SWAPu32(0x00000000); // nop
2960 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
2961 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
2962 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
2963 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
2964 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
2965 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
2966 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
2967
2968 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
2969 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
2970 ptr[0x68/4] = SWAPu32(0x24630004); // addiu $v1, $v1, 4
2971 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
2972
2973 ptr[0xb0/4] = HLEOP(hleop_exception);
2974}
2975
2976static const struct {
2977 u32 addr;
2978 enum hle_op op;
2979} chainfns[] = {
2980 { 0xbfc050a4, hleop_exc0_0_1 },
2981 { 0xbfc04fbc, hleop_exc0_0_2 },
2982 { 0xbfc0506c, hleop_exc0_1_1 },
2983 { 0xbfc04dec, hleop_exc0_1_2 },
2984 { 0x1a00, hleop_exc0_2_2 },
2985 { 0x19c8, hleop_exc1_0_1 },
2986 { 0x18bc, hleop_exc1_0_2 },
2987 { 0x1990, hleop_exc1_1_1 },
2988 { 0x1858, hleop_exc1_1_2 },
2989 { 0x1958, hleop_exc1_2_1 },
2990 { 0x17f4, hleop_exc1_2_2 },
2991 { 0x1920, hleop_exc1_3_1 },
2992 { 0x1794, hleop_exc1_3_2 },
2993 { 0x2458, hleop_exc3_0_2 },
2994 { 0x49bc, hleop_exc_padcard1 },
2995 { 0x4a4c, hleop_exc_padcard2 },
2996};
2997
2998static int chain_hle_op(u32 handler)
2999{
3000 size_t i;
3001
3002 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3003 if (chainfns[i].addr == handler)
3004 return chainfns[i].op;
3005 return hleop_dummy;
3006}
3007
3008static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3009{
3010 d[0] = SWAPu32(next);
3011 d[1] = SWAPu32(handler1);
3012 d[2] = SWAPu32(handler2);
3013
3014 // install the hle traps
3015 PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3016 PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3017}
3018
3019static void setup_tt(u32 tcb_cnt, u32 evcb_cnt)
3020{
3021 u32 *ram32 = (u32 *)psxM;
3022 u32 s_excb = 0x20, s_evcb = 0x1c * evcb_cnt;
3023 u32 s_pcb = 4, s_tcb = 0xc0 * tcb_cnt;
3024 u32 p_excb, p_evcb, p_pcb, p_tcb;
3025
3026 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3027 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3028 p_excb = psxBios_SysMalloc_(s_excb);
3029 p_evcb = psxBios_SysMalloc_(s_evcb);
3030 p_pcb = psxBios_SysMalloc_(s_pcb);
3031 p_tcb = psxBios_SysMalloc_(s_tcb);
3032
3033 // "table of tables". Some games modify it
3034 assert(A_TT_ExCB == 0x0100);
3035 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3036 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3037 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3038 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3039 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3040 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3041 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3042 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3043 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3044 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3045 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3046 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3047
3048 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3049 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3050 storeRam32(p_excb + 4*4, 0x0000); // chain2
3051 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3052
3053 storeRam32(p_pcb, p_tcb);
3054 storeRam32(p_tcb, 0x4000); // first TCB
3055
3056 // default events
3057 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3058 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3059 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3060 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3061 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3062 DeliverEvent(0xf0000003, 0x0010);
3063}
3064
3065void psxBiosInit() {
3066 u32 *ptr, *ram32, *rom32;
3067 int i;
3068 uLongf len;
3069
3070 memset(psxM, 0, 0x10000);
3071 for(i = 0; i < 256; i++) {
3072 biosA0[i] = NULL;
3073 biosB0[i] = NULL;
3074 biosC0[i] = NULL;
3075 }
3076 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3077 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3078 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3079 biosA0[0x3f] = psxBios_printf_psxout;
3080
3081 if (!Config.HLE) return;
3082
3083 for(i = 0; i < 256; i++) {
3084 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3085 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3086 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3087 }
3088
3089 biosA0[0x00] = psxBios_open;
3090 biosA0[0x01] = psxBios_lseek;
3091 biosA0[0x02] = psxBios_read;
3092 biosA0[0x03] = psxBios_write;
3093 biosA0[0x04] = psxBios_close;
3094 //biosA0[0x05] = psxBios_ioctl;
3095 //biosA0[0x06] = psxBios_exit;
3096 //biosA0[0x07] = psxBios_sys_a0_07;
3097 biosA0[0x08] = psxBios_getc;
3098 biosA0[0x09] = psxBios_putc;
3099 biosA0[0x0a] = psxBios_todigit;
3100 //biosA0[0x0b] = psxBios_atof;
3101 //biosA0[0x0c] = psxBios_strtoul;
3102 //biosA0[0x0d] = psxBios_strtol;
3103 biosA0[0x0e] = psxBios_abs;
3104 biosA0[0x0f] = psxBios_labs;
3105 biosA0[0x10] = psxBios_atoi;
3106 biosA0[0x11] = psxBios_atol;
3107 //biosA0[0x12] = psxBios_atob;
3108 biosA0[0x13] = psxBios_setjmp;
3109 biosA0[0x14] = psxBios_longjmp;
3110 biosA0[0x15] = psxBios_strcat;
3111 biosA0[0x16] = psxBios_strncat;
3112 biosA0[0x17] = psxBios_strcmp;
3113 biosA0[0x18] = psxBios_strncmp;
3114 biosA0[0x19] = psxBios_strcpy;
3115 biosA0[0x1a] = psxBios_strncpy;
3116 biosA0[0x1b] = psxBios_strlen;
3117 biosA0[0x1c] = psxBios_index;
3118 biosA0[0x1d] = psxBios_rindex;
3119 biosA0[0x1e] = psxBios_strchr;
3120 biosA0[0x1f] = psxBios_strrchr;
3121 biosA0[0x20] = psxBios_strpbrk;
3122 biosA0[0x21] = psxBios_strspn;
3123 biosA0[0x22] = psxBios_strcspn;
3124 biosA0[0x23] = psxBios_strtok;
3125 biosA0[0x24] = psxBios_strstr;
3126 biosA0[0x25] = psxBios_toupper;
3127 biosA0[0x26] = psxBios_tolower;
3128 biosA0[0x27] = psxBios_bcopy;
3129 biosA0[0x28] = psxBios_bzero;
3130 biosA0[0x29] = psxBios_bcmp;
3131 biosA0[0x2a] = psxBios_memcpy;
3132 biosA0[0x2b] = psxBios_memset;
3133 biosA0[0x2c] = psxBios_memmove;
3134 biosA0[0x2d] = psxBios_memcmp;
3135 biosA0[0x2e] = psxBios_memchr;
3136 biosA0[0x2f] = psxBios_rand;
3137 biosA0[0x30] = psxBios_srand;
3138 biosA0[0x31] = psxBios_qsort;
3139 //biosA0[0x32] = psxBios_strtod;
3140 biosA0[0x33] = psxBios_malloc;
3141 biosA0[0x34] = psxBios_free;
3142 //biosA0[0x35] = psxBios_lsearch;
3143 //biosA0[0x36] = psxBios_bsearch;
3144 biosA0[0x37] = psxBios_calloc;
3145 biosA0[0x38] = psxBios_realloc;
3146 biosA0[0x39] = psxBios_InitHeap;
3147 //biosA0[0x3a] = psxBios__exit;
3148 biosA0[0x3b] = psxBios_getchar;
3149 biosA0[0x3c] = psxBios_putchar;
3150 //biosA0[0x3d] = psxBios_gets;
3151 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3152 //biosA0[0x41] = psxBios_LoadTest;
3153 biosA0[0x42] = psxBios_Load;
3154 biosA0[0x43] = psxBios_Exec;
3155 biosA0[0x44] = psxBios_FlushCache;
3156 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3157 biosA0[0x46] = psxBios_GPU_dw;
3158 biosA0[0x47] = psxBios_mem2vram;
3159 biosA0[0x48] = psxBios_SendGPU;
3160 biosA0[0x49] = psxBios_GPU_cw;
3161 biosA0[0x4a] = psxBios_GPU_cwb;
3162 biosA0[0x4b] = psxBios_GPU_SendPackets;
3163 biosA0[0x4c] = psxBios_sys_a0_4c;
3164 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3165 //biosA0[0x4e] = psxBios_GPU_sync;
3166 //biosA0[0x4f] = psxBios_sys_a0_4f;
3167 //biosA0[0x50] = psxBios_sys_a0_50;
3168 biosA0[0x51] = psxBios_LoadExec;
3169 //biosA0[0x52] = psxBios_GetSysSp;
3170 //biosA0[0x53] = psxBios_sys_a0_53;
3171 //biosA0[0x54] = psxBios__96_init_a54;
3172 //biosA0[0x55] = psxBios__bu_init_a55;
3173 biosA0[0x56] = psxBios_CdRemove;
3174 //biosA0[0x57] = psxBios_sys_a0_57;
3175 //biosA0[0x58] = psxBios_sys_a0_58;
3176 //biosA0[0x59] = psxBios_sys_a0_59;
3177 //biosA0[0x5a] = psxBios_sys_a0_5a;
3178 //biosA0[0x5b] = psxBios_dev_tty_init;
3179 //biosA0[0x5c] = psxBios_dev_tty_open;
3180 //biosA0[0x5d] = psxBios_sys_a0_5d;
3181 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3182 //biosA0[0x5f] = psxBios_dev_cd_open;
3183 //biosA0[0x60] = psxBios_dev_cd_read;
3184 //biosA0[0x61] = psxBios_dev_cd_close;
3185 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3186 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3187 //biosA0[0x64] = psxBios_dev_cd_chdir;
3188 //biosA0[0x65] = psxBios_dev_card_open;
3189 //biosA0[0x66] = psxBios_dev_card_read;
3190 //biosA0[0x67] = psxBios_dev_card_write;
3191 //biosA0[0x68] = psxBios_dev_card_close;
3192 //biosA0[0x69] = psxBios_dev_card_firstfile;
3193 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3194 //biosA0[0x6b] = psxBios_dev_card_erase;
3195 //biosA0[0x6c] = psxBios_dev_card_undelete;
3196 //biosA0[0x6d] = psxBios_dev_card_format;
3197 //biosA0[0x6e] = psxBios_dev_card_rename;
3198 //biosA0[0x6f] = psxBios_dev_card_6f;
3199 biosA0[0x70] = psxBios__bu_init;
3200 biosA0[0x71] = psxBios__96_init;
3201 biosA0[0x72] = psxBios_CdRemove;
3202 //biosA0[0x73] = psxBios_sys_a0_73;
3203 //biosA0[0x74] = psxBios_sys_a0_74;
3204 //biosA0[0x75] = psxBios_sys_a0_75;
3205 //biosA0[0x76] = psxBios_sys_a0_76;
3206 //biosA0[0x77] = psxBios_sys_a0_77;
3207 //biosA0[0x78] = psxBios__96_CdSeekL;
3208 //biosA0[0x79] = psxBios_sys_a0_79;
3209 //biosA0[0x7a] = psxBios_sys_a0_7a;
3210 //biosA0[0x7b] = psxBios_sys_a0_7b;
3211 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3212 //biosA0[0x7d] = psxBios_sys_a0_7d;
3213 //biosA0[0x7e] = psxBios__96_CdRead;
3214 //biosA0[0x7f] = psxBios_sys_a0_7f;
3215 //biosA0[0x80] = psxBios_sys_a0_80;
3216 //biosA0[0x81] = psxBios_sys_a0_81;
3217 //biosA0[0x82] = psxBios_sys_a0_82;
3218 //biosA0[0x83] = psxBios_sys_a0_83;
3219 //biosA0[0x84] = psxBios_sys_a0_84;
3220 //biosA0[0x85] = psxBios__96_CdStop;
3221 //biosA0[0x86] = psxBios_sys_a0_86;
3222 //biosA0[0x87] = psxBios_sys_a0_87;
3223 //biosA0[0x88] = psxBios_sys_a0_88;
3224 //biosA0[0x89] = psxBios_sys_a0_89;
3225 //biosA0[0x8a] = psxBios_sys_a0_8a;
3226 //biosA0[0x8b] = psxBios_sys_a0_8b;
3227 //biosA0[0x8c] = psxBios_sys_a0_8c;
3228 //biosA0[0x8d] = psxBios_sys_a0_8d;
3229 //biosA0[0x8e] = psxBios_sys_a0_8e;
3230 //biosA0[0x8f] = psxBios_sys_a0_8f;
3231 biosA0[0x90] = hleExc0_1_2;
3232 biosA0[0x91] = hleExc0_0_2;
3233 biosA0[0x92] = hleExc0_1_1;
3234 biosA0[0x93] = hleExc0_0_1;
3235 //biosA0[0x94] = psxBios_sys_a0_94;
3236 //biosA0[0x95] = psxBios_sys_a0_95;
3237 //biosA0[0x96] = psxBios_AddCDROMDevice;
3238 //biosA0[0x97] = psxBios_AddMemCardDevide;
3239 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3240 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3241 //biosA0[0x9a] = psxBios_sys_a0_9a;
3242 //biosA0[0x9b] = psxBios_sys_a0_9b;
3243 //biosA0[0x9c] = psxBios_SetConf;
3244 //biosA0[0x9d] = psxBios_GetConf;
3245 //biosA0[0x9e] = psxBios_sys_a0_9e;
3246 biosA0[0x9f] = psxBios_SetMem;
3247 //biosA0[0xa0] = psxBios__boot;
3248 //biosA0[0xa1] = psxBios_SystemError;
3249 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3250 biosA0[0xa3] = psxBios_DequeueCdIntr;
3251 //biosA0[0xa4] = psxBios_sys_a0_a4;
3252 //biosA0[0xa5] = psxBios_ReadSector;
3253 biosA0[0xa6] = psxBios_get_cd_status;
3254 //biosA0[0xa7] = psxBios_bufs_cb_0;
3255 //biosA0[0xa8] = psxBios_bufs_cb_1;
3256 //biosA0[0xa9] = psxBios_bufs_cb_2;
3257 //biosA0[0xaa] = psxBios_bufs_cb_3;
3258 biosA0[0xab] = psxBios__card_info;
3259 biosA0[0xac] = psxBios__card_load;
3260 //biosA0[0axd] = psxBios__card_auto;
3261 //biosA0[0xae] = psxBios_bufs_cd_4;
3262 //biosA0[0xaf] = psxBios_sys_a0_af;
3263 //biosA0[0xb0] = psxBios_sys_a0_b0;
3264 //biosA0[0xb1] = psxBios_sys_a0_b1;
3265 //biosA0[0xb2] = psxBios_do_a_long_jmp
3266 //biosA0[0xb3] = psxBios_sys_a0_b3;
3267 //biosA0[0xb4] = psxBios_sub_function;
3268//*******************B0 CALLS****************************
3269 biosB0[0x00] = psxBios_SysMalloc;
3270 //biosB0[0x01] = psxBios_sys_b0_01;
3271 biosB0[0x02] = psxBios_SetRCnt;
3272 biosB0[0x03] = psxBios_GetRCnt;
3273 biosB0[0x04] = psxBios_StartRCnt;
3274 biosB0[0x05] = psxBios_StopRCnt;
3275 biosB0[0x06] = psxBios_ResetRCnt;
3276 biosB0[0x07] = psxBios_DeliverEvent;
3277 biosB0[0x08] = psxBios_OpenEvent;
3278 biosB0[0x09] = psxBios_CloseEvent;
3279 biosB0[0x0a] = psxBios_WaitEvent;
3280 biosB0[0x0b] = psxBios_TestEvent;
3281 biosB0[0x0c] = psxBios_EnableEvent;
3282 biosB0[0x0d] = psxBios_DisableEvent;
3283 biosB0[0x0e] = psxBios_OpenTh;
3284 biosB0[0x0f] = psxBios_CloseTh;
3285 biosB0[0x10] = psxBios_ChangeTh;
3286 //biosB0[0x11] = psxBios_psxBios_b0_11;
3287 biosB0[0x12] = psxBios_InitPAD;
3288 biosB0[0x13] = psxBios_StartPAD;
3289 biosB0[0x14] = psxBios_StopPAD;
3290 biosB0[0x15] = psxBios_PAD_init;
3291 biosB0[0x16] = psxBios_PAD_dr;
3292 biosB0[0x17] = psxBios_ReturnFromException;
3293 biosB0[0x18] = psxBios_ResetEntryInt;
3294 biosB0[0x19] = psxBios_HookEntryInt;
3295 //biosB0[0x1a] = psxBios_sys_b0_1a;
3296 //biosB0[0x1b] = psxBios_sys_b0_1b;
3297 //biosB0[0x1c] = psxBios_sys_b0_1c;
3298 //biosB0[0x1d] = psxBios_sys_b0_1d;
3299 //biosB0[0x1e] = psxBios_sys_b0_1e;
3300 //biosB0[0x1f] = psxBios_sys_b0_1f;
3301 biosB0[0x20] = psxBios_UnDeliverEvent;
3302 //biosB0[0x21] = psxBios_sys_b0_21;
3303 //biosB0[0x22] = psxBios_sys_b0_22;
3304 //biosB0[0x23] = psxBios_sys_b0_23;
3305 //biosB0[0x24] = psxBios_sys_b0_24;
3306 //biosB0[0x25] = psxBios_sys_b0_25;
3307 //biosB0[0x26] = psxBios_sys_b0_26;
3308 //biosB0[0x27] = psxBios_sys_b0_27;
3309 //biosB0[0x28] = psxBios_sys_b0_28;
3310 //biosB0[0x29] = psxBios_sys_b0_29;
3311 //biosB0[0x2a] = psxBios_sys_b0_2a;
3312 //biosB0[0x2b] = psxBios_sys_b0_2b;
3313 //biosB0[0x2c] = psxBios_sys_b0_2c;
3314 //biosB0[0x2d] = psxBios_sys_b0_2d;
3315 //biosB0[0x2e] = psxBios_sys_b0_2e;
3316 //biosB0[0x2f] = psxBios_sys_b0_2f;
3317 //biosB0[0x30] = psxBios_sys_b0_30;
3318 //biosB0[0x31] = psxBios_sys_b0_31;
3319 biosB0[0x32] = psxBios_open;
3320 biosB0[0x33] = psxBios_lseek;
3321 biosB0[0x34] = psxBios_read;
3322 biosB0[0x35] = psxBios_write;
3323 biosB0[0x36] = psxBios_close;
3324 //biosB0[0x37] = psxBios_ioctl;
3325 //biosB0[0x38] = psxBios_exit;
3326 //biosB0[0x39] = psxBios_sys_b0_39;
3327 //biosB0[0x3a] = psxBios_getc;
3328 //biosB0[0x3b] = psxBios_putc;
3329 biosB0[0x3c] = psxBios_getchar;
3330 //biosB0[0x3e] = psxBios_gets;
3331 //biosB0[0x40] = psxBios_cd;
3332 biosB0[0x41] = psxBios_format;
3333 biosB0[0x42] = psxBios_firstfile;
3334 biosB0[0x43] = psxBios_nextfile;
3335 biosB0[0x44] = psxBios_rename;
3336 biosB0[0x45] = psxBios_delete;
3337 //biosB0[0x46] = psxBios_undelete;
3338 //biosB0[0x47] = psxBios_AddDevice;
3339 //biosB0[0x48] = psxBios_RemoteDevice;
3340 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3341 biosB0[0x4a] = psxBios_InitCARD;
3342 biosB0[0x4b] = psxBios_StartCARD;
3343 biosB0[0x4c] = psxBios_StopCARD;
3344 //biosB0[0x4d] = psxBios_sys_b0_4d;
3345 biosB0[0x4e] = psxBios__card_write;
3346 biosB0[0x4f] = psxBios__card_read;
3347 biosB0[0x50] = psxBios__new_card;
3348 biosB0[0x51] = psxBios_Krom2RawAdd;
3349 //biosB0[0x52] = psxBios_sys_b0_52;
3350 //biosB0[0x53] = psxBios_sys_b0_53;
3351 //biosB0[0x54] = psxBios__get_errno;
3352 biosB0[0x55] = psxBios__get_error;
3353 biosB0[0x56] = psxBios_GetC0Table;
3354 biosB0[0x57] = psxBios_GetB0Table;
3355 biosB0[0x58] = psxBios__card_chan;
3356 //biosB0[0x59] = psxBios_sys_b0_59;
3357 //biosB0[0x5a] = psxBios_sys_b0_5a;
3358 biosB0[0x5b] = psxBios_ChangeClearPad;
3359 biosB0[0x5c] = psxBios__card_status;
3360 biosB0[0x5d] = psxBios__card_wait;
3361//*******************C0 CALLS****************************
3362 biosC0[0x00] = psxBios_InitRCnt;
3363 biosC0[0x01] = psxBios_InitException;
3364 biosC0[0x02] = psxBios_SysEnqIntRP;
3365 biosC0[0x03] = psxBios_SysDeqIntRP;
3366 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3367 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3368 //biosC0[0x06] = psxBios_ExceptionHandler;
3369 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3370 biosC0[0x08] = psxBios_SysInitMemory;
3371 //biosC0[0x09] = psxBios_SysInitKMem;
3372 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3373 //biosC0[0x0b] = psxBios_SystemError;
3374 biosC0[0x0c] = psxBios_InitDefInt;
3375 //biosC0[0x0d] = psxBios_sys_c0_0d;
3376 //biosC0[0x0e] = psxBios_sys_c0_0e;
3377 //biosC0[0x0f] = psxBios_sys_c0_0f;
3378 //biosC0[0x10] = psxBios_sys_c0_10;
3379 //biosC0[0x11] = psxBios_sys_c0_11;
3380 //biosC0[0x12] = psxBios_InstallDevices;
3381 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3382 //biosC0[0x14] = psxBios_sys_c0_14;
3383 //biosC0[0x15] = psxBios__cdevinput;
3384 //biosC0[0x16] = psxBios__cdevscan;
3385 //biosC0[0x17] = psxBios__circgetc;
3386 //biosC0[0x18] = psxBios__circputc;
3387 //biosC0[0x19] = psxBios_ioabort;
3388 //biosC0[0x1a] = psxBios_sys_c0_1a
3389 //biosC0[0x1b] = psxBios_KernelRedirect;
3390 //biosC0[0x1c] = psxBios_PatchAOTable;
3391//************** THE END ***************************************
3392/**/
3393
3394 pad_buf = NULL;
3395 heap_addr = NULL;
3396 heap_end = NULL;
3397 heap_size = 0;
3398 memset(FDesc, 0, sizeof(FDesc));
3399 card_active_chan = 0;
3400
3401 // initial RNG seed
3402 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3403
3404 rom32 = (u32 *)psxR;
3405 rom32[0x100/4] = SWAP32(0x19951204);
3406 rom32[0x104/4] = SWAP32(3);
3407 strcpy(psxR + 0x108, "PCSX authors");
3408 strcpy(psxR + 0x12c, "PCSX HLE");
3409
3410 // fonts
3411 len = 0x80000 - 0x66000;
3412 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3413 len = 0x80000 - 0x69d68;
3414 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3415
3416 // memory size 2 MB
3417 psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3418
3419 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3420 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3421 Here are some examples of games not working with this fix in place :
3422 R-type won't get past the Irem logo if not implemented.
3423 Crash Team Racing will softlock after the Sony logo.
3424 */
3425
3426 ram32 = (u32 *)psxM;
3427 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3428 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3429 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3430 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3431
3432 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3433 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3434
3435 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3436 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3437 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3438 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3439
3440 ram32[0x00a0/4] = HLEOP(hleop_a0);
3441 ram32[0x00b0/4] = HLEOP(hleop_b0);
3442 ram32[0x00c0/4] = HLEOP(hleop_c0);
3443
3444 setup_tt(4, 16);
3445
3446 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3447 strcpy((char *)&ram32[0xeff0/4], "bu");
3448
3449 // default exception handler chains
3450 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3451 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3452 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3453 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3454 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3455 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3456 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3457 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3458
3459 setup_mips_code();
3460
3461 // fill the api jumptables with fake entries as some games patch them
3462 // (or rather the funcs listed there)
3463 ptr = (u32 *)&psxM[A_A0_TABLE];
3464 for (i = 0; i < 256; i++)
3465 ptr[i] = SWAP32(0x1000);
3466
3467 ptr = (u32 *)&psxM[A_B0_TABLE];
3468 for (i = 0; i < 256; i++)
3469 ptr[i] = SWAP32(0x2000);
3470 // B(5b) is special because games patch (sometimes even jump to)
3471 // code at fixed offsets from it, nocash lists offsets:
3472 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3473 // call: +7a0=4b70, +884=4c54, +894=4c64
3474 ptr[0x5b] = SWAP32(0x43d0);
3475 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3476
3477 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3478 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3479 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3480
3481 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3482 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3483
3484 ptr = (u32 *)&psxM[A_C0_TABLE];
3485 for (i = 0; i < 256/2; i++)
3486 ptr[i] = SWAP32(0x3000);
3487 ptr[6] = SWAP32(A_EXCEPTION);
3488
3489 // more HLE traps
3490 ram32[0x1000/4] = HLEOP(hleop_dummy);
3491 ram32[0x2000/4] = HLEOP(hleop_dummy);
3492 ram32[0x3000/4] = HLEOP(hleop_dummy);
3493 ram32[0x4c54/4] = HLEOP(hleop_dummy); // for B12_InitPad?
3494 ram32[0x8000/4] = HLEOP(hleop_execret);
3495
3496 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3497 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3498 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3499 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3500 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3501 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3502}
3503
3504void psxBiosShutdown() {
3505}
3506
3507void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt) {
3508 if (tcb_cnt != 4 || evcb_cnt != 16)
3509 setup_tt(tcb_cnt, evcb_cnt);
3510}
3511
3512#define psxBios_PADpoll(pad) { \
3513 PAD##pad##_startPoll(pad); \
3514 pad_buf##pad[0] = 0; \
3515 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3516 if (!(pad_buf##pad[1] & 0x0f)) { \
3517 bufcount = 32; \
3518 } else { \
3519 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3520 } \
3521 PAD##pad##_poll(0); \
3522 i = 2; \
3523 while (bufcount--) { \
3524 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3525 } \
3526}
3527
3528static void biosPadHLE() {
3529 if (pad_buf != NULL) {
3530 u32 *buf = (u32*)pad_buf;
3531
3532 PAD1_startPoll(1);
3533 if (PAD1_poll(0x42) == 0x23) {
3534 PAD1_poll(0);
3535 *buf = PAD1_poll(0) << 8;
3536 *buf |= PAD1_poll(0);
3537 PAD1_poll(0);
3538 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3539 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3540 } else {
3541 PAD1_poll(0);
3542 *buf = PAD1_poll(0) << 8;
3543 *buf|= PAD1_poll(0);
3544 }
3545
3546 PAD2_startPoll(2);
3547 if (PAD2_poll(0x42) == 0x23) {
3548 PAD2_poll(0);
3549 *buf |= PAD2_poll(0) << 24;
3550 *buf |= PAD2_poll(0) << 16;
3551 PAD2_poll(0);
3552 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3553 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3554 } else {
3555 PAD2_poll(0);
3556 *buf |= PAD2_poll(0) << 24;
3557 *buf |= PAD2_poll(0) << 16;
3558 }
3559 }
3560}
3561
3562static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3563{
3564 use_cycles(10);
3565 if (enable) {
3566 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3567 psxBios_ReturnFromException();
3568 }
3569 else
3570 pc0 = ra;
3571}
3572
3573// hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3574// so this is only partially implemented
3575void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3576{
3577 u32 cdrom_dma_ack_enable = 1; // a000b93c
3578 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3579}
3580
3581void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3582{
3583 u32 ret = 0;
3584 //PSXBIOS_LOG("%s\n", __func__);
3585
3586 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3587 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3588 //if (--cdrom_irq_counter == 0) // 0xa0009180
3589 // DeliverEvent(0xf0000003, 0x10);
3590 use_cycles(22);
3591 ret = 1;
3592 }
3593 mips_return_c(ret, 20);
3594}
3595
3596void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3597{
3598 u32 cdrom_irq_ack_enable = 1; // a000b938
3599 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3600}
3601
3602void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3603{
3604 u32 ret = 0;
3605 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3606 PSXBIOS_LOG("%s TODO\n", __func__);
3607 ret = 1;
3608 }
3609 mips_return_c(ret, 20);
3610}
3611
3612void hleExc0_2_2_syscall() // not in any A/B/C table
3613{
3614 u32 code = (psxRegs.CP0.n.Cause & 0x3c) >> 2;
3615 u32 tcbPtr = loadRam32(A_TT_PCB);
3616 TCB *tcb = loadRam32ptr(tcbPtr);
3617
3618 if (code != R3000E_Syscall) {
3619 if (code != 0) {
3620 DeliverEvent(0xf0000010, 0x1000);
3621 psxBios_SystemErrorUnresolvedException();
3622 }
3623 mips_return_c(0, 17);
3624 return;
3625 }
3626
3627 //printf("%s c=%d a0=%d\n", __func__, code, a0);
3628 tcb->epc += SWAP32(4);
3629 switch (a0) {
3630 case 0: // noop
3631 break;
3632
3633 case 1: { // EnterCritical - disable irqs
3634 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3635 tcb->reg[2] = SWAP32(was_enabled);
3636 tcb->sr &= SWAP32(~0x404);
3637 break;
3638 }
3639 case 2: // ExitCritical - enable irqs
3640 tcb->sr |= SWAP32(0x404);
3641 break;
3642
3643 case 3: { // ChangeThreadSubFunction
3644 u32 tcbPtr = loadRam32(A_TT_PCB);
3645 storeRam32(tcbPtr, a1);
3646 break;
3647 }
3648 default:
3649 DeliverEvent(0xf0000010, 0x4000);
3650 break;
3651 }
3652 use_cycles(30);
3653 psxBios_ReturnFromException();
3654}
3655
3656void hleExc1_0_1(void)
3657{
3658 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3659 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3660}
3661
3662static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3663{
3664 u32 ret = 0;
3665 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3666 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3667 ret = 1;
3668 }
3669 mips_return_c(ret, 22);
3670}
3671
3672void hleExc1_0_2(void)
3673{
3674 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3675}
3676
3677void hleExc1_1_1(void)
3678{
3679 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3680 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3681}
3682
3683void hleExc1_1_2(void)
3684{
3685 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3686}
3687
3688void hleExc1_2_1(void)
3689{
3690 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3691 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3692}
3693
3694void hleExc1_2_2(void)
3695{
3696 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3697}
3698
3699void hleExc1_3_1(void)
3700{
3701 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3702 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3703}
3704
3705void hleExc1_3_2(void)
3706{
3707 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3708}
3709
3710void hleExc3_0_2_defint(void)
3711{
3712 static const struct {
3713 u8 ev, irqbit;
3714 } tab[] = {
3715 { 3, 2 }, // cdrom
3716 { 9, 9 }, // spu
3717 { 2, 1 }, // gpu
3718 { 10, 10 }, // io
3719 { 11, 8 }, // sio
3720 { 1, 0 }, // vbl
3721 { 5, 4 }, // rcnt0
3722 { 6, 5 }, // rcnt1
3723 { 6, 6 }, // rcnt2 (bug)
3724 { 8, 7 }, // sio rx
3725 { 4, 3 }, // sio
3726 };
3727 size_t i;
3728 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3729 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3730 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3731 use_cycles(7);
3732 }
3733
3734 }
3735 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3736}
3737
3738void hleExcPadCard1(void)
3739{
3740 if (loadRam32(A_PAD_IRQR_ENA)) {
3741 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3742 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
3743 int i, bufcount;
3744
3745 psxBios_PADpoll(1);
3746 psxBios_PADpoll(2);
3747 biosPadHLE();
3748 use_cycles(100);
3749 }
3750 if (loadRam32(A_PAD_ACK_VBL))
3751 psxHwWrite16(0x1f801070, ~1);
3752 if (loadRam32(A_CARD_IRQR_ENA)) {
3753 // todo, maybe
3754 }
3755
3756 mips_return_c(0, 18);
3757}
3758
3759void hleExcPadCard2(void)
3760{
3761 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
3762 mips_return_c(ret, 15);
3763}
3764
3765void psxBiosException() {
3766 u32 tcbPtr = loadRam32(A_TT_PCB);
3767 u32 *chains = loadRam32ptr(A_TT_ExCB);
3768 TCB *tcb = loadRam32ptr(tcbPtr);
3769 u32 ptr, *chain;
3770 int c, lim;
3771 int i;
3772
3773 // save the regs
3774 // $at, $v0, $v1 already saved by the mips code at A_EXCEPTION
3775 for (i = 4; i < 32; i++) {
3776 if (i == 26) // $k0
3777 continue;
3778 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
3779 }
3780 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
3781 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
3782 tcb->epc = SWAP32(psxRegs.CP0.n.EPC);
3783 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
3784 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
3785 sp = fp = loadRam32(A_EXC_SP);
3786 gp = A_EXC_GP;
3787 use_cycles(46);
3788
3789 // do the chains (always 4)
3790 for (c = lim = 0; c < 4; c++) {
3791 if (chains[c * 2] == 0)
3792 continue;
3793 ptr = SWAP32(chains[c * 2]);
3794 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
3795 chain = castRam32ptr(ptr);
3796 use_cycles(14);
3797 lim++;
3798 if (chain[2] == 0)
3799 continue;
3800 softCallInException(SWAP32(chain[2]));
3801 if (returned_from_exception())
3802 return;
3803
3804 if (v0 == 0 || chain[1] == 0)
3805 continue;
3806 softCallInException(SWAP32(chain[1]));
3807 if (returned_from_exception())
3808 return;
3809 }
3810 }
3811 assert(lim < 100);
3812
3813 // return from exception (custom or default)
3814 use_cycles(23);
3815 ptr = loadRam32(A_EEXIT_PTR);
3816 if (ptr != A_EEXIT_DEF) {
3817 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
3818 longjmp_load(jmp_buf);
3819 v0 = 1;
3820 pc0 = ra;
3821 return;
3822 }
3823 psxBios_ReturnFromException();
3824}
3825
3826#define bfreeze(ptr, size) { \
3827 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3828 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3829 base += size; \
3830}
3831
3832#define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3833#define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3834
3835#define bfreezepsxMptr(ptr, type) { \
3836 if (Mode == 1) { \
3837 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3838 else psxRu32ref(base) = 0; \
3839 } else { \
3840 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3841 else (ptr) = NULL; \
3842 } \
3843 base += sizeof(u32); \
3844}
3845
3846void psxBiosFreeze(int Mode) {
3847 u32 base = 0x40000;
3848
3849 bfreezepsxMptr(pad_buf, int);
3850 bfreezepsxMptr(heap_addr, u32);
3851 bfreezes(FDesc);
3852 bfreezel(&card_active_chan);
3853 bfreezel(&heap_size);
3854}