Added support for custom music

This commit is contained in:
MysterD 2022-04-10 09:11:45 -07:00
parent 7de32ee5bb
commit 9dc78a0971
11 changed files with 279 additions and 2 deletions

View File

@ -41,6 +41,7 @@ in_files = [
"src/pc/lua/utils/smlua_collision_utils.h",
"src/pc/lua/utils/smlua_model_utils.h",
"src/pc/lua/utils/smlua_text_utils.h",
"src/pc/lua/utils/smlua_audio_utils.h",
"src/game/object_helpers.c",
"src/game/obj_behaviors.c",
"src/game/obj_behaviors_2.c",
@ -58,7 +59,7 @@ override_allowed_functions = {
"src/game/save_file.h": [ "save_file_get_", "save_file_set_flags", "save_file_clear_flags" ],
"src/pc/lua/utils/smlua_model_utils.h": [ "smlua_model_util_get_id" ],
"src/game/object_list_processor.h": [ "set_object_respawn_info_bits" ],
"src/game/mario_misc.h": [ "bhv_toad.*", "bhv_unlock_door.*" ]
"src/game/mario_misc.h": [ "bhv_toad.*", "bhv_unlock_door.*" ],
}
override_disallowed_functions = {
@ -84,7 +85,8 @@ override_disallowed_functions = {
"src/game/spawn_sound.c": [ "spawner" ],
"src/pc/lua/utils/smlua_obj_utils.h": [ "spawn_object_remember_field" ],
"src/game/camera.h": [ "update_camera", "init_camera", "stub_camera", "^reset_camera", "move_point_along_spline" ],
"src/game/behavior_actions.h": [ "bhv_dust_smoke_loop", "bhv_init_room" ]
"src/game/behavior_actions.h": [ "bhv_dust_smoke_loop", "bhv_init_room" ],
"src/pc/lua/utils/smlua_audio_utils.h": [ "smlua_audio_utils_override"],
}
lua_function_params = {

View File

@ -7017,6 +7017,14 @@ function save_file_set_flags(flags)
-- ...
end
--- @param sequenceId integer
--- @param bankId integer
--- @param m64Name string
--- @return nil
function smlua_audio_utils_replace_sequence(sequenceId, bankId, m64Name)
-- ...
end
--- @param startX number
--- @param startY number
--- @param startZ number

View File

@ -1302,6 +1302,11 @@
<br />
- smlua_audio_utils.h
- [smlua_audio_utils_replace_sequence](#smlua_audio_utils_replace_sequence)
<br />
- smlua_collision_utils.h
- [collision_find_surface_on_ray](#collision_find_surface_on_ray)
- [get_water_surface_pseudo_floor](#get_water_surface_pseudo_floor)
@ -24550,6 +24555,34 @@ The `reliable` field will ensure that the packet arrives, but should be used spa
<br />
---
# functions from smlua_audio_utils.h
<br />
## [smlua_audio_utils_replace_sequence](#smlua_audio_utils_replace_sequence)
### Lua Example
`smlua_audio_utils_replace_sequence(sequenceId, bankId, m64Name)`
### Parameters
| Field | Type |
| ----- | ---- |
| sequenceId | `integer` |
| bankId | `integer` |
| m64Name | `string` |
### Returns
- None
### C Prototype
`void smlua_audio_utils_replace_sequence(u8 sequenceId, u8 bankId, const char* m64Name);`
[:arrow_up_small:](#)
<br />
---
# functions from smlua_collision_utils.h

View File

@ -10,6 +10,7 @@
#include "pc/platform.h"
#include "pc/fs/fs.h"
#include "pc/lua/utils/smlua_audio_utils.h"
#define ALIGN16(val) (((val) + 0xF) & ~0xF)
@ -1374,6 +1375,7 @@ void *sequence_dma_immediate(s32 seqId, s32 arg1) {
seqLength = gSeqFileHeader->seqArray[seqId].len + 0xf;
seqLength = ALIGN16(seqLength);
seqData = gSeqFileHeader->seqArray[seqId].offset;
ptr = alloc_bank_or_seq(&gSeqLoadedPool, 1, seqLength, arg1, seqId);
if (ptr == NULL) {
return NULL;
@ -1396,6 +1398,7 @@ void *sequence_dma_async(s32 seqId, s32 arg1, struct SequencePlayer *seqPlayer)
seqLength = gSeqFileHeader->seqArray[seqId].len + 0xf;
seqLength = ALIGN16(seqLength);
seqData = gSeqFileHeader->seqArray[seqId].offset;
ptr = alloc_bank_or_seq(&gSeqLoadedPool, 1, seqLength, arg1, seqId);
if (ptr == NULL) {
eu_stubbed_printf_0("Heap Overflow Error\n");
@ -1558,6 +1561,25 @@ void load_sequence_internal(u32 player, u32 seqId, s32 loadAsync) {
struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
UNUSED u32 padding[2];
// do custom music override
{
s32 bankId = 0;
if (smlua_audio_utils_override(seqId, &bankId, &sequenceData)) {
sequence_player_disable(seqPlayer);
seqPlayer->defaultBank[0] = bankId;
if (!bank_load_immediate(bankId, 2)) { return; }
seqPlayer->seqId = seqId;
gSeqLoadStatus[seqId] = SOUND_LOAD_STATUS_COMPLETE;
init_sequence_player(player);
seqPlayer->scriptState.depth = 0;
seqPlayer->delay = 0;
seqPlayer->enabled = TRUE;
seqPlayer->seqData = sequenceData;
seqPlayer->scriptState.pc = sequenceData;
return;
}
}
if (seqId >= gSequenceCount) {
return;
}

View File

@ -1561,4 +1561,7 @@ void fake_lvl_init_from_save_file(void) {
save_file_move_cap_to_default_location();
select_mario_cam_mode();
set_yoshi_as_not_dead();
fadeout_music(30);
gChangeLevel = gLevelValues.entryLevel;
}

View File

@ -143,6 +143,7 @@ void smlua_update(void) {
void smlua_shutdown(void) {
smlua_text_utils_reset_all();
smlua_audio_utils_reset_all();
smlua_cobject_allowlist_shutdown();
smlua_cpointer_allowlist_shutdown();
lua_State* L = gLuaState;

View File

@ -24,6 +24,7 @@
#include "src/pc/lua/utils/smlua_collision_utils.h"
#include "src/pc/lua/utils/smlua_model_utils.h"
#include "src/pc/lua/utils/smlua_text_utils.h"
#include "src/pc/lua/utils/smlua_audio_utils.h"
#include "src/engine/surface_load.h"
#include "src/game/object_list_processor.h"
#include "src/game/behavior_actions.h"
@ -13182,6 +13183,24 @@ int smlua_func_find_unimportant_object(UNUSED lua_State* L) {
return 1;
}
/*
int smlua_func_geo_choose_area_ext(lua_State* L) {
if(!smlua_functions_valid_param_count(L, 3)) { return 0; }
s32 callContext = smlua_to_integer(L, 1);
if (!gSmLuaConvertSuccess) { return 0; }
struct GraphNode* node = (struct GraphNode*)smlua_to_cobject(L, 2, LOT_GRAPHNODE);
if (!gSmLuaConvertSuccess) { return 0; }
// Mat4 mtx = (Mat4)smlua_to_cobject(L, 3, LOT_???); <--- UNIMPLEMENTED
if (!gSmLuaConvertSuccess) { return 0; }
extern Gfx *geo_choose_area_ext(UNUSED s32 callContext, struct GraphNode *node, UNUSED Mat4 mtx);
UNIMPLEMENTED -->(L, geo_choose_area_ext(callContext, node, mtx));
return 1;
}
*/
int smlua_func_geo_offset_klepto_debug(lua_State* L) {
if(!smlua_functions_valid_param_count(L, 3)) { return 0; }
@ -14597,6 +14616,25 @@ int smlua_func_save_file_set_flags(lua_State* L) {
return 1;
}
/////////////////////////
// smlua_audio_utils.h //
/////////////////////////
int smlua_func_smlua_audio_utils_replace_sequence(lua_State* L) {
if(!smlua_functions_valid_param_count(L, 3)) { return 0; }
u8 sequenceId = smlua_to_integer(L, 1);
if (!gSmLuaConvertSuccess) { return 0; }
u8 bankId = smlua_to_integer(L, 2);
if (!gSmLuaConvertSuccess) { return 0; }
const char* m64Name = smlua_to_string(L, 3);
if (!gSmLuaConvertSuccess) { return 0; }
smlua_audio_utils_replace_sequence(sequenceId, bankId, m64Name);
return 1;
}
/////////////////////////////
// smlua_collision_utils.h //
/////////////////////////////
@ -16827,6 +16865,7 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "enable_time_stop_including_mario", smlua_func_enable_time_stop_including_mario);
smlua_bind_function(L, "find_object_with_behavior", smlua_func_find_object_with_behavior);
smlua_bind_function(L, "find_unimportant_object", smlua_func_find_unimportant_object);
//smlua_bind_function(L, "geo_choose_area_ext", smlua_func_geo_choose_area_ext); <--- UNIMPLEMENTED
smlua_bind_function(L, "geo_offset_klepto_debug", smlua_func_geo_offset_klepto_debug);
//smlua_bind_function(L, "geo_offset_klepto_held_object", smlua_func_geo_offset_klepto_held_object); <--- UNIMPLEMENTED
//smlua_bind_function(L, "geo_switch_anim_state", smlua_func_geo_switch_anim_state); <--- UNIMPLEMENTED
@ -16930,6 +16969,9 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "save_file_get_total_star_count", smlua_func_save_file_get_total_star_count);
smlua_bind_function(L, "save_file_set_flags", smlua_func_save_file_set_flags);
// smlua_audio_utils.h
smlua_bind_function(L, "smlua_audio_utils_replace_sequence", smlua_func_smlua_audio_utils_replace_sequence);
// smlua_collision_utils.h
smlua_bind_function(L, "collision_find_surface_on_ray", smlua_func_collision_find_surface_on_ray);
smlua_bind_function(L, "get_water_surface_pseudo_floor", smlua_func_get_water_surface_pseudo_floor);

View File

@ -0,0 +1,119 @@
#include "types.h"
#include "pc/mods/mods.h"
#include "pc/lua/smlua.h"
#include "pc/debuglog.h"
#define MAX_OVERRIDE 64
struct AudioOverride {
bool enabled;
bool loaded;
const char* filename;
u64 length;
u8 bank;
u8* buffer;
};
struct AudioOverride sAudioOverrides[MAX_OVERRIDE] = { 0 };
static smlua_audio_utils_reset(struct AudioOverride* override) {
if (override == NULL) { return; }
override->enabled = false;
override->loaded = false;
if (override->filename) {
free(override->filename);
override->filename = NULL;
}
override->length = 0;
override->bank = 0;
if (override->buffer != NULL) {
free(override->filename);
override->filename = NULL;
}
}
void smlua_audio_utils_reset_all(void) {
for (s32 i = 0; i < MAX_OVERRIDE; i++) {
smlua_audio_utils_reset(&sAudioOverrides[i]);
}
}
bool smlua_audio_utils_override(u8 sequenceId, s32* bankId, void** seqData) {
if (sequenceId >= MAX_OVERRIDE) { return false; }
struct AudioOverride* override = &sAudioOverrides[sequenceId];
if (!override->enabled) { return false; }
if (override->loaded) {
*seqData = override->buffer;
*bankId = override->bank;
return true;
}
static u8* buffer = NULL;
static long int length = 0;
FILE* fp = fopen(override->filename, "rb");
if (!fp) { return false; }
fseek(fp, 0L, SEEK_END);
length = ftell(fp);
buffer = malloc(length+1);
if (buffer == NULL) {
LOG_ERROR("Failed to malloc m64 sound file");
fclose(fp);
return false;
}
fseek(fp, 0L, SEEK_SET);
fread(buffer, length, 1, fp);
fclose(fp);
// cache
override->loaded = true;
override->buffer = buffer;
override->length = length;
*seqData = buffer;
*bankId = override->bank;
return true;
}
void smlua_audio_utils_replace_sequence(u8 sequenceId, u8 bankId, const char* m64Name) {
if (gLuaActiveMod == NULL) { return; }
if (sequenceId >= MAX_OVERRIDE) {
LOG_LUA("Invalid sequenceId given to smlua_audio_utils_replace_sequence(): %d", sequenceId);
return;
}
char m64path[SYS_MAX_PATH] = { 0 };
if (snprintf(m64path, SYS_MAX_PATH-1, "sound/%s.m64", m64Name) < 0) {
LOG_LUA("Could not find m64 at path: %s", m64path);
return;
}
for (s32 i = 0; i < gLuaActiveMod->fileCount; i++) {
struct ModFile* file = &gLuaActiveMod->files[i];
if (!strcmp(file->relativePath, m64path)) {
char fullPath[SYS_MAX_PATH] = { 0 };
if (snprintf(fullPath, SYS_MAX_PATH - 1, "%s/%s", gLuaActiveMod->basePath, m64path) < 0) {
LOG_ERROR("Failed to concat full path to m64: %s", m64Name);
return;
}
struct AudioOverride* override = &sAudioOverrides[sequenceId];
smlua_audio_utils_reset(override);
override->filename = strdup(fullPath);
override->enabled = true;
override->bank = bankId;
return;
}
}
LOG_LUA("Could not find m64 at path: %s", m64path);
}

View File

@ -0,0 +1,8 @@
#ifndef SMLUA_AUDIO_UTILS_H
#define SMLUA_AUDIO_UTILS_H
bool smlua_audio_utils_override(u8 sequenceId, s32* bankId, void** seqData);
void smlua_audio_utils_replace_sequence(u8 sequenceId, u8 bankId, const char* m64Name);
#endif

View File

@ -295,6 +295,44 @@ static bool mod_load_files(struct Mod* mod, char* modName, char* fullPath) {
closedir(d);
}
}
// deal with sound directory
{
// concat sound directory
char soundPath[SYS_MAX_PATH] = { 0 };
if (!concat_path(soundPath, fullPath, "sound")) {
LOG_ERROR("Could not concat directory '%s' + '%s'", fullPath, "sound");
return false;
}
// open sound directory
struct dirent* dir = NULL;
DIR* d = opendir(soundPath);
if (d) {
// iterate mod directory
char path[SYS_MAX_PATH] = { 0 };
char relativePath[SYS_MAX_PATH] = { 0 };
while ((dir = readdir(d)) != NULL) {
// sanity check / fill path[]
if (!directory_sanity_check(dir, soundPath, path)) { continue; }
if (snprintf(relativePath, SYS_MAX_PATH - 1, "sound/%s", dir->d_name) < 0) {
LOG_ERROR("Could not concat sound path!");
return false;
}
// only consider m64 files
if (!str_ends_with(path, ".m64")) {
continue;
}
// allocate file
struct ModFile* file = mod_allocate_file(mod, relativePath);
if (file == NULL) { return false; }
}
closedir(d);
}
}
return true;
}

View File

@ -4,6 +4,7 @@
#include "object_fields.h"
#include "object_constants.h"
#include "behavior_table.h"
#include "src/game/hardcoded.h"
#ifdef DISCORD_SDK
#include "discord/discord.h"
#endif