From 45c8eb1490fb1bae68d3906b2106b44f30704dc4 Mon Sep 17 00:00:00 2001 From: headshot2017 Date: Thu, 26 Jan 2023 20:00:02 -0400 Subject: [PATCH 01/10] add libsm64 functions to play sound/music from ckosmic's fork. also libsm64.h will now include audio_defines.h and seq_ids.h for easy access to sound and music IDs --- src/libsm64.c | 35 +++++++++++++++++++++++++++++++++++ src/libsm64.h | 11 +++++++++++ test/main.cpp | 3 +++ 3 files changed, 49 insertions(+) diff --git a/src/libsm64.c b/src/libsm64.c index acbf28f..0f0603e 100644 --- a/src/libsm64.c +++ b/src/libsm64.c @@ -339,3 +339,38 @@ SM64_LIB_FN float sm64_surface_find_poison_gas_level( float x, float z ) { return find_poison_gas_level( x, z ); } + +SM64_LIB_FN void sm64_seq_player_play_sequence(uint8_t player, uint8_t seqId, uint16_t arg2) +{ + seq_player_play_sequence(player,seqId,arg2); +} + +SM64_LIB_FN void sm64_play_music(uint8_t player, uint16_t seqArgs, uint16_t fadeTimer) +{ + play_music(player,seqArgs,fadeTimer); +} + +SM64_LIB_FN void sm64_stop_background_music(uint16_t seqId) +{ + stop_background_music(seqId); +} + +SM64_LIB_FN void sm64_fadeout_background_music(uint16_t arg0, uint16_t fadeOut) +{ + fadeout_background_music(arg0,fadeOut); +} + +SM64_LIB_FN uint16_t sm64_get_current_background_music() +{ + return get_current_background_music(); +} + +SM64_LIB_FN void sm64_play_sound(int32_t soundBits, float *pos) +{ + play_sound(soundBits,pos); +} + +SM64_LIB_FN void sm64_play_sound_global(int32_t soundBits) +{ + play_sound(soundBits,gGlobalSoundSource); +} diff --git a/src/libsm64.h b/src/libsm64.h index 447f71b..0b03e13 100644 --- a/src/libsm64.h +++ b/src/libsm64.h @@ -5,6 +5,9 @@ #include #include +#include "decomp/include/audio_defines.h" +#include "decomp/include/seq_ids.h" + #ifdef _WIN32 #ifdef SM64_LIB_EXPORT #define SM64_LIB_FN __declspec(dllexport) @@ -155,4 +158,12 @@ extern SM64_LIB_FN float sm64_surface_find_floor( float xPos, float yPos, float extern SM64_LIB_FN float sm64_surface_find_water_level( float x, float z ); extern SM64_LIB_FN float sm64_surface_find_poison_gas_level( float x, float z ); +extern SM64_LIB_FN void sm64_seq_player_play_sequence(uint8_t player, uint8_t seqId, uint16_t arg2); +extern SM64_LIB_FN void sm64_play_music(uint8_t player, uint16_t seqArgs, uint16_t fadeTimer); +extern SM64_LIB_FN void sm64_stop_background_music(uint16_t seqId); +extern SM64_LIB_FN void sm64_fadeout_background_music(uint16_t arg0, uint16_t fadeOut); +extern SM64_LIB_FN uint16_t sm64_get_current_background_music(); +extern SM64_LIB_FN void sm64_play_sound(int32_t soundBits, float *pos); +extern SM64_LIB_FN void sm64_play_sound_global(int32_t soundBits); + #endif//LIB_SM64_H diff --git a/test/main.cpp b/test/main.cpp index ef12037..3e50a73 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -115,6 +115,8 @@ int main( void ) audio_init(); + sm64_play_music(0, SEQ_LEVEL_WATER | SEQ_VARIATION, 0); + do { float dt = (SDL_GetTicks() - lastTicks) / 1000.f; @@ -219,6 +221,7 @@ int main( void ) } while( context_flip_frame_poll_events() ); + sm64_stop_background_music(sm64_get_current_background_music()); sm64_global_terminate(); context_terminate(); From 71c89100474e0cdee34d33df921877a3bfcfe536 Mon Sep 17 00:00:00 2001 From: headshot2017 Date: Thu, 26 Jan 2023 20:03:48 -0400 Subject: [PATCH 02/10] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cb26825..60da2f4 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ project under the `test` directory as well, demonstrating usage of the library. - Run `make` to build. If you want to link musl libc instead of glibc run `LIBSM64_MUSL=1 make` instead. - To run the test program you'll need a SM64 US ROM in the root of the repository with the name `baserom.us.z64`. -## Building on Windows (test program not supported) +## Building on Windows - [Follow steps 1-4 for setting up MSYS2 MinGW 64 here](https://github.com/sm64-port/sm64-port#windows), but replace the repository URL with `https://github.com/libsm64/libsm64.git` - Run `make` to build From f4b62324964897f50f002062f2e9d1df8f98bb9b Mon Sep 17 00:00:00 2001 From: headshot2017 Date: Thu, 26 Jan 2023 20:06:01 -0400 Subject: [PATCH 03/10] fix mario slow climb sound --- src/decomp/game/mario_actions_automatic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/decomp/game/mario_actions_automatic.c b/src/decomp/game/mario_actions_automatic.c index b7707e2..afbe2b7 100644 --- a/src/decomp/game/mario_actions_automatic.c +++ b/src/decomp/game/mario_actions_automatic.c @@ -612,6 +612,8 @@ s32 act_ledge_climb_slow(struct MarioState *m) { return let_go_of_ledge(m); } + m->actionTimer++; + if (m->actionTimer >= 28 && (m->input & (INPUT_NONZERO_ANALOG | INPUT_A_PRESSED | INPUT_OFF_FLOOR | INPUT_ABOVE_SLIDE))) { From e9a3114084ce62432f8d1a7e06dd0197fbe7604c Mon Sep 17 00:00:00 2001 From: headshot2017 Date: Thu, 26 Jan 2023 20:17:30 -0400 Subject: [PATCH 04/10] fix snoring sfx not stopping on wake up also stops the snoring sound when mario is deleted --- src/decomp/game/mario_actions_stationary.c | 16 ++++++++-------- src/libsm64.c | 2 ++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/decomp/game/mario_actions_stationary.c b/src/decomp/game/mario_actions_stationary.c index 0f042dd..f46cb04 100644 --- a/src/decomp/game/mario_actions_stationary.c +++ b/src/decomp/game/mario_actions_stationary.c @@ -331,14 +331,14 @@ s32 act_sleeping(struct MarioState *m) { } s32 act_waking_up(struct MarioState *m) { -// if (!m->actionTimer) { -// func_803205E8(SOUND_MARIO_SNORING1, m->marioObj->header.gfx.cameraToObject); -// func_803205E8(SOUND_MARIO_SNORING2, m->marioObj->header.gfx.cameraToObject); -//#ifndef VERSION_JP -// func_803205E8(SOUND_MARIO_SNORING3, m->marioObj->header.gfx.cameraToObject); -//#endif -// raise_background_noise(2); -// } + if (!m->actionTimer) { + stop_sound(SOUND_MARIO_SNORING1, m->marioObj->header.gfx.cameraToObject); + stop_sound(SOUND_MARIO_SNORING2, m->marioObj->header.gfx.cameraToObject); +#ifndef VERSION_JP + stop_sound(SOUND_MARIO_SNORING3, m->marioObj->header.gfx.cameraToObject); +#endif + raise_background_noise(2); + } if (m->input & INPUT_UNKNOWN_10) { return set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0); diff --git a/src/libsm64.c b/src/libsm64.c index 0f0603e..f4504f6 100644 --- a/src/libsm64.c +++ b/src/libsm64.c @@ -265,6 +265,8 @@ SM64_LIB_FN void sm64_mario_delete( int32_t marioId ) struct GlobalState *globalState = ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState; global_state_bind( globalState ); + stop_sound(SOUND_MARIO_SNORING3, gMarioState->marioObj->header.gfx.cameraToObject); + free( gMarioObject ); free_area( gCurrentArea ); From bd2b13871d876d76aa05ff85870eb63c12c2821d Mon Sep 17 00:00:00 2001 From: headshot2017 Date: Thu, 26 Jan 2023 21:58:16 -0400 Subject: [PATCH 05/10] add loads of features from ckosmic fork * set action * set action with arg * set animation ID (added an include in libsm64.h) * set anim frame * set state (to instantly change caps for example) * set position * set angle and faceangle * set velocity and forward velocity * set water level * take damage * heal mario * kill mario instantly * give mario a cap and play animation * attack --- src/fake_interaction.c | 301 +++++++++++++++++++++++++++++++++++++++++ src/fake_interaction.h | 8 ++ src/libsm64.c | 275 +++++++++++++++++++++++++++++++++++++ src/libsm64.h | 22 +++ 4 files changed, 606 insertions(+) create mode 100644 src/fake_interaction.c create mode 100644 src/fake_interaction.h diff --git a/src/fake_interaction.c b/src/fake_interaction.c new file mode 100644 index 0000000..606d990 --- /dev/null +++ b/src/fake_interaction.c @@ -0,0 +1,301 @@ +#include "decomp/global_state.h" + +#include "debug_print.h" +#include "load_surfaces.h" +#include "gfx_adapter.h" +#include "load_anim_data.h" +#include "load_tex_data.h" +#include "obj_pool.h" + +#include "decomp/game/interaction.h" +#include "decomp/include/object_fields.h" +#include "decomp/include/sm64.h" +#include "decomp/shim.h" +#include "decomp/game/mario.h" +#include "decomp/engine/math_util.h" +#include "fake_interaction.h" + +#define INT_GROUND_POUND_OR_TWIRL (1 << 0) // 0x01 +#define INT_PUNCH (1 << 1) // 0x02 +#define INT_KICK (1 << 2) // 0x04 +#define INT_TRIP (1 << 3) // 0x08 +#define INT_SLIDE_KICK (1 << 4) // 0x10 +#define INT_FAST_ATTACK_OR_SHELL (1 << 5) // 0x20 +#define INT_HIT_FROM_ABOVE (1 << 6) // 0x40 +#define INT_HIT_FROM_BELOW (1 << 7) // 0x80 + +#define INT_ATTACK_NOT_FROM_BELOW \ + (INT_GROUND_POUND_OR_TWIRL | INT_PUNCH | INT_KICK | INT_TRIP | INT_SLIDE_KICK \ + | INT_FAST_ATTACK_OR_SHELL | INT_HIT_FROM_ABOVE) + +#define INT_ANY_ATTACK \ + (INT_GROUND_POUND_OR_TWIRL | INT_PUNCH | INT_KICK | INT_TRIP | INT_SLIDE_KICK \ + | INT_FAST_ATTACK_OR_SHELL | INT_HIT_FROM_ABOVE | INT_HIT_FROM_BELOW) + +#define INT_ATTACK_NOT_WEAK_FROM_ABOVE \ + (INT_GROUND_POUND_OR_TWIRL | INT_PUNCH | INT_KICK | INT_TRIP | INT_HIT_FROM_BELOW) + +#define sDelayInvincTimer (g_state->msDelayInvincTimer) +#define sInvulnerable (g_state->msInvulnerable) + +static u32 sForwardKnockbackActions[][3] = { + { ACT_SOFT_FORWARD_GROUND_KB, ACT_FORWARD_GROUND_KB, ACT_HARD_FORWARD_GROUND_KB }, + { ACT_FORWARD_AIR_KB, ACT_FORWARD_AIR_KB, ACT_HARD_FORWARD_AIR_KB }, + { ACT_FORWARD_WATER_KB, ACT_FORWARD_WATER_KB, ACT_FORWARD_WATER_KB }, +}; + +static u32 sBackwardKnockbackActions[][3] = { + { ACT_SOFT_BACKWARD_GROUND_KB, ACT_BACKWARD_GROUND_KB, ACT_HARD_BACKWARD_GROUND_KB }, + { ACT_BACKWARD_AIR_KB, ACT_BACKWARD_AIR_KB, ACT_HARD_BACKWARD_AIR_KB }, + { ACT_BACKWARD_WATER_KB, ACT_BACKWARD_WATER_KB, ACT_BACKWARD_WATER_KB }, +}; + +uint32_t fake_damage_knock_back(struct MarioState *m, uint32_t damage,uint32_t interactionSubtype,float xSrc,float ySrc,float zSrc) { + + if (!sInvulnerable && !(m->flags & MARIO_VANISH_CAP) + && !(interactionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) { + //o->oInteractStatus = INT_STATUS_INTERACTED | INT_STATUS_ATTACKED_MARIO; + //m->interactObj = o; + + // calculate damage, substitute for take_damage_from_interact_object + if (!(m->flags & MARIO_CAP_ON_HEAD)) { + damage += (damage + 1) / 2; + } + + if (m->flags & MARIO_METAL_CAP) { + damage = 0; + } + + m->hurtCounter += 4 * damage; // apply hurt counter + + if (interactionSubtype & INT_SUBTYPE_BIG_KNOCKBACK) { + m->forwardVel = 40.0f; + } + + if (damage > 0) { + play_sound(SOUND_MARIO_ATTACKED, m->marioObj->header.gfx.cameraToObject); + } + + //update_mario_sound_and_camera(m); + return drop_and_set_mario_action(m, fake_determine_knockback_action(m, damage,xSrc,ySrc,zSrc), + damage); + } + + return FALSE; +} + +s16 fake_mario_obj_angle_to_object(struct MarioState *m, float xSrc,float zSrc) { + f32 dx = xSrc - m->pos[0]; + f32 dz = zSrc - m->pos[2]; + + return atan2s(dz, dx); +} + +u32 fake_determine_knockback_action(struct MarioState *m, s32 damage,float xSrc,float ySrc,float zSrc) { + u32 bonkAction; + + s16 terrainIndex = 0; // 1 = air, 2 = water, 0 = default + s16 strengthIndex = 0; + + s16 angleToObject = fake_mario_obj_angle_to_object(m, xSrc,zSrc); + s16 facingDYaw = angleToObject - m->faceAngle[1]; + s16 remainingHealth = m->health - 0x40 * m->hurtCounter; + + if (m->action & (ACT_FLAG_SWIMMING | ACT_FLAG_METAL_WATER)) { + terrainIndex = 2; + } else if (m->action & (ACT_FLAG_AIR | ACT_FLAG_ON_POLE | ACT_FLAG_HANGING)) { + terrainIndex = 1; + } + + if (remainingHealth < 0x100) { + strengthIndex = 2; + } else if (damage >= 4) { + strengthIndex = 2; + } else if (damage >= 2) { + strengthIndex = 1; + } + + m->faceAngle[1] = angleToObject; + + if (terrainIndex == 2) { + if (m->forwardVel < 28.0f) { + mario_set_forward_vel(m, 28.0f); + } + + if (m->pos[1] >= ySrc) { + if (m->vel[1] < 20.0f) { + m->vel[1] = 20.0f; + } + } else { + if (m->vel[1] > 0.0f) { + m->vel[1] = 0.0f; + } + } + } else { + if (m->forwardVel < 16.0f) { + mario_set_forward_vel(m, 16.0f); + } + } + + if (-0x4000 <= facingDYaw && facingDYaw <= 0x4000) { + m->forwardVel *= -1.0f; + bonkAction = sBackwardKnockbackActions[terrainIndex][strengthIndex]; + } else { + m->faceAngle[1] += 0x8000; + bonkAction = sForwardKnockbackActions[terrainIndex][strengthIndex]; + } + + return bonkAction; +} + +s16 fake_mario_obj_angle_to_pos(struct MarioState *m, float x, float z) { + f32 dx = x - m->pos[0]; + f32 dz = z - m->pos[2]; + + return atan2s(dz, dx); +} + +void fake_bounce_back_from_attack(struct MarioState *m, u32 interaction) { + if (interaction & (INT_PUNCH | INT_KICK | INT_TRIP)) { + if (m->action == ACT_PUNCHING) { + m->action = ACT_MOVE_PUNCHING; + } + + if (m->action & ACT_FLAG_AIR) { + mario_set_forward_vel(m, -16.0f); + } else { + mario_set_forward_vel(m, -48.0f); + } + + //set_camera_shake_from_hit(SHAKE_ATTACK); + m->particleFlags |= PARTICLE_TRIANGLE; + } + + if (interaction & (INT_PUNCH | INT_KICK | INT_TRIP | INT_FAST_ATTACK_OR_SHELL)) { + play_sound(SOUND_ACTION_HIT_2, m->marioObj->header.gfx.cameraToObject); + } +} + +u32 fake_determine_interaction(struct MarioState *m, float x, float y, float z) { + u32 interaction = 0; + u32 action = m->action; + + s16 dYawToObject = fake_mario_obj_angle_to_pos(m, x, z) - m->faceAngle[1]; + if (action & ACT_FLAG_ATTACKING) { + if (action == ACT_PUNCHING || action == ACT_MOVE_PUNCHING || action == ACT_JUMP_KICK) { + + + if (m->flags & MARIO_PUNCHING) { + // 120 degrees total, or 60 each way + if (-0x2AAA <= dYawToObject && dYawToObject <= 0x2AAA) { + interaction = INT_PUNCH; + } + } + if (m->flags & MARIO_KICKING) { + // 120 degrees total, or 60 each way + if (-0x2AAA <= dYawToObject && dYawToObject <= 0x2AAA) { + interaction = INT_KICK; + } + } + if (m->flags & MARIO_TRIPPING) { + // 180 degrees total, or 90 each way + if (-0x4000 <= dYawToObject && dYawToObject <= 0x4000) { + interaction = INT_TRIP; + } + } + } else if (action == ACT_GROUND_POUND || action == ACT_TWIRLING) { + if (m->vel[1] < 0.0f) { + interaction = INT_GROUND_POUND_OR_TWIRL; + } + } else if (action == ACT_GROUND_POUND_LAND || action == ACT_TWIRL_LAND) { + // Neither ground pounding nor twirling change Mario's vertical speed on landing., + // so the speed check is nearly always true (perhaps not if you land while going upwards?) + // Additionally, actionState it set on each first thing in their action, so this is + // only true prior to the very first frame (i.e. active 1 frame prior to it run). + if (m->vel[1] < 0.0f && m->actionState == 0) { + interaction = INT_GROUND_POUND_OR_TWIRL; + } + } else if (action == ACT_SLIDE_KICK || action == ACT_SLIDE_KICK_SLIDE) { + interaction = INT_SLIDE_KICK; + } else if (action & ACT_FLAG_RIDING_SHELL) { + interaction = INT_FAST_ATTACK_OR_SHELL; + } else if (m->forwardVel <= -26.0f || 26.0f <= m->forwardVel) { + interaction = INT_FAST_ATTACK_OR_SHELL; + } + } + + // Prior to this, the interaction type could be overwritten. This requires, however, + // that the interaction not be set prior. This specifically overrides turning a ground + // pound into just a bounce. + if (interaction == 0 && (action & ACT_FLAG_AIR)) { + if (m->vel[1] < 0.0f) { + if (m->pos[1] > y) { + interaction = INT_HIT_FROM_ABOVE; + } + } else { + if (m->pos[1] < y) { + interaction = INT_HIT_FROM_BELOW; + } + } + } + + return interaction; +} + +void fake_bounce_off_object(struct MarioState *m, float x, float y, float z, float hitboxHeight, f32 velY) { + //m->pos[1] = y + hitboxHeight; + m->vel[1] = velY; + + m->flags &= ~MARIO_UNKNOWN_08; + + play_sound(SOUND_ACTION_BOUNCE_OFF_OBJECT, m->marioObj->header.gfx.cameraToObject); +} + +u32 fake_interact_hit_from_below(struct MarioState *m, float x, float y, float z, float hitboxHeight) { + + u32 interaction; + if (m->flags & MARIO_METAL_CAP) { + interaction = INT_FAST_ATTACK_OR_SHELL; + } else { + interaction = fake_determine_interaction(m, x, y, z); + } + + if (interaction & INT_ANY_ATTACK) { + fake_bounce_back_from_attack(m, interaction); + + if (interaction & INT_HIT_FROM_BELOW) { + m->vel[1] = 0.0f; + } + + if (interaction & INT_HIT_FROM_ABOVE) { + fake_bounce_off_object(m, x, y, z, hitboxHeight, 30.0f); + } + return TRUE; + } else/* if (fake_damage_knock_back(m, 0, 0, x, y, z))*/ { + return FALSE; + } + + return FALSE; +} + +u32 fake_interact_bounce_top(struct MarioState *m, float x, float y, float z, float hitboxHeight) { + u32 interaction; + if (m->flags & MARIO_METAL_CAP) { + interaction = INT_FAST_ATTACK_OR_SHELL; + } else { + interaction = fake_determine_interaction(m, x, y, z); + } + + if (interaction & INT_ATTACK_NOT_FROM_BELOW) { + fake_bounce_back_from_attack(m, interaction); + + if (interaction & INT_HIT_FROM_ABOVE) { + fake_bounce_off_object(m, x, y, z, hitboxHeight, 30.0f); + } + return TRUE; + } else/* if (fake_damage_knock_back(m, 0, 0, x, y, z))*/ { + return FALSE; + } + + return FALSE; +} \ No newline at end of file diff --git a/src/fake_interaction.h b/src/fake_interaction.h new file mode 100644 index 0000000..a6277ee --- /dev/null +++ b/src/fake_interaction.h @@ -0,0 +1,8 @@ +#pragma once +#include "decomp/include/types.h" + +u32 fake_determine_knockback_action(struct MarioState *m, s32 damage,float xSrc,float ySrc,float zSrc); +s16 fake_mario_obj_angle_to_object(struct MarioState *m, float xSrc,float zSrc); +uint32_t fake_damage_knock_back(struct MarioState *m, uint32_t damage,uint32_t interactionSubtype,float xSrc,float ySrc,float zSrc); +u32 fake_interact_hit_from_below(struct MarioState *m, float x, float y, float z, float hitboxHeight); +u32 fake_interact_bounce_top(struct MarioState *m, float x, float y, float z, float hitboxHeight); \ No newline at end of file diff --git a/src/libsm64.c b/src/libsm64.c index f4504f6..9fe3fb3 100644 --- a/src/libsm64.c +++ b/src/libsm64.c @@ -33,6 +33,7 @@ #include "load_audio_data.h" #include "load_tex_data.h" #include "obj_pool.h" +#include "fake_interaction.h" static struct AllocOnlyPool *s_mario_geo_pool = NULL; static struct GraphNode *s_mario_graph_node = NULL; @@ -252,6 +253,10 @@ SM64_LIB_FN void sm64_mario_tick( int32_t marioId, const struct SM64MarioInputs vec3f_copy( outState->position, gMarioState->pos ); vec3f_copy( outState->velocity, gMarioState->vel ); outState->faceAngle = (float)gMarioState->faceAngle[1] / 32768.0f * 3.14159f; + outState->action = gMarioState->action; + outState->flags = gMarioState->flags; + outState->particleFlags = gMarioState->particleFlags; + outState->invincTimer = gMarioState->invincTimer; } SM64_LIB_FN void sm64_mario_delete( int32_t marioId ) @@ -274,6 +279,276 @@ SM64_LIB_FN void sm64_mario_delete( int32_t marioId ) obj_pool_free_index( &s_mario_instance_pool, marioId ); } +SM64_LIB_FN void sm64_set_mario_action(int32_t marioId, uint32_t action) +{ + if( marioId >= s_mario_instance_pool.size || s_mario_instance_pool.objects[marioId] == NULL ) + { + DEBUG_PRINT("Tried to use non-existant Mario with ID: %d", marioId); + return; + } + + struct GlobalState *globalState = ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState; + global_state_bind( globalState ); + + set_mario_action(gMarioState, action, 0); +} + +SM64_LIB_FN void sm64_set_mario_action_arg(int32_t marioId, uint32_t action, uint32_t actionArg) +{ + if( marioId >= s_mario_instance_pool.size || s_mario_instance_pool.objects[marioId] == NULL ) + { + DEBUG_PRINT("Tried to use non-existant Mario with ID: %d", marioId); + return; + } + + struct GlobalState *globalState = ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState; + global_state_bind( globalState ); + + set_mario_action(gMarioState, action, actionArg); +} + +SM64_LIB_FN void sm64_set_mario_animation(int32_t marioId, int32_t animID) +{ + if( marioId >= s_mario_instance_pool.size || s_mario_instance_pool.objects[marioId] == NULL ) + { + DEBUG_PRINT("Tried to use non-existant Mario with ID: %d", marioId); + return; + } + + struct GlobalState *globalState = ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState; + global_state_bind( globalState ); + + set_mario_animation(gMarioState, animID); +} + +SM64_LIB_FN void sm64_set_mario_anim_frame(int32_t marioId, int16_t animFrame) +{ + if( marioId >= s_mario_instance_pool.size || s_mario_instance_pool.objects[marioId] == NULL ) + { + DEBUG_PRINT("Tried to use non-existant Mario with ID: %d", marioId); + return; + } + + struct GlobalState *globalState = ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState; + global_state_bind( globalState ); + + gMarioState->marioObj->header.gfx.animInfo.animFrame = animFrame; +} + +SM64_LIB_FN void sm64_set_mario_state(int32_t marioId, uint32_t flags) +{ + if( marioId >= s_mario_instance_pool.size || s_mario_instance_pool.objects[marioId] == NULL ) + { + DEBUG_PRINT("Tried to use non-existant Mario with ID: %d", marioId); + return; + } + + struct GlobalState *globalState = ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState; + global_state_bind( globalState ); + + gMarioState->flags = flags; +} + +SM64_LIB_FN void sm64_set_mario_position(int32_t marioId, float x, float y, float z) +{ + if( marioId >= s_mario_instance_pool.size || s_mario_instance_pool.objects[marioId] == NULL ) + { + DEBUG_PRINT("Tried to use non-existant Mario with ID: %d", marioId); + return; + } + + struct GlobalState *globalState = ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState; + global_state_bind( globalState ); + + gMarioState->pos[0] = x; + gMarioState->pos[1] = y; + gMarioState->pos[2] = z; + vec3f_copy(gMarioState->marioObj->header.gfx.pos, gMarioState->pos); +} + +SM64_LIB_FN void sm64_set_mario_angle(int32_t marioId, float x, float y, float z) +{ + if( marioId >= s_mario_instance_pool.size || s_mario_instance_pool.objects[marioId] == NULL ) + { + DEBUG_PRINT("Tried to use non-existant Mario with ID: %d", marioId); + return; + } + + struct GlobalState *globalState = ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState; + global_state_bind( globalState ); + + vec3s_set(gMarioState->faceAngle, (int16_t)(x / 3.14159f * 32768.f), (int16_t)(y / 3.14159f * 32768.f), (int16_t)(z / 3.14159f * 32768.f)); + vec3s_copy(gMarioState->marioObj->header.gfx.angle, gMarioState->faceAngle); +} + +SM64_LIB_FN void sm64_set_mario_faceangle(int32_t marioId, float y) +{ + if( marioId >= s_mario_instance_pool.size || s_mario_instance_pool.objects[marioId] == NULL ) + { + DEBUG_PRINT("Tried to use non-existant Mario with ID: %d", marioId); + return; + } + + struct GlobalState *globalState = ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState; + global_state_bind( globalState ); + + gMarioState->faceAngle[1] = (int16_t)(y / 3.14159f * 32768.f); + vec3s_set(gMarioState->marioObj->header.gfx.angle, 0, gMarioState->faceAngle[1], 0); +} + +SM64_LIB_FN void sm64_set_mario_velocity(int32_t marioId, float x, float y, float z) +{ + if( marioId >= s_mario_instance_pool.size || s_mario_instance_pool.objects[marioId] == NULL ) + { + DEBUG_PRINT("Tried to use non-existant Mario with ID: %d", marioId); + return; + } + + struct GlobalState *globalState = ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState; + global_state_bind( globalState ); + + gMarioState->vel[0] = x; + gMarioState->vel[1] = y; + gMarioState->vel[2] = z; +} + +SM64_LIB_FN void sm64_set_mario_forward_velocity(int32_t marioId, float vel) +{ + if( marioId >= s_mario_instance_pool.size || s_mario_instance_pool.objects[marioId] == NULL ) + { + DEBUG_PRINT("Tried to use non-existant Mario with ID: %d", marioId); + return; + } + + struct GlobalState *globalState = ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState; + global_state_bind( globalState ); + + gMarioState->forwardVel = vel; +} + +SM64_LIB_FN void sm64_set_mario_water_level(int32_t marioId, signed int level) +{ + if( marioId >= s_mario_instance_pool.size || s_mario_instance_pool.objects[marioId] == NULL ) + { + DEBUG_PRINT("Tried to use non-existant Mario with ID: %d", marioId); + return; + } + + struct GlobalState *globalState = ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState; + global_state_bind( globalState ); + + gMarioState->waterLevel = level; +} + +SM64_LIB_FN void sm64_mario_take_damage(int32_t marioId, uint32_t damage, uint32_t subtype, float x, float y, float z) +{ + if( marioId >= s_mario_instance_pool.size || s_mario_instance_pool.objects[marioId] == NULL ) + { + DEBUG_PRINT("Tried to use non-existant Mario with ID: %d", marioId); + return; + } + + struct GlobalState *globalState = ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState; + global_state_bind( globalState ); + + fake_damage_knock_back(gMarioState, damage, subtype, x, y, z); +} + +SM64_LIB_FN void sm64_mario_heal(int32_t marioId, uint8_t healCounter) +{ + if( marioId >= s_mario_instance_pool.size || s_mario_instance_pool.objects[marioId] == NULL ) + { + DEBUG_PRINT("Tried to use non-existant Mario with ID: %d", marioId); + return; + } + + struct GlobalState *globalState = ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState; + global_state_bind( globalState ); + + gMarioState->healCounter += healCounter; +} + +SM64_LIB_FN void sm64_mario_kill(int32_t marioId) +{ + if( marioId >= s_mario_instance_pool.size || s_mario_instance_pool.objects[marioId] == NULL ) + { + DEBUG_PRINT("Tried to use non-existant Mario with ID: %d", marioId); + return; + } + + struct GlobalState *globalState = ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState; + global_state_bind( globalState ); + + gMarioState->health = 0xff; +} + +SM64_LIB_FN void sm64_mario_interact_cap(int32_t marioId, uint32_t capFlag, uint16_t capTime, uint8_t playMusic) +{ + if( marioId >= s_mario_instance_pool.size || s_mario_instance_pool.objects[marioId] == NULL ) + { + DEBUG_PRINT("Tried to use non-existant Mario with ID: %d", marioId); + return; + } + + struct GlobalState *globalState = ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState; + global_state_bind( globalState ); + + uint16_t capMusic = 0; + if(gMarioState->action != ACT_GETTING_BLOWN && capFlag != 0) + { + gMarioState->flags &= ~MARIO_CAP_ON_HEAD & ~MARIO_CAP_IN_HAND; + gMarioState->flags |= capFlag; + + switch(capFlag) + { + case MARIO_VANISH_CAP: + if(capTime == 0) capTime = 600; + capMusic = SEQUENCE_ARGS(4, SEQ_EVENT_POWERUP); + break; + case MARIO_METAL_CAP: + if(capTime == 0) capTime = 600; + capMusic = SEQUENCE_ARGS(4, SEQ_EVENT_METAL_CAP); + break; + case MARIO_WING_CAP: + if(capTime == 0) capTime = 1800; + capMusic = SEQUENCE_ARGS(4, SEQ_EVENT_POWERUP); + break; + } + + if (capTime > gMarioState->capTimer) { + gMarioState->capTimer = capTime; + } + + if ((gMarioState->action & ACT_FLAG_IDLE) || gMarioState->action == ACT_WALKING) { + gMarioState->flags |= MARIO_CAP_IN_HAND; + set_mario_action(gMarioState, ACT_PUTTING_ON_CAP, 0); + } else { + gMarioState->flags |= MARIO_CAP_ON_HEAD; + } + + play_sound(SOUND_MENU_STAR_SOUND, gMarioState->marioObj->header.gfx.cameraToObject); + play_sound(SOUND_MARIO_HERE_WE_GO, gMarioState->marioObj->header.gfx.cameraToObject); + + if (playMusic != 0 && capMusic != 0) { + play_cap_music(capMusic); + } + } +} + +SM64_LIB_FN bool sm64_mario_attack(int32_t marioId, float x, float y, float z, float hitboxHeight) +{ + if( marioId >= s_mario_instance_pool.size || s_mario_instance_pool.objects[marioId] == NULL ) + { + DEBUG_PRINT("Tried to use non-existant Mario with ID: %d", marioId); + return false; + } + + struct GlobalState *globalState = ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState; + global_state_bind( globalState ); + + return fake_interact_bounce_top(gMarioState, x, y, z, hitboxHeight); +} + SM64_LIB_FN uint32_t sm64_surface_object_create( const struct SM64SurfaceObject *surfaceObject ) { uint32_t id = surfaces_load_object( surfaceObject ); diff --git a/src/libsm64.h b/src/libsm64.h index 0b03e13..73d2842 100644 --- a/src/libsm64.h +++ b/src/libsm64.h @@ -5,6 +5,7 @@ #include #include +#include "decomp/include/mario_animation_ids.h" #include "decomp/include/audio_defines.h" #include "decomp/include/seq_ids.h" @@ -52,6 +53,10 @@ struct SM64MarioState float velocity[3]; float faceAngle; int16_t health; + uint32_t action; + uint32_t flags; + uint32_t particleFlags; + int16_t invincTimer; }; struct SM64MarioGeometryBuffers @@ -145,6 +150,23 @@ extern SM64_LIB_FN int32_t sm64_mario_create( float x, float y, float z ); extern SM64_LIB_FN void sm64_mario_tick( int32_t marioId, const struct SM64MarioInputs *inputs, struct SM64MarioState *outState, struct SM64MarioGeometryBuffers *outBuffers ); extern SM64_LIB_FN void sm64_mario_delete( int32_t marioId ); +extern SM64_LIB_FN void sm64_set_mario_action(int32_t marioId, uint32_t action); +extern SM64_LIB_FN void sm64_set_mario_action_arg(int32_t marioId, uint32_t action, uint32_t actionArg); +extern SM64_LIB_FN void sm64_set_mario_animation(int32_t marioId, int32_t animID); +extern SM64_LIB_FN void sm64_set_mario_anim_frame(int32_t marioId, int16_t animFrame); +extern SM64_LIB_FN void sm64_set_mario_state(int32_t marioId, uint32_t flags); +extern SM64_LIB_FN void sm64_set_mario_position(int32_t marioId, float x, float y, float z); +extern SM64_LIB_FN void sm64_set_mario_angle(int32_t marioId, float x, float y, float z); +extern SM64_LIB_FN void sm64_set_mario_faceangle(int32_t marioId, float y); +extern SM64_LIB_FN void sm64_set_mario_velocity(int32_t marioId, float x, float y, float z); +extern SM64_LIB_FN void sm64_set_mario_forward_velocity(int32_t marioId, float vel); +extern SM64_LIB_FN void sm64_set_mario_water_level(int32_t marioId, signed int level); +extern SM64_LIB_FN void sm64_mario_take_damage(int32_t marioId, uint32_t damage, uint32_t subtype, float x, float y, float z); +extern SM64_LIB_FN void sm64_mario_heal(int32_t marioId, uint8_t healCounter); +extern SM64_LIB_FN void sm64_mario_kill(int32_t marioId); +extern SM64_LIB_FN void sm64_mario_interact_cap(int32_t marioId, uint32_t capFlag, uint16_t capTime, uint8_t playMusic); +extern SM64_LIB_FN bool sm64_mario_attack(int32_t marioId, float x, float y, float z, float hitboxHeight); + extern SM64_LIB_FN uint32_t sm64_surface_object_create( const struct SM64SurfaceObject *surfaceObject ); extern SM64_LIB_FN void sm64_surface_object_move( uint32_t objectId, const struct SM64ObjectTransform *transform ); extern SM64_LIB_FN void sm64_surface_object_delete( uint32_t objectId ); From 349a3eb702d54ffca0854f73cbbed7d2bcbb4a27 Mon Sep 17 00:00:00 2001 From: headshot2017 Date: Thu, 26 Jan 2023 22:25:21 -0400 Subject: [PATCH 06/10] allow setting poison gas level also commented out some find_water_level calls --- src/decomp/game/mario.c | 10 ++++++---- src/decomp/game/mario_step.c | 6 ++++-- src/decomp/include/types.h | 1 + src/libsm64.c | 14 ++++++++++++++ src/libsm64.h | 1 + 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/decomp/game/mario.c b/src/decomp/game/mario.c index 1a594ce..d1b2871 100644 --- a/src/decomp/game/mario.c +++ b/src/decomp/game/mario.c @@ -1321,7 +1321,7 @@ void update_mario_joystick_inputs(struct MarioState *m) { * Resolves wall collisions, and updates a variety of inputs. */ void update_mario_geometry_inputs(struct MarioState *m) { - f32 gasLevel; + //f32 gasLevel; f32 ceilToFloorDist; f32_find_wall_collision(&m->pos[0], &m->pos[1], &m->pos[2], 60.0f, 50.0f); @@ -1343,8 +1343,8 @@ void update_mario_geometry_inputs(struct MarioState *m) { } m->ceilHeight = vec3f_find_ceil(&m->pos[0], m->floorHeight, &m->ceil); - gasLevel = find_poison_gas_level(m->pos[0], m->pos[2]); - m->waterLevel = find_water_level(m->pos[0], m->pos[2]); + //gasLevel = find_poison_gas_level(m->pos[0], m->pos[2]); + //m->waterLevel = find_water_level(m->pos[0], m->pos[2]); if (m->floor != NULL) { m->floorAngle = atan2s(m->floor->normal.z, m->floor->normal.x); @@ -1371,7 +1371,7 @@ void update_mario_geometry_inputs(struct MarioState *m) { m->input |= INPUT_IN_WATER; } - if (m->pos[1] < (gasLevel - 100.0f)) { + if (m->pos[1] < (m->gasLevel - 100.0f)) { m->input |= INPUT_IN_POISON_GAS; } @@ -1831,6 +1831,8 @@ int init_mario(void) { gMarioState->waterLevel = find_water_level(gMarioSpawnInfo->startPos[0], gMarioSpawnInfo->startPos[2]); + gMarioState->gasLevel = + find_poison_gas_level(gMarioSpawnInfo->startPos[0], gMarioSpawnInfo->startPos[2]); gMarioState->area = gCurrentArea; gMarioState->marioObj = gMarioObject; diff --git a/src/decomp/game/mario_step.c b/src/decomp/game/mario_step.c index 37e92f9..1bbbd41 100644 --- a/src/decomp/game/mario_step.c +++ b/src/decomp/game/mario_step.c @@ -269,7 +269,8 @@ static s32 perform_ground_quarter_step(struct MarioState *m, Vec3f nextPos) { floorHeight = find_floor(nextPos[0], nextPos[1], nextPos[2], &floor); ceilHeight = vec3f_find_ceil(nextPos, floorHeight, &ceil); - waterLevel = find_water_level(nextPos[0], nextPos[2]); + //waterLevel = find_water_level(nextPos[0], nextPos[2]); + waterLevel = m->waterLevel; m->wall = upperWall; @@ -403,7 +404,8 @@ s32 perform_air_quarter_step(struct MarioState *m, Vec3f intendedPos, u32 stepAr floorHeight = find_floor(nextPos[0], nextPos[1], nextPos[2], &floor); ceilHeight = vec3f_find_ceil(nextPos, floorHeight, &ceil); - waterLevel = find_water_level(nextPos[0], nextPos[2]); + //waterLevel = find_water_level(nextPos[0], nextPos[2]); + waterLevel = m->waterLevel; m->wall = NULL; diff --git a/src/decomp/include/types.h b/src/decomp/include/types.h index 5272aa7..118b5c6 100644 --- a/src/decomp/include/types.h +++ b/src/decomp/include/types.h @@ -325,6 +325,7 @@ struct MarioState /*0xC4*/ f32 unkC4; u16 curTerrain; // libsm64: added field + s32 gasLevel; // libsm64: added field }; #endif // TYPES_H diff --git a/src/libsm64.c b/src/libsm64.c index 9fe3fb3..1def575 100644 --- a/src/libsm64.c +++ b/src/libsm64.c @@ -440,6 +440,20 @@ SM64_LIB_FN void sm64_set_mario_water_level(int32_t marioId, signed int level) gMarioState->waterLevel = level; } +SM64_LIB_FN void sm64_set_mario_gas_level(int32_t marioId, signed int level) +{ + if( marioId >= s_mario_instance_pool.size || s_mario_instance_pool.objects[marioId] == NULL ) + { + DEBUG_PRINT("Tried to use non-existant Mario with ID: %d", marioId); + return; + } + + struct GlobalState *globalState = ((struct MarioInstance *)s_mario_instance_pool.objects[ marioId ])->globalState; + global_state_bind( globalState ); + + gMarioState->gasLevel = level; +} + SM64_LIB_FN void sm64_mario_take_damage(int32_t marioId, uint32_t damage, uint32_t subtype, float x, float y, float z) { if( marioId >= s_mario_instance_pool.size || s_mario_instance_pool.objects[marioId] == NULL ) diff --git a/src/libsm64.h b/src/libsm64.h index 73d2842..c2f81ba 100644 --- a/src/libsm64.h +++ b/src/libsm64.h @@ -161,6 +161,7 @@ extern SM64_LIB_FN void sm64_set_mario_faceangle(int32_t marioId, float y); extern SM64_LIB_FN void sm64_set_mario_velocity(int32_t marioId, float x, float y, float z); extern SM64_LIB_FN void sm64_set_mario_forward_velocity(int32_t marioId, float vel); extern SM64_LIB_FN void sm64_set_mario_water_level(int32_t marioId, signed int level); +extern SM64_LIB_FN void sm64_set_mario_gas_level(int32_t marioId, signed int level); extern SM64_LIB_FN void sm64_mario_take_damage(int32_t marioId, uint32_t damage, uint32_t subtype, float x, float y, float z); extern SM64_LIB_FN void sm64_mario_heal(int32_t marioId, uint8_t healCounter); extern SM64_LIB_FN void sm64_mario_kill(int32_t marioId); From 535a89bea154ce3b94b37825f33f5b03e2df21a6 Mon Sep 17 00:00:00 2001 From: headshot2017 Date: Thu, 26 Jan 2023 22:25:55 -0400 Subject: [PATCH 07/10] marioId is an int32 --- test/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/main.cpp b/test/main.cpp index 3e50a73..687956b 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -73,7 +73,7 @@ int main( void ) sm64_global_init( rom, texture ); sm64_audio_init(rom); sm64_static_surfaces_load( surfaces, surfaces_count ); - uint32_t marioId = sm64_mario_create( 0, 1000, 0 ); + int32_t marioId = sm64_mario_create( 0, 1000, 0 ); free( rom ); From e7b3421feff0479ea33865e0634868f43fa2aa7a Mon Sep 17 00:00:00 2001 From: headshot2017 Date: Wed, 1 Feb 2023 22:29:02 -0400 Subject: [PATCH 08/10] libsm64.h must be portable --- src/libsm64.c | 1 + src/libsm64.h | 4 ---- test/main.cpp | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/libsm64.c b/src/libsm64.c index 1def575..87cd9ad 100644 --- a/src/libsm64.c +++ b/src/libsm64.c @@ -14,6 +14,7 @@ #include "decomp/include/PR/os_cont.h" #include "decomp/engine/math_util.h" #include "decomp/include/sm64.h" +#include "decomp/include/seq_ids.h" #include "decomp/shim.h" #include "decomp/memory.h" #include "decomp/global_state.h" diff --git a/src/libsm64.h b/src/libsm64.h index c2f81ba..d6770a6 100644 --- a/src/libsm64.h +++ b/src/libsm64.h @@ -5,10 +5,6 @@ #include #include -#include "decomp/include/mario_animation_ids.h" -#include "decomp/include/audio_defines.h" -#include "decomp/include/seq_ids.h" - #ifdef _WIN32 #ifdef SM64_LIB_EXPORT #define SM64_LIB_FN __declspec(dllexport) diff --git a/test/main.cpp b/test/main.cpp index 687956b..79a4b4d 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -115,7 +115,7 @@ int main( void ) audio_init(); - sm64_play_music(0, SEQ_LEVEL_WATER | SEQ_VARIATION, 0); + sm64_play_music(0, 0x05 | 0x80, 0); // from decomp/include/seq_ids.h: SEQ_LEVEL_WATER | SEQ_VARIATION do { From 80b710f4822cf0e53825662ae8a8c070e5d83c55 Mon Sep 17 00:00:00 2001 From: headshot2017 Date: Fri, 3 Feb 2023 19:25:11 -0400 Subject: [PATCH 09/10] increase cell_height and floor_lower limits a change from ckosmic's fork that went past my radar --- src/decomp/engine/surface_collision.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/decomp/engine/surface_collision.h b/src/decomp/engine/surface_collision.h index 5f1995a..ee1b958 100644 --- a/src/decomp/engine/surface_collision.h +++ b/src/decomp/engine/surface_collision.h @@ -9,8 +9,8 @@ #define LEVEL_BOUNDARY_MAX 0x2000 #define CELL_SIZE 0x400 -#define CELL_HEIGHT_LIMIT 20000.f -#define FLOOR_LOWER_LIMIT -11000.f +#define CELL_HEIGHT_LIMIT 100000.f +#define FLOOR_LOWER_LIMIT -110000.f s32 f32_find_wall_collision(f32 *xPtr, f32 *yPtr, f32 *zPtr, f32 offsetY, f32 radius); s32 find_wall_collisions(struct SM64WallCollisionData *colData); From 6dfc5d1943ec4ded5d8139f3a3029892a1db5545 Mon Sep 17 00:00:00 2001 From: headshot2017 Date: Sat, 4 Feb 2023 21:39:10 -0400 Subject: [PATCH 10/10] add function to set sound volume --- src/libsm64.c | 5 +++++ src/libsm64.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/libsm64.c b/src/libsm64.c index 87cd9ad..734f05d 100644 --- a/src/libsm64.c +++ b/src/libsm64.c @@ -666,3 +666,8 @@ SM64_LIB_FN void sm64_play_sound_global(int32_t soundBits) { play_sound(soundBits,gGlobalSoundSource); } + +SM64_LIB_FN void sm64_set_sound_volume(float vol) +{ + gAudioVolume = vol; +} diff --git a/src/libsm64.h b/src/libsm64.h index d6770a6..01ac9ad 100644 --- a/src/libsm64.h +++ b/src/libsm64.h @@ -184,5 +184,6 @@ extern SM64_LIB_FN void sm64_fadeout_background_music(uint16_t arg0, uint16_t fa extern SM64_LIB_FN uint16_t sm64_get_current_background_music(); extern SM64_LIB_FN void sm64_play_sound(int32_t soundBits, float *pos); extern SM64_LIB_FN void sm64_play_sound_global(int32_t soundBits); +extern SM64_LIB_FN void sm64_set_sound_volume(float vol); #endif//LIB_SM64_H