From 4a3ef802d5fc74e85922c2343b0ce95aa48e3d62 Mon Sep 17 00:00:00 2001 From: Denis Kopyrin Date: Sun, 27 Mar 2022 10:39:44 +0800 Subject: [PATCH] Fixed eeprom saving on VC (#334) * Fixed eeprom saving on VC * Specify SM for EEP4K, for any other savetype use ED * Moved IS_VC() check to an earlier point, switch IS_VC()->gIsVC * Moved binary VC files to bin folder, added checks for EEP * Do not keep vc_bin if EEP is not set --- asm/rom_header.s | 4 +++ asm/vc_bin.s | 23 +++++++++++++ bin/vc/osEepStatusVC.bin | Bin 0 -> 560 bytes bin/vc/osEepromReadVC.bin | Bin 0 -> 512 bytes bin/vc/osEepromWriteVC.bin | Bin 0 -> 448 bytes sm64.ld | 3 ++ src/boot/main.c | 3 ++ src/game/game_init.c | 5 ++- src/game/save_file.c | 11 ++++-- src/game/vc_bin.h | 7 ++++ src/game/vc_ultra.c | 68 +++++++++++++++++++++++++++++++++++++ src/game/vc_ultra.h | 7 ++++ 12 files changed, 128 insertions(+), 3 deletions(-) create mode 100644 asm/vc_bin.s create mode 100644 bin/vc/osEepStatusVC.bin create mode 100644 bin/vc/osEepromReadVC.bin create mode 100644 bin/vc/osEepromWriteVC.bin create mode 100644 src/game/vc_bin.h create mode 100644 src/game/vc_ultra.c create mode 100644 src/game/vc_ultra.h diff --git a/asm/rom_header.s b/asm/rom_header.s index cc9432d0..0673aee8 100644 --- a/asm/rom_header.s +++ b/asm/rom_header.s @@ -17,7 +17,11 @@ .ascii INTERNAL_ROM_NAME /* Internal ROM name */ .word 0x00000000 /* Unknown */ .word 0x0000004E /* Cartridge */ +#if defined(EEP4K) +.ascii "SM" /* Cartridge ID */ +#else .ascii "ED" /* Cartridge ID */ +#endif /* Region */ #if defined(VERSION_JP) || defined(VERSION_SH) diff --git a/asm/vc_bin.s b/asm/vc_bin.s new file mode 100644 index 00000000..7a89d676 --- /dev/null +++ b/asm/vc_bin.s @@ -0,0 +1,23 @@ +// VC is using binary matching to stub functions - this hex was copied from SM64 +// osEepromRead/Write are performing infinite cycle inside them which causes recompiler do go crazy +// _osEepStatus does not have any suspicious asm in it but it is just VC hacked anyways +// If it is not replaced with a VC variant, EEP probe fails + +.include "macros.inc" +.section .text + +#if defined(EEP) +// 0x80329150 = 0xE4150 +.balign 16 +glabel osEepromReadVC +.incbin "bin/vc/osEepromReadVC.bin" + +// 0x80328af0 = 0xE3AF0 +.balign 16 +glabel osEepromWriteVC +.incbin "bin/vc/osEepromWriteVC.bin" + +.balign 16 +glabel __osEepStatusVC +.incbin "bin/vc/osEepStatusVC.bin" +#endif diff --git a/bin/vc/osEepStatusVC.bin b/bin/vc/osEepStatusVC.bin new file mode 100644 index 0000000000000000000000000000000000000000..e763f78c248255c6eae011d163359c959f2150a8 GIT binary patch literal 560 zcmY%2`~QLsUxS(Ixx#|=`x!*mFJUlPzm&mb{Q?G^_3Ic^)-Pbt=wHvE(Z7>H!-lcJ zjDi0^1A_&J;u?j*0(A`rMomTr0TG4&-`B5T(6HfZFjL`VU<9dC^(rh_qgl9S{VJ## zs~J=lCNMDcuVc{YU&ElHdY*w%^C1I^YA*xh`t=MNU^CV-sHjLV{8y1=U{v8?U{>K| z_^-mn@Lz?S;lBzG!~exQ7-SajWRP9Ffqv~ zy$2Z>`a$M!G5oV(Z7^H8kbz<6LI&pEn+z-}OA8BBSQr>r?qp!uxs!pte+7ezDklTS z`jreSJUojc7HTmttY5^S)4znlfPq0nm4~N`L4}QhQH7g<733$7c?+})CVN*BSP*{S)V;zG^|4IfG^;HZqor(+$GZh(_*E%vVbm}m$%+z6EU+crbGIm-- z6Jvgc0}T9`%nQ#lFi+mepg4IogF^pG1``HJCk96D0M(^h3=I7{7)&OwVNhDk!@$(P pp21||TLxyq1#ovVF)k2LWnd6c?cdKJqP~~GfcXIf2gnb|7y$JpmLmWF literal 0 HcmV?d00001 diff --git a/bin/vc/osEepromReadVC.bin b/bin/vc/osEepromReadVC.bin new file mode 100644 index 0000000000000000000000000000000000000000..dd3481a17c216263580cd52e77d698e5809911cf GIT binary patch literal 512 zcmY%2`~SrHr3^Nc*E87L@HLpJo+~WSe8}Lqem{fA`Xvk&>z6S&tY5%jvVH-BfrtVF z^ZIoRIsyy~St?Bb|MT!HvSDCgVCY}MV8O$)I9q)wgU0$r3?}_M7)-<&7+67a(|0mx zm@qal2rDu$gZKgr4ACk~3>=eJFlZTaGBgM(FmQmxk~l!1YN z{R&8!_pf9y=wHp?z`Qa*aiSN4!on;DhW<4S2L0<898~)m7&RXz6S&tY5%jBBH>+ynY>n zjsOEgv+YFWHTnOVvsZRW@r#i`2PzeH+czzJrB=f zjsB$!4mPX}W-3by3wU@IMX0baFoNw{!eGI`prOjc)5V~|#=y9K0fRyRS_Xsu^$Z3! zj16WCyaf#mdK`)>JPiNW=oA*H{$OC#W@Hc$QTYFD{SJs4khyCV3fI8QW?)cIRgq+1 z1?dObvB0um0?3UR_N-zs=wHF0qw3ATsF}#XqRPp@xPCQ*fr!HYpX*mL==85)&{1E@ zpwQXKz%a9sfqCsh28Pal29}xq4D4&yGq7|vGH}dnWZ+)Akbz_J4hBVINrnRql8($g fJd1qSuV66g2ZiT;1`+kW3>M4}AYlax6J!hkmaB7k literal 0 HcmV?d00001 diff --git a/sm64.ld b/sm64.ld index 7bff39df..94841950 100755 --- a/sm64.ld +++ b/sm64.ld @@ -159,6 +159,9 @@ SECTIONS { KEEP(BUILD_DIR/asm/entry.o(.text*)); KEEP(BUILD_DIR/asm/n64_assert.o(.text*)); +#ifdef EEP + KEEP(BUILD_DIR/asm/vc_bin.o(.text*)); +#endif BUILD_DIR/src/boot*.o(.text*); BUILD_DIR/src/hvqm*.o(.text*); diff --git a/src/boot/main.c b/src/boot/main.c index 75a9dc54..1b3f198e 100644 --- a/src/boot/main.c +++ b/src/boot/main.c @@ -21,6 +21,8 @@ #include "game/puppyprint.h" #include "game/puppylights.h" +#include "game/vc_check.h" + // Message IDs enum MessageIDs { MESG_SP_COMPLETE = 100, @@ -302,6 +304,7 @@ void thread3_main(UNUSED void *arg) { setup_mesg_queues(); alloc_pool(); load_engine_code_segment(); + gIsVC = IS_VC(); #ifndef UNF crash_screen_init(); #endif diff --git a/src/game/game_init.c b/src/game/game_init.c index a53913bb..7f0fc4f1 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -29,6 +29,7 @@ #include "puppycam2.h" #include "debug_box.h" #include "vc_check.h" +#include "vc_ultra.h" // First 3 controller slots struct Controller gControllers[3]; @@ -653,7 +654,9 @@ void init_controllers(void) { #ifdef EEP // strangely enough, the EEPROM probe for save data is done in this function. // save pak detection? - gEepromProbe = osEepromProbe(&gSIEventMesgQueue); + gEepromProbe = gIsVC + ? osEepromProbeVC(&gSIEventMesgQueue) + : osEepromProbe (&gSIEventMesgQueue); #endif #ifdef SRAM gSramProbe = nuPiInitSram(); diff --git a/src/game/save_file.c b/src/game/save_file.c index 07f0faad..6a81260e 100644 --- a/src/game/save_file.c +++ b/src/game/save_file.c @@ -52,6 +52,9 @@ s8 gLevelToCourseNumTable[] = { STATIC_ASSERT(ARRAY_COUNT(gLevelToCourseNumTable) == LEVEL_COUNT - 1, "change this array if you are adding levels"); #ifdef EEP +#include "vc_check.h" +#include "vc_ultra.h" + /** * Read from EEPROM to a given address. * The EEPROM address is computed using the offset of the destination address from gSaveBuffer. @@ -70,7 +73,9 @@ static s32 read_eeprom_data(void *buffer, s32 size) { block_until_rumble_pak_free(); #endif triesLeft--; - status = osEepromLongRead(&gSIEventMesgQueue, offset, buffer, size); + status = gIsVC + ? osEepromLongReadVC(&gSIEventMesgQueue, offset, buffer, size) + : osEepromLongRead (&gSIEventMesgQueue, offset, buffer, size); #if ENABLE_RUMBLE release_rumble_pak_control(); #endif @@ -98,7 +103,9 @@ static s32 write_eeprom_data(void *buffer, s32 size) { block_until_rumble_pak_free(); #endif triesLeft--; - status = osEepromLongWrite(&gSIEventMesgQueue, offset, buffer, size); + status = gIsVC + ? osEepromLongWriteVC(&gSIEventMesgQueue, offset, buffer, size) + : osEepromLongWrite (&gSIEventMesgQueue, offset, buffer, size); #if ENABLE_RUMBLE release_rumble_pak_control(); #endif diff --git a/src/game/vc_bin.h b/src/game/vc_bin.h new file mode 100644 index 00000000..47219980 --- /dev/null +++ b/src/game/vc_bin.h @@ -0,0 +1,7 @@ +// These functions are actually fully binary, I use these invokations for my convenience + +#include + +s32 osEepromReadVC(OSMesgQueue *mq, u8 address, u8 *buffer); +s32 osEepromWriteVC(OSMesgQueue *mq, u8 address, u8 *buffer); +s32 __osEepStatusVC(OSMesgQueue *mq, OSContStatus *data); diff --git a/src/game/vc_ultra.c b/src/game/vc_ultra.c new file mode 100644 index 00000000..fe11661e --- /dev/null +++ b/src/game/vc_ultra.c @@ -0,0 +1,68 @@ +#include "vc_ultra.h" + +#include "vc_bin.h" + +#ifdef EEP +// These functions are real implementations of libultra functions +// with an exception that some VC useless code was dropped from them +// for the cleaner understanding purposes. +// These functions are generally wrappers around binary stubs from vc_bin +s32 osEepromProbeVC(OSMesgQueue *mq) +{ + s32 ret; + u16 type; + ret = 0; + OSContStatus sdata; + ret = __osEepStatusVC(mq, &sdata); // call to binary stub + type = sdata.type & (CONT_EEPROM | CONT_EEP16K); + if (ret != 0) + { + ret = 0; + } + else + { + switch (type) + { + case CONT_EEPROM: + ret = EEPROM_TYPE_4K; + break; + case CONT_EEPROM | CONT_EEP16K: + ret = EEPROM_TYPE_16K; + break; + default: + ret = 0; + break; + } + } + + return ret; +} + +s32 osEepromLongReadVC(OSMesgQueue *mq, u8 address, u8 *buffer, int length) +{ + s32 ret; + ret = 0; + while (length > 0) + { + osEepromReadVC(mq, address, buffer); // call to binary stub + length -= EEPROM_BLOCK_SIZE; + address++; + buffer += EEPROM_BLOCK_SIZE; + } + return ret; +} + +s32 osEepromLongWriteVC(OSMesgQueue *mq, u8 address, u8 *buffer, int length) +{ + s32 ret; + ret = 0; + while (length > 0) + { + osEepromWriteVC(mq, address, buffer); // call to binary stub + length -= EEPROM_BLOCK_SIZE; + address++; + buffer += EEPROM_BLOCK_SIZE; + } + return ret; +} +#endif diff --git a/src/game/vc_ultra.h b/src/game/vc_ultra.h new file mode 100644 index 00000000..0faf942a --- /dev/null +++ b/src/game/vc_ultra.h @@ -0,0 +1,7 @@ +// Some libultra functions that use VC alternatives + +#include + +s32 osEepromProbeVC(OSMesgQueue *mq); +s32 osEepromLongReadVC(OSMesgQueue *mq, u8 address, u8 *buffer, int length); +s32 osEepromLongWriteVC(OSMesgQueue *mq, u8 address, u8 *buffer, int length);