From 269cd5ef88d9f3ac8d2f65871f003c5fb56dca34 Mon Sep 17 00:00:00 2001 From: Prakxo Date: Sat, 9 Sep 2023 15:07:18 +0200 Subject: [PATCH] link famicom_emu --- config/rel_slices.yml | 4 + config/symbols.yml | 1 + include/Famicom/famicom.h | 6 + include/audio.h | 2 +- include/famicom_emu.h | 12 +- include/jaudio_NES/game64.h | 2 +- include/jsyswrap.h | 13 ++ include/libc64/sprintf.h | 6 + include/m_common_data.h | 8 +- include/m_scene.h | 3 + rel/audio.c | 2 +- rel/famicom_emu.c | 256 ++++++++++++++++++++++++++++++++++++ src/libc64/sprintf.c | 3 + 13 files changed, 311 insertions(+), 7 deletions(-) create mode 100644 include/libc64/sprintf.h create mode 100644 rel/famicom_emu.c diff --git a/config/rel_slices.yml b/config/rel_slices.yml index fa3d5813..d518201c 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -362,6 +362,10 @@ save_menu.c: .text: [0x8062CA5C, 0x8062D39C] .rodata: [0x8064D1F8, 0x8064D318] .data: [0x806D4B80, 0x806D4B98] +famicom_emu.c: + .text: [0x8062D39C, 0x8062D8FC] + .data: [0x806D4B98, 0x806D4CB0] + .bss: [0x8148DA68, 0x8148DA78] m_prenmi.c: .text: [0x8062D8FC, 0x8062DC04] .rodata: [0x8064D318, 0x8064D340] diff --git a/config/symbols.yml b/config/symbols.yml index 89179927..df056c81 100644 --- a/config/symbols.yml +++ b/config/symbols.yml @@ -3335,6 +3335,7 @@ global: 0x801ef128: FREE_SEQP_QUEUE 0x801ef580: commentImageBuffer 0x801f4dc4: famicomCommon + 0x801f4dc0: save_game_image 0x801f4e7c: famicomCommonSave 0x801f683c: nesrom_filename_ptrs 0x801f6840: nesrom_filename_strbuf diff --git a/include/Famicom/famicom.h b/include/Famicom/famicom.h index eff1fece..98e7cdcf 100644 --- a/include/Famicom/famicom.h +++ b/include/Famicom/famicom.h @@ -70,11 +70,17 @@ typedef struct famicom_common_s { extern void* my_malloc_current; +extern u8 save_game_image; typedef u8 (*FAMICOM_GETSAVECHAN_PROC)(int* player_no, int* slot_card_result); extern void famicom_setCallback_getSaveChan(FAMICOM_GETSAVECHAN_PROC getSaveChan_proc); extern int famicom_mount_archive(); extern int famicom_mount_archive_end_check(); +extern int famicom_rom_load_check(); +extern int famicom_1frame(); +extern int famicom_init(int, void*, u8); +extern int famicom_cleanup(); + #ifdef __cplusplus } diff --git a/include/audio.h b/include/audio.h index 9a3134a1..5fe96d79 100644 --- a/include/audio.h +++ b/include/audio.h @@ -73,7 +73,7 @@ extern void sAdo_BgmCrossfadeStart(u8 b); extern void sAdo_SubGameStart(); extern void sAdo_SubGameEnd(); -extern u8 sAdo_SubGameOK(); +extern int sAdo_SubGameOK(); extern void sAdo_Tenki(u8 mode); diff --git a/include/famicom_emu.h b/include/famicom_emu.h index 60ad768a..242feea9 100644 --- a/include/famicom_emu.h +++ b/include/famicom_emu.h @@ -15,8 +15,16 @@ typedef struct game_famicom_emu_s { extern void* my_malloc_func[]; -extern void famicom_emu_init(GAME_FAMICOM_EMU* famicom_emu); -extern void famicom_emu_cleanup(GAME_FAMICOM_EMU* famicom_emu); +void my_alloc_cleanup(); +void my_zelda_getmemblocksize(void *); +void my_zelda_gettotalfreesize(); +void* my_zelda_malloc_align(size_t, u32); +void my_zelda_free(void *); +void famicom_emu_main(GAME *); +void famicom_emu_init(GAME_FAMICOM_EMU *); +void famicom_emu_cleanup(GAME *); +int famicom_gba_getImage(u32, int *); +void famicom_gba_removeImage(void *); #ifdef __cplusplus } diff --git a/include/jaudio_NES/game64.h b/include/jaudio_NES/game64.h index b6b3e8e7..624fbcf2 100644 --- a/include/jaudio_NES/game64.h +++ b/include/jaudio_NES/game64.h @@ -36,7 +36,7 @@ extern void Na_MDPlayerPos(u16,u16,u16,int, f32); extern void Na_BGMVolume(f32,u16); extern void Na_SubGameStart(); extern void Na_SubGameEnd(); -extern int Na_SubGameOK(); +extern u8 Na_SubGameOK(); extern void Na_Tenki(u8); extern void Na_KishaStatusTrg(u8); extern void Na_KishaStatusLevel(f32 speed, u32 ongenNum1, u16 angle1, f32 distance1, u32 ongenNum2, u16 angle2, f32 distance2); diff --git a/include/jsyswrap.h b/include/jsyswrap.h index 47509eb2..801e9c9c 100644 --- a/include/jsyswrap.h +++ b/include/jsyswrap.h @@ -2,12 +2,25 @@ #define JSYSWRAP_H #include "types.h" +#include "dolphin/gx.h" #ifdef __cplusplus extern "C" { #endif extern void JW_JUTReport(int pos_x, int pos_y, int show_count, const char* fmt, ...); +extern void JC_JFWDisplay_startFadeOut(void*, int); +extern void* JC_JFWDisplay_getManager(); +extern void JC_JFWDisplay_clearEfb(void*, GXColor*); +extern GXRenderModeObj* JC_JFWDisplay_getRenderMode(void*); +extern void* JC_JFWDisplay_changeToSingleXfb(void*, int); + +extern void JC_JFWDisplay_startFadeIn(void*, int); +extern void JC_JFWDisplay_changeToDoubleXfb(void*); +extern u32 JC__JKRGetResource(char*); +extern int JC__JKRGetMemBlockSize(int, u32); + +extern void JC__JKRRemoveResource(void*); #ifdef __cplusplus } diff --git a/include/libc64/sprintf.h b/include/libc64/sprintf.h new file mode 100644 index 00000000..34c9fc3a --- /dev/null +++ b/include/libc64/sprintf.h @@ -0,0 +1,6 @@ +#ifndef SPRINTF_H +#define SPRINTF_H + +s32 sprintf(char* dst, const char* fmt, ...); + +#endif \ No newline at end of file diff --git a/include/m_common_data.h b/include/m_common_data.h index 6a0a884d..7af759ee 100644 --- a/include/m_common_data.h +++ b/include/m_common_data.h @@ -202,7 +202,10 @@ typedef struct common_data_s { /* 0x0285C0 */ s8 player_decoy_flag; /* 0x0285C1 */ u8 _285C1[0x0285C6 - 0x0285C1]; /* 0x0285C6 */ u8 event_id; - /* 0x0285C7 */ u8 _285C3[0x028838 - 0x0285C7]; + /* 0x0285C7 */ u8 _285C3[0x0287F8 - 0x0285C7]; + /* 0x0287F8 */ s8 current_famicom_rom; + /* 0x0287F9 */ s8 famicom_287F9; + /* 0x0287FA */ u8 _287FA[0x28838 - 0x0287FA]; /* 0x028838 */ s8 player_bee_swell_flag; /* 0x028839 */ s8 player_bee_chase_flag; /* 0x02883A */ u8 goki_shocked_flag; @@ -249,7 +252,8 @@ typedef struct common_data_s { /* 0x02DB40 */ u8 auto_nwrite_set; /* when true, saved nwrite time will be utilized. Seems to be used to keep same date for fishing tourney stuff. */ /* 0x02DB42 */ u16 select_last_select_no; /* 0x02DB44 */ u16 select_last_top_no; - /* 0x02DB46 */ u8 tmp3[0x2DBB0 - 0x2DB46]; + /* 0x02DB46 */ u8 tmp3[0x2DBAC - 0x2DB46]; + /* 0X02DBAC */ int famicom_2DBAC; /* 0x02DBB0 */ s16 can_look_goki_count; /* 0x02DBB4 */ f32 rainbow_opacity; /* current opacity of rainbow (0.0f - 1.0f) */ /* 0x02DBB8 */ u32 event_flags[7]; /* TODO: make array size a definition/enum */ diff --git a/include/m_scene.h b/include/m_scene.h index ab67bdbd..f3ff2ae8 100644 --- a/include/m_scene.h +++ b/include/m_scene.h @@ -3,6 +3,7 @@ #include "types.h" #include "m_lib.h" +#include "famicom_emu.h" #ifdef __cplusplus extern "C" { @@ -103,6 +104,8 @@ extern void mSc_data_bank_ct(GAME_PLAY*, Object_Exchange_c*); extern void Door_info_ct(Door_data_c**); extern void Scene_ct(GAME_PLAY*, void*); extern void mSc_decide_exchange_bank(Object_Exchange_c*); +extern void return_emu_game(GAME*); + #ifdef __cplusplus } diff --git a/rel/audio.c b/rel/audio.c index c562f2cb..33707972 100644 --- a/rel/audio.c +++ b/rel/audio.c @@ -281,7 +281,7 @@ extern void sAdo_SubGameEnd(){ Na_SubGameEnd(); } -extern u8 sAdo_SubGameOK(){ +extern int sAdo_SubGameOK(){ return Na_SubGameOK(); } diff --git a/rel/famicom_emu.c b/rel/famicom_emu.c new file mode 100644 index 00000000..e43e63bb --- /dev/null +++ b/rel/famicom_emu.c @@ -0,0 +1,256 @@ + +#include "famicom_emu.h" + +#include "m_malloc.h" +#include "_mem.h" +#include "dolphin/gx.h" +#include "Famicom/famicom.h" +#include "m_scene.h" +#include "jsyswrap.h" +#include "m_common_data.h" +#include "m_debug.h" +#include "libc64/sprintf.h" + +int famicom_done; +int famicom_done_countdown; +void* freeXfbBase; +u32 freeXfbSize; + +void* my_malloc_func[] = { + my_zelda_malloc_align, + my_zelda_free, + my_zelda_getmemblocksize, + my_zelda_gettotalfreesize, +}; + + + +void my_alloc_init(GAME_FAMICOM_EMU* famicom, void* start, size_t size){ + + u32 freebytes; + u32 alloc; + u32 aligned; + u32 tsize; + + freebytes = game_getFreeBytes(&famicom->game); + alloc = (u32)THA_alloc16(&famicom->game.tha, freebytes); + aligned = ALIGN_NEXT(alloc, 16); + tsize = aligned - alloc; + + zelda_InitArena((void*)aligned, freebytes - tsize); + + if((start != NULL) && (size != 0)){ + + zelda_AddBlockArena(start, size); + } + +} + +void my_alloc_cleanup(){ + + zelda_CleanupArena(); +} + +void my_zelda_getmemblocksize(void* ptr){ + + zelda_GetMemBlockSize(ptr); +} + +void my_zelda_gettotalfreesize(){ + + zelda_GetTotalFreeSize(); +} + +void* my_zelda_malloc_align(size_t size, u32 align){ + + void* aligned = zelda_malloc_align(size, align); + + if(aligned != NULL){ + + memset(aligned, 0xFF, size); + } + return aligned; +} + +void my_zelda_free(void* ptr){ + + zelda_free(ptr); +} +#pragma pool_data off + +void famicom_emu_main(GAME* famicom){ + static GXColor black_color = {0,0,0,0}; + GXColor t; + int i; + int padid; + pad_t* current_pad; + u32 combo; + void* manager; + + if(famicom_done == 0){ + if(famicom_rom_load_check() < 0){ + Common_Set(famicom_2DBAC, Common_Get(famicom_2DBAC) | 1); + famicom_done = 1; + famicom_done_countdown = 0; + } + else{ + for(padid = 0,i = 4; i != 0; i--, padid++){ + + current_pad = &gamePT->pads[padid]; + combo = current_pad->now.button | current_pad->on.button; + + if(combo == (BUTTON_Z | BUTTON_R | BUTTON_L) || (combo == 0xF0)){ + + famicom_done = 1; + famicom_done_countdown = 60; + JC_JFWDisplay_startFadeOut(JC_JFWDisplay_getManager(), famicom_done_countdown); + break; + } + } + } + } + if (famicom_done != 0) { + if ( famicom_done_countdown == 0) { + return_emu_game(famicom); + } else { + famicom_done_countdown -= 1; + } + } + + JW_BeginFrame(); + famicom->disable_display = 1; + + if(famicom_done == 0){ + + famicom_1frame(); + } + else{ + manager = JC_JFWDisplay_getManager(); + t = black_color; + JC_JFWDisplay_clearEfb(manager, &t); + } + JW_EndFrame(); +} + +#pragma pool_data on + + +void famicom_emu_init(GAME_FAMICOM_EMU* famicom){ + + int rom_id; + u8 player; + int debug; + void* manager; + GXRenderModeObj* render; + + famicom_done = 0; + famicom_done_countdown = 0; + game_resize_hyral(&famicom->game, 0); + Common_Set(famicom_287F9, 0); + + rom_id = Common_Get(current_famicom_rom); + player = Common_Get(player_no); + save_game_image = (GETREG(HREG, 4) == 1); + debug = GETREG(HREG,3); + + if((rom_id > 0) && ( debug != 0)){ + rom_id = debug & (-debug & ~debug) >> 0x1f; + } + + famicom->game.exec = famicom_emu_main; + famicom->game.cleanup = famicom_emu_cleanup; + + + while(sAdo_SubGameOK() == 0){ + VIWaitForRetrace(); + sAdo_GameFrame(); + } + + manager = JC_JFWDisplay_getManager(); + render = JC_JFWDisplay_getRenderMode(manager); + freeXfbBase = JC_JFWDisplay_changeToSingleXfb(manager, 1); + freeXfbSize = render->efbHeight * render->viXOrigin * sizeof(u16); + + my_alloc_init(famicom, freeXfbBase, freeXfbSize); + + if(famicom_init(rom_id, my_malloc_func, player) != 0){ + Common_Set(famicom_2DBAC, Common_Get(famicom_2DBAC) | 1); + return_emu_game(&famicom->game); + } +} + + +void famicom_emu_cleanup(GAME*){ + + JC_JFWDisplay_startFadeIn(JC_JFWDisplay_getManager(), 1); + + if(famicom_cleanup() != 0){ + + Common_Set(famicom_2DBAC, Common_Get(famicom_2DBAC) | 2); + } + + my_alloc_cleanup(); + + if(freeXfbBase != NULL){ + + JC_JFWDisplay_changeToDoubleXfb(JC_JFWDisplay_getManager()); + freeXfbBase = NULL; + freeXfbSize = 0; + } + sAdo_SubGameEnd(); +} + +int famicom_gba_getImage(u32 rom_id, int* ptr){ + static char* names[] = { + "cluclu", + "usa_balloon", + "donkey", + "usa_jr_math", + "pinball", + "tennis", + "usa_golf", + NULL, + "usa_baseball", + NULL, + "usa_donkey3", + "donkeyjr", + "soccer", + "exbike", + NULL, + "usa_icecl", + "mario", + "smario", + NULL + }; + + char buf[256]; + u32 resource; + int block; + char* rom; + + + if(rom_id > 0x13){ + return 0; + } + + + rom = names[(rom_id == 0) ? 0 : rom_id -1]; + + if(rom == NULL){ + return 0; + } + else{ + sprintf(buf, "/FAMICOM/GBA/jb_%s.bin.szs", rom); + resource = JC__JKRGetResource(buf); + if((resource != 0) && (ptr != NULL)){ + block = JC__JKRGetMemBlockSize(0, resource); + *ptr = block; + } + } + return resource; +} + +void famicom_gba_removeImage(void* p){ + + JC__JKRRemoveResource(p); +} \ No newline at end of file diff --git a/src/libc64/sprintf.c b/src/libc64/sprintf.c index 338d7f40..c81ad969 100644 --- a/src/libc64/sprintf.c +++ b/src/libc64/sprintf.c @@ -1,6 +1,9 @@ +#include "libc64/sprintf.h" + #include "libultra/xprintf.h" #include "_mem.h" + static void* proutPrintf(void* dst, const char* fmt, size_t size) { return (void*)((u8*)memcpy(dst, fmt, size) + size); }