Merge pull request #267 from Cuyler36/ac_misin

Implement & link ac_misin
This commit is contained in:
Cuyler36
2024-02-28 14:57:27 -05:00
committed by GitHub
4 changed files with 478 additions and 47 deletions
+4
View File
@@ -430,6 +430,10 @@ ac_mbg.c:
.text: [0x8042DCA0, 0x8042DEC8]
.rodata: [0x80644218, 0x80644238]
.data: [0x80684BB0, 0x80684CB8]
ac_misin.c:
.text: [0x8042DEC8, 0x8042EAE0]
.rodata: [0x80644238, 0x80644288]
.data: [0x80684CB8, 0x80684D20]
ac_museum_fossil.c:
.text: [0x8042EDC0, 0x8042F170]
.rodata: [0x806442A0, 0x806442D0]
+52 -1
View File
@@ -3,11 +3,63 @@
#include "types.h"
#include "m_actor.h"
#include "m_needlework.h"
#include "c_keyframe.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct misin_actor_s MISIN_ACTOR;
typedef void (*aMSN_REQUEST_MISIN_STOP_PROC)(void);
typedef void (*aMSN_REQUEST_MISIN_MOVE_PROC)(void);
typedef void (*aMSN_REQUEST_DUSTCLOTH_STOP_PROC)(void);
typedef void (*aMSN_REQUEST_DUSTCLOTH_MOVE_PROC)(void);
typedef struct misin_clip_s {
MISIN_ACTOR* misin_actor_p;
aMSN_REQUEST_MISIN_STOP_PROC request_misin_stop_proc;
aMSN_REQUEST_MISIN_MOVE_PROC request_misin_move_proc;
aMSN_REQUEST_DUSTCLOTH_STOP_PROC request_dustcloth_stop_proc;
aMSN_REQUEST_DUSTCLOTH_MOVE_PROC request_dustcloth_move_proc;
} aMSN_Clip_c;
#define aMSN_GetClip() ((aMSN_Clip_c*)Common_Get(clip).misin_clip)
typedef struct misin_dustcloth_s {
s16 switch_flag;
s16 frame;
xyz_t pos;
xyz_t target_pos;
int target_idx;
s16 target_angle_y;
int moving_flag;
mNW_original_design_c* original_p;
u16* palette_p;
} aMSN_DustCloth_c;
typedef struct misin_misin_s {
s16 status;
f32 speed;
xyz_t pos;
f32 needle_y_counter;
xyz_t needle_offset;
s16 y_scroll;
cKF_SkeletonInfo_R_c keyframe;
s_xyz work[17];
s_xyz morph[17];
Mtx mtx[2][16] ATTRIBUTE_ALIGN(8);
} aMSN_Misin_c;
struct misin_actor_s {
ACTOR actor_class;
aMSN_DustCloth_c dustcloth;
aMSN_Misin_c misin;
aMSN_Clip_c clip;
};
extern ACTOR_PROFILE Misin_Profile;
#ifdef __cplusplus
@@ -15,4 +67,3 @@ extern ACTOR_PROFILE Misin_Profile;
#endif
#endif
+52 -46
View File
@@ -32,52 +32,58 @@ typedef void (*CLIP_NONE_PROC)();
/* sizeof(Clip_c) == 0x104 */
typedef struct clip_s {
/* 0x000 */ void* _000[(0x020 - 0x000) / sizeof(void*)];
/* 0x020 */ int arrange_ftr_num;
/* 0x024 */ void* _024[(0x040 - 0x024) / sizeof(void*)];
/* 0x040 */ aNPC_Clip_c* npc_clip;
/* 0x044 */ void* _044[(0x060 - 0x044) / sizeof(void*)];
/* 0x060 */ aSM_Clip_c* shop_manekin_clip;
/* 0x064 */ void* _064;
/* 0x068 */ CLIP_NONE_PROC _068;
/* 0x06C */ aQMgr_Clip_c* quest_manager_clip;
/* 0x070 */ aSI_Clip_c* shop_indoor_clip;
/* 0x074 */ bIT_Clip_c* bg_item_clip;
/* 0x078 */ aWeather_Clip_c* weather_clip;
/* 0x07C */ aINS_Clip_c* insect_clip;
/* 0x080 */ aMR_Clip_c* my_room_clip;
/* 0x084 */ void* _084;
/* 0x088 */ aHOI_Clip_c* handOverItem_clip;
/* 0x08C */ aSTR_Clip_c* structure_clip;
/* 0x090 */ eEC_EffectControl_Clip_c* effect_clip;
/* 0x094 */ aTOL_Clip_c* tools_clip;
/* 0x098 */ void* _098;
/* 0x09C */ aMI_Clip_c* my_indoor_clip;
/* 0x0A0 */ mDemo_Clip_c* demo_clip; /* can be multiple clip classes */
/* 0x0A4 */ mDemo_Clip_c* demo_clip2; /* can be multiple clip classes */
/* 0x0A8 */ void* _0A8;
/* 0x0AC */ aGYO_Clip_c* gyo_clip;
/* 0x0B0 */ void* _0B0;
/* 0x0B4 */ void* _0B4;
/* 0x0B8 */ aShopUmbrella_Clip_c* shop_umbrella_clip;
/* 0x0BC */ aAR_Clip_c* arrange_room_clip;
/* 0x0C0 */ void* _0C0;
/* 0x0C4 */ void* _0C4;
/* 0x0C8 */ void* shrine_clip;
/* 0x0CC */ void* _0CC;
/* 0x0D0 */ void* _0D0;
/* 0x0D4 */ CLIP_NONE_PROC ball_redma_proc; /* removed in DnM+ */
/* 0x0D8 */ void* _0D8;
/* 0x0DC */ aAL_Clip_c* animal_logo_clip;
/* 0x0E0 */ void* _0E0;
/* 0x0E4 */ void* _0E4;
/* 0x0E8 */ void* _0E8;
/* 0x0EC */ aAPC_Clip_c* aprilfool_control_clip;
/* 0x0F0 */ aEvMgr_Clip_c* event_manager_clip;
/* 0x0F4 */ aGHC_Clip_c* groundhog_control_clip;
/* 0x0F8 */ void* _0F8;
/* 0x0FC */ void* _0FC;
/* 0x100 */ void* _100;
/* 0x000 */ void* _000[(0x020 - 0x000) / sizeof(void*)];
/* 0x020 */ int arrange_ftr_num;
/* 0x024 */ void* _024;
/* 0x028 */ void* misin_clip;
/* 0x02C */ void* _02C;
/* 0x030 */ void* _030;
/* 0x034 */ void* _034;
/* 0x038 */ void* _038;
/* 0x03C */ void* _03C;
/* 0x040 */ aNPC_Clip_c* npc_clip;
/* 0x044 */ void* _044[(0x060 - 0x044) / sizeof(void*)];
/* 0x060 */ aSM_Clip_c* shop_manekin_clip;
/* 0x064 */ void* _064;
/* 0x068 */ CLIP_NONE_PROC _068;
/* 0x06C */ aQMgr_Clip_c* quest_manager_clip;
/* 0x070 */ aSI_Clip_c* shop_indoor_clip;
/* 0x074 */ bIT_Clip_c* bg_item_clip;
/* 0x078 */ aWeather_Clip_c* weather_clip;
/* 0x07C */ aINS_Clip_c* insect_clip;
/* 0x080 */ aMR_Clip_c* my_room_clip;
/* 0x084 */ void* _084;
/* 0x088 */ aHOI_Clip_c* handOverItem_clip;
/* 0x08C */ aSTR_Clip_c* structure_clip;
/* 0x090 */ eEC_EffectControl_Clip_c* effect_clip;
/* 0x094 */ aTOL_Clip_c* tools_clip;
/* 0x098 */ void* _098;
/* 0x09C */ aMI_Clip_c* my_indoor_clip;
/* 0x0A0 */ mDemo_Clip_c* demo_clip; /* can be multiple clip classes */
/* 0x0A4 */ mDemo_Clip_c* demo_clip2; /* can be multiple clip classes */
/* 0x0A8 */ void* _0A8;
/* 0x0AC */ aGYO_Clip_c* gyo_clip;
/* 0x0B0 */ void* _0B0;
/* 0x0B4 */ void* _0B4;
/* 0x0B8 */ aShopUmbrella_Clip_c* shop_umbrella_clip;
/* 0x0BC */ aAR_Clip_c* arrange_room_clip;
/* 0x0C0 */ void* _0C0;
/* 0x0C4 */ void* _0C4;
/* 0x0C8 */ void* shrine_clip;
/* 0x0CC */ void* _0CC;
/* 0x0D0 */ void* _0D0;
/* 0x0D4 */ CLIP_NONE_PROC ball_redma_proc; /* removed in DnM+ */
/* 0x0D8 */ void* _0D8;
/* 0x0DC */ aAL_Clip_c* animal_logo_clip;
/* 0x0E0 */ void* _0E0;
/* 0x0E4 */ void* _0E4;
/* 0x0E8 */ void* _0E8;
/* 0x0EC */ aAPC_Clip_c* aprilfool_control_clip;
/* 0x0F0 */ aEvMgr_Clip_c* event_manager_clip;
/* 0x0F4 */ aGHC_Clip_c* groundhog_control_clip;
/* 0x0F8 */ void* _0F8;
/* 0x0FC */ void* _0FC;
/* 0x100 */ void* _100;
} Clip_c;
extern void clip_clear();
+370
View File
@@ -0,0 +1,370 @@
#include "ac_misin.h"
#include "m_common_data.h"
#include "m_malloc.h"
#include "m_player_lib.h"
#include "m_rcp.h"
#include "sys_matrix.h"
static void Misin_Actor_ct(ACTOR* actorx, GAME* game);
static void Misin_Actor_dt(ACTOR* actorx, GAME* game);
static void Misin_Actor_draw(ACTOR* actorx, GAME* game);
static void Misin_Actor_move(ACTOR* actorx, GAME* game);
ACTOR_PROFILE Misin_Profile = {
mAc_PROFILE_MISIN,
ACTOR_PART_BG,
ACTOR_STATE_CAN_MOVE_IN_DEMO_SCENES | ACTOR_STATE_NO_DRAW_WHILE_CULLED | ACTOR_STATE_NO_MOVE_WHILE_CULLED,
EMPTY_NO,
ACTOR_OBJ_BANK_KEEP,
sizeof(MISIN_ACTOR),
&Misin_Actor_ct,
&Misin_Actor_dt,
&Misin_Actor_move,
&Misin_Actor_draw,
NULL,
};
static void aMSN_SetDustclothSwitch(s16 switch_flag) {
if (aMSN_GetClip() != NULL) {
aMSN_GetClip()->misin_actor_p->dustcloth.switch_flag = switch_flag;
}
}
static void aMSN_RequestDustclothMove(void) {
aMSN_SetDustclothSwitch(TRUE);
}
static void aMSN_RequestDustclothStop(void) {
aMSN_SetDustclothSwitch(FALSE);
}
static xyz_t aMSN_dustcloth_target_table[4] = {
{ -4.0f, 0.0f, 4.0f },
{ -4.0f, 0.0f, -4.0f },
{ 4.0f, 0.0f, -4.0f },
{ 4.0f, 0.0f, 4.0f },
};
static void aMSN_DustclothCT(aMSN_DustCloth_c* dustcloth, GAME* game) {
dustcloth->switch_flag = TRUE;
dustcloth->frame = 0;
dustcloth->original_p = (mNW_original_design_c*)zelda_malloc_align(sizeof(mNW_original_design_c), 32);
if (dustcloth->original_p != NULL) {
if (RANDOM(3) == 1) {
mNW_CopyOriginalTextureClass(dustcloth->original_p,
&Save_Get(needlework).original_design[RANDOM(1000) & 7]);
} else {
dustcloth->palette_p = (u16*)zelda_malloc_align(sizeof(u16) * 16, 32);
if (dustcloth->palette_p != NULL) {
mActor_name_t cloth;
mSP_SelectRandomItem_New(NULL, &cloth, 1, NULL, 0, mSP_KIND_CLOTH, mSP_LISTTYPE_ABC, FALSE);
mPlib_Load_PlayerTexAndPallet(dustcloth->original_p->design.data, dustcloth->palette_p,
ITEM_NAME_GET_INDEX(cloth));
}
}
}
dustcloth->target_idx = 1;
dustcloth->pos.x = 91.0f;
dustcloth->pos.y = 0.0f;
dustcloth->pos.z = 136.0f;
dustcloth->target_pos = aMSN_dustcloth_target_table[(dustcloth->target_idx - 1) & 3];
}
static void aMSN_SetMisinStatus(s16 status) {
if (aMSN_GetClip() != NULL) {
aMSN_GetClip()->misin_actor_p->misin.status = status;
}
}
static void aMSN_RequestMisinStop(void) {
aMSN_SetMisinStatus(FALSE);
}
static void aMSN_ReqeustMisinMove(void) {
aMSN_SetMisinStatus(TRUE);
}
extern cKF_Skeleton_R_c cKF_bs_r_obj_misin;
extern cKF_Animation_R_c cKF_ba_r_obj_misin;
static void aMSN_MisinCT(aMSN_Misin_c* misin, GAME* game) {
cKF_SkeletonInfo_R_c* keyframe = &misin->keyframe;
misin->status = TRUE;
cKF_SkeletonInfo_R_ct(keyframe, &cKF_bs_r_obj_misin, &cKF_ba_r_obj_misin, misin->work, misin->morph);
cKF_SkeletonInfo_R_init_standard_repeat(keyframe, &cKF_ba_r_obj_misin, NULL);
cKF_SkeletonInfo_R_play(keyframe);
misin->speed = 1.0f;
keyframe->frame_control.speed = 1.0f;
misin->pos.x = 0.0f;
misin->pos.y = 0.0f;
misin->pos.z = 0.0f;
misin->needle_y_counter = 0.0f;
}
static void aMSN_SetClipInfo(ACTOR* actorx, GAME* game) {
MISIN_ACTOR* misin_actor = (MISIN_ACTOR*)actorx;
aMSN_Clip_c* clip = &misin_actor->clip;
clip->misin_actor_p = misin_actor;
clip->request_misin_stop_proc = &aMSN_RequestMisinStop;
clip->request_misin_move_proc = &aMSN_ReqeustMisinMove;
clip->request_dustcloth_stop_proc = &aMSN_RequestDustclothStop;
clip->request_dustcloth_move_proc = &aMSN_RequestDustclothMove;
Common_Get(clip).misin_clip = clip;
}
static void Misin_Actor_ct(ACTOR* actorx, GAME* game) {
MISIN_ACTOR* misin_actor = (MISIN_ACTOR*)actorx;
aMSN_DustCloth_c* dustcloth = &misin_actor->dustcloth;
aMSN_Misin_c* misin = &misin_actor->misin;
aMSN_DustclothCT(dustcloth, game);
aMSN_MisinCT(misin, game);
aMSN_SetClipInfo(actorx, game);
}
static void Misin_Actor_dt(ACTOR* actorx, GAME* game) {
MISIN_ACTOR* misin = (MISIN_ACTOR*)actorx;
if (misin->dustcloth.original_p != NULL) {
zelda_free(misin->dustcloth.original_p);
}
if (misin->dustcloth.palette_p != NULL) {
zelda_free(misin->dustcloth.palette_p);
}
Common_Get(clip).misin_clip = NULL;
}
extern Gfx obj_misin_cloth_model[];
static void aMSN_DrawDustcloth(aMSN_DustCloth_c* dustcloth, GAME* game) {
s16 target_angle_y = dustcloth->target_angle_y;
if (dustcloth->original_p != NULL) {
_texture_z_light_fog_prim(game->graph);
OPEN_DISP(game->graph);
/* Segment 8 holds the custom design or shirt texture */
gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_8, dustcloth->original_p->design.data);
if (dustcloth->palette_p != NULL) {
/* Segment 9 holds the palette for the shirt */
gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_9, dustcloth->palette_p);
} else {
/* Segment 9 holds the palette for the custom design */
gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_9, mNW_PaletteIdx2Palette(dustcloth->original_p->palette));
}
Matrix_translate(dustcloth->pos.x, dustcloth->pos.y, dustcloth->pos.z, 0);
Matrix_RotateY(target_angle_y, 1);
Matrix_translate(-dustcloth->target_pos.x, -dustcloth->target_pos.y, -dustcloth->target_pos.z, 1);
Matrix_scale(0.01f, 0.01f, 0.01f, 1);
gSPMatrix(NEXT_POLY_OPA_DISP, _Matrix_to_Mtx_new(game->graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(NEXT_POLY_OPA_DISP, obj_misin_cloth_model);
CLOSE_DISP(game->graph);
}
}
static int aMSN_DrawMisinBefore(GAME* game, cKF_SkeletonInfo_R_c* keyframe, int joint_idx, Gfx** joint_shape,
u8* joint_flags, void* arg, s_xyz* joint_rot, xyz_t* joint_pos) {
/* Skip drawing the needle model */
if (joint_idx == 3) {
*joint_shape = NULL;
}
return TRUE;
}
extern Gfx obj_misin_hari_model[];
static int aMSN_DrawMisinAfter(GAME* game, cKF_SkeletonInfo_R_c* keyframe, int joint_idx, Gfx** joint_shape,
u8* joint_flags, void* arg, s_xyz* joint_rot, xyz_t* joint_pos) {
aMSN_Misin_c* misin = (aMSN_Misin_c*)arg;
/* Now draw the needle model */
if (joint_idx == 3) {
OPEN_DISP(game->graph);
Matrix_translate(87.0f, 62.0f + misin->needle_offset.y, 141.0f, 0);
Matrix_RotateY(DEG2SHORT_ANGLE(0.0f), 1);
Matrix_RotateZ(DEG2SHORT_ANGLE(-90.0f), 1);
Matrix_scale(0.01f, 0.01f, 0.01f, 1);
gSPMatrix(NEXT_POLY_OPA_DISP, _Matrix_to_Mtx_new(game->graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(NEXT_POLY_OPA_DISP, obj_misin_hari_model);
CLOSE_DISP(game->graph);
}
return TRUE;
}
static Gfx* aMSN_MakeBeltGFX(aMSN_Misin_c* misin, GAME* game) {
return two_tex_scroll_dolphin(game->graph, 0, 0, misin->y_scroll, 8, 32, 1, 0, 0, 0, 0);
}
static void aMSN_DrawMisin(aMSN_Misin_c* misin, GAME* game) {
cKF_SkeletonInfo_R_c* keyframe = &misin->keyframe;
Mtx* mtx_p = misin->mtx[game->frame_counter & 1];
Gfx* belt_gfx = aMSN_MakeBeltGFX(misin, game);
_texture_z_light_fog_prim(game->graph);
if (belt_gfx != NULL) {
OPEN_DISP(game->graph);
Matrix_translate(misin->pos.x, misin->pos.y, misin->pos.z, 0);
Matrix_RotateY(DEG2SHORT_ANGLE(0.0f), 1);
Matrix_scale(0.01f, 0.01f, 0.01f, 1);
gSPMatrix(NEXT_POLY_OPA_DISP, _Matrix_to_Mtx_new(game->graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
/* Segment 9 has the scrolled belt gfx */
gSPSegment(NEXT_POLY_OPA_DISP, G_MWO_SEGMENT_9, belt_gfx);
/* Draw animated model */
cKF_Si3_draw_R_SV(game, keyframe, mtx_p, &aMSN_DrawMisinBefore, &aMSN_DrawMisinAfter, misin);
CLOSE_DISP(game->graph);
}
}
static void Misin_Actor_draw(ACTOR* actorx, GAME* game) {
MISIN_ACTOR* misin = (MISIN_ACTOR*)actorx;
aMSN_DrawDustcloth(&misin->dustcloth, game);
aMSN_DrawMisin(&misin->misin, game);
}
static void aMSN_MoveDustcloth(aMSN_DustCloth_c* dustcloth, GAME* game) {
static s16 target_angle_table[4] = {
DEG2SHORT_ANGLE(0.0f),
DEG2SHORT_ANGLE(90.0f),
DEG2SHORT_ANGLE(-180.0f),
DEG2SHORT_ANGLE(-90.0f),
};
dustcloth->moving_flag = FALSE;
if (dustcloth->switch_flag != FALSE) {
if (dustcloth->frame == 137) {
int target_idx = dustcloth->target_idx;
dustcloth->target_pos = aMSN_dustcloth_target_table[target_idx];
dustcloth->target_angle_y = target_angle_table[target_idx];
if (dustcloth->target_angle_y == DEG2SHORT_ANGLE(0.0f)) {
dustcloth->target_angle_y = -1;
}
}
if (dustcloth->frame < 98) {
f32 percent = get_percent(97, 0, dustcloth->frame);
int now_idx = dustcloth->target_idx;
int prev_idx = (dustcloth->target_idx - 1) & 3;
/* Interpolate position between last target pos & now target pos */
dustcloth->target_pos.x =
aMSN_dustcloth_target_table[prev_idx].x +
percent * (aMSN_dustcloth_target_table[now_idx].x - aMSN_dustcloth_target_table[prev_idx].x);
dustcloth->target_pos.z =
aMSN_dustcloth_target_table[prev_idx].z +
percent * (aMSN_dustcloth_target_table[now_idx].z - aMSN_dustcloth_target_table[prev_idx].z);
/* Set rotation */
dustcloth->target_angle_y = target_angle_table[prev_idx];
if (dustcloth->frame > 21) {
/* Play sewing SFX */
xyz_t pos = { 91.0f, 40.0f, 136.0f };
sAdo_OngenPos((u32)&aMSN_MoveDustcloth, 0x48, &pos);
}
} else if (dustcloth->frame >= 120) {
f32 percent = get_percent(138, 120, dustcloth->frame);
int now_idx = dustcloth->target_idx;
int prev_idx = (dustcloth->target_idx - 1) & 3;
/* Interpolate rotation */
dustcloth->target_angle_y = target_angle_table[prev_idx] + (s16)(percent * (f32)DEG2SHORT_ANGLE(90.0f));
}
if (!(dustcloth->frame > 4 && dustcloth->frame < 118)) {
dustcloth->moving_flag = TRUE;
}
dustcloth->frame++;
if (dustcloth->frame >= 138) {
dustcloth->target_idx = (dustcloth->target_idx + 1) & 3;
dustcloth->frame = 0;
}
}
}
static void aMSN_SetNeedleOffsetPosition(aMSN_Misin_c* misin, aMSN_DustCloth_c* dustcloth) {
static xyz_t zero_offset = { 0.0f, 0.0f, 0.0f };
int counter = misin->needle_y_counter;
if (counter < 10) {
misin->needle_offset.y = (misin->needle_y_counter / 10.0f) * -3.0f;
} else if (counter < 17) {
misin->needle_offset.y = ((misin->needle_y_counter - 10.0f) / 7.0f) * 3.0f + -3.0f;
} else {
misin->needle_offset = zero_offset;
}
if (dustcloth->moving_flag == FALSE) {
misin->needle_y_counter += misin->speed;
}
if (misin->needle_y_counter > 19.0f) {
misin->needle_y_counter -= 19.0f;
}
}
static void aMSN_MoveMisin(aMSN_Misin_c* misin, aMSN_DustCloth_c* dustcloth, GAME* game) {
f32 target_speed;
cKF_SkeletonInfo_R_c* keyframe;
if (misin->status == TRUE) {
target_speed = 1.0f;
} else {
target_speed = 0.0f;
}
keyframe = &misin->keyframe;
aMSN_SetNeedleOffsetPosition(misin, dustcloth);
misin->y_scroll += (s16)(misin->speed * -6.0f);
cKF_SkeletonInfo_R_play(keyframe);
if (misin->speed < target_speed) {
misin->speed += 0.01f;
} else {
misin->speed -= 0.01f;
}
if (misin->speed < 0.0f) {
misin->speed = 0.0f;
} else if (misin->speed > 1.0f) {
misin->speed = 1.0f;
}
keyframe->frame_control.speed = misin->speed;
}
static void Misin_Actor_move(ACTOR* actorx, GAME* game) {
MISIN_ACTOR* misin = (MISIN_ACTOR*)actorx;
aMSN_DustCloth_c* dustcloth = &misin->dustcloth;
aMSN_MoveDustcloth(dustcloth, game);
aMSN_MoveMisin(&misin->misin, dustcloth, game);
}