diff --git a/config/rel_slices.yml b/config/rel_slices.yml index e188817c..8837575a 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -131,6 +131,11 @@ m_flashrom.c: .text: [0x803AC5C8, 0x803AF48C] .data: [0x80654188, 0x80654298] .bss: [0x81295BD8, 0x81295C30] +m_font.c: + .text: [0x803AF48C, 0x803B15E0] + .rodata: [0x80642080, 0x80642258] + .data: [0x80654298, 0x806544D0] + .bss: [0x81295C30, 0x81295C70] m_fuusen.c: .text: [0x803B15E0, 0x803B1908] .rodata: [0x80642258, 0x80642288] @@ -513,6 +518,12 @@ ac_t_utiwa.c: .text: [0x804AA4C8, 0x804AA72C] .data: [0x8068F310, 0x8068F370] .rodata: [0x80645F30, 0x80645F38] +ac_t_zinnia1.c: + .text: [0x804AA72C, 0x804AA880] + .data: [0x8068F370, 0x8068F3B0] +ac_t_zinnia2.c: + .text: [0x804AA880, 0x804AA9d4] + .data: [0x8068F3B0, 0x8068F3F0] ac_tools.c: .text: [0x804AC034, 0x804AC2D8] .rodata: [0x80645F90, 0x80645F98] @@ -599,6 +610,9 @@ ac_ev_gypsy.c: .text: [0x80520D78, 0x80521414] .rodata: [0x80649228, 0x80649238] .data: [0x806A0938, 0x806A09F8] +ac_ev_kabuPeddler.c: + .text: [0x80521414, 0x80521D34] + .data: [0x806A09F8, 0x806A0AD8] ac_ev_santa.c: .text: [0x80523498, 0x8052400C] .rodata: [0x80649268, 0x80649270] diff --git a/include/Famicom/famicom.h b/include/Famicom/famicom.h index b1b63014..06ca55ca 100644 --- a/include/Famicom/famicom.h +++ b/include/Famicom/famicom.h @@ -8,13 +8,18 @@ extern "C" { #endif +#define FAMICOM_INTERNAL_ROM_NUM 19 + +#define NESTAG_CMD_SIZE 3 +#define NESTAG_SIZE (NESTAG_CMD_SIZE + 1) + #define NESTAG_END "END" #define NESTAG_VEQ "VEQ" #define NESTAG_VNE "VNE" #define NESTAG_GID "GID" #define NESTAG_GNM "GNM" #define NESTAG_CPN "CPN" -#define NESTAG_OFS "OFS" +#define NESTAG_OFS "OFS" /* Offset into the shared highscore data to read/write at */ #define NESTAG_HSC "HSC" #define NESTAG_GNO "GNO" #define NESTAG_BBR "BBR" @@ -100,6 +105,8 @@ typedef struct famicom_common_s { extern void* my_malloc_current; extern u8 save_game_image; +extern FamicomCommon famicomCommon; + 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(); @@ -109,6 +116,8 @@ extern int famicom_1frame(); extern int famicom_init(int, void*, u8); extern int famicom_cleanup(); +extern void nesinfo_tags_set(int rom_no); + #ifdef __cplusplus } diff --git a/include/Famicom/ks_nes_common.h b/include/Famicom/ks_nes_common.h index daa108d8..6642239f 100644 --- a/include/Famicom/ks_nes_common.h +++ b/include/Famicom/ks_nes_common.h @@ -27,7 +27,8 @@ typedef struct ks_nes_common_work_obj_s { } ksNesCommonWorkObj; typedef struct ks_nes_state_obj_s { - u8 _temp[0x1A78]; + /* 0x0000 */ u8 wram[2048]; + /* 0x0800 */ u8 _temp[0x1A78 - 0x800]; } ksNesStateObj; #ifdef __cplusplus diff --git a/include/_mem.h b/include/_mem.h index f5134435..9174dcae 100644 --- a/include/_mem.h +++ b/include/_mem.h @@ -11,6 +11,7 @@ extern "C" { void * memcpy(void * dst, const void * src, size_t n); void * memset(void * dst, int val, size_t n); +int memcmp(const void* src1, const void* src2, size_t n); void __fill_mem(void * dst, int val, unsigned long n); #pragma section code_type diff --git a/include/ac_ev_kabuPeddler.h b/include/ac_ev_kabuPeddler.h index 67e839d9..d79ca08a 100644 --- a/include/ac_ev_kabuPeddler.h +++ b/include/ac_ev_kabuPeddler.h @@ -3,11 +3,27 @@ #include "types.h" #include "m_actor.h" +#include "ac_npc.h" #ifdef __cplusplus extern "C" { #endif +#define aEKPD_KABU_TYPE_NUM 4 + +typedef struct ev_kabuPeddler_s EV_KABUPEDDLER_ACTOR; + +typedef void (*aEKPD_PROC)(EV_KABUPEDDLER_ACTOR*, GAME_PLAY*); +typedef void (*aEKPD_SETUP_PROC)(EV_KABUPEDDLER_ACTOR*, GAME_PLAY*, int); + +struct ev_kabuPeddler_s { + NPC_ACTOR npc_class; + int kabu_type; + int talk_act; + aEKPD_PROC talk_proc; + aEKPD_SETUP_PROC setup_talk_proc; +}; + extern ACTOR_PROFILE Ev_KabuPeddler_Profile; #ifdef __cplusplus diff --git a/include/ac_t_zinnia1.h b/include/ac_t_zinnia1.h index e72db1c4..20c24214 100644 --- a/include/ac_t_zinnia1.h +++ b/include/ac_t_zinnia1.h @@ -3,6 +3,7 @@ #include "types.h" #include "m_actor.h" +#include "ac_tools.h" #ifdef __cplusplus extern "C" { @@ -10,6 +11,15 @@ extern "C" { extern ACTOR_PROFILE T_Zinnia1_Profile; +typedef void (*ZINNIA1_PROC)(ACTOR*); + +typedef struct t_zinnia1_s { + TOOLS_ACTOR tools_class; + ZINNIA1_PROC proc; + int current_id; + +} ZINNIA1_ACTOR; + #ifdef __cplusplus } #endif diff --git a/include/ac_t_zinnia2.h b/include/ac_t_zinnia2.h index 895393a8..9fcaa00c 100644 --- a/include/ac_t_zinnia2.h +++ b/include/ac_t_zinnia2.h @@ -3,6 +3,7 @@ #include "types.h" #include "m_actor.h" +#include "ac_tools.h" #ifdef __cplusplus extern "C" { @@ -10,6 +11,15 @@ extern "C" { extern ACTOR_PROFILE T_Zinnia2_Profile; +typedef void (*ZINNIA2_PROC)(ACTOR*); + +typedef struct t_zinnia2_s { + TOOLS_ACTOR tools_class; + ZINNIA2_PROC proc; + int current_id; + +} ZINNIA2_ACTOR; + #ifdef __cplusplus } #endif diff --git a/src/ac_ev_kabuPeddler.c b/src/ac_ev_kabuPeddler.c new file mode 100644 index 00000000..5b56a53b --- /dev/null +++ b/src/ac_ev_kabuPeddler.c @@ -0,0 +1,84 @@ +#include "ac_ev_kabuPeddler.h" + +#include "m_common_data.h" +#include "m_font.h" +#include "m_msg.h" +#include "m_player_lib.h" +#include "m_play.h" + +enum { + aEKPD_ACTION_TALK_END_WAIT, + aEKPD_ACTION_SELL_CHECK, + aEKPD_ACTION_SELL_CHECK_AFTER, + aEKPD_ACTION_SELL_CHECK2, + aEKPD_ACTION_SELL_CEHCK_AFTER2, + aEKPD_ACTION_MONEY_GET_DEMO_START_WAIT, + aEKPD_ACTION_MONEY_GET_DEMO_END_WAIT, + aEKPD_ACTION_KABU_TRANS_DEMO_START_WAIT, + + aEKPD_ACTION_NUM +}; + +static void aEKPD_actor_ct(ACTOR* actorx, GAME* game); +static void aEKPD_actor_dt(ACTOR* actorx, GAME* game); +static void aEKPD_actor_draw(ACTOR* actorx, GAME* game); +static void aEKPD_actor_move(ACTOR* actorx, GAME* game); +static void aEKPD_actor_save(ACTOR* actorx, GAME* game); +static void aEKPD_actor_init(ACTOR* actorx, GAME* game); + +ACTOR_PROFILE Ev_KabuPeddler_Profile = { + mAc_PROFILE_EV_KABUPEDDLER, + ACTOR_PART_NPC, + ACTOR_STATE_NONE, + SP_NPC_KABUPEDDLER, + ACTOR_OBJ_BANK_KEEP, + sizeof(EV_KABUPEDDLER_ACTOR), + &aEKPD_actor_ct, + &aEKPD_actor_dt, + &aEKPD_actor_init, + mActor_NONE_PROC1, + &aEKPD_actor_save +}; + +static void aEKPD_setupAction(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play, int talk_act); +static void aEKPD_talk_request(ACTOR*, GAME*); +static int aEKPD_talk_init(ACTOR*, GAME*); +static int aEKPD_talk_end_chk(ACTOR*, GAME*); + +static void aEKPD_actor_ct(ACTOR* actorx, GAME* game) { + static aNPC_ct_data_c ct_data = { + &aEKPD_actor_move, + &aEKPD_actor_draw, + 3, + &aEKPD_talk_request, + &aEKPD_talk_init, + &aEKPD_talk_end_chk, + 0 + }; + + EV_KABUPEDDLER_ACTOR* kabuPeddler = (EV_KABUPEDDLER_ACTOR*)actorx; + + if ((*Common_Get(clip).npc_clip->birth_check_proc)(actorx, game) == TRUE) { + (*Common_Get(clip).npc_clip->ct_proc)(actorx, game, &ct_data); + kabuPeddler->setup_talk_proc = &aEKPD_setupAction; + } +} + +static void aEKPD_actor_save(ACTOR* actorx, GAME* game) { + (*Common_Get(clip).npc_clip->save_proc)(actorx, game); +} + +static void aEKPD_actor_dt(ACTOR* actorx, GAME* game) { + (*Common_Get(clip).npc_clip->dt_proc)(actorx, game); + mEv_actor_dying_message(mEv_EVENT_KABU_PEDDLER, actorx); +} + +static void aEKPD_actor_init(ACTOR* actorx, GAME* game) { + (*Common_Get(clip).npc_clip->init_proc)(actorx, game); +} + +static void aEKPD_actor_draw(ACTOR* actorx, GAME* game) { + (*Common_Get(clip).npc_clip->draw_proc)(actorx, game); +} + +#include "../src/ac_ev_kabuPeddler_move.c_inc" diff --git a/src/ac_ev_kabuPeddler_move.c_inc b/src/ac_ev_kabuPeddler_move.c_inc new file mode 100644 index 00000000..01e11037 --- /dev/null +++ b/src/ac_ev_kabuPeddler_move.c_inc @@ -0,0 +1,219 @@ +static int aEKPD_check_look() { + mEv_kabu_peddler_c* peddler_data = &Save_Get(event_save_data).weekly.kabu_peddler; + int res = FALSE; + + if (mPr_CheckCmpPersonalID(&peddler_data->spoken_pids[Common_Get(player_no)], + &Common_Get(now_private)->player_ID) == TRUE) { + res = TRUE; + } + + return res; +} + +static void aEKPD_set_price_str_sub(u32 price, int free_str_no) { + u8 price_str[6]; + + mFont_UnintToString(price_str, sizeof(price_str), price, 5, TRUE, FALSE, TRUE); + mMsg_Set_free_str(mMsg_Get_base_window_p(), free_str_no, price_str, sizeof(price_str)); +} + +static void aEKPD_set_price_str() { + static int sum[aEKPD_KABU_TYPE_NUM] = { 1, 10, 50, 100 }; + u32 price = Save_Get(kabu_price_schedule).daily_price[lbRTC_SUNDAY]; + int i; + + for (i = 0; i < aEKPD_KABU_TYPE_NUM; i++) { + aEKPD_set_price_str_sub(price * sum[i], i); + } +} + +static int aEKPD_get_trans_space_idx() { + return mPr_GetPossessionItemIdx(Common_Get(now_private), EMPTY_NO); +} + +static void aEKPD_hand_over_kabu(int idx, int kabu_type) { + static mActor_name_t kabu_no[aEKPD_KABU_TYPE_NUM - 1] = { ITM_KABU_10, ITM_KABU_50, ITM_KABU_100 }; + + mPr_SetPossessionItem(Common_Get(now_private), idx, kabu_no[kabu_type], mPr_ITEM_COND_NORMAL); +} + +static void aEKPD_sell_check(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play) { + static int next_act[] = { aEKPD_ACTION_TALK_END_WAIT, aEKPD_ACTION_SELL_CHECK_AFTER, aEKPD_ACTION_SELL_CEHCK_AFTER2, + 0 }; + int talk_act_idx; + int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9); + + if (order != 0 && mMsg_Check_MainNormalContinue(mMsg_Get_base_window_p()) == TRUE) { + int choseNum = mChoice_Get_ChoseNum(mChoice_Get_base_window_p()); + + switch (choseNum) { + case mChoice_CHOICE0: + case mChoice_CHOICE1: + case mChoice_CHOICE2: { + if (kabuPeddler->talk_act == aEKPD_ACTION_SELL_CHECK) { + talk_act_idx = 1; + } else { + talk_act_idx = 2; + } + break; + } + + case mChoice_CHOICE3: { + talk_act_idx = 3; + break; + } + + default: { + talk_act_idx = 0; + break; + } + } + + if (talk_act_idx != 0) { + (*kabuPeddler->setup_talk_proc)(kabuPeddler, play, next_act[talk_act_idx]); + mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0); + kabuPeddler->kabu_type = choseNum; + } + } +} + +static void aEKPD_sell_check_after(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play) { + static int sell_sum[aEKPD_KABU_TYPE_NUM] = { 10, 50, 100, 0 }; + static int next_msg_no[] = { 0x0711, 0x0710, 0x070F }; + static int next_msg_no2[] = { 0x0711, 0x0717, 0x0716 }; + static int next_act[] = { aEKPD_ACTION_MONEY_GET_DEMO_START_WAIT, aEKPD_ACTION_TALK_END_WAIT, + aEKPD_ACTION_TALK_END_WAIT }; + + if (mMsg_Check_MainNormalContinue(mMsg_Get_base_window_p()) == TRUE) { + u32 price; + int talk_act_idx; + int trans_space_idx = aEKPD_get_trans_space_idx(); + + if (trans_space_idx != -1) { + price = Save_Get(kabu_price_schedule).daily_price[lbRTC_SUNDAY] * sell_sum[kabuPeddler->kabu_type]; + + if (mSP_money_check(price) == TRUE) { + mSP_get_sell_price(price); /* take money from player */ + aEKPD_hand_over_kabu(trans_space_idx, kabuPeddler->kabu_type); + talk_act_idx = 0; + } else { + talk_act_idx = 1; + } + } else { + talk_act_idx = 2; + } + + if (kabuPeddler->talk_act == 2) { + mMsg_Set_continue_msg_num(mMsg_Get_base_window_p(), next_msg_no[talk_act_idx]); + } else { + mMsg_Set_continue_msg_num(mMsg_Get_base_window_p(), next_msg_no2[talk_act_idx]); + } + + (*kabuPeddler->setup_talk_proc)(kabuPeddler, play, next_act[talk_act_idx]); + } +} + +static void aEKPD_money_get_demo_start_wait(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play) { + if (Common_Get(clip).handOverItem_clip->request_mode == aHOI_REQUEST_TRANS_WAIT) { + mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 1, 3); + (*kabuPeddler->setup_talk_proc)(kabuPeddler, play, aEKPD_ACTION_MONEY_GET_DEMO_END_WAIT); + } +} + +static void aEKPD_money_get_demo_end_wait(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play) { + if (Common_Get(clip).handOverItem_clip->master_actor == NULL) { + mMsg_Unset_LockContinue(mMsg_Get_base_window_p()); + (*kabuPeddler->setup_talk_proc)(kabuPeddler, play, aEKPD_ACTION_KABU_TRANS_DEMO_START_WAIT); + } +} + +static void aEKPD_kabu_trans_demo_start_wait(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play) { + int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 1); + + if (order == 2) { + (*kabuPeddler->setup_talk_proc)(kabuPeddler, play, aEKPD_ACTION_SELL_CHECK2); + } +} + +static void aEKPD_sell_check_init(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play) { + aEKPD_set_price_str(); + mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0); +} + +static void aEKPD_sell_check2_init(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play) { + mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 0, (mActor_name_t)(ITM_KABU_START + kabuPeddler->kabu_type)); + mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 1, 7); + mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 2, 0); +} + +static void aEKPD_money_get_demo_start_wait_init(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play) { + mMsg_Set_LockContinue(mMsg_Get_base_window_p()); + mPlib_request_main_give_type1((GAME*)play, ITM_MONEY_10000, 7, FALSE, FALSE); +} + +typedef void (*aEKPD_INIT_PROC)(EV_KABUPEDDLER_ACTOR*, GAME_PLAY*); + +static void aEKPD_init_proc(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play, int act) { + static aEKPD_INIT_PROC init_proc[aEKPD_ACTION_NUM] = { + (aEKPD_INIT_PROC)&none_proc1, &aEKPD_sell_check_init, (aEKPD_INIT_PROC)&none_proc1, + &aEKPD_sell_check2_init, (aEKPD_INIT_PROC)&none_proc1, &aEKPD_money_get_demo_start_wait_init, + (aEKPD_INIT_PROC)&none_proc1, (aEKPD_INIT_PROC)&none_proc1 + }; + + (*init_proc[act])(kabuPeddler, play); +} + +static void aEKPD_setupAction(EV_KABUPEDDLER_ACTOR* kabuPeddler, GAME_PLAY* play, int act) { + static aEKPD_PROC process[aEKPD_ACTION_NUM] = { (aEKPD_PROC)&none_proc1, &aEKPD_sell_check, + &aEKPD_sell_check_after, &aEKPD_sell_check, + &aEKPD_sell_check_after, &aEKPD_money_get_demo_start_wait, + &aEKPD_money_get_demo_end_wait, &aEKPD_kabu_trans_demo_start_wait }; + + kabuPeddler->talk_act = act; + kabuPeddler->talk_proc = process[act]; + aEKPD_init_proc(kabuPeddler, play, act); +} + +static void aEKPD_set_talk_info(ACTOR* actorx) { + int msg_no = aEKPD_check_look() == TRUE ? 0x0718 : 0x06FD; + + mDemo_Set_msg_num(msg_no); +} + +static void aEKPD_talk_request(ACTOR* actorx, GAME* game) { + mDemo_Request(mDemo_TYPE_TALK, actorx, &aEKPD_set_talk_info); +} + +static int aEKPD_talk_init(ACTOR* actorx, GAME* game) { + EV_KABUPEDDLER_ACTOR* kabuPeddler = (EV_KABUPEDDLER_ACTOR*)actorx; + GAME_PLAY* play = (GAME_PLAY*)game; + + if (aEKPD_check_look() == FALSE) { + mEv_kabu_peddler_c* kabu_data = &Save_Get(event_save_data).weekly.kabu_peddler; + + mPr_CopyPersonalID(&kabu_data->spoken_pids[Common_Get(player_no)], &Common_Get(now_private)->player_ID); + } + + (*kabuPeddler->setup_talk_proc)(kabuPeddler, play, aEKPD_ACTION_SELL_CHECK); + mDemo_Set_ListenAble(); + return TRUE; +} + +static int aEKPD_talk_end_chk(ACTOR* actorx, GAME* game) { + EV_KABUPEDDLER_ACTOR* kabuPeddler = (EV_KABUPEDDLER_ACTOR*)actorx; + GAME_PLAY* play = (GAME_PLAY*)game; + int res = FALSE; + + (*kabuPeddler->talk_proc)(kabuPeddler, play); + + if (mDemo_Check(mDemo_TYPE_TALK, actorx) == FALSE) { + mEv_set_status(mEv_EVENT_KABU_PEDDLER, mEv_STATUS_TALK); + res = TRUE; + } + + return res; +} + +static void aEKPD_actor_move(ACTOR* actorx, GAME* game) { + (*Common_Get(clip).npc_clip->move_proc)(actorx, game); +} diff --git a/src/ac_t_zinnia1.c b/src/ac_t_zinnia1.c new file mode 100644 index 00000000..f9841099 --- /dev/null +++ b/src/ac_t_zinnia1.c @@ -0,0 +1,83 @@ +#include "ac_t_zinnia1.h" + +#include "m_name_table.h" +#include "sys_matrix.h" +#include "m_lib.h" +#include "m_rcp.h" + +static void aTZN1_actor_ct(ACTOR* actor, GAME* game); +static void aTZN1_actor_draw(ACTOR* actor, GAME* game); +static void aTZN1_actor_move(ACTOR* actor, GAME* game); +static void aTZN1_setupAction(ACTOR* actor, int action); + +ACTOR_PROFILE T_Zinnia1_Profile = { + mAc_PROFILE_T_ZINNIA1, + ACTOR_PART_BG, + ACTOR_STATE_NO_DRAW_WHILE_CULLED | ACTOR_STATE_NO_MOVE_WHILE_CULLED, + EMPTY_NO, + ACTOR_OBJ_BANK_TOOLS, + sizeof(ZINNIA1_ACTOR), + &aTZN1_actor_ct, + NONE_ACTOR_PROC, + &aTZN1_actor_move, + &aTZN1_actor_draw, + NULL +}; + +extern Gfx crw_zinnia1_body_model[]; + +static void aTZN1_actor_ct(ACTOR* actor, GAME* game){ + aTZN1_setupAction(actor, 4); +} + +static void aTZN1_destruct(ACTOR* actor){ + Actor_delete(actor); +} + +static void aTZN1_setupAction(ACTOR* actor, int action){ + ZINNIA1_ACTOR* zinnia1 = (ZINNIA1_ACTOR*)actor; + static ZINNIA1_PROC process[] = { + (ZINNIA1_PROC)none_proc1, (ZINNIA1_PROC)none_proc1, (ZINNIA1_PROC)none_proc1, aTZN1_destruct,(ZINNIA1_PROC)none_proc1, NULL + }; + + zinnia1->proc = process[action]; + zinnia1->current_id = action; + zinnia1->tools_class.work0 = action; +} + +static void aTZN1_actor_move(ACTOR* actor, GAME* game){ + ZINNIA1_ACTOR* zinnia1 = (ZINNIA1_ACTOR*)actor; + + if(zinnia1->tools_class.work0 != zinnia1->current_id){ + aTZN1_setupAction(actor, zinnia1->tools_class.work0); + } + + zinnia1->proc(actor); +} + +static void aTZN1_actor_draw(ACTOR* actor, GAME* game){ + ZINNIA1_ACTOR* zinnia1 = (ZINNIA1_ACTOR*)actor; + + GRAPH* graph; + Gfx* gfxp; + + if(zinnia1->tools_class.init_matrix == 1){ + graph = game->graph; + + OPEN_DISP(graph); + + Matrix_put(&zinnia1->tools_class.matrix_work); + Matrix_Position_Zero(&zinnia1->tools_class.actor_class.world.position); + + zinnia1->tools_class.init_matrix = 0; + + _texture_z_light_fog_prim_npc(graph); + + gfxp = NOW_POLY_OPA_DISP; + gSPMatrix(gfxp++, _Matrix_to_Mtx_new(graph),G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(gfxp++, crw_zinnia1_body_model); + SET_POLY_OPA_DISP(gfxp); + + CLOSE_DISP(graph); + } +} diff --git a/src/ac_t_zinnia2.c b/src/ac_t_zinnia2.c new file mode 100644 index 00000000..3d329a20 --- /dev/null +++ b/src/ac_t_zinnia2.c @@ -0,0 +1,83 @@ +#include "ac_t_zinnia2.h" + +#include "m_name_table.h" +#include "sys_matrix.h" +#include "m_lib.h" +#include "m_rcp.h" + +static void aTZN2_actor_ct(ACTOR* actor, GAME* game); +static void aTZN2_actor_draw(ACTOR* actor, GAME* game); +static void aTZN2_actor_move(ACTOR* actor, GAME* game); +static void aTZN2_setupAction(ACTOR* actor, int action); + +ACTOR_PROFILE T_Zinnia2_Profile = { + mAc_PROFILE_T_ZINNIA2, + ACTOR_PART_BG, + ACTOR_STATE_NO_DRAW_WHILE_CULLED | ACTOR_STATE_NO_MOVE_WHILE_CULLED, + EMPTY_NO, + ACTOR_OBJ_BANK_TOOLS, + sizeof(ZINNIA2_ACTOR), + &aTZN2_actor_ct, + NONE_ACTOR_PROC, + &aTZN2_actor_move, + &aTZN2_actor_draw, + NULL +}; + +extern Gfx crw_zinnia2_body_model[]; + +static void aTZN2_actor_ct(ACTOR* actor, GAME* game){ + aTZN2_setupAction(actor, 4); +} + +static void aTZN2_destruct(ACTOR* actor){ + Actor_delete(actor); +} + +static void aTZN2_setupAction(ACTOR* actor, int action){ + ZINNIA2_ACTOR* zinnia2 = (ZINNIA2_ACTOR*)actor; + static ZINNIA2_PROC process[] = { + (ZINNIA2_PROC)none_proc1, (ZINNIA2_PROC)none_proc1, (ZINNIA2_PROC)none_proc1, aTZN2_destruct,(ZINNIA2_PROC)none_proc1, NULL + }; + + zinnia2->proc = process[action]; + zinnia2->current_id = action; + zinnia2->tools_class.work0 = action; +} + +static void aTZN2_actor_move(ACTOR* actor, GAME* game){ + ZINNIA2_ACTOR* zinnia2 = (ZINNIA2_ACTOR*)actor; + + if(zinnia2->tools_class.work0 != zinnia2->current_id){ + aTZN2_setupAction(actor, zinnia2->tools_class.work0); + } + + zinnia2->proc(actor); +} + +static void aTZN2_actor_draw(ACTOR* actor, GAME* game){ + ZINNIA2_ACTOR* zinnia2 = (ZINNIA2_ACTOR*)actor; + + GRAPH* graph; + Gfx* gfxp; + + if(zinnia2->tools_class.init_matrix == 1){ + graph = game->graph; + + OPEN_DISP(graph); + + Matrix_put(&zinnia2->tools_class.matrix_work); + Matrix_Position_Zero(&zinnia2->tools_class.actor_class.world.position); + + zinnia2->tools_class.init_matrix = 0; + + _texture_z_light_fog_prim_npc(graph); + + gfxp = NOW_POLY_OPA_DISP; + gSPMatrix(gfxp++, _Matrix_to_Mtx_new(graph),G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(gfxp++, crw_zinnia2_body_model); + SET_POLY_OPA_DISP(gfxp); + + CLOSE_DISP(graph); + } +} diff --git a/src/m_font_main.c_inc b/src/m_font_main.c_inc index e7d4357e..1bde1bf9 100644 --- a/src/m_font_main.c_inc +++ b/src/m_font_main.c_inc @@ -39,7 +39,7 @@ typedef struct control_code_s { s8 attribute; } mFont_ControlCodeInfo_t; -static mFont_ControlCodeInfo_t mFont_cont_info_tbl[mFont_CONT_CODE_NUM] = { +static const mFont_ControlCodeInfo_t mFont_cont_info_tbl[mFont_CONT_CODE_NUM] = { { 2, mFont_CONT_ATTRIBUTE_0 }, { 2, mFont_CONT_ATTRIBUTE_0 }, { 2, mFont_CONT_ATTRIBUTE_0 }, @@ -669,7 +669,6 @@ static void mFont_gppDrawCharRect( *gfx_pp = g; } -// TODO: Non-matching static void mFont_gppDrawCharPoly( GRAPH* graph, Gfx** gfx_pp, @@ -683,21 +682,29 @@ static void mFont_gppDrawCharPoly( int ulx, uly, lrx, lry; xy_t vert_tl, vert_br; f32 inv_half_s, inv_half_t; + f32 t0, t1; mFont_gppLoadTexture(&g, c, &uls, &ult, &lrs, &lrt); vert_tl.x = pos_tl->x - ((f32)SCREEN_WIDTH * 0.5f); vert_tl.y = -(pos_tl->y - ((f32)SCREEN_HEIGHT * 0.5f)); - vert_br.x = pos_br->x - ((f32)SCREEN_WIDTH * 0.5f) - vert_tl.x; - vert_br.y = -(pos_br->y - ((f32)SCREEN_HEIGHT * 0.5f)) - vert_tl.y; + vert_br.x = vert_tl.x; + vert_br.y = vert_tl.y; + t0 = pos_br->x - ((f32)SCREEN_WIDTH * 0.5f) - vert_tl.x; + t1 = -(pos_br->y - ((f32)SCREEN_HEIGHT * 0.5f)) - vert_tl.y; inv_half_s = 0.5f / (f32)s; inv_half_t = 0.5f / (f32)t; + + vert_br.x += t0 * (1.0f - inv_half_s); + vert_br.y += t1 * (1.0f - inv_half_t); + vert_tl.x += t0 * inv_half_s; + vert_tl.y += t1 * inv_half_t; - ulx = (vert_tl.x + vert_br.x * inv_half_s) * mFont_SCALE_F; - uly = (vert_tl.y + vert_br.y * inv_half_t) * mFont_SCALE_F; - lrx = (vert_tl.x + vert_br.x * (1.0f - inv_half_s)) * mFont_SCALE_F; - lry = (vert_tl.y + vert_br.y * (1.0f - inv_half_t)) * mFont_SCALE_F; + ulx = (int)(vert_tl.x * mFont_SCALE_F); + uly = (int)(vert_tl.y * mFont_SCALE_F); + lrx = (int)(vert_br.x * mFont_SCALE_F); + lry = (int)(vert_br.y * mFont_SCALE_F); lrs = ((uls + s) << 6) - 32; lrt = ((ult + t) << 6) - 32; diff --git a/src/static/Famicom/famicom_nesinfo.cpp b/src/static/Famicom/famicom_nesinfo.cpp new file mode 100644 index 00000000..22c05cc0 --- /dev/null +++ b/src/static/Famicom/famicom_nesinfo.cpp @@ -0,0 +1,276 @@ +#include "Famicom/famicom.h" + +#include "_mem.h" +#include "dolphin/os.h" + +static u8 highscore_num = 0; +static u8 highscore_updated = 0; +static u8* highscore_flags = nullptr; +static u8 nesinfo_mcrd_cont_no = 0; +static u8* nesinfo_mcrd_game_name = nullptr; +static u8* nesinfo_ptr = nullptr; +static u32 nesinfo_tags_size = 0; +static u8* nesinfo_tags_start = nullptr; +static u8* nesinfo_tags_end = nullptr; +static char* nesinfo_tags_gameName = nullptr; +static char* nesinfo_tags_kanjiName = nullptr; +static u8* nesinfo_tags_moriName = nullptr; +static u32 nesinfo_data_size = 0; +static u8* nesinfo_data_start = nullptr; +static u8* nesinfo_data_end = nullptr; +static u32 nesinfo_rom_size = 0; +static u8* nesinfo_rom_start = nullptr; +static u8* nesinfo_rom_end = nullptr; +static u32 nesinfo_expand_rom_size = 0; +static bool tcs_bad = false; +static bool ics_bad = false; + +enum highscore_state { HIGHSCORE_STATE_UNSET, HIGHSCORE_STATE_SET, HIGHSCORE_STATE_2, HIGHSCORE_STATE_UNINITIALIZED }; + +enum famicom_games { + FAMICOM_GAME_CLU_CLU_LAND, + FAMICOM_GAME_BALLOON_FIGHT, + FAMICOM_GAME_DONKEY_KONG, + FAMICOM_GAME_DONKEY_KONG_JR_MATH, + FAMICOM_GAME_PINBALL, + +}; + +#define END_TAG() 'E', 'N', 'D', 0 +#define GID_TAG(l) 'G', 'I', 'D', (l) +#define GNM_TAG(l) 'G', 'N', 'M', (l) +#define GNO_TAG() 'G', 'N', 'O', sizeof(u8) +#define OFS_TAG() 'O', 'F', 'S', sizeof(u16) +#define HSC_TAG(l) 'H', 'S', 'C', (sizeof(u16) + l) + +#define OFS_U16(ofs) ((u8)((u32)(ofs) >> 8), (u8)(ofs)) + +static u8 tags_table_default[] = { END_TAG() }; + +// clang-format off +static u8 tags_table_cluclu_land[] = { + GID_TAG(2), 'C', 'L', + GNM_TAG(12), 'C', 'L', 'U', ' ', 'C', 'L', 'U', ' ', 'L', 'A', 'N', 'D', + GNO_TAG(), FAMICOM_GAME_CLU_CLU_LAND, + OFS_TAG(), OFS_U16(0x0000), + HSC_TAG(4), OFS_U16(0x8020), 0, 0, 0, 0, + END_TAG(), +}; + +static u8 tags_table_balloon_fight[] = { + GID_TAG(2), 'B', 'F', + GNM_TAG(13), 'B', 'A', 'L', 'L', 'O', 'O', 'N', ' ', 'F', 'I', 'G', 'H', 'T', + GNO_TAG(), FAMICOM_GAME_BALLOON_FIGHT, + OFS_TAG(), OFS_U16(0x0004), + HSC_TAG(5), OFS_U16(0x0629), 0, 0, 0, 1, 0, + HSC_TAG(5), OFS_U16(0x062E), 0, 0, 0, 1, 0, + HSC_TAG(5), OFS_U16(0x0633), 0, 0, 5, 2, 0, + END_TAG(), +}; + +static u8 tags_table_donkey_kong[] = { + GID_TAG(2), 'D', 'K', + GNM_TAG(11), 'D', 'O', 'N', 'K', 'E', 'Y', ' ', 'K', 'O', 'N', 'G', + GNO_TAG(), FAMICOM_GAME_DONKEY_KONG, + OFS_TAG(), OFS_U16(0x0013), + HSC_TAG(2), OFS_U16(0x0507), 0, 0, + HSC_TAG(2), OFS_U16(0x0509), 0, 0, + END_TAG(), +}; + +static u8 tags_table_sansu_asobi[] = { + GID_TAG(2), 'C', 'A', + GNM_TAG(13), 'D', 'O', 'N', 'K', 'Y', ' ', 'J', 'R', ' ', 'M', 'A', 'T', 'H', + GNO_TAG(), FAMICOM_GAME_DONKEY_KONG_JR_MATH, + OFS_TAG(), OFS_U16(0x0017), + HSC_TAG(2), OFS_U16(0x04D7), 0, 0, + HSC_TAG(2), OFS_U16(0x04D9), 0, 0, + HSC_TAG(2), OFS_U16(0x04DB), 0, 0, + HSC_TAG(2), OFS_U16(0x04DD), 0, 0, + HSC_TAG(2), OFS_U16(0x04DF), 0, 0, + HSC_TAG(2), OFS_U16(0x04E1), 0, 0, + HSC_TAG(2), OFS_U16(0x04E3), 0, 0, + HSC_TAG(2), OFS_U16(0x04E5), 0, 0, + HSC_TAG(2), OFS_U16(0x04E7), 0, 0, + END_TAG(), +}; + +static u8 tags_table_pinball[] = { + GID_TAG(2), 'P', 'N', + GNM_TAG(7), 'P', 'I', 'N', 'B', 'A', 'L', 'L', + GNO_TAG(), FAMICOM_GAME_PINBALL, + OFS_TAG(), OFS_U16(0x0029), + HSC_TAG(2), OFS_U16(0x0507), 0, 0, + HSC_TAG(2), OFS_U16(0x0509), 0, 0, + END_TAG(), +}; + +typedef struct nesinfo_tag_s { + u8* tags_table; + size_t tags_size; + char* gameName; + char* kanjiName; +} nesinfo_tag_info; + +static nesinfo_tag_info tags_table_table[FAMICOM_INTERNAL_ROM_NUM]; + +// clang-format on + +static u8 moriNameTable[FAMICOM_INTERNAL_ROM_NUM][16] = { + // TODO +}; + +static void update_highscore_raw(u32 ofs, u32 size, u8* initial_value, u8* high_score, u8* state) { + u8* current_score_p = &famicomCommon.sp->wram[ofs]; + + if (*state == HIGHSCORE_STATE_UNINITIALIZED) { + memcpy(high_score, initial_value, size); + *state = HIGHSCORE_STATE_UNSET; // default highscore + // High score data was not found, so it has been initialized. + OSReport("ハイスコアデータがないので初期化しました\n"); + } + + if (*state == HIGHSCORE_STATE_UNSET) { + if (memcmp(current_score_p, initial_value, size) == 0) { + // The high score in WRAM has been reset to its default value. + OSReport("WRAMのハイスコアが初期値になりました\n"); + memcpy(current_score_p, high_score, size); + *state = HIGHSCORE_STATE_SET; + } else { + // The high score in WRAM has not been reset to its default value. Offset=%04x\n + OSReport("WRAMのハイスコアが初期値になっていません オフセット=%04x\n", ofs); + } + } else { + if (memcmp(current_score_p, high_score, size) != 0) { + // The high score in WRAM has been updated. + OSReport("WRAMのハイスコアが更新されました\n"); + memcpy(high_score, current_score_p, size); + highscore_updated = true; + } + } +} + +static u16 nesinfo_get_u16(u8* data) { + return (u16)(((u32)data[0] << 8) + (u32)data[1]); +} + +static u8 nesinfo_get_u8(u8* data) { + return (u8)(u32)data[0]; +} + +static void nesinfo_set_u16(u8* data, u16* value) { + data[0] = (u8)(((u32)value >> 8) & 0xFF); + data[1] = (u8)((u32)value & 0xFF); +} + +static u8* nesinfo_next_tag_raw(u8* data) { + if (data == nullptr || (nesinfo_tags_end != nullptr && data >= nesinfo_tags_end) || + memcmp(data, NESTAG_END, NESTAG_CMD_SIZE) == 0) { + return nullptr; + } else { + return &data[data[NESTAG_CMD_SIZE] + NESTAG_SIZE]; + } +} + +static u8* nesinfo_next_tag(u8* data) { + do { + data = nesinfo_next_tag_raw(data); + if (data == nullptr) { + break; + } + + if (memcmp(data, NESTAG_VEQ, NESTAG_CMD_SIZE) == 0) { + if (data[NESTAG_SIZE + 1] != 1) { + data = nesinfo_next_tag_raw(data); + } + } else if (memcmp(data, NESTAG_VNE, NESTAG_CMD_SIZE) == 0) { + if (data[NESTAG_SIZE + 1] == 1) { + data = nesinfo_next_tag_raw(data); + } + } else { + break; // found a tag to return + } + } while (data != nullptr); + + return data; +} + +static u16 calc_check_sum2(void* data, size_t size) { + if (((u32)data & 1) == 0) { + u16 sum; + size_t i; + u16* data2; + + data2 = (u16*)data; + sum = 0; + for (i = 0; i < size; i += 2) { + sum += *data2++; + } + + return sum; + } else { + u16 sum0; + u16 sum1; + size_t i; + u8* data_u8; + + data_u8 = (u8*)data; + sum0 = 0; + sum1 = 0; + for (i = 0; i < size - 1; i += sizeof(u16)) { + sum0 += data_u8[0]; + sum1 += data_u8[1]; + data_u8 += sizeof(u16); + } + + if (i < size) { + sum0 += data_u8[0]; + data_u8 += sizeof(u8); + } + + return (u16)((sum0 << 8) + sum1); + } +} + +static void print_stringn_lf(u8* data, size_t size) { + while (size-- > 0) { + OSReport("%c", *data++); + } + + OSReport("\n"); +} + +static void print_hex_lf(u8* data, size_t size) { + while (size-- > 0) { + OSReport(" %02x", *data++); + } + + OSReport("\n"); +} + +extern void nesinfo_tags_set(int rom_no) { + nesinfo_tags_start = nullptr; + nesinfo_tags_end = nullptr; + nesinfo_tags_size = 0; + nesinfo_tags_gameName = nullptr; + nesinfo_tags_kanjiName = nullptr; + nesinfo_tags_moriName = nullptr; + + if (rom_no < 0) { + return; + } + + if (rom_no < 0 || rom_no >= FAMICOM_INTERNAL_ROM_NUM) { + return; + } + + nesinfo_tags_start = tags_table_table[rom_no].tags_table; + nesinfo_tags_end = nesinfo_tags_start + tags_table_table[rom_no].tags_size; + nesinfo_tags_size = (u32)(nesinfo_tags_end - nesinfo_tags_start); + nesinfo_tags_gameName = tags_table_table[rom_no].gameName; + nesinfo_tags_kanjiName = tags_table_table[rom_no].kanjiName; + + if (rom_no < FAMICOM_INTERNAL_ROM_NUM) { + nesinfo_tags_moriName = moriNameTable[rom_no]; + } +}