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