diff --git a/asm/rom_header.s b/asm/rom_header.s index cc9432d09..0673aee82 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 000000000..7a89d6768 --- /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 000000000..e763f78c2 Binary files /dev/null and b/bin/vc/osEepStatusVC.bin differ diff --git a/bin/vc/osEepromReadVC.bin b/bin/vc/osEepromReadVC.bin new file mode 100644 index 000000000..dd3481a17 Binary files /dev/null and b/bin/vc/osEepromReadVC.bin differ diff --git a/bin/vc/osEepromWriteVC.bin b/bin/vc/osEepromWriteVC.bin new file mode 100644 index 000000000..9bc94ae5b Binary files /dev/null and b/bin/vc/osEepromWriteVC.bin differ diff --git a/sm64.ld b/sm64.ld index 7bff39dfb..94841950e 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 75a9dc54c..1b3f198e6 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 a53913bb1..7f0fc4f1c 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 07f0faad1..6a81260e7 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 000000000..472199802 --- /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 000000000..fe11661e0 --- /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 000000000..0faf942a6 --- /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);