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