diff --git a/config/rel_slices.yml b/config/rel_slices.yml index f9b209fe..ee4a3a14 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -172,6 +172,11 @@ THA_GA.c: .text: [0x80404AE0, 0x80404B40] TwoHeadArena.c: .text: [0x80404B40, 0x80404C68] +game.c: + .text: [0x80404C68, 0x80405370] + .rodata: [0x806436E8, 0x806436F8] + .data: [0x8065ECA0, 0x8065ECA8] + .bss: [0x812F31B8, 0x812F31E8] gamealloc.c: .text: [0x80405370, 0x804054B0] gfxalloc.c: diff --git a/config/symbols.yml b/config/symbols.yml index a3310bd8..81d13183 100644 --- a/config/symbols.yml +++ b/config/symbols.yml @@ -52511,6 +52511,7 @@ global: 0x812F31BC: last_now_button 0x812F31C4: last_on_trigger 0x812F31CC: last_button + 0x812F31D4: game_GameFrame 0x812F31D8: game_GameFrameF 0x812F31DC: game_GameFrame_2F 0x812F31E0: game_GameFrame__1F diff --git a/include/game.h b/include/game.h index 960c5e7e..cdffd3a3 100644 --- a/include/game.h +++ b/include/game.h @@ -33,11 +33,8 @@ struct game_s { /* 0x00A8 */ MCON mcon; }; -extern void game_ct(GAME*, void (*)(GAME*), GRAPH*); -extern void game_dt(GAME* game); -extern void game_main(GAME* game); -extern int game_is_doing(GAME* game); -extern void (*game_get_next_game_init(GAME* game))(GAME*); +#define GAME_HYRAL_SIZE (0x100000) +#define GAME_FRAME (1) #define GAME_NEXT_GAME(game, init_name, class_name) \ do { \ @@ -46,6 +43,13 @@ do { \ g->next_game_class_size = sizeof(GAME_##class_name); \ } while (0) +#define GAME_NEXT_GAME_NULL(game) \ +do { \ + GAME* _game = (game); \ + _game->next_game_init = NULL; \ + _game->next_game_class_size = 0; \ +} while (0) + #define GAME_GOTO_NEXT(game, init_name, class_name) \ do { \ GAME* t_game = (game); \ @@ -53,11 +57,24 @@ do { \ GAME_NEXT_GAME(t_game, init_name, class_name); \ } while (0) -extern void SetGameFrame(int frame); - -extern void game_get_controller(GAME* game); -extern void game_debug_draw_last(GAME* game, GRAPH* graph); +extern void game_debug_draw_last(GAME* this, GRAPH* graph); extern void game_draw_last(GRAPH* graph); +extern void game_get_controller(GAME* this); +extern void SetGameFrame(int frame); +extern void game_main(GAME* this); +extern void game_resize_hyral(GAME* this, int size); +extern void game_ct(GAME* this, void (*init)(GAME*), GRAPH* graph); +extern void game_dt(GAME* this); +extern void (*game_get_next_game_init(GAME* this))(GAME*); +#ifndef MUST_MATCH +extern size_t game_get_next_game_class_size(GAME* this); +#endif +extern int game_is_doing(GAME* this); +extern int game_getFreeBytes(GAME* this); +extern void game_goto_next_game_play(GAME* this); +#ifndef MUST_MATCH +extern void game_goto_next_game_famicom_emu(GAME* this); +#endif extern GAME* gamePT; diff --git a/include/libjsys/jsyswrapper.h b/include/libjsys/jsyswrapper.h index 5786bd02..be1ab21e 100644 --- a/include/libjsys/jsyswrapper.h +++ b/include/libjsys/jsyswrapper.h @@ -71,6 +71,7 @@ extern void* JC_JFWSystem_getSystemHeap(); extern void* JC_JFWDisplay_getManager(); extern void JC_JFWDisplay_startFadeOut(void* manager, int len); extern void JC_JFWDisplay_startFadeIn(void* manager, int len); +extern void JC_JFWDisplay_setFrameRate(void* manager, u16 framerate); extern void JC_JKRAramHeap_dump(void* heap); extern void* JC_JKRAram_getAramHeap(); diff --git a/include/m_music_ovl.h b/include/m_music_ovl.h new file mode 100644 index 00000000..75fc764e --- /dev/null +++ b/include/m_music_ovl.h @@ -0,0 +1,24 @@ +#ifndef M_MUSIC_OVL_H +#define M_MUSIC_OVL_H + +#include "types.h" +#include "m_music_ovl_h.h" +#include "m_submenu_ovl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct music_ovl_s { + +}; + +extern void mMU_music_ovl_set_proc(Submenu* submenu); +extern void mMU_music_ovl_construct(Submenu* submenu); +extern void mMU_music_ovl_destruct(Submenu* submenu); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/m_music_ovl_h.h b/include/m_music_ovl_h.h new file mode 100644 index 00000000..f05013af --- /dev/null +++ b/include/m_music_ovl_h.h @@ -0,0 +1,16 @@ +#ifndef M_MUSIC_OVL_H_H +#define M_MUSIC_OVL_H_H + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct music_ovl_s mMU_Overlay_c; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/m_submenu_ovl.h b/include/m_submenu_ovl.h index 495c87ed..9a5c55fd 100644 --- a/include/m_submenu_ovl.h +++ b/include/m_submenu_ovl.h @@ -10,6 +10,7 @@ #include "PreRender.h" #include "m_map_ovl_h.h" #include "m_bank_ovl_h.h" +#include "m_music_ovl_h.h" #ifdef __cplusplus extern "C" { @@ -99,7 +100,8 @@ struct submenu_overlay_s { /* 0x96C */ mSM_CHANGE_VIEW_PROC change_view_proc; /* 0x970 */ u8 _940[0x9B4 - 0x970]; /* 0x9B4 */ mMP_Overlay_c* map_ovl; - /* 0x9B8 */ u8 _9B8[0x9D4 - 0x9B8]; + /* 0x9B8 */ u8 _9B8[0x9D0 - 0x9B8]; + /* 0x9D0 */ mMU_Overlay_c* music_ovl; /* 0x9D4 */ mBN_Overlay_c* bank_ovl; /* 0x9D8 */ u8 _9D8[0xA00 - 0x9D8]; /* 0xA00 */ Mtx* projection_matrix; diff --git a/include/types.h b/include/types.h index 2dbea5be..f4f68dab 100644 --- a/include/types.h +++ b/include/types.h @@ -79,6 +79,12 @@ typedef u32 unknown; #define FORCESTRIP #endif +#ifdef MUST_MATCH + #define MATCH_FORCESTRIP FORCESTRIP +#else + #define MATCH_FORCESTRIP +#endif + #if !defined(__INTELLISENSE__) && defined(MUST_MATCH) #define BSS_ORDER_GROUP_START FORCESTRIP ORDER_BSS_DATA { #define BSS_ORDER_GROUP_END } diff --git a/rel/game.c b/rel/game.c new file mode 100644 index 00000000..67052d80 --- /dev/null +++ b/rel/game.c @@ -0,0 +1,261 @@ +#include "game.h" + +#include "m_debug.h" +#include "zurumode.h" +#include "libforest/gbi_extensions.h" +#include "famicom_emu.h" +#include "m_play.h" +#include "gfxalloc.h" +#include "gamealloc.h" +#include "THA_GA.h" +#include "libjsys/jsyswrapper.h" + +GAME* game_class_p; +u8 game_GameFrame; +f32 game_GameFrameF; +f32 game_GameFrame_2F; +f32 game_GameFrame__1F; + +static u16 last_button[MAXCONTROLLERS]; +static u16 last_now_button[MAXCONTROLLERS]; +static u16 last_on_trigger[MAXCONTROLLERS]; + +GAME* gamePT; + +BSS_ORDER_GROUP_START + BSS_ORDER_ITEM(gamePT) + BSS_ORDER_ITEM(last_now_button) + BSS_ORDER_ITEM(last_on_trigger) + BSS_ORDER_ITEM(last_button) + BSS_ORDER_ITEM(game_GameFrame) + BSS_ORDER_ITEM(game_GameFrameF) + BSS_ORDER_ITEM(game_GameFrame_2F) + BSS_ORDER_ITEM(game_GameFrame__1F) + BSS_ORDER_ITEM(game_class_p) +BSS_ORDER_GROUP_END + +static void game_move_first(GAME* this) { + if (zurumode_flag) { + Debug_mode_input(&this->pads[1]); + } + + JC_JUTProcBar_setVisible(JC_JUTProcBar_getManager(), GETREG(SREG, 0) != 0); + JC_JUTProcBar_setVisibleHeapBar(JC_JUTProcBar_getManager(), GETREG(SREG, 0) != 0); +} + +extern void game_debug_draw_last(GAME* this, GRAPH* graph) { + int i; + Gfx* gfx; + Gfx* close; + + if (zurumode_flag) { + OPEN_DISP(graph); + + gfx = NOW_POLY_OPA_DISP; + close = gfxopen(gfx); + gSPDisplayList(NOW_OVERLAY_DISP++, close); + + for (i = 0; i < MAXCONTROLLERS; i++) { + pad_t* pad = &this->pads[i]; + if (pad->now.errno == 0) { + last_now_button[i] = pad->now.button; + last_on_trigger[i] = pad->on.button; + last_button[i] = last_now_button[i] | last_on_trigger[i]; + } + else { + last_now_button[i] = 0; + last_on_trigger[i] = 0; + last_button[i] = i == 0 ? 0xffff : 0; + } + + SETREG(HREG, 40 + i, last_button[i]); + } + + gSPEndDisplayList(close++); + gfxclose(gfx, close); + SET_POLY_OPA_DISP(close); + + CLOSE_DISP(graph); + } + + if (zurumode_flag) { + Debug_mode_output(graph); + } +} + +static void game_draw_first(GRAPH* graph) { + OPEN_DISP(graph); + + gSPSegment(NOW_BG_OPA_DISP++, G_MWO_NUMLIGHT, 0x80000000); + + CLOSE_DISP(graph); +} + +extern void game_draw_last(GRAPH* graph) { + Gfx* close; + Gfx* poly_gfx; + + OPEN_DISP(graph); + + poly_gfx = NOW_POLY_OPA_DISP; + close = gfxopen(poly_gfx); + + gSPDisplayList(NOW_OVERLAY_DISP++, close); + gSPEndDisplayList(close++); + + gfxclose(poly_gfx, close); + SET_POLY_OPA_DISP(close); + + CLOSE_DISP(graph); +} + +extern void game_get_controller(GAME* this) { + if (this->pad_initialized == TRUE) { + padmgr_RequestPadData(this->pads, 1); + } + else { + padmgr_ClearPadData(this->pads); + } +} + +extern void SetGameFrame(int frame) { + if (game_GameFrame != frame) { + game_GameFrame = frame; + game_GameFrameF = (int)(u8)frame; + game_GameFrame_2F = game_GameFrameF * 0.5f; + game_GameFrame__1F = 1.0f / game_GameFrameF; + + SETREG(SREG, 30, (u16)frame); + + if (GETREG(SREG, 29) > 0) { + frame = GETREG(SREG, 29); + } + + JC_JFWDisplay_setFrameRate(JC_JFWDisplay_getManager(), frame); + } +} + +extern void game_main(GAME* this) { + GRAPH* graph = this->graph; + + if (GETREG(SREG, 30) != game_GameFrame || GETREG(SREG, 29)) { + SetGameFrame(GETREG(SREG, 30)); + } + + game_draw_first(graph); + GRAPH_SET_DOING_POINT(graph, GAME_TIME); + mTM_time(); + GRAPH_SET_DOING_POINT(graph, GAME_TIME_FINISHED); + GRAPH_SET_DOING_POINT(graph, GAME_EXEC); + this->exec(this); + GRAPH_SET_DOING_POINT(graph, GAME_EXEC_FINISHED); + GRAPH_SET_DOING_POINT(graph, GAME_BGM); + mBGM_main(this); + GRAPH_SET_DOING_POINT(graph, GAME_BGM_FINISHED); + game_move_first(this); + this->frame_counter++; +} + +static void game_init_hyral(GAME* this, size_t size) { + u8* hyral = (u8*)gamealloc_malloc(&this->gamealloc, size); + if (hyral != NULL) { + THA_ct(&this->tha, (char*)hyral, size); + } + else { + THA_ct(&this->tha, NULL, 0); + _dbg_hungup(__FILE__, 559); + } +} + +extern void game_resize_hyral(GAME* this, int size) { + size_t max_size, free_size, alloc_size; + u8* old_hyral; + u8* hyral; + + old_hyral = (u8*)this->tha.buf_p; + THA_dt(&this->tha); + gamealloc_free(&this->gamealloc, old_hyral); + GetFreeArena(&max_size, &free_size, &alloc_size); + max_size -= 0x50; + + if (size <= 0) { + size = max_size + size; + if (size < 0) { + size = 0; + } + } + else { + if (size > max_size) { + size = max_size; + } + } + + hyral = (u8*)gamealloc_malloc(&this->gamealloc, (u32)size); + if (hyral != NULL) { + THA_ct(&this->tha, (char*)hyral, (u32)size); + } + else { + THA_ct(&this->tha, NULL, 0); + _dbg_hungup(__FILE__, 633); + } +} + +extern void game_ct(GAME* this, void (*init)(GAME*), GRAPH* graph) { + gamePT = this; + graph->need_viupdate = TRUE; + mCon_ct(); + this->graph = graph; + this->frame_counter = 0; + this->exec = NULL; + this->cleanup = NULL; + this->doing = TRUE; + this->pad_initialized = TRUE; + GAME_NEXT_GAME_NULL(this); + gamealloc_init(&this->gamealloc); + game_init_hyral(this, GAME_HYRAL_SIZE); + SetGameFrame(GAME_FRAME); + __gfxprint_default_flags |= GFXPRINT_FLAG_HIGHRES; + init(this); + mBGM_init(); + GBAInit(); + mVibctl_init(); +} + +extern void game_dt(GAME* this) { + mCon_dt(); + mBGM_cleanup(); + if (this->cleanup != NULL) { + this->cleanup(this); + } + + mVibctl_cleanup(); + THA_dt(&this->tha); + gamealloc_cleanup(&this->gamealloc); + gamePT = NULL; +} + +extern void (*game_get_next_game_init(GAME* this))(GAME*) { + return this->next_game_init; +} + +/* @fabricated */ +MATCH_FORCESTRIP extern size_t game_get_next_game_class_size(GAME* this) { + return this->next_game_class_size; +} + +extern int game_is_doing(GAME* this) { + return this->doing; +} + +extern int game_getFreeBytes(GAME* this) { + return THA_getFreeBytes16(&this->tha); +} + +extern void game_goto_next_game_play(GAME* this) { + GAME_GOTO_NEXT(this, play, PLAY); +} + +/* @fabricated */ +MATCH_FORCESTRIP extern void game_goto_next_game_famicom_emu(GAME* this) { + GAME_GOTO_NEXT(this, famicom_emu, FAMICOM_EMU); +} diff --git a/rel/m_music_ovl.c b/rel/m_music_ovl.c new file mode 100644 index 00000000..f10cb952 --- /dev/null +++ b/rel/m_music_ovl.c @@ -0,0 +1,5 @@ +#include "m_music_ovl.h" + +static void mMU_move_Move(Submenu* submenu, mSM_MenuInfo_c* menu) { + (*submenu->overlay->move_Move_proc)(submenu, menu); +}