diff --git a/config/rel_slices.yml b/config/rel_slices.yml index 9a265cf6..391c0b0f 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -62,6 +62,9 @@ m_needlework.c: .text: [0x803C98EC, 0x803C9F7C] .data: [0x8065ABC0, 0x8065AE30] .bss: [0x81298F60, 0x81299180] +m_olib.c: + .text: [0x803D88E8, 0x803D8A34] + .rodata: [0x80642A00, 0x80642A10] m_pause.c: .text: [0x803D8A34, 0x803D8AEC] m_police_box.c: @@ -78,11 +81,11 @@ m_room_type/mRmTp_FtrItemNo2FtrIdx.c: #m_skin_matrix.c: # .text: [0x803f1528, 0x803f1bb4] # .rodata: [0x80643310, 0x80643318] +m_view.c: + .text: [0x803F3E58, 0x803F4E08] + .rodata: [0x806433D8, 0x80643408] sys_stacks.c: .bss: [0x812F5670, 0x812F9670] -m_olib.c: - .text: [0x803D88E8, 0x803D8A34] - .rodata: [0x80642A00, 0x80642A10] THA_GA.c: .text: [0x80404AE0, 0x80404B40] TwoHeadArena.c: diff --git a/include/m_pause.h b/include/m_pause.h index 4df379d1..13298d6c 100644 --- a/include/m_pause.h +++ b/include/m_pause.h @@ -11,7 +11,7 @@ extern "C" { typedef struct pause_t{ int enabled; int timer; -}pause_t; // size = 0x8 +} pause_t; // size = 0x8 void Pause_ct(pause_t* pause); diff --git a/include/m_play.h b/include/m_play.h index 5530d3ea..887bb842 100644 --- a/include/m_play.h +++ b/include/m_play.h @@ -7,6 +7,7 @@ #include "m_view.h" #include "m_camera2.h" #include "m_submenu.h" +#include "m_pause.h" #include "m_play_h.h" #ifdef __cplusplus @@ -21,8 +22,8 @@ struct game_play_s { /* 0x1A68 */ View view; /* 0x1B88 */ Camera2 camera; /* 0x1CC0 */ u8 _1CC0[0x1DA0 - 0x1CC0]; - /* 0x1DA0 */ int isPause; - /* 0x1DA4 */ u8 _1DA4[0x1DEC - 0x1DA4]; + /* 0x1DA0 */ pause_t pause; + /* 0x1DA8 */ u8 _1DA8[0x1DEC - 0x1DA8]; /* 0x1DEC */ Submenu submenu; /* 0x1FA4 */ u8 _1FA4[0x200C - 0x1FA4]; /* 0x200C */ MtxF matrix; diff --git a/include/m_view.h b/include/m_view.h index 1e21cc4b..dc642b88 100644 --- a/include/m_view.h +++ b/include/m_view.h @@ -11,6 +11,7 @@ extern "C" { #endif +#define VIEW_UPDATE_NONE 0 #define VIEW_UPDATE_LOOKAT (1 << 0) // 1 #define VIEW_UPDATE_SCISSOR (1 << 1) // 2 #define VIEW_UPDATE_PERSPECTIVE (1 << 2) // 4 @@ -50,7 +51,15 @@ typedef struct view_s { } View; extern void initView(View* view, GRAPH* graph); -extern void showView(View* view, int flags); +extern void setLookAtView(View* view, xyz_t* eye, xyz_t* center, xyz_t* up); +extern void setScaleView(View* view, f32 scale); +extern void setPerspectiveView(View* view, f32 fovY, f32 near, f32 far); +extern void setScissorView(View* view, rect* screen); +extern int stretchViewInit(View* view); +extern int showView(View* view, int flags); +extern int showPerspectiveView(View* view); +extern int showOrthoView(View* view); +extern int showView1(View* view, int flag_mask, Gfx** gfx_p); #ifdef __cplusplus } diff --git a/include/m_watch_my_step.h b/include/m_watch_my_step.h index b1e22763..aa4de694 100644 --- a/include/m_watch_my_step.h +++ b/include/m_watch_my_step.h @@ -33,6 +33,14 @@ extern void watch_my_step_ct(); extern void watch_my_step_move(GAME_PLAY* play); extern void watch_my_step_draw(GAME_PLAY* play); +extern void navigate_camera_ct(); +extern void navigate_camera_move(GAME_PLAY* play); +extern void navigate_camera_draw(GAME_PLAY* play); + +extern void mWt_mybell_confirmation_ct(); +extern void mWt_mybell_confirmation_move(GAME_PLAY* play); +extern void mWt_mybell_confirmation_draw(GAME_PLAY* play); + #ifdef __cplusplus } #endif diff --git a/include/sys_matrix.h b/include/sys_matrix.h index 0e68ece9..2f1b3798 100644 --- a/include/sys_matrix.h +++ b/include/sys_matrix.h @@ -25,7 +25,7 @@ extern void Matrix_scale(f32 x, f32 y, f32 z, u8 flag); extern void Matrix_RotateX(s16 x, int flag); extern void Matrix_RotateY(s16 x, int flag); extern void Matrix_RotateZ(s16 x, int flag); -extern void Matrix_RotateXYZ(s16 x, s16 y, s16 z, int flag); +extern void Matrix_rotateXYZ(s16 x, s16 y, s16 z, int flag); extern void Matrix_softcv3_mult(xyz_t* src, s_xyz* dest); extern void Matrix_softcv3_load(s_xyz* src, f32 x, f32 y, f32 z); extern Mtx* _MtxF_to_Mtx(MtxF* src, Mtx* dest); @@ -36,7 +36,7 @@ extern void Matrix_Position_Zero(xyz_t* screen_pos); extern void Matrix_Position_VecX(xyz_t* screen_pos, f32 x); extern void Matrix_Position_VecZ(xyz_t* screen_pos, f32 x); extern void Matrix_copy_MtxF(MtxF* dest, MtxF* src); -extern void Matrix_MtxToMtxF(Mtx* src, MtxF* dest); +extern void Matrix_MtxtoMtxF(Mtx* src, MtxF* dest); extern void Matrix_reverse(MtxF* m); extern void Matrix_to_rotate_new(MtxF* m, s_xyz* vec, int flag); extern void Matrix_to_rotate2_new(MtxF* m, s_xyz* vec, int flag); diff --git a/rel/m_lib.c b/rel/m_lib.c index b4ea57ac..985501a4 100644 --- a/rel/m_lib.c +++ b/rel/m_lib.c @@ -678,7 +678,7 @@ extern void none_proc2(ACTOR* actor, GAME* game) {} * @param play Pointer to a GAME_PLAY structure. * @return TRUE if the game is in pause state, FALSE otherwise. */ -extern int _Game_play_isPause(GAME_PLAY* play) { return (play->isPause != 0); } +extern int _Game_play_isPause(GAME_PLAY* play) { return (play->pause.enabled != 0); } /** * @brief Calculate a percentage with respect to minimum and maximum values, and apply scaling. diff --git a/rel/m_view.c b/rel/m_view.c new file mode 100644 index 00000000..f6ae2a55 --- /dev/null +++ b/rel/m_view.c @@ -0,0 +1,437 @@ +#include "m_view.h" + +#include "main.h" +#include "m_common_data.h" +#include "m_field_info.h" +#include "sys_matrix.h" +#include "libultra/libultra.h" + +static void set_viewport(Vp* viewport, rect* screen_rect) { + int width = screen_rect->r - screen_rect->l; + int height = screen_rect->bottom - screen_rect->top; + + viewport->vp.vscale[0] = width * 4; + viewport->vp.vscale[1] = height * 4; + viewport->vp.vscale[2] = 511; + viewport->vp.vscale[3] = 0; + + viewport->vp.vtrans[0] = (width + screen_rect->l) * 4; + viewport->vp.vtrans[1] = (height + screen_rect->top) * 4; + viewport->vp.vtrans[2] = 511; + viewport->vp.vtrans[3] = 0; +} + +extern void initView(View* view, GRAPH* graph) { + view->graph = graph; + + view->screen.top = 0; + view->screen.bottom = SCREEN_HEIGHT; + view->screen.l = 0; + view->screen.r = SCREEN_WIDTH; + + view->fovY = 20.0f; + view->near = 200.0f; + + if (Common_Get(field_type) != mFI_FIELDTYPE2_FG) { + view->near = 20.0f; + } + + view->far = 1600.0f; + + view->scale = 1.0f; + + view->eye.x = 0.0f; + view->eye.y = 0.0f; + view->eye.z = -1.0f; + + /* copy -> paste bug here */ + #ifndef BUGFIXES + view->center.x = 0.0f; + view->center.x = 0.0f; + view->center.x = 0.0f; + #else + view->center.x = 0.0f; + view->center.y = 0.0f; + view->center.z = 0.0f; + #endif + + view->up.x = 0.0f; + view->up.y = 1.0f; + view->up.z = 0.0f; + + view->flag = VIEW_UPDATE_LOOKAT | VIEW_UPDATE_SCISSOR | VIEW_UPDATE_PERSPECTIVE; + stretchViewInit(view); +} + +extern void setLookAtView(View* view, xyz_t* eye, xyz_t* center, xyz_t* up) { + if (eye->x == center->x && eye->z == center->z) { + eye->x += 0.1f; + } + + view->eye = *eye; + view->center = *center; + view->up = *up; + + view->flag |= VIEW_UPDATE_LOOKAT; +} + +extern void setScaleView(View* view, f32 scale) { + view->scale = scale; + + view->flag |= VIEW_UPDATE_PERSPECTIVE; +} + +extern void setPerspectiveView(View* view, f32 fovY, f32 near, f32 far) { + view->fovY = fovY; + view->near = near; + view->far = far; + + view->flag |= VIEW_UPDATE_PERSPECTIVE; +} + +extern void setScissorView(View* view, rect* screen) { + view->screen = *screen; + + view->flag |= VIEW_UPDATE_SCISSOR; +} + +static void setScissorX(Gfx** gfx_p, int left, int top, int right, int bottom) { + Gfx* gfx = *gfx_p; + + if (left == 0 && top == 0 && right == SCREEN_WIDTH && bottom == SCREEN_HEIGHT) { + right *= 2; + bottom *= 2; + } + + gDPSetScissor(gfx++, G_SC_NON_INTERLACE, left, top, right, bottom); + *gfx_p = gfx; +} + +static void setScissor(View* view) { + GRAPH* g = view->graph; + int left = view->screen.l; + int top = view->screen.top; + int right = view->screen.r; + int bottom = view->screen.bottom; + Gfx* gfx; + + OPEN_DISP(g); + + gfx = NOW_POLY_OPA_DISP; + setScissorX(&gfx, left, top, right, bottom); + SET_POLY_OPA_DISP(gfx); + + gfx = NOW_POLY_XLU_DISP; + setScissorX(&gfx, left, top, right, bottom); + SET_POLY_XLU_DISP(gfx); + + gfx = NOW_SHADOW_DISP; + setScissorX(&gfx, left, top, right, bottom); + SET_SHADOW_DISP(gfx); + + gfx = NOW_LIGHT_DISP; + setScissorX(&gfx, left, top, right, bottom); + SET_LIGHT_DISP(gfx); + + CLOSE_DISP(g); +} + +extern int stretchViewInit(View* view) { + view->stretch.target_rotate.x = 0.0f; + view->stretch.target_rotate.y = 0.0f; + view->stretch.target_rotate.z = 0.0f; + + view->stretch.target_scale.x = 1.0f; + view->stretch.target_scale.y = 1.0f; + view->stretch.target_scale.z = 1.0f; + + view->stretch.rotate = view->stretch.target_rotate; + view->stretch.scale = view->stretch.target_scale; + view->stretch.step = 0.0f; + + return 0; +} + +static int do_stretch_view(View* view, Mtx* mtx) { + f32 step = view->stretch.step; + + if (step == 0.0f) { + return FALSE; + } + else if (step == 1.0f) { + view->stretch.rotate = view->stretch.target_rotate; + view->stretch.scale = view->stretch.target_scale; + view->stretch.step = 0.0f; + } + else { + view->stretch.rotate.x += view->stretch.step * (view->stretch.target_rotate.x - view->stretch.rotate.x); + view->stretch.rotate.y += view->stretch.step * (view->stretch.target_rotate.y - view->stretch.rotate.y); + view->stretch.rotate.z += view->stretch.step * (view->stretch.target_rotate.z - view->stretch.rotate.z); + + view->stretch.scale.x += view->stretch.step * (view->stretch.target_scale.x - view->stretch.scale.x); + view->stretch.scale.y += view->stretch.step * (view->stretch.target_scale.y - view->stretch.scale.y); + view->stretch.scale.z += view->stretch.step * (view->stretch.target_scale.z - view->stretch.scale.z); + } + + { + s_xyz rot; + MtxF mtx_f; + + rot.x = view->stretch.rotate.x * 10430.378f; // 57.3 degrees? + rot.y = view->stretch.rotate.y * 10430.378f; + rot.z = view->stretch.rotate.z * 10430.378f; + + /* push matrix to current */ + Matrix_MtxtoMtxF(mtx, &mtx_f); + Matrix_put(&mtx_f); + + /* do rotation */ + Matrix_RotateX(rot.x, 1); + Matrix_RotateY(rot.y, 1); + Matrix_RotateZ(rot.z, 1); + + /* do scaling */ + Matrix_scale(view->stretch.scale.x, view->stretch.scale.y, view->stretch.scale.z, 1); + + /* undo rotation */ + Matrix_RotateZ(-rot.z, 1); + Matrix_RotateY(-rot.y, 1); + Matrix_RotateX(-rot.x, 1); + + /* update matrix */ + _Matrix_to_Mtx(mtx); + } + + return TRUE; +} + +extern int showView(View* view, int flag_mask) { + if (((flag_mask >> 4) | (flag_mask & view->flag)) & VIEW_UPDATE_ORTHOGRAPHIC) { + return showOrthoView(view); + } + else { + return showPerspectiveView(view); + } +} + +extern int showPerspectiveView(View* view) { + GRAPH* g = view->graph; + Vp* vp; + Mtx* mtx; + + OPEN_DISP(g); + + /* update viewport */ + vp = GRAPH_ALLOC_TYPE(g, Vp, 1); + set_viewport(vp, &view->screen); + view->viewport = *vp; + + /* update scissor */ + setScissor(view); + + /* push viewport */ + gSPViewport(NOW_POLY_OPA_DISP++, vp); + gSPViewport(NOW_POLY_XLU_DISP++, vp); + gSPViewport(NOW_SHADOW_DISP++, vp); + gSPViewport(NOW_LIGHT_DISP++, vp); + gSPViewport(NOW_BG_OPA_DISP++, vp); + gSPViewport(NOW_BG_XLU_DISP++, vp); + + /* update perspective matrix */ + mtx = GRAPH_ALLOC_TYPE(g, Mtx, 1); + view->p_projection = mtx; + guPerspective( + mtx, + &view->normal, + view->fovY, + (f32)(view->screen.r - view->screen.l) / (f32)(view->screen.bottom - view->screen.top), + view->near, view->far, + view->scale + ); + + view->mtx_projection = *mtx; + + do_stretch_view(view, mtx); + + gSPPerspNormalize(NOW_POLY_OPA_DISP++, view->normal); + gSPMatrix(NOW_POLY_OPA_DISP++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); + + gSPPerspNormalize(NOW_POLY_XLU_DISP++, view->normal); + gSPMatrix(NOW_POLY_XLU_DISP++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); + + gSPPerspNormalize(NOW_SHADOW_DISP++, view->normal); + gSPMatrix(NOW_SHADOW_DISP++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); + + gSPPerspNormalize(NOW_LIGHT_DISP++, view->normal); + gSPMatrix(NOW_LIGHT_DISP++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); + + gSPPerspNormalize(NOW_BG_OPA_DISP++, view->normal); + gSPMatrix(NOW_BG_OPA_DISP++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); + + gSPPerspNormalize(NOW_BG_XLU_DISP++, view->normal); + gSPMatrix(NOW_BG_XLU_DISP++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); + + /* update look-at (viewing) matrix */ + mtx = GRAPH_ALLOC_TYPE(g, Mtx, 1); + view->p_viewing = mtx; + guLookAt( + mtx, + view->eye.x, view->eye.y, view->eye.z, + view->center.x, view->center.y, view->center.z, + view->up.x, view->up.y, view->up.z + ); + view->mtx_viewing = *mtx; + + gSPMatrix(NOW_POLY_OPA_DISP++, mtx, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION); + + gSPMatrix(NOW_POLY_XLU_DISP++, mtx, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION); + + gSPMatrix(NOW_SHADOW_DISP++, mtx, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION); + + gSPMatrix(NOW_LIGHT_DISP++, mtx, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION); + + gSPMatrix(NOW_BG_OPA_DISP++, mtx, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION); + + gSPMatrix(NOW_BG_XLU_DISP++, mtx, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION); + + CLOSE_DISP(g); + + return TRUE; +} + +extern int showOrthoView(View* view) { + GRAPH* g = view->graph; + Vp* vp; + Mtx* mtx; + + OPEN_DISP(g); + + /* update viewport */ + vp = GRAPH_ALLOC_TYPE(g, Vp, 1); + set_viewport(vp, &view->screen); + view->viewport = *vp; + + /* update scissor */ + setScissor(view); + + /* push viewport */ + gSPViewport(NOW_POLY_OPA_DISP++, vp); + gSPViewport(NOW_POLY_XLU_DISP++, vp); + gSPViewport(NOW_SHADOW_DISP++, vp); + gSPViewport(NOW_LIGHT_DISP++, vp); + gSPViewport(NOW_OVERLAY_DISP++, vp); + gSPViewport(NOW_BG_OPA_DISP++, vp); + gSPViewport(NOW_BG_XLU_DISP++, vp); + + /* update orthographic proj matrix */ + mtx = GRAPH_ALLOC_TYPE(g, Mtx, 1); + view->p_projection = mtx; + + guOrtho( + mtx, + -(f32)ScreenWidth / 2.0f, (f32)ScreenWidth / 2.0f, + -(f32)ScreenHeight / 2.0f, (f32)ScreenHeight / 2.0f, + view->near, + view->far, + view->scale + ); + + view->mtx_projection = *mtx; + + gSPMatrix(NOW_POLY_OPA_DISP++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); + + gSPMatrix(NOW_POLY_XLU_DISP++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); + + gSPMatrix(NOW_SHADOW_DISP++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); + + gSPMatrix(NOW_LIGHT_DISP++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); + + gSPMatrix(NOW_BG_OPA_DISP++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); + + gSPMatrix(NOW_BG_XLU_DISP++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); + + CLOSE_DISP(g); + + return TRUE; +} + +extern int showView1(View* view, int flag_mask, Gfx** gfx_p) { + Gfx* gfx; + GRAPH* g; + int flags; + + gfx = *gfx_p; + flag_mask = (flag_mask >> 4) | (flag_mask & view->flag); + g = view->graph; + + OPEN_DISP(g); + + if (flag_mask & VIEW_UPDATE_SCISSOR) { + Gfx* gfx_save; + Vp* vp = GRAPH_ALLOC_TYPE(g, Vp, 1); + set_viewport(vp, &view->screen); + view->viewport = *vp; + + gDPPipeSync(gfx++); + gfx_save = gfx; + setScissorX(&gfx_save, view->screen.l, view->screen.top, view->screen.r, view->screen.bottom); + gfx = gfx_save; + gSPViewport(gfx++, vp); + } + + if (flag_mask & VIEW_UPDATE_ORTHOGRAPHIC) { + Mtx* m = GRAPH_ALLOC_TYPE(g, Mtx, 1); + + view->p_projection = m; + guOrtho( + m, + -(f32)ScreenWidth / 2.0f, (f32)ScreenWidth / 2.0f, + -(f32)ScreenHeight / 2.0f, (f32)ScreenHeight / 2.0f, + view->near, + view->far, + view->scale + ); + + view->mtx_projection = *m; + gSPMatrix(gfx++, m, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); + } + else if (flag_mask & (VIEW_UPDATE_SCISSOR | VIEW_UPDATE_PERSPECTIVE)) { + Mtx* m = GRAPH_ALLOC_TYPE(g, Mtx, 1); + + view->p_projection = m; + guPerspective( + m, + &view->normal, + view->fovY, + (f32)(view->screen.r - view->screen.l) / (f32)(view->screen.bottom - view->screen.top), + view->near, view->far, + view->scale + ); + + view->mtx_projection = *m; + gSPPerspNormalize(gfx++, view->normal); + gSPMatrix(gfx++, m, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); + } + + if (flag_mask & VIEW_UPDATE_LOOKAT) { + Mtx* m = GRAPH_ALLOC_TYPE(g, Mtx, 1); + + view->p_viewing = m; + guLookAt( + m, + view->eye.x, view->eye.y, view->eye.z, + view->center.x, view->center.y, view->center.z, + view->up.x, view->up.y, view->up.z + ); + + view->mtx_viewing = *m; + gSPMatrix(gfx++, m, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION); + } + + CLOSE_DISP(g); + + view->flag = VIEW_UPDATE_NONE; + *gfx_p = gfx; + + return TRUE; +} diff --git a/rel/m_watch_my_step.c b/rel/m_watch_my_step.c index 2bd4fc24..76835f25 100644 --- a/rel/m_watch_my_step.c +++ b/rel/m_watch_my_step.c @@ -62,9 +62,6 @@ typedef struct mybell_confirmation_s { static mWt_mybell_confirmation_c S_mybell_conf; -static void navigate_camera_ct(); -static void mWt_mybell_confirmation_ct(); - extern void watch_my_step_ct() { bzero(&S_watch_my_step, sizeof(mWt_watch_my_step_c)); S_watch_my_step.item_no = EMPTY_NO; @@ -72,9 +69,6 @@ extern void watch_my_step_ct() { mWt_mybell_confirmation_ct(); } -static void navigate_camera_move(GAME_PLAY* play); -static void mWt_mybell_confirmation_move(GAME_PLAY* play); - extern void watch_my_step_move(GAME_PLAY* play) { mActor_name_t window_item; PLAYER_ACTOR* player_actor = get_player_actor_withoutCheck(play); @@ -196,9 +190,6 @@ extern void watch_my_step_move(GAME_PLAY* play) { } } -static void navigate_camera_draw(GAME_PLAY*); -static void mWt_mybell_confirmation_draw(GAME_PLAY*); - // TODO: @nonmatching extern void watch_my_step_draw(GAME_PLAY* play) { GAME* game = (GAME*)play;