From 3e6bf9845be84f10b56e1ea5e2b27d4d1666f2b6 Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Mon, 19 Jan 2026 10:22:56 +0100 Subject: [PATCH 1/3] OpenBIOS: add preliminary ZN-1/ZN-2 support --- src/mips/common/hardware/hwregs.h | 2 + src/mips/common/hardware/hwregs.inc | 2 + src/mips/openbios/Makefile | 14 +- src/mips/openbios/README.md | 5 +- src/mips/openbios/boot/psx.s | 4 + src/mips/openbios/boot/system573.s | 12 +- src/mips/openbios/boot/zn.s | 255 ++++++++++++++++++++++++++++ src/mips/openbios/main/main.c | 31 +++- 8 files changed, 306 insertions(+), 19 deletions(-) create mode 100644 src/mips/openbios/boot/zn.s diff --git a/src/mips/common/hardware/hwregs.h b/src/mips/common/hardware/hwregs.h index effcfc087..1af61756a 100644 --- a/src/mips/common/hardware/hwregs.h +++ b/src/mips/common/hardware/hwregs.h @@ -60,4 +60,6 @@ SOFTWARE. #define SYS573_WATCHDOG HW_U16(0x1f5c0000) #define SYS573_7SEG_POST HW_U16(0x1f640010) +#define ZN_BOARD_CONFIG HW_U8(0x1fa10200) + #define POST HW_U8(0xbf802041) diff --git a/src/mips/common/hardware/hwregs.inc b/src/mips/common/hardware/hwregs.inc index f277f9ea8..4250de4e8 100644 --- a/src/mips/common/hardware/hwregs.inc +++ b/src/mips/common/hardware/hwregs.inc @@ -43,3 +43,5 @@ SOFTWARE. .set SYS573_JAMMA_P2_EXT, 0x1f40000e .set SYS573_WATCHDOG, 0x1f5c0000 .set SYS573_7SEG_POST, 0x1f640010 + +.set ZN_BOARD_CONFIG, 0x1fa10200 diff --git a/src/mips/openbios/Makefile b/src/mips/openbios/Makefile index 9d2978e44..81075f3b0 100644 --- a/src/mips/openbios/Makefile +++ b/src/mips/openbios/Makefile @@ -88,19 +88,23 @@ uC-sdk-glue/init.c \ # Ensure all files are always cleaned up. ifeq ($(MAKECMDGOALS),clean) -SRCS += boot/psx.s boot/system573.s font1.o font2.o ./psexe_data.o +SRCS += boot/psx.s boot/system573.s boot/zn.s font1.o font2.o ./psexe_data.o endif ifeq ($(MAKECMDGOALS),deepclean) -SRCS += boot/psx.s boot/system573.s font1.o font2.o ./psexe_data.o +SRCS += boot/psx.s boot/system573.s boot/zn.s font1.o font2.o ./psexe_data.o endif CPPFLAGS = -ifeq ($(BOARD),system573) -CPPFLAGS += -DOPENBIOS_BOARD_SYS573 -# The 573 does not support CD-ROM or cheat cart booting. +ifneq ($(BOARD),psx) +# Disable cheat cart builds and CD-ROM/shell support for arcade boards. BOOT = rom BOOT_MODE = psexe +ifeq ($(BOARD),system573) +CPPFLAGS += -DOPENBIOS_BOARD_SYS573 +else ifeq ($(BOARD),zn) +CPPFLAGS += -DOPENBIOS_BOARD_ZN +endif endif ifeq ($(BOOT),rom) diff --git a/src/mips/openbios/README.md b/src/mips/openbios/README.md index 211cb323c..dc90acdca 100644 --- a/src/mips/openbios/README.md +++ b/src/mips/openbios/README.md @@ -32,7 +32,8 @@ The Makefile features several toggles to mutate the way the compilation works. D - `BUILD=SmallDebug` will produce a working, yet somewhat debuggable version of the code. - `BOOT=cart` will build the kernel as an expansion port ROM, bootable from an Action Replay or similar cheat carts. This will disable support for booting from a cart in order to prevent bootlooping. -- `BOARD=system573` will build a kernel that can run on the Konami System 573 arcade board. Note that this option is only useful alongside `EMBED_PSEXE`, as it will force `BOOT=rom` and `BOOT_MODE=psexe` due to the 573's different CD-ROM hardware. +- `BOARD=system573` will build a kernel that can run on the Konami System 573 arcade board. This option is only useful alongside `EMBED_PSEXE`, as it will force `BOOT=rom` and `BOOT_MODE=psexe`; as with Konami's BIOS, game booting is not implemented in the kernel and must be handled by a custom shell. +- `BOARD=zn` will build a kernel that can run on the Sony ZN-1 and ZN-2 arcade boards. This option is only useful alongside `EMBED_PSEXE`, as it will force `BOOT=rom` and `BOOT_MODE=psexe`; unlike the official ZN BIOSes, OpenBIOS does *not* implement game decryption and booting in the kernel. - `EMBED_PSEXE=binary.ps-exe` will embed the specified executable into the kernel and run it before the shell. - `BOOT_MODE=fast` will skip running the shell and try booting from the CD-ROM after the embedded executable returns, or immediately on boot if `EMBED_PSEXE` is not used. Note that the code will *not* wait for a disc to be inserted after the executable returns. The old `FASTBOOT=true` option is kept for compatibility and is equivalent to `BOOT_MODE=fast`. - `BOOT_MODE=psexe` will remove the shell and CD-ROM boot code altogether. This is meant to be used alongside `EMBED_PSEXE` to build ROMs for arcade systems and such, which typically use non-standard storage devices and require a custom shell. @@ -53,7 +54,7 @@ While the first part is the main one that's being targeted here, the second one The original code was most likely chunked into several sub-projects, that were all linked together like a giant patchwork. This approach is less readable, and for this reason, we're not going to do this. However this will result in the ROM/RAM split to be less obvious, and slower at times than the original. Tuning of the hot functions is eventually required. -The startup point for the ROM version is the function `_reset` located in [`boot/psx.s`](boot/psx.s) (or [`boot/system573.s`](boot/system573.s) depending on which board the kernel is compiled for). The rom cart version is the function `_cartBoot` in the same file. +The startup point for the ROM version is the function `_reset` located in [`boot/psx.s`](boot/psx.s) (or [`system573.s`](boot/system573.s) or [`zn.s`](boot/zn.s) depending on which board the kernel is compiled for). The rom cart version is the function `_cartBoot` in the same file. ## Direction diff --git a/src/mips/openbios/boot/psx.s b/src/mips/openbios/boot/psx.s index 9a714ecbd..9ee8d3564 100644 --- a/src/mips/openbios/boot/psx.s +++ b/src/mips/openbios/boot/psx.s @@ -212,6 +212,10 @@ bss_init_skip: li $t0, 0xb88 sw $t0, RAM_SIZE + /* set __globals60.ramsize to 2 MB */ + li $t0, 2 + sw $t0, 0x60($0) + jal _ucsdk_start li $t0, 0x1f802080 diff --git a/src/mips/openbios/boot/system573.s b/src/mips/openbios/boot/system573.s index d1adef1e1..97b86a475 100644 --- a/src/mips/openbios/boot/system573.s +++ b/src/mips/openbios/boot/system573.s @@ -113,10 +113,10 @@ _boot: /* Clear the watchdog. */ sh $0, SYS573_WATCHDOG - /* The 700B01 BIOS uses the following code to determine whether the board - is an older one with eight 512 KB RAM chips, or a revision D populated - with two 2 MB chips. The 700A01 BIOS predates such revision and always - sets the RAM size register to 0xc80. */ + /* The 700B01 BIOS probes the ASIC revision bit to determine whether the + board is an older one with eight 512 KB RAM chips or a revision D + populated with two 4 MB (?) chips. The 700A01 BIOS predates revision D + and simply uses a hardcoded DRAM controller configuration instead. */ lhu $t1, SYS573_JAMMA_P2_EXT li $t0, 0xc80 andi $t1, 1 << 10 @@ -228,6 +228,10 @@ bss_init_skip: la $sp, __sp move $fp, $sp + /* set __globals60.ramsize to 4 MB */ + li $t0, 4 + sw $t0, 0x60($0) + jal _ucsdk_start li $t0, 0x1f802080 diff --git a/src/mips/openbios/boot/zn.s b/src/mips/openbios/boot/zn.s new file mode 100644 index 000000000..28210e5cc --- /dev/null +++ b/src/mips/openbios/boot/zn.s @@ -0,0 +1,255 @@ +/* + +MIT License + +Copyright (c) 2019 PCSX-Redux authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +.include "common/hardware/hwregs.inc" + + .section .boot, "ax", @progbits + .align 2 + .global flushCache + .global _reset + .type _reset, @function + +_reset: + /* set bios memory bus width and speed. */ + li $t0, (19 << 16) | 0x243f + sw $t0, SBUS_DEV2_CTRL + + /* psx.s configures the DRAM controller here, but we are going to do that + after setting up DEV1/EXP3 as we have to probe a bit in there first. */ + nop + nop + nop + nop + + /* this may be here to let the hardware pick up the new bus settings + before moving on with the actual code. Also, some tools like IDA + or even PCSX-Redux use it as a signature to detect this is a PS1 + BIOS file. */ + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + + /* jumping over the interrupt vector. */ + j _boot + +.ascii "OpenBIOS" + + .section .text._boot, "ax", @progbits + .align 2 + .global _boot + .type _boot, @function + +_boot: + /* initializing all of the buses now */ + + /* Floating time increased by 1 cycle from the default value in psx.s */ + li $t0, 0x31225 + sw $t0, SBUS_COM_CTRL + + li $t0, 0x1f000000 + sw $t0, SBUS_DEV0_ADDR + + li $t0, 0x1f802000 + sw $t0, SBUS_DEV8_ADDR + + /* 8 MB with a 16-bit bus, different value from the default one in psx.s */ + li $t0, 0x1734ff + sw $t0, SBUS_DEV0_CTRL + + li $t0, 0x200931e1 + sw $t0, SBUS_DEV4_CTRL + + /* 1 byte with an 8-bit bus, different value from the default one in psx.s + (probably a failed attempt to set the CD-ROM region size to 0 bytes so + that any access would have generated an exception) */ + li $t0, 0x843 + sw $t0, SBUS_DEV5_CTRL + + /* 2 MB with a 16-bit bus, different value from the default one in psx.s */ + li $t0, 0x153410 + sw $t0, SBUS_DEV1_CTRL + + /* 256 bytes with a 16-bit bus, different value from the default one in psx.s + (the ZN BIOS actually uses 0x71011 here, but it needs to be extended from + 128 to 256 bytes in order for the writes to 0x1f802080 not to crash on + real hardware) + */ + li $t0, 0x81011 + sw $t0, SBUS_DEV8_CTRL + + /* The ZN BIOS probes the board configuration register to determine the RAM + layout and sets up both the DRAM controller and __globals60.ramsize + accordingly. */ + lbu $t1, ZN_BOARD_CONFIG + la $t0, _zn_ram_configs + andi $t1, 3 + sll $t1, 2 + addu $t1, $t0 + + lhu $t0, 0($t1) + lhu $t1, 2($t1) + sw $t0, RAM_SIZE + nop + sw $t1, 0x60($0) + + /* clearing out all registers */ + .set push + .set noat + move $1, $0 + .set pop + move $2, $0 + move $3, $0 + move $4, $0 + move $5, $0 + move $6, $0 + move $7, $0 + move $8, $0 + move $9, $0 + move $10, $0 + move $11, $0 + move $12, $0 + move $13, $0 + move $14, $0 + move $15, $0 + move $16, $0 + move $17, $0 + move $18, $0 + move $19, $0 + move $20, $0 + move $21, $0 + move $22, $0 + move $23, $0 + move $24, $0 + move $25, $0 + move $26, $0 + move $27, $0 + move $28, $0 + move $29, $0 + move $30, $0 + move $31, $0 + + jal flushCache + + /* ensuring cop0 is fully reset */ + mtc0 $0, $7 + nop + mtc0 $0, $3 + nop + mtc0 $0, $5 + nop + mtc0 $0, $6 + nop + mtc0 $0, $9 + nop + mtc0 $0, $11 + nop + mtc0 $0, $12 + nop + mtc0 $0, $13 + nop + + /* Extra from OpenBIOS, not in the original BIOS: + Enable cop2, as some games may rely on it being + enabled as a side effect of the shell running, + and our replacement shell does not enable it. */ + lui $t0, 0x4000 + mtc0 $t0, $12 + nop + + /* Now we are ready for a typical crt0. + The original bios does not do this, most likely + for speed reasons. It would be more efficient to + run these loops in RAM instead of the ROM. But + we have enough code that would rely in all this + to be set up already before starting, it would + be a mistake to not do it here. */ + la $t0, __data_start + la $t1, __data_end + la $t2, __rom_data_start + + beq $t0, $t1, data_copy_skip + +data_copy: + lw $t3, 0($t2) + sw $t3, 0($t0) + addiu $t0, 4 + addiu $t2, 4 + bne $t0, $t1, data_copy + +data_copy_skip: + la $t0, __bss_start + la $t1, __bss_end + + beq $t0, $t1, bss_init_skip + +bss_init: + sw $0, 0($t0) + addiu $t0, 4 + bne $t0, $t1, bss_init + +bss_init_skip: + /* technically have to set $gp, but we are not using it, so, not */ + la $sp, __sp + move $fp, $sp + + jal _ucsdk_start + + li $t0, 0x1f802080 + li $t1, 10 + sb $t1, 0($t0) + sb $t1, 1($t0) +stop: + b stop + + .section .rodata._zn_ram_configs, "a", @progbits + .align 2 + +_zn_ram_configs: + /* Configuration 00: two 2 MB banks, bit 3 set */ + .hword 0xcbc, 4 + /* Configuration 01: two 2 MB banks */ + .hword 0xcb4, 4 + /* Configuration 10: single 8 MB bank */ + .hword 0xbb4, 8 + /* Configuration 11: two 8 MB banks */ + .hword 0xfa4, 16 diff --git a/src/mips/openbios/main/main.c b/src/mips/openbios/main/main.c index c21bcaf8e..18d57005b 100644 --- a/src/mips/openbios/main/main.c +++ b/src/mips/openbios/main/main.c @@ -70,11 +70,10 @@ void bootThunk() { } int main() { - // RAM size - __globals60.ramsize = 0x02; - // ?? + // __globals60.ramsize would be set here in the retail BIOS, however we have + // already done so in the startup code (it's easier to do it there for + // arcade boards - the ZN kernel does the same). __globals60.unk1 = 0x00; - // ?? __globals60.unk2 = 0xff; POST = 0x0f; @@ -84,14 +83,14 @@ int main() { // separate functions for each hook, one in charge of validating the // signature and the other actually jumping to the vector. For simplicity's // sake, both steps are combined into a call to a single function here. The - // 573 kernel lacks these calls completely (rather than stubbing out the - // function's body as done here). + // 573 and ZN kernels lack these calls completely (rather than stubbing out + // the function's body as done here). runExp1PreHook(); POST = 0x0e; // Same as above, the retail BIOS lacks the drawSplashScreen() call // completely instead of merely stubbing out the function. Note that this - // functionality is in no way 573-specific, so it makes sense to allow + // functionality is in no way arcade-specific, so it makes sense to allow // enabling it regardless of the target platform. drawSplashScreen(); g_installTTY = 0; @@ -296,6 +295,21 @@ void gameMainThunk(struct psxExeHeader *binaryInfo, int argc, char **argv) { extern struct BuildId __build_id, __build_id_end; +// This function is specific to the ZN kernel and prints some basic information +// about the amount of memory installed on the board, complete with typos and a +// hint at the fact there may have been a version of the SPU with support for +// more than 512 KB of RAM. +static void printBoardConfiguration() { +#ifdef OPENBIOS_BOARD_ZN + uint8_t config = ZN_BOARD_CONFIG; + int is2MBSPURAM = (config >> 2) & 1; + int is2MBVRAM = (config >> 3) & 1; + int revision = (config >> 5) & 7; + psxprintf("Borad Configuration: %02x (rev=%d,mem=%dM,smem=%cM,vmem=%dM)\n", config, revision - 2, + __globals60.ramsize, is2MBSPURAM ? '2' : 'h', is2MBVRAM + 1); +#endif +} + static void boot(char *systemCnfPath, char *binaryPath) { POST = 1; writeCOP0Status(readCOP0Status() & ~0x401); @@ -339,9 +353,10 @@ static void boot(char *systemCnfPath, char *binaryPath) { } buildIDstring[count * 2] = 0; } - psxprintf("PS-X Realtime Kernel OpenBios - build id %s.\nCopyright (C) 2019-2025 PCSX-Redux authors.\n", + psxprintf("PS-X Realtime Kernel OpenBios - build id %s.\nCopyright (C) 2019-2026 PCSX-Redux authors.\n", buildIDstring); } + printBoardConfiguration(); POST = 6; muteSpu(); s_configuration = g_defaultConfiguration; From 4370a66e01786e30d2453b71dc8d39ee432e61de Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Mon, 19 Jan 2026 11:18:26 +0100 Subject: [PATCH 2/3] OpenBIOS: ZN-2 additions, implement getSystemInfo() --- src/mips/common/hardware/hwregs.h | 3 ++ src/mips/openbios/boot/zn.s | 12 +++-- src/mips/openbios/kernel/handlers.c | 2 +- src/mips/openbios/kernel/misc.c | 81 +++++++++++++++++++++++++++-- src/mips/openbios/kernel/misc.h | 3 ++ src/mips/openbios/main/main.c | 4 +- src/mips/openbios/main/main.h | 12 ++++- 7 files changed, 104 insertions(+), 13 deletions(-) diff --git a/src/mips/common/hardware/hwregs.h b/src/mips/common/hardware/hwregs.h index 1af61756a..fb421d977 100644 --- a/src/mips/common/hardware/hwregs.h +++ b/src/mips/common/hardware/hwregs.h @@ -61,5 +61,8 @@ SOFTWARE. #define SYS573_7SEG_POST HW_U16(0x1f640010) #define ZN_BOARD_CONFIG HW_U8(0x1fa10200) +#define ZN_SIO0_MUX HW_U8(0x1fa10300) +#define ZN_COIN_CTRL HW_U8(0x1fa20000) +#define ZN_IRQ10_MUX HW_U8(0x1fa30000) #define POST HW_U8(0xbf802041) diff --git a/src/mips/openbios/boot/zn.s b/src/mips/openbios/boot/zn.s index 28210e5cc..9353ca5c1 100644 --- a/src/mips/openbios/boot/zn.s +++ b/src/mips/openbios/boot/zn.s @@ -96,7 +96,9 @@ _boot: li $t0, 0x1734ff sw $t0, SBUS_DEV0_CTRL - li $t0, 0x200931e1 + /* Read/write waitstates increased to 15 cycles from the default value in + psx.s (for ZN-2, the ZN-1 BIOS uses the same configuration as psx.s) */ + li $t0, 0x200931ff sw $t0, SBUS_DEV4_CTRL /* 1 byte with an 8-bit bus, different value from the default one in psx.s @@ -110,11 +112,11 @@ _boot: sw $t0, SBUS_DEV1_CTRL /* 256 bytes with a 16-bit bus, different value from the default one in psx.s - (the ZN BIOS actually uses 0x71011 here, but it needs to be extended from - 128 to 256 bytes in order for the writes to 0x1f802080 not to crash on - real hardware) + (the ZN-1/ZN-2 kernels actually use 0x71011/0x71077 respectively here, but + it needs to be extended from 128 to 256 bytes in order for the writes to + 0x1f802080 not to crash on real hardware) */ - li $t0, 0x81011 + li $t0, 0x81077 sw $t0, SBUS_DEV8_CTRL /* The ZN BIOS probes the board configuration register to determine the RAM diff --git a/src/mips/openbios/kernel/handlers.c b/src/mips/openbios/kernel/handlers.c index f9ef6daf3..55f56a3ca 100644 --- a/src/mips/openbios/kernel/handlers.c +++ b/src/mips/openbios/kernel/handlers.c @@ -210,7 +210,7 @@ static const void *romA0table[0xc0] = { buLowLevelOpError1, buLowLevelOpError2, buLowLevelOpError3, cardInfo, // a8 buReadTOC, buSetAutoFormat, unimplementedThunk, unimplementedThunk, // ac unimplementedThunk, unimplementedThunk, ioabortraw, unimplementedThunk, // b0 - unimplementedThunk, unimplementedThunk, unimplementedThunk, unimplementedThunk, // b4 + getSystemInfo, unimplementedThunk, unimplementedThunk, unimplementedThunk, // b4 unimplementedThunk, unimplementedThunk, unimplementedThunk, unimplementedThunk, // b8 unimplementedThunk, unimplementedThunk, unimplementedThunk, unimplementedThunk, // bc }; diff --git a/src/mips/openbios/kernel/misc.c b/src/mips/openbios/kernel/misc.c index bd256e607..571016e71 100644 --- a/src/mips/openbios/kernel/misc.c +++ b/src/mips/openbios/kernel/misc.c @@ -30,17 +30,90 @@ SOFTWARE. #include "openbios/fileio/fileio.h" #include "openbios/kernel/globals.h" +#if defined(OPENBIOS_BOARD_SYS573) +static const char s_kernelName[] = "OpenBIOS (System 573)"; +static const int s_kernelFlags = 2; +static const int s_isArcadeBoard = 1; +static const int s_unknownFlag = 0; + +static __inline__ int getBoardRevision() { return 0; } +static __inline__ int getVRAMSize() { return 2048; } +static __inline__ int getSPURAMSize() { return 512; } +#elif defined(OPENBIOS_BOARD_ZN) +static const char s_kernelName[] = "OpenBIOS (ZN-1/ZN-2)"; +static const int s_kernelFlags = 0x11001; +static const int s_isArcadeBoard = 1; +static const int s_unknownFlag = 1; + +static __inline__ int getBoardRevision() { return ((ZN_BOARD_CONFIG >> 5) & 7) - 2; } +static __inline__ int getVRAMSize() { return ((ZN_BOARD_CONFIG >> 3) & 1) ? 2048 : 1024; } +static __inline__ int getSPURAMSize() { return ((ZN_BOARD_CONFIG >> 2) & 1) ? 2048 : 512; } +#else +static const char s_kernelName[] = "OpenBIOS"; +static const int s_kernelFlags = 3; +static const int s_isArcadeBoard = 0; +static const int s_unknownFlag = 1; + +static __inline__ int getBoardRevision() { return 0; } +static __inline__ int getVRAMSize() { return 1024; } +static __inline__ int getSPURAMSize() { return 512; } +#endif + +static __inline__ uint32_t getCPURevision() { + uint32_t ret; + asm("mfc0 %0, $15\nnop\n" : "=r"(ret)); + return ret; +} + +uint32_t getSystemInfo(int index) { + switch (index) { + case 0: + return 0x20260101; + case 1: + return s_kernelFlags; + case 2: + return (uint32_t) s_kernelName; + case 3: + return getCPURevision(); + case 4: + return getBoardRevision(); + case 5: + return __globals60.ramsize << 10; + case 6: + return s_isArcadeBoard; + case 7: + return getVRAMSize(); + case 9: + return getSPURAMSize(); + case 12: + case 13: + return s_unknownFlag; + case 14: + return s_isArcadeBoard ^ 1; + default: + return 0; + } +} + void setMemSize(int memSize) { - uint32_t current = RAM_SIZE; + uint32_t value = RAM_SIZE & ~0x700; switch (memSize) { + // The retail BIOS only implements the cases for 2 and 8 MB here, + // however the 573 and ZN kernels have all cases implemented. case 2: - RAM_SIZE = current & ~0x300; + RAM_SIZE = value; + break; + case 4: + RAM_SIZE = value | 0x400; break; case 8: - RAM_SIZE = current | 0x300; + RAM_SIZE = value | 0x300; + break; + case 16: + RAM_SIZE = value | 0x700; break; default: - psxprintf("Effective memory must be 2/8 MBytes\n"); + psxprintf("Effective memory must be 2/4/8/16 MBytes\n"); return; } diff --git a/src/mips/openbios/kernel/misc.h b/src/mips/openbios/kernel/misc.h index 76a3d6f7a..dbd7ff039 100644 --- a/src/mips/openbios/kernel/misc.h +++ b/src/mips/openbios/kernel/misc.h @@ -26,4 +26,7 @@ SOFTWARE. #pragma once +#include + +uint32_t getSystemInfo(int index); void setMemSize(int memSize); diff --git a/src/mips/openbios/main/main.c b/src/mips/openbios/main/main.c index 18d57005b..2c282bc7c 100644 --- a/src/mips/openbios/main/main.c +++ b/src/mips/openbios/main/main.c @@ -314,11 +314,11 @@ static void boot(char *systemCnfPath, char *binaryPath) { POST = 1; writeCOP0Status(readCOP0Status() & ~0x401); muteSpu(); + clearZNRegisters(); POST = 2; // The 573 kernel kicks the watchdog before, after and in the middle of // copyDataAndInitializeBSS(), as it is by far the slowest part of the - // initialization sequence. clearWatchdog() is an inline function that does - // nothing in non-573 builds (see main.h). + // initialization sequence. clearWatchdog(); copyDataAndInitializeBSS(); POST = 3; diff --git a/src/mips/openbios/main/main.h b/src/mips/openbios/main/main.h index c8edae03a..546455ed7 100644 --- a/src/mips/openbios/main/main.h +++ b/src/mips/openbios/main/main.h @@ -34,12 +34,22 @@ SOFTWARE. // this inconsistency, we are going to always use an inline function for this // purpose. This additionally lets us easily stub out all watchdog calls for // non-573 builds in a single place. -static inline void clearWatchdog() { +static __inline__ void clearWatchdog() { #ifdef OPENBIOS_BOARD_SYS573 SYS573_WATCHDOG = 0; #endif } +// Similar to the case above. The ZN kernel clears these registers in a few +// different places but they are all gathered here for simplicity's sake. +static __inline__ void clearZNRegisters() { +#ifndef OPENBIOS_BOARD_ZN + ZN_SIO0_MUX = 0; + ZN_COIN_CTRL = 0; + ZN_IRQ10_MUX = 0; +#endif +} + void setConfiguration(int eventsCount, int taskCount, void* stackBase); void getConfiguration(int* eventsCount, int* taskCount, void** stackBase); From d03a31a6c4eebc028f526a2a40979576539fd744 Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Tue, 17 Feb 2026 23:36:13 +0100 Subject: [PATCH 3/3] OpenBIOS: fix __globals60.ramsize --- src/mips/openbios/README.md | 2 +- src/mips/openbios/boot/zn.s | 44 +++++++++++++++++++++------------ src/mips/openbios/kernel/misc.c | 2 +- src/mips/openbios/main/main.h | 2 +- 4 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/mips/openbios/README.md b/src/mips/openbios/README.md index dc90acdca..72af09421 100644 --- a/src/mips/openbios/README.md +++ b/src/mips/openbios/README.md @@ -33,7 +33,7 @@ The Makefile features several toggles to mutate the way the compilation works. D - `BUILD=SmallDebug` will produce a working, yet somewhat debuggable version of the code. - `BOOT=cart` will build the kernel as an expansion port ROM, bootable from an Action Replay or similar cheat carts. This will disable support for booting from a cart in order to prevent bootlooping. - `BOARD=system573` will build a kernel that can run on the Konami System 573 arcade board. This option is only useful alongside `EMBED_PSEXE`, as it will force `BOOT=rom` and `BOOT_MODE=psexe`; as with Konami's BIOS, game booting is not implemented in the kernel and must be handled by a custom shell. -- `BOARD=zn` will build a kernel that can run on the Sony ZN-1 and ZN-2 arcade boards. This option is only useful alongside `EMBED_PSEXE`, as it will force `BOOT=rom` and `BOOT_MODE=psexe`; unlike the official ZN BIOSes, OpenBIOS does *not* implement game decryption and booting in the kernel. +- `BOARD=zn` will build a kernel that can run on the Sony ZN-1 arcade board (ZN-2 support is currently broken and needs further testing). This option is only useful alongside `EMBED_PSEXE`, as it will force `BOOT=rom` and `BOOT_MODE=psexe`; unlike the official ZN BIOSes, OpenBIOS does *not* implement game decryption and booting in the kernel. - `EMBED_PSEXE=binary.ps-exe` will embed the specified executable into the kernel and run it before the shell. - `BOOT_MODE=fast` will skip running the shell and try booting from the CD-ROM after the embedded executable returns, or immediately on boot if `EMBED_PSEXE` is not used. Note that the code will *not* wait for a disc to be inserted after the executable returns. The old `FASTBOOT=true` option is kept for compatibility and is equivalent to `BOOT_MODE=fast`. - `BOOT_MODE=psexe` will remove the shell and CD-ROM boot code altogether. This is meant to be used alongside `EMBED_PSEXE` to build ROMs for arcade systems and such, which typically use non-standard storage devices and require a custom shell. diff --git a/src/mips/openbios/boot/zn.s b/src/mips/openbios/boot/zn.s index 9353ca5c1..ec9ad43e2 100644 --- a/src/mips/openbios/boot/zn.s +++ b/src/mips/openbios/boot/zn.s @@ -114,8 +114,7 @@ _boot: /* 256 bytes with a 16-bit bus, different value from the default one in psx.s (the ZN-1/ZN-2 kernels actually use 0x71011/0x71077 respectively here, but it needs to be extended from 128 to 256 bytes in order for the writes to - 0x1f802080 not to crash on real hardware) - */ + 0x1f802080 not to crash on real hardware) */ li $t0, 0x81077 sw $t0, SBUS_DEV8_CTRL @@ -125,14 +124,11 @@ _boot: lbu $t1, ZN_BOARD_CONFIG la $t0, _zn_ram_configs andi $t1, 3 - sll $t1, 2 - addu $t1, $t0 + sll $t1, 1 + addu $t0, $t1 - lhu $t0, 0($t1) - lhu $t1, 2($t1) + lhu $t0, 0($t0) sw $t0, RAM_SIZE - nop - sw $t1, 0x60($0) /* clearing out all registers */ .set push @@ -234,6 +230,15 @@ bss_init_skip: la $sp, __sp move $fp, $sp + /* set __globals60.ramsize */ + lbu $t1, ZN_BOARD_CONFIG + la $t0, _zn_ram_sizes + andi $t1, 3 + addu $t0, $t1 + + lbu $t0, 0($t0) + sw $t0, 0x60($0) + jal _ucsdk_start li $t0, 0x1f802080 @@ -245,13 +250,20 @@ stop: .section .rodata._zn_ram_configs, "a", @progbits .align 2 + .type _zn_ram_configs, @object _zn_ram_configs: - /* Configuration 00: two 2 MB banks, bit 3 set */ - .hword 0xcbc, 4 - /* Configuration 01: two 2 MB banks */ - .hword 0xcb4, 4 - /* Configuration 10: single 8 MB bank */ - .hword 0xbb4, 8 - /* Configuration 11: two 8 MB banks */ - .hword 0xfa4, 16 + .hword 0xcbc /* 00: two 2 MB banks, bit 3 set */ + .hword 0xcb4 /* 01: two 2 MB banks */ + .hword 0xbb4 /* 10: single 8 MB bank */ + .hword 0xfa4 /* 11: two 8 MB banks */ + + .section .rodata._zn_ram_sizes, "a", @progbits + .align 1 + .type _zn_ram_sizes, @object + +_zn_ram_sizes: + .byte 4 /* 00: two 2 MB banks, bit 3 set */ + .byte 4 /* 01: two 2 MB banks */ + .byte 8 /* 10: single 8 MB bank */ + .byte 16 /* 11: two 8 MB banks */ diff --git a/src/mips/openbios/kernel/misc.c b/src/mips/openbios/kernel/misc.c index 571016e71..915757623 100644 --- a/src/mips/openbios/kernel/misc.c +++ b/src/mips/openbios/kernel/misc.c @@ -41,7 +41,7 @@ static __inline__ int getVRAMSize() { return 2048; } static __inline__ int getSPURAMSize() { return 512; } #elif defined(OPENBIOS_BOARD_ZN) static const char s_kernelName[] = "OpenBIOS (ZN-1/ZN-2)"; -static const int s_kernelFlags = 0x11001; +static const int s_kernelFlags = 0x11001; // ZN-1: 0x11001, ZN-2: 0x13000 static const int s_isArcadeBoard = 1; static const int s_unknownFlag = 1; diff --git a/src/mips/openbios/main/main.h b/src/mips/openbios/main/main.h index 546455ed7..52a1d9b04 100644 --- a/src/mips/openbios/main/main.h +++ b/src/mips/openbios/main/main.h @@ -43,7 +43,7 @@ static __inline__ void clearWatchdog() { // Similar to the case above. The ZN kernel clears these registers in a few // different places but they are all gathered here for simplicity's sake. static __inline__ void clearZNRegisters() { -#ifndef OPENBIOS_BOARD_ZN +#ifdef OPENBIOS_BOARD_ZN ZN_SIO0_MUX = 0; ZN_COIN_CTRL = 0; ZN_IRQ10_MUX = 0;