Merge branch 'dev' into main

This commit is contained in:
SonicandTailsCD 2024-10-17 08:39:35 -07:00 committed by GitHub
commit f7c702090d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
74 changed files with 1430 additions and 1293 deletions

View file

@ -48,7 +48,7 @@ COOPNET ?= 1
# Enable docker build workarounds # Enable docker build workarounds
DOCKERBUILD ?= 0 DOCKERBUILD ?= 0
# Sets your optimization level for building. # Sets your optimization level for building.
# A choose is chosen by default for you. # A choice is made by default for you.
OPT_LEVEL ?= -1 OPT_LEVEL ?= -1
# Enable compiling with more debug info. # Enable compiling with more debug info.
DEBUG_INFO_LEVEL ?= 2 DEBUG_INFO_LEVEL ?= 2
@ -69,8 +69,6 @@ ifeq ($(shell arch),arm64)
else else
MIN_MACOS_VERSION ?= 10.15 MIN_MACOS_VERSION ?= 10.15
endif endif
# Homebrew Prefix
BREW_PREFIX ?= $(shell brew --prefix)
# Make some small adjustments for handheld devices # Make some small adjustments for handheld devices
HANDHELD ?= 0 HANDHELD ?= 0
@ -125,6 +123,10 @@ endif
ifeq ($(HOST_OS),Darwin) ifeq ($(HOST_OS),Darwin)
OSX_BUILD := 1 OSX_BUILD := 1
ifndef BREW_PREFIX
BREW_PREFIX := $(shell brew --prefix)
endif
endif endif
# MXE overrides # MXE overrides
@ -1327,9 +1329,6 @@ $(SOUND_BIN_DIR)/ctl_header: $(SOUND_BIN_DIR)/sound_data.ctl
$(SOUND_BIN_DIR)/tbl_header: $(SOUND_BIN_DIR)/sound_data.ctl $(SOUND_BIN_DIR)/tbl_header: $(SOUND_BIN_DIR)/sound_data.ctl
@true @true
$(SOUND_BIN_DIR)/samples_offsets.inc.c: $(SOUND_BIN_DIR)/sound_data.ctl
@true
$(SOUND_BIN_DIR)/sequences_offsets.inc.c: $(SOUND_BIN_DIR)/sequences.bin $(SOUND_BIN_DIR)/sequences_offsets.inc.c: $(SOUND_BIN_DIR)/sequences.bin
@true @true
@ -1343,6 +1342,9 @@ $(SOUND_BIN_DIR)/bank_sets: $(SOUND_BIN_DIR)/sequences.bin
$(SOUND_BIN_DIR)/sequences_header: $(SOUND_BIN_DIR)/sequences.bin $(SOUND_BIN_DIR)/sequences_header: $(SOUND_BIN_DIR)/sequences.bin
@true @true
$(SOUND_BIN_DIR)/sequences_offsets.inc.c: $(SOUND_BIN_DIR)/sequences.bin
@true
$(SOUND_BIN_DIR)/%.m64: $(SOUND_BIN_DIR)/%.o $(SOUND_BIN_DIR)/%.m64: $(SOUND_BIN_DIR)/%.o
$(call print,Converting to M64:,$<,$@) $(call print,Converting to M64:,$<,$@)
$(V)$(OBJCOPY) -j .rodata $< -O binary $@ $(V)$(OBJCOPY) -j .rodata $< -O binary $@

View file

@ -114,7 +114,7 @@ override_disallowed_functions = {
"src/pc/lua/utils/smlua_obj_utils.h": [ "spawn_object_remember_field" ], "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/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", "audio_custom_shutdown", "smlua_audio_custom_init", "smlua_audio_custom_deinit", "audio_sample_destroy_pending_copies", "audio_custom_update_volume" ], "src/pc/lua/utils/smlua_audio_utils.h": [ "smlua_audio_utils_override", "audio_custom_shutdown", "smlua_audio_custom_deinit", "audio_sample_destroy_pending_copies", "audio_custom_update_volume" ],
"src/pc/djui/djui_hud_utils.h": [ "djui_hud_render_texture", "djui_hud_render_texture_raw", "djui_hud_render_texture_tile", "djui_hud_render_texture_tile_raw" ], "src/pc/djui/djui_hud_utils.h": [ "djui_hud_render_texture", "djui_hud_render_texture_raw", "djui_hud_render_texture_tile", "djui_hud_render_texture_tile_raw" ],
"src/pc/lua/utils/smlua_level_utils.h": [ "smlua_level_util_reset" ], "src/pc/lua/utils/smlua_level_utils.h": [ "smlua_level_util_reset" ],
"src/pc/lua/utils/smlua_text_utils.h": [ "smlua_text_utils_init", "smlua_text_utils_shutdown", "smlua_text_utils_reset_all" ], "src/pc/lua/utils/smlua_text_utils.h": [ "smlua_text_utils_init", "smlua_text_utils_shutdown", "smlua_text_utils_reset_all" ],

View file

@ -1,77 +1,5 @@
math.randomseed(get_time()) math.randomseed(get_time())
--------------
-- CObjects --
--------------
_CObjectPool = {}
_CObject = {
__index = function (t,k)
return _get_field(t['_lot'], t['_pointer'], k, t)
end,
__newindex = function (t,k,v)
_set_field(t['_lot'], t['_pointer'], k, v, t)
end,
__tostring = function(t)
return 'CObject: ' .. t['_lot'] .. ', [' .. string.format('0x%08X', t['_pointer']) .. ']'
end,
__eq = function (a, b)
return a['_pointer'] == b['_pointer'] and a['_lot'] == b['_lot'] and a['_pointer'] ~= nil and a['_lot'] ~= nil
end
}
function _NewCObject(lot, pointer)
if _CObjectPool[lot] == nil then
_CObjectPool[lot] = {}
end
if _CObjectPool[lot][pointer] == nil then
local obj = {}
rawset(obj, '_pointer', pointer)
rawset(obj, '_lot', lot)
setmetatable(obj, _CObject)
_CObjectPool[lot][pointer] = obj
return obj
end
return _CObjectPool[lot][pointer]
end
local _CPointerPool = {}
_CPointer = {
__index = function (t,k)
return nil
end,
__newindex = function (t,k,v)
end,
__tostring = function(t)
return 'CPointer: ' .. t['_lvt'] .. ', [' .. string.format('0x%08X', t['_pointer']) .. ']'
end,
__eq = function (a, b)
return a['_pointer'] == b['_pointer'] and a['_pointer'] ~= nil and a['_lvt'] ~= nil
end
}
function _NewCPointer(lvt, pointer)
if _CPointerPool[lvt] == nil then
_CPointerPool[lvt] = {}
end
if _CPointerPool[lvt][pointer] == nil then
local obj = {}
rawset(obj, '_pointer', pointer)
rawset(obj, '_lvt', lvt)
setmetatable(obj, _CPointer)
_CPointerPool[lvt][pointer] = obj
return obj
end
return _CPointerPool[lvt][pointer]
end
_SyncTable = { _SyncTable = {
__index = function (t,k) __index = function (t,k)
local _table = rawget(t, '_table') local _table = rawget(t, '_table')

View file

@ -2,78 +2,6 @@
math.randomseed(get_time()) math.randomseed(get_time())
--------------
-- CObjects --
--------------
_CObjectPool = {}
_CObject = {
__index = function (t,k)
return _get_field(t['_lot'], t['_pointer'], k, t)
end,
__newindex = function (t,k,v)
_set_field(t['_lot'], t['_pointer'], k, v, t)
end,
__tostring = function(t)
return 'CObject: ' .. t['_lot'] .. ', [' .. string.format('0x%08X', t['_pointer']) .. ']'
end,
__eq = function (a, b)
return a['_pointer'] == b['_pointer'] and a['_lot'] == b['_lot'] and a['_pointer'] ~= nil and a['_lot'] ~= nil
end
}
function _NewCObject(lot, pointer)
if _CObjectPool[lot] == nil then
_CObjectPool[lot] = {}
end
if _CObjectPool[lot][pointer] == nil then
local obj = {}
rawset(obj, '_pointer', pointer)
rawset(obj, '_lot', lot)
setmetatable(obj, _CObject)
_CObjectPool[lot][pointer] = obj
return obj
end
return _CObjectPool[lot][pointer]
end
local _CPointerPool = {}
_CPointer = {
__index = function (t,k)
return nil
end,
__newindex = function (t,k,v)
end,
__tostring = function(t)
return 'CPointer: ' .. t['_lvt'] .. ', [' .. string.format('0x%08X', t['_pointer']) .. ']'
end,
__eq = function (a, b)
return a['_pointer'] == b['_pointer'] and a['_pointer'] ~= nil and a['_lvt'] ~= nil
end
}
function _NewCPointer(lvt, pointer)
if _CPointerPool[lvt] == nil then
_CPointerPool[lvt] = {}
end
if _CPointerPool[lvt][pointer] == nil then
local obj = {}
rawset(obj, '_pointer', pointer)
rawset(obj, '_lvt', lvt)
setmetatable(obj, _CPointer)
_CPointerPool[lvt][pointer] = obj
return obj
end
return _CPointerPool[lvt][pointer]
end
_SyncTable = { _SyncTable = {
__index = function (t,k) __index = function (t,k)
local _table = rawget(t, '_table') local _table = rawget(t, '_table')
@ -3779,6 +3707,9 @@ INT_TWIRL = (1 << 8)
--- @type InteractionFlag --- @type InteractionFlag
INT_GROUND_POUND_OR_TWIRL = (INT_GROUND_POUND | INT_TWIRL) INT_GROUND_POUND_OR_TWIRL = (INT_GROUND_POUND | INT_TWIRL)
--- @type InteractionFlag
INT_LUA = (1 << 31)
--- @class InteractionType --- @class InteractionType
--- @type InteractionType --- @type InteractionType
@ -9230,7 +9161,10 @@ HOOK_ON_LANGUAGE_CHANGED = 44
HOOK_ON_MODS_LOADED = 45 HOOK_ON_MODS_LOADED = 45
--- @type LuaHookedEventType --- @type LuaHookedEventType
HOOK_MAX = 46 HOOK_ON_NAMETAGS_RENDER = 46
--- @type LuaHookedEventType
HOOK_MAX = 47
--- @class LuaModMenuElementType --- @class LuaModMenuElementType

View file

@ -7807,6 +7807,11 @@ function camera_freeze()
-- ... -- ...
end end
--- @return boolean
function camera_get_checking_surfaces()
-- ...
end
--- @return boolean --- @return boolean
function camera_is_frozen() function camera_is_frozen()
-- ... -- ...
@ -7826,6 +7831,11 @@ function camera_romhack_allow_dpad_usage(allow)
-- ... -- ...
end end
--- @param value boolean
function camera_set_checking_surfaces(value)
-- ...
end
--- @param rco RomhackCameraOverride --- @param rco RomhackCameraOverride
function camera_set_romhack_override(rco) function camera_set_romhack_override(rco)
-- ... -- ...
@ -8181,6 +8191,11 @@ function deref_s32_pointer(pointer)
-- ... -- ...
end end
--- @return boolean
function djui_attempting_to_open_playerlist()
-- ...
end
--- @return boolean --- @return boolean
function djui_is_playerlist_open() function djui_is_playerlist_open()
-- ... -- ...
@ -8211,6 +8226,12 @@ function djui_set_popup_disabled_override(value)
-- ... -- ...
end end
--- @param localIndex integer
--- @return string
function get_coopnet_id(localIndex)
-- ...
end
--- @return integer --- @return integer
function get_current_save_file_num() function get_current_save_file_num()
-- ... -- ...

View file

@ -149,12 +149,12 @@ static void DynOS_Actor_Generate(const SysPath &aPackFolder, Array<Pair<u64, Str
// If there is an existing binary file for this layout, skip and go to the next actor // If there is an existing binary file for this layout, skip and go to the next actor
SysPath _BinFilename = fstring("%s/%s.bin", aPackFolder.c_str(), _GeoRootName.begin()); SysPath _BinFilename = fstring("%s/%s.bin", aPackFolder.c_str(), _GeoRootName.begin());
if (fs_sys_file_exists(_BinFilename.c_str())) { if (fs_sys_file_exists(_BinFilename.c_str())) {
#ifdef DEVELOPMENT
// Compress file to gain some space // Compress file to gain some space
if (!DynOS_Bin_IsCompressed(_BinFilename)) { if (configCompressOnStartup && !DynOS_Bin_IsCompressed(_BinFilename)) {
DynOS_Bin_Compress(_BinFilename); DynOS_Bin_Compress(_BinFilename);
} }
#endif
return; return;
} }
} }
@ -260,14 +260,14 @@ void DynOS_Actor_GeneratePack(const SysPath &aPackFolder) {
if (SysPath(_PackEnt->d_name) == ".") continue; if (SysPath(_PackEnt->d_name) == ".") continue;
if (SysPath(_PackEnt->d_name) == "..") continue; if (SysPath(_PackEnt->d_name) == "..") continue;
#ifdef DEVELOPMENT
// Compress .bin files to gain some space // Compress .bin files to gain some space
if (configCompressOnStartup) {
SysPath _Filename = fstring("%s/%s", aPackFolder.c_str(), _PackEnt->d_name); SysPath _Filename = fstring("%s/%s", aPackFolder.c_str(), _PackEnt->d_name);
if (SysPath(_PackEnt->d_name).find(".bin") != SysPath::npos && !DynOS_Bin_IsCompressed(_Filename)) { if (SysPath(_PackEnt->d_name).find(".bin") != SysPath::npos && !DynOS_Bin_IsCompressed(_Filename)) {
DynOS_Bin_Compress(_Filename); DynOS_Bin_Compress(_Filename);
continue; continue;
} }
#endif }
// For each subfolder, read tokens from model.inc.c and geo.inc.c // For each subfolder, read tokens from model.inc.c and geo.inc.c
SysPath _Folder = fstring("%s/%s", aPackFolder.c_str(), _PackEnt->d_name); SysPath _Folder = fstring("%s/%s", aPackFolder.c_str(), _PackEnt->d_name);

View file

@ -691,13 +691,13 @@ void DynOS_Col_Generate(const SysPath &aPackFolder, Array<Pair<u64, String>> _Ac
// If there is an existing binary file for this collision, skip and go to the next actor // If there is an existing binary file for this collision, skip and go to the next actor
SysPath _ColFilename = fstring("%s/%s.col", aPackFolder.c_str(), _ColRootName.begin()); SysPath _ColFilename = fstring("%s/%s.col", aPackFolder.c_str(), _ColRootName.begin());
if (fs_sys_file_exists(_ColFilename.c_str())) { if (fs_sys_file_exists(_ColFilename.c_str())) {
#ifdef DEVELOPMENT
// Compress file to gain some space // Compress file to gain some space
if (!DynOS_Bin_IsCompressed(_ColFilename)) { if (configCompressOnStartup && !DynOS_Bin_IsCompressed(_ColFilename)) {
DynOS_Bin_Compress(_ColFilename); DynOS_Bin_Compress(_ColFilename);
} }
continue; continue;
#endif
} }
// Init // Init

View file

@ -1119,12 +1119,12 @@ static bool DynOS_Lvl_GeneratePack_Internal(const SysPath &aPackFolder, Array<Pa
// If there is an existing binary file for this level, skip and go to the next level // If there is an existing binary file for this level, skip and go to the next level
SysPath _LvlFilename = fstring("%s/%s.lvl", aPackFolder.c_str(), _LvlRootName.begin()); SysPath _LvlFilename = fstring("%s/%s.lvl", aPackFolder.c_str(), _LvlRootName.begin());
if (fs_sys_file_exists(_LvlFilename.c_str())) { if (fs_sys_file_exists(_LvlFilename.c_str())) {
#ifdef DEVELOPMENT
// Compress file to gain some space // Compress file to gain some space
if (!DynOS_Bin_IsCompressed(_LvlFilename)) { if (configCompressOnStartup && !DynOS_Bin_IsCompressed(_LvlFilename)) {
DynOS_Bin_Compress(_LvlFilename); DynOS_Bin_Compress(_LvlFilename);
} }
#endif
continue; continue;
} }
@ -1247,15 +1247,14 @@ void DynOS_Lvl_GeneratePack(const SysPath &aPackFolder) {
if (SysPath(_PackEnt->d_name) == ".") continue; if (SysPath(_PackEnt->d_name) == ".") continue;
if (SysPath(_PackEnt->d_name) == "..") continue; if (SysPath(_PackEnt->d_name) == "..") continue;
#ifdef DEVELOPMENT
// Compress .lvl files to gain some space // Compress .lvl files to gain some space
// TODO: is this required anymore? if (configCompressOnStartup) {
/*SysPath _Filename = fstring("%s/%s", aPackFolder.c_str(), _PackEnt->d_name); SysPath _Filename = fstring("%s/%s", aPackFolder.c_str(), _PackEnt->d_name);
if (SysPath(_PackEnt->d_name).find(".lvl") != SysPath::npos && !DynOS_Bin_IsCompressed(_Filename)) { if (SysPath(_PackEnt->d_name).find(".lvl") != SysPath::npos && !DynOS_Bin_IsCompressed(_Filename)) {
DynOS_Bin_Compress(_Filename); DynOS_Bin_Compress(_Filename);
continue; continue;
}*/ }
#endif }
// For each subfolder, read tokens from script.c // For each subfolder, read tokens from script.c
SysPath _Folder = fstring("%s/%s", aPackFolder.c_str(), _PackEnt->d_name); SysPath _Folder = fstring("%s/%s", aPackFolder.c_str(), _PackEnt->d_name);

View file

@ -1,8 +1,13 @@
#include "dynos.cpp.h" #include "dynos.cpp.h"
extern "C" {
#include "pc/loading.h" #include "pc/loading.h"
}
void DynOS_Gfx_GeneratePacks(const char* directory) { void DynOS_Gfx_GeneratePacks(const char* directory) {
LOADING_SCREEN_MUTEX(snprintf(gCurrLoadingSegment.str, 256, "Generating DynOS Packs In Path:\n\\#808080\\%s", directory)); LOADING_SCREEN_MUTEX(
loading_screen_reset_progress_bar();
snprintf(gCurrLoadingSegment.str, 256, "Generating DynOS Packs In Path:\n\\#808080\\%s", directory);
);
DIR *modsDir = opendir(directory); DIR *modsDir = opendir(directory);
if (!modsDir) { return; } if (!modsDir) { return; }

View file

@ -1398,6 +1398,7 @@ static const void* sDynosBuiltinFuncs[] = {
define_builtin(geo_movtex_draw_water_regions_ext), define_builtin(geo_movtex_draw_water_regions_ext),
define_builtin(lvl_init_or_update), define_builtin(lvl_init_or_update),
define_builtin(geo_choose_area_ext), define_builtin(geo_choose_area_ext),
define_builtin(geo_mario_cap_display_list),
// Behaviors // Behaviors
define_builtin(bhv_cap_switch_loop), define_builtin(bhv_cap_switch_loop),

File diff suppressed because it is too large Load diff

View file

@ -1309,6 +1309,7 @@
| INT_HIT_FROM_BELOW | (1 << 7) | | INT_HIT_FROM_BELOW | (1 << 7) |
| INT_TWIRL | (1 << 8) | | INT_TWIRL | (1 << 8) |
| INT_GROUND_POUND_OR_TWIRL | (INT_GROUND_POUND | INT_TWIRL) | | INT_GROUND_POUND_OR_TWIRL | (INT_GROUND_POUND | INT_TWIRL) |
| INT_LUA | (1 << 31) |
### [enum InteractionType](#InteractionType) ### [enum InteractionType](#InteractionType)
| Identifier | Value | | Identifier | Value |
@ -3297,7 +3298,8 @@
| HOOK_ON_ATTACK_OBJECT | 43 | | HOOK_ON_ATTACK_OBJECT | 43 |
| HOOK_ON_LANGUAGE_CHANGED | 44 | | HOOK_ON_LANGUAGE_CHANGED | 44 |
| HOOK_ON_MODS_LOADED | 45 | | HOOK_ON_MODS_LOADED | 45 |
| HOOK_MAX | 46 | | HOOK_ON_NAMETAGS_RENDER | 46 |
| HOOK_MAX | 47 |
### [enum LuaModMenuElementType](#LuaModMenuElementType) ### [enum LuaModMenuElementType](#LuaModMenuElementType)
| Identifier | Value | | Identifier | Value |

View file

@ -824,6 +824,24 @@
<br /> <br />
## [camera_get_checking_surfaces](#camera_get_checking_surfaces)
### Lua Example
`local booleanValue = camera_get_checking_surfaces()`
### Parameters
- None
### Returns
- `boolean`
### C Prototype
`bool camera_get_checking_surfaces(void);`
[:arrow_up_small:](#)
<br />
## [camera_is_frozen](#camera_is_frozen) ## [camera_is_frozen](#camera_is_frozen)
### Lua Example ### Lua Example
@ -900,6 +918,26 @@
<br /> <br />
## [camera_set_checking_surfaces](#camera_set_checking_surfaces)
### Lua Example
`camera_set_checking_surfaces(value)`
### Parameters
| Field | Type |
| ----- | ---- |
| value | `boolean` |
### Returns
- None
### C Prototype
`void camera_set_checking_surfaces(bool value);`
[:arrow_up_small:](#)
<br />
## [camera_set_romhack_override](#camera_set_romhack_override) ## [camera_set_romhack_override](#camera_set_romhack_override)
### Lua Example ### Lua Example
@ -1953,6 +1991,24 @@
<br /> <br />
## [djui_attempting_to_open_playerlist](#djui_attempting_to_open_playerlist)
### Lua Example
`local booleanValue = djui_attempting_to_open_playerlist()`
### Parameters
- None
### Returns
- `boolean`
### C Prototype
`bool djui_attempting_to_open_playerlist(void);`
[:arrow_up_small:](#)
<br />
## [djui_is_playerlist_open](#djui_is_playerlist_open) ## [djui_is_playerlist_open](#djui_is_playerlist_open)
### Lua Example ### Lua Example
@ -2066,6 +2122,26 @@
<br /> <br />
## [get_coopnet_id](#get_coopnet_id)
### Lua Example
`local stringValue = get_coopnet_id(localIndex)`
### Parameters
| Field | Type |
| ----- | ---- |
| localIndex | `integer` |
### Returns
- `string`
### C Prototype
`const char* get_coopnet_id(s8 localIndex);`
[:arrow_up_small:](#)
<br />
## [get_current_save_file_num](#get_current_save_file_num) ## [get_current_save_file_num](#get_current_save_file_num)
### Lua Example ### Lua Example

View file

@ -1641,10 +1641,12 @@
- [camera_config_set_x_sensitivity](functions-5.md#camera_config_set_x_sensitivity) - [camera_config_set_x_sensitivity](functions-5.md#camera_config_set_x_sensitivity)
- [camera_config_set_y_sensitivity](functions-5.md#camera_config_set_y_sensitivity) - [camera_config_set_y_sensitivity](functions-5.md#camera_config_set_y_sensitivity)
- [camera_freeze](functions-5.md#camera_freeze) - [camera_freeze](functions-5.md#camera_freeze)
- [camera_get_checking_surfaces](functions-5.md#camera_get_checking_surfaces)
- [camera_is_frozen](functions-5.md#camera_is_frozen) - [camera_is_frozen](functions-5.md#camera_is_frozen)
- [camera_reset_overrides](functions-5.md#camera_reset_overrides) - [camera_reset_overrides](functions-5.md#camera_reset_overrides)
- [camera_romhack_allow_centering](functions-5.md#camera_romhack_allow_centering) - [camera_romhack_allow_centering](functions-5.md#camera_romhack_allow_centering)
- [camera_romhack_allow_dpad_usage](functions-5.md#camera_romhack_allow_dpad_usage) - [camera_romhack_allow_dpad_usage](functions-5.md#camera_romhack_allow_dpad_usage)
- [camera_set_checking_surfaces](functions-5.md#camera_set_checking_surfaces)
- [camera_set_romhack_override](functions-5.md#camera_set_romhack_override) - [camera_set_romhack_override](functions-5.md#camera_set_romhack_override)
- [camera_unfreeze](functions-5.md#camera_unfreeze) - [camera_unfreeze](functions-5.md#camera_unfreeze)
@ -1719,12 +1721,14 @@
- [allocate_mario_action](functions-5.md#allocate_mario_action) - [allocate_mario_action](functions-5.md#allocate_mario_action)
- [course_is_main_course](functions-5.md#course_is_main_course) - [course_is_main_course](functions-5.md#course_is_main_course)
- [deref_s32_pointer](functions-5.md#deref_s32_pointer) - [deref_s32_pointer](functions-5.md#deref_s32_pointer)
- [djui_attempting_to_open_playerlist](functions-5.md#djui_attempting_to_open_playerlist)
- [djui_is_playerlist_open](functions-5.md#djui_is_playerlist_open) - [djui_is_playerlist_open](functions-5.md#djui_is_playerlist_open)
- [djui_is_popup_disabled](functions-5.md#djui_is_popup_disabled) - [djui_is_popup_disabled](functions-5.md#djui_is_popup_disabled)
- [djui_menu_get_font](functions-5.md#djui_menu_get_font) - [djui_menu_get_font](functions-5.md#djui_menu_get_font)
- [djui_popup_create_global](functions-5.md#djui_popup_create_global) - [djui_popup_create_global](functions-5.md#djui_popup_create_global)
- [djui_reset_popup_disabled_override](functions-5.md#djui_reset_popup_disabled_override) - [djui_reset_popup_disabled_override](functions-5.md#djui_reset_popup_disabled_override)
- [djui_set_popup_disabled_override](functions-5.md#djui_set_popup_disabled_override) - [djui_set_popup_disabled_override](functions-5.md#djui_set_popup_disabled_override)
- [get_coopnet_id](functions-5.md#get_coopnet_id)
- [get_current_save_file_num](functions-5.md#get_current_save_file_num) - [get_current_save_file_num](functions-5.md#get_current_save_file_num)
- [get_date_and_time](functions-5.md#get_date_and_time) - [get_date_and_time](functions-5.md#get_date_and_time)
- [get_dialog_box_state](functions-5.md#get_dialog_box_state) - [get_dialog_box_state](functions-5.md#get_dialog_box_state)

View file

@ -137,6 +137,7 @@ The lua functions sent to `hook_event()` will be automatically called by SM64 wh
| HOOK_ON_ATTACK_OBJECT | Called when a player attacks an object. May be double-fired in some cases, you'll need to write special code for this | [MarioState](structs.md#MarioState) attacker, [Object](structs.md#Object) victim, `integer` interactionId | | HOOK_ON_ATTACK_OBJECT | Called when a player attacks an object. May be double-fired in some cases, you'll need to write special code for this | [MarioState](structs.md#MarioState) attacker, [Object](structs.md#Object) victim, `integer` interactionId |
| HOOK_ON_LANGUAGE_CHANGED | Called when the language is changed | `string` language | | HOOK_ON_LANGUAGE_CHANGED | Called when the language is changed | `string` language |
| HOOK_ON_MODS_LOADED | Called directly after every mod file is loaded in by smlua | None | | HOOK_ON_MODS_LOADED | Called directly after every mod file is loaded in by smlua | None |
| HOOK_ON_NAMETAGS_RENDER | Called when nametags are rendered. Return a `string` to change what renders on the nametag, return an empty `string` to render nothing. | `string` playerIndex |
### Parameters ### Parameters

View file

@ -28,7 +28,7 @@ Setting up Visual Studio Code will allow you to have all of the modern benefits
--- ---
5. Add a new item containing the location of `<your repro>/autogen/lua_definitions` 5. Add a new item containing the location of `<your repo>/autogen/lua_definitions`
![lua-definitions](https://user-images.githubusercontent.com/12403224/158046824-1894318a-7ce9-41ef-bacc-17f95fa05f31.png) ![lua-definitions](https://user-images.githubusercontent.com/12403224/158046824-1894318a-7ce9-41ef-bacc-17f95fa05f31.png)

View file

@ -33,7 +33,7 @@ VOICETABLE_BIRDO = {
[CHAR_SOUND_SO_LONGA_BOWSER] = "birdo_solonga_bowser.ogg", [CHAR_SOUND_SO_LONGA_BOWSER] = "birdo_solonga_bowser.ogg",
[CHAR_SOUND_SNORING1] = "birdo_snoring1.ogg", [CHAR_SOUND_SNORING1] = "birdo_snoring1.ogg",
[CHAR_SOUND_SNORING2] = "birdo_snoring2.ogg", [CHAR_SOUND_SNORING2] = "birdo_snoring2.ogg",
[CHAR_SOUND_SNORING3] = { "birdo_snoring2.ogg", "birdo_snoring1.ogg", "birdo_snoring3.ogg" }, [CHAR_SOUND_SNORING3] = { "birdo_snoring1.ogg", "birdo_snoring2.ogg" },
[CHAR_SOUND_TWIRL_BOUNCE] = "birdo_twirl_bounce.ogg", [CHAR_SOUND_TWIRL_BOUNCE] = "birdo_twirl_bounce.ogg",
[CHAR_SOUND_UH] = "birdo_uh.ogg", [CHAR_SOUND_UH] = "birdo_uh.ogg",
[CHAR_SOUND_UH2] = "birdo_uh2.ogg", [CHAR_SOUND_UH2] = "birdo_uh2.ogg",

View file

@ -3,11 +3,19 @@
if not _G.charSelectExists then return end if not _G.charSelectExists then return end
local voiceTables = {
[VOICETABLE_TOADETTE] = true,
[VOICETABLE_YOSHI] = true,
[VOICETABLE_PEACH] = true,
[VOICETABLE_DAISY] = true,
[VOICETABLE_BIRDO] = true
}
--- @param m MarioState --- @param m MarioState
local function mario_update(m) local function mario_update(m)
if is_player_active(m) == 0 then return end if is_player_active(m) == 0 then return end
local voiceTable = charSelect.character_get_voice(m) local voiceTable = charSelect.character_get_voice(m)
if voiceTable then if voiceTables[voiceTable] then
return charSelect.voice.snore(m) return charSelect.voice.snore(m)
end end
end end
@ -16,7 +24,7 @@ end
--- @param sound CharacterSound --- @param sound CharacterSound
local function character_sound(m, sound) local function character_sound(m, sound)
local voiceTable = charSelect.character_get_voice(m) local voiceTable = charSelect.character_get_voice(m)
if voiceTable then if voiceTables[voiceTable] then
return charSelect.voice.sound(m, sound) return charSelect.voice.sound(m, sound)
end end
end end

View file

@ -118,7 +118,7 @@ charBeingSet = false
stopPalettes = false stopPalettes = false
for i in pairs(gActiveMods) do for i in pairs(gActiveMods) do
if (gActiveMods[i].incompatible ~= nil and gActiveMods[i].incompatible:find("gamemode")) and not (gActiveMods[i].name:find("Personal Star Counter EX+")) then if (gActiveMods[i].incompatible ~= nil and gActiveMods[i].incompatible:find("gamemode")) and not (gActiveMods[i].name:find("Personal Star Counter")) then
stopPalettes = true stopPalettes = true
end end
end end

View file

@ -32,6 +32,9 @@ void bhv_piranha_plant_bubble_loop(void) {
f32 scale = 0; f32 scale = 0;
s32 i; s32 i;
s32 frame = parent->header.gfx.animInfo.animFrame; s32 frame = parent->header.gfx.animInfo.animFrame;
if (frame < 0) {
frame = 0;
}
// TODO: rename lastFrame if it is inaccurate // TODO: rename lastFrame if it is inaccurate
if (parent->header.gfx.animInfo.curAnim == NULL) { return; } if (parent->header.gfx.animInfo.curAnim == NULL) { return; }
s32 lastFrame = parent->header.gfx.animInfo.curAnim->loopEnd - 2; s32 lastFrame = parent->header.gfx.animInfo.curAnim->loopEnd - 2;

View file

@ -122,6 +122,7 @@ void piranha_plant_act_woken_up(void) {
*/ */
o->oDamageOrCoinValue = 3; o->oDamageOrCoinValue = 3;
#endif #endif
if (o->oTimer == 0) if (o->oTimer == 0)
stop_secondary_music(50); stop_secondary_music(50);
@ -270,6 +271,9 @@ void piranha_plant_act_biting(void) {
cur_obj_init_animation_with_sound(0); cur_obj_init_animation_with_sound(0);
cur_obj_set_hitbox_radius_and_height(150.0f, 100.0f);
cur_obj_set_hurtbox_radius_and_height(150.0f, 100.0f);
// Play a bite sound effect on certain frames. // Play a bite sound effect on certain frames.
if (is_item_in_array(frame, sPiranhaPlantBiteSoundFrames)) { if (is_item_in_array(frame, sPiranhaPlantBiteSoundFrames)) {
cur_obj_play_sound_2(SOUND_OBJ2_PIRANHA_PLANT_BITE); cur_obj_play_sound_2(SOUND_OBJ2_PIRANHA_PLANT_BITE);
@ -368,9 +372,6 @@ void bhv_piranha_plant_loop(void) {
sync_object_init_field(o, &o->oTimer); sync_object_init_field(o, &o->oTimer);
} }
cur_obj_set_hitbox_radius_and_height(150.0f, 100.0f);
cur_obj_set_hurtbox_radius_and_height(150.0f, 100.0f);
CUR_OBJ_CALL_ACTION_FUNCTION(TablePiranhaPlantActions); CUR_OBJ_CALL_ACTION_FUNCTION(TablePiranhaPlantActions);
// In WF, hide all Piranha Plants once high enough up. // In WF, hide all Piranha Plants once high enough up.
if (gCurrLevelNum == LEVEL_WF) { if (gCurrLevelNum == LEVEL_WF) {

View file

@ -70,17 +70,14 @@ static inline void shift_UV_NORMAL(struct ScrollTarget *scroll, u16 vertcount, s
verts[0]->n.flag++; verts[0]->n.flag++;
} else { } else {
if (bhv < SCROLL_UV_X) { if (bhv < SCROLL_UV_X) {
u8 bhvIndex = MIN(bhv, 2);
for (i = 0; i < vertcount; i++) { for (i = 0; i < vertcount; i++) {
verts[i]->n.ob[bhvIndex] = scroll->interpF32[i]; scroll->prevF32[i] = scroll->interpF32[i];
} }
} else { } else {
u8 bhvIndex = MIN(bhv-SCROLL_UV_X, 1);
for (i = 0; i < vertcount; i++) { for (i = 0; i < vertcount; i++) {
verts[i]->n.tc[bhvIndex] = scroll->interpS16[i]; scroll->prevS16[i] = scroll->interpS16[i];
} }
} }
scroll->needInterp = false;
} }
} }

View file

@ -3085,7 +3085,7 @@ void update_lakitu(struct Camera *c) {
distToFloor = find_floor(gLakituState.pos[0], distToFloor = find_floor(gLakituState.pos[0],
gLakituState.pos[1] + 20.0f, gLakituState.pos[1] + 20.0f,
gLakituState.pos[2], &floor); gLakituState.pos[2], &floor);
gCheckingSurfaceCollisionsForCamera = false; gCheckingSurfaceCollisionsForCamera = FALSE;
if (distToFloor != gLevelValues.floorLowerLimit) { if (distToFloor != gLevelValues.floorLowerLimit) {
if (gLakituState.pos[1] < (distToFloor += 100.0f)) { if (gLakituState.pos[1] < (distToFloor += 100.0f)) {
gLakituState.pos[1] = distToFloor; gLakituState.pos[1] = distToFloor;
@ -12299,9 +12299,9 @@ void mode_rom_hack_camera(struct Camera *c) {
if (gMarioStates[0].controller->buttonPressed & U_JPAD) { if (gMarioStates[0].controller->buttonPressed & U_JPAD) {
sRomHackYaw = DEGREES(180 + 90) - gMarioStates[0].faceAngle[1]; sRomHackYaw = DEGREES(180 + 90) - gMarioStates[0].faceAngle[1];
} else if (gMarioStates[0].controller->buttonDown & L_JPAD) { } else if (gMarioStates[0].controller->buttonDown & L_JPAD) {
sRomHackYaw -= DEGREES(1) * (camera_config_is_x_inverted() ? -1 : 1); sRomHackYaw -= DEGREES(0.5) * (camera_config_is_x_inverted() ? -1 : 1);
} else if (gMarioStates[0].controller->buttonDown & R_JPAD) { } else if (gMarioStates[0].controller->buttonDown & R_JPAD) {
sRomHackYaw += DEGREES(1) * (camera_config_is_x_inverted() ? -1 : 1); sRomHackYaw += DEGREES(0.5) * (camera_config_is_x_inverted() ? -1 : 1);
} else if (gMarioStates[0].controller->buttonPressed & D_JPAD) { } else if (gMarioStates[0].controller->buttonPressed & D_JPAD) {
sRomHackYaw = snap_to_45_degrees(sRomHackYaw); sRomHackYaw = snap_to_45_degrees(sRomHackYaw);
} }

View file

@ -88,7 +88,6 @@ static u32 sBackwardKnockbackActions[][3] = {
}; };
static u8 sDisplayingDoorText = FALSE; static u8 sDisplayingDoorText = FALSE;
static u8 sCanInteractDoor = TRUE;
static u8 sJustTeleported = FALSE; static u8 sJustTeleported = FALSE;
u8 gPssSlideStarted = FALSE; u8 gPssSlideStarted = FALSE;
extern u8 gLastCollectedStarOrKey; extern u8 gLastCollectedStarOrKey;
@ -158,8 +157,9 @@ u32 determine_interaction(struct MarioState *m, struct Object *o) {
} }
if (interaction == 0 && action & ACT_FLAG_ATTACKING) { if (interaction == 0 && action & ACT_FLAG_ATTACKING) {
u32 flags = (o->oInteractType & INTERACT_PLAYER) ? (MARIO_PUNCHING | MARIO_KICKING) : (MARIO_PUNCHING | MARIO_KICKING | MARIO_TRIPPING); u32 flags = (MARIO_PUNCHING | MARIO_KICKING | MARIO_TRIPPING);
if (m->flags & flags) { if ((action == ACT_PUNCHING || action == ACT_MOVE_PUNCHING || action == ACT_JUMP_KICK) ||
(m->flags & flags && interaction & INT_LUA)) {
s16 dYawToObject = mario_obj_angle_to_object(m, o) - m->faceAngle[1]; s16 dYawToObject = mario_obj_angle_to_object(m, o) - m->faceAngle[1];
if (m->flags & MARIO_PUNCHING) { if (m->flags & MARIO_PUNCHING) {
@ -237,6 +237,7 @@ u32 determine_interaction(struct MarioState *m, struct Object *o) {
u32 attack_object(struct MarioState* m, struct Object *o, s32 interaction) { u32 attack_object(struct MarioState* m, struct Object *o, s32 interaction) {
if (!o) { return 0; } if (!o) { return 0; }
u32 attackType = 0; u32 attackType = 0;
interaction &= ~INT_LUA;
switch (interaction) { switch (interaction) {
case INT_GROUND_POUND: case INT_GROUND_POUND:
@ -672,7 +673,8 @@ u32 determine_knockback_action(struct MarioState *m, UNUSED s32 arg) {
if (!is_player_active(m2)) { continue; } if (!is_player_active(m2)) { continue; }
if (m2->marioObj == NULL) { continue; } if (m2->marioObj == NULL) { continue; }
if (m2->marioObj != m->interactObj) { continue; } if (m2->marioObj != m->interactObj) { continue; }
if (m2->action == ACT_JUMP_KICK) { scaler = 2; } if (m2->action == ACT_JUMP_KICK) { scaler = 2.0f; }
if (m2->action == ACT_DIVE) { scaler += fabs(m2->forwardVel * 0.01); }
if (m2->flags & MARIO_METAL_CAP) { scaler *= 1.25f; } if (m2->flags & MARIO_METAL_CAP) { scaler *= 1.25f; }
break; break;
} }
@ -1048,7 +1050,7 @@ u32 interact_warp(struct MarioState *m, UNUSED u32 interactType, struct Object *
u32 display_door_dialog(struct MarioState *m, u32 actionArg) { u32 display_door_dialog(struct MarioState *m, u32 actionArg) {
if (!m) { return FALSE; } if (!m) { return FALSE; }
if (m != &gMarioStates[0]) { return FALSE; } if (m != &gMarioStates[0]) { return FALSE; }
return sCanInteractDoor ? set_mario_action(m, ACT_READING_AUTOMATIC_DIALOG, actionArg) : FALSE; return (!sDisplayingDoorText) ? set_mario_action(m, ACT_READING_AUTOMATIC_DIALOG, actionArg) : FALSE;
} }
u8 prevent_interact_door(struct MarioState* m, struct Object* o) { u8 prevent_interact_door(struct MarioState* m, struct Object* o) {
@ -1082,7 +1084,6 @@ u32 interact_warp_door(struct MarioState *m, UNUSED u32 interactType, struct Obj
if (!(saveFlags & SAVE_FLAG_HAVE_KEY_2)) { if (!(saveFlags & SAVE_FLAG_HAVE_KEY_2)) {
if (display_door_dialog(m, (saveFlags & SAVE_FLAG_HAVE_KEY_1) ? gBehaviorValues.dialogs.KeyDoor1HaveDialog : gBehaviorValues.dialogs.KeyDoor1DontHaveDialog)) { if (display_door_dialog(m, (saveFlags & SAVE_FLAG_HAVE_KEY_1) ? gBehaviorValues.dialogs.KeyDoor1HaveDialog : gBehaviorValues.dialogs.KeyDoor1DontHaveDialog)) {
sDisplayingDoorText = TRUE; sDisplayingDoorText = TRUE;
sCanInteractDoor = FALSE;
} }
return FALSE; return FALSE;
} }
@ -1094,7 +1095,6 @@ u32 interact_warp_door(struct MarioState *m, UNUSED u32 interactType, struct Obj
if (!(saveFlags & SAVE_FLAG_HAVE_KEY_1)) { if (!(saveFlags & SAVE_FLAG_HAVE_KEY_1)) {
if (display_door_dialog(m, (saveFlags & SAVE_FLAG_HAVE_KEY_2) ? gBehaviorValues.dialogs.KeyDoor2HaveDialog : gBehaviorValues.dialogs.KeyDoor2DontHaveDialog)) { if (display_door_dialog(m, (saveFlags & SAVE_FLAG_HAVE_KEY_2) ? gBehaviorValues.dialogs.KeyDoor2HaveDialog : gBehaviorValues.dialogs.KeyDoor2DontHaveDialog)) {
sDisplayingDoorText = TRUE; sDisplayingDoorText = TRUE;
sCanInteractDoor = FALSE;
} }
return FALSE; return FALSE;
} }
@ -1225,16 +1225,8 @@ u32 interact_door(struct MarioState *m, UNUSED u32 interactType, struct Object *
text += requiredNumStars - numStars; text += requiredNumStars - numStars;
if ((requiredNumStars == 70) || display_door_dialog(m, text)) {
if (requiredNumStars == 70) {
m->interactObj = o;
m->usedObj = o;
set_mario_action(m, ACT_ENTERING_STAR_DOOR, should_push_or_pull_door(m, o));
}
sDisplayingDoorText = TRUE; sDisplayingDoorText = TRUE;
sCanInteractDoor = FALSE; return set_mario_action(m, ACT_READING_AUTOMATIC_DIALOG, text);
return TRUE;
}
} }
} else if (m->action == ACT_IDLE && sDisplayingDoorText == TRUE && requiredNumStars == 70) { } else if (m->action == ACT_IDLE && sDisplayingDoorText == TRUE && requiredNumStars == 70) {
m->interactObj = o; m->interactObj = o;
@ -1327,10 +1319,11 @@ static u8 resolve_player_collision(struct MarioState* m, struct MarioState* m2)
} }
u8 determine_player_damage_value(u32 interaction) { u8 determine_player_damage_value(u32 interaction) {
if (interaction & INT_GROUND_POUND_OR_TWIRL) { return 3; } if (interaction & INT_GROUND_POUND) { return 4; }
if (interaction & (INT_TWIRL | INT_PUNCH | INT_TRIP)) { return 3; }
if (interaction & INT_KICK) { return 2; } if (interaction & INT_KICK) { return 2; }
if (interaction & INT_ATTACK_SLIDE) { return 1; } if (interaction & INT_SLIDE_KICK) { return 2; }
return 2; return 1;
} }
u8 player_is_sliding(struct MarioState* m) { u8 player_is_sliding(struct MarioState* m) {
@ -1877,7 +1870,7 @@ u32 interact_breakable(struct MarioState *m, UNUSED u32 interactType, struct Obj
m->interactObj = o; m->interactObj = o;
switch (interaction) { switch (interaction & ~INT_LUA) {
case INT_HIT_FROM_ABOVE: case INT_HIT_FROM_ABOVE:
bounce_off_object(m, o, 30.0f); //! Not in the 0x8F mask bounce_off_object(m, o, 30.0f); //! Not in the 0x8F mask
break; break;
@ -1909,7 +1902,7 @@ u32 interact_koopa_shell(struct MarioState *m, UNUSED u32 interactType, struct O
if (!(m->action & ACT_FLAG_RIDING_SHELL)) { if (!(m->action & ACT_FLAG_RIDING_SHELL)) {
u32 interaction = determine_interaction(m, o); u32 interaction = determine_interaction(m, o);
if (interaction == INT_HIT_FROM_ABOVE || m->action == ACT_WALKING if (interaction & INT_HIT_FROM_ABOVE || m->action == ACT_WALKING
|| m->action == ACT_HOLD_WALKING) { || m->action == ACT_HOLD_WALKING) {
m->interactObj = o; m->interactObj = o;
m->usedObj = o; m->usedObj = o;
@ -2322,13 +2315,12 @@ void mario_process_interactions(struct MarioState *m) {
check_kick_or_punch_wall(m); check_kick_or_punch_wall(m);
m->flags &= ~MARIO_PUNCHING & ~MARIO_KICKING & ~MARIO_TRIPPING; m->flags &= ~MARIO_PUNCHING & ~MARIO_KICKING & ~MARIO_TRIPPING;
// limit to only local mario
if (m == &gMarioStates[0]) {
if (!(m->marioObj->collidedObjInteractTypes & (INTERACT_WARP_DOOR | INTERACT_DOOR))) { if (!(m->marioObj->collidedObjInteractTypes & (INTERACT_WARP_DOOR | INTERACT_DOOR))) {
sDisplayingDoorText = FALSE; sDisplayingDoorText = FALSE;
sCanInteractDoor = TRUE;
} }
if (!(m->marioObj->collidedObjInteractTypes & INTERACT_WARP)) { if (!(m->marioObj->collidedObjInteractTypes & INTERACT_WARP)) {
if (m == &gMarioStates[0]) {
// limit to only local mario
sJustTeleported = FALSE; sJustTeleported = FALSE;
} }
} }

View file

@ -53,6 +53,7 @@ enum InteractionFlag {
INT_HIT_FROM_BELOW = /* 0x00000080 */ (1 << 7), INT_HIT_FROM_BELOW = /* 0x00000080 */ (1 << 7),
INT_TWIRL = /* 0x00000100 */ (1 << 8), INT_TWIRL = /* 0x00000100 */ (1 << 8),
INT_GROUND_POUND_OR_TWIRL = (INT_GROUND_POUND | INT_TWIRL), INT_GROUND_POUND_OR_TWIRL = (INT_GROUND_POUND | INT_TWIRL),
INT_LUA = /* 0x10000000 */ (1 << 31) ,
}; };
#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_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)

View file

@ -251,7 +251,7 @@ u16 level_control_timer(s32 timerOp) {
u32 pressed_pause(void) { u32 pressed_pause(void) {
if (gServerSettings.pauseAnywhere) { if (gServerSettings.pauseAnywhere) {
if (get_dialog_id() < 0 && !gWarpTransition.isActive && sDelayedWarpOp == WARP_OP_NONE) { if (get_dialog_id() < 0) {
return gPlayer1Controller->buttonPressed & START_BUTTON; return gPlayer1Controller->buttonPressed & START_BUTTON;
} }
} else { } else {

View file

@ -4,6 +4,7 @@
#include "memory.h" #include "memory.h"
#include "print.h" #include "print.h"
#include "pc/debuglog.h" #include "pc/debuglog.h"
#include "pc/lua/smlua.h"
#define ALIGN16(val) (((val) + 0xF) & ~0xF) #define ALIGN16(val) (((val) + 0xF) & ~0xF)
@ -222,7 +223,7 @@ void growing_array_free(struct GrowingArray **array) {
if (*array) { if (*array) {
for (u32 i = 0; i != (*array)->capacity; ++i) { for (u32 i = 0; i != (*array)->capacity; ++i) {
if ((*array)->buffer[i]) { if ((*array)->buffer[i]) {
free((*array)->buffer[i]); smlua_free((*array)->buffer[i]);
} }
} }
free((*array)->buffer); free((*array)->buffer);

View file

@ -2635,7 +2635,8 @@ s32 cur_obj_is_mario_ground_pounding_platform(void) {
if (!is_player_active(&gMarioStates[i])) { continue; } if (!is_player_active(&gMarioStates[i])) { continue; }
if (!gMarioStates[i].marioObj) { continue; } if (!gMarioStates[i].marioObj) { continue; }
if (gMarioStates[i].marioObj->platform == o) { if (gMarioStates[i].marioObj->platform == o) {
if ((determine_interaction(&gMarioStates[i], o) & INT_GROUND_POUND) || (gMarioStates[i].action == ACT_GROUND_POUND_LAND)) { u32 interaction = determine_interaction(&gMarioStates[i], o);
if ((gMarioStates[i].action == ACT_GROUND_POUND_LAND) || (interaction & INT_GROUND_POUND && interaction & INT_LUA)) {
return TRUE; return TRUE;
} }
} }

View file

@ -616,7 +616,7 @@ static void geo_process_translation_rotation(struct GraphNodeTranslationRotation
Mat4 mtxf; Mat4 mtxf;
Vec3f translation; Vec3f translation;
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\. // Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB.
if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; } if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
vec3s_to_vec3f(translation, node->translation); vec3s_to_vec3f(translation, node->translation);

View file

@ -140,7 +140,7 @@ void patch_scroll_targets_before(void) {
} }
} }
#define SHORT_RANGE 32767 #define SHORT_RANGE 0x7FFF
void patch_scroll_targets_interpolated(f32 delta) { void patch_scroll_targets_interpolated(f32 delta) {
f32 antiDelta = 1.0f - delta; f32 antiDelta = 1.0f - delta;

View file

@ -186,6 +186,10 @@ unsigned int configDjuiThemeFont = FONT_NORMAL;
unsigned int configDjuiScale = 0; unsigned int configDjuiScale = 0;
// other // other
unsigned int configRulesVersion = 0; unsigned int configRulesVersion = 0;
bool configCompressOnStartup = false;
// secrets
bool configExCoopTheme = false;
static const struct ConfigOption options[] = { static const struct ConfigOption options[] = {
// window settings // window settings
@ -311,7 +315,27 @@ static const struct ConfigOption options[] = {
{.name = "djui_theme_font", .type = CONFIG_TYPE_UINT, .uintValue = &configDjuiThemeFont}, {.name = "djui_theme_font", .type = CONFIG_TYPE_UINT, .uintValue = &configDjuiThemeFont},
{.name = "djui_scale", .type = CONFIG_TYPE_UINT, .uintValue = &configDjuiScale}, {.name = "djui_scale", .type = CONFIG_TYPE_UINT, .uintValue = &configDjuiScale},
// other // other
{.name = "rules_version", .type = CONFIG_TYPE_UINT, .uintValue = &configRulesVersion} {.name = "rules_version", .type = CONFIG_TYPE_UINT, .uintValue = &configRulesVersion},
{.name = "compress_on_startup", .type = CONFIG_TYPE_BOOL, .boolValue = &configCompressOnStartup},
};
struct SecretConfigOption {
const char *name;
enum ConfigOptionType type;
union {
bool *boolValue;
unsigned int *uintValue;
float* floatValue;
char* stringValue;
u64* u64Value;
u8 (*colorValue)[3];
};
int maxStringLength;
bool inConfig;
};
static struct SecretConfigOption secret_options[] = {
{.name = "ex_coop_theme", .type = CONFIG_TYPE_BOOL, .boolValue = &configExCoopTheme},
}; };
// FunctionConfigOption functions // FunctionConfigOption functions
@ -619,6 +643,15 @@ static void configfile_load_internal(const char *filename, bool* error) {
} }
} }
// secret options
for (unsigned int i = 0; i < ARRAY_LEN(secret_options); i++) {
if (strcmp(tokens[0], secret_options[i].name) == 0) {
secret_options[i].inConfig = true;
option = (const struct ConfigOption *) &secret_options[i];
break;
}
}
if (option == NULL) { if (option == NULL) {
#ifdef DEVELOPMENT #ifdef DEVELOPMENT
printf("unknown option '%s'\n", tokens[0]); printf("unknown option '%s'\n", tokens[0]);
@ -708,21 +741,11 @@ void configfile_load(void) {
#endif #endif
} }
// Writes the config file to 'filename' static void configfile_save_option(FILE *file, const struct ConfigOption *option, bool isSecret) {
void configfile_save(const char *filename) { if (isSecret) {
FILE *file; const struct SecretConfigOption *secret_option = (const struct SecretConfigOption *) option;
if (!secret_option->inConfig) { return; }
file = fopen(fs_get_write_path(filename), "w");
if (file == NULL) {
// error
return;
} }
printf("Saving configuration to '%s'\n", filename);
for (unsigned int i = 0; i < ARRAY_LEN(options); i++) {
const struct ConfigOption *option = &options[i];
switch (option->type) { switch (option->type) {
case CONFIG_TYPE_BOOL: case CONFIG_TYPE_BOOL:
fprintf(file, "%s %s\n", option->name, *option->boolValue ? "true" : "false"); fprintf(file, "%s %s\n", option->name, *option->boolValue ? "true" : "false");
@ -752,6 +775,28 @@ void configfile_save(const char *filename) {
LOG_ERROR("Configfile wrote bad type '%d': %s", (int)option->type, option->name); LOG_ERROR("Configfile wrote bad type '%d': %s", (int)option->type, option->name);
break; break;
} }
}
// Writes the config file to 'filename'
void configfile_save(const char *filename) {
FILE *file;
file = fopen(fs_get_write_path(filename), "w");
if (file == NULL) {
// error
return;
}
printf("Saving configuration to '%s'\n", filename);
for (unsigned int i = 0; i < ARRAY_LEN(options); i++) {
const struct ConfigOption *option = &options[i];
configfile_save_option(file, option, false);
}
for (unsigned int i = 0; i < ARRAY_LEN(secret_options); i++) {
const struct ConfigOption *option = (const struct ConfigOption *) &secret_options[i];
configfile_save_option(file, option, true);
} }
// save function options // save function options

View file

@ -135,6 +135,10 @@ extern unsigned int configDjuiThemeFont;
extern unsigned int configDjuiScale; extern unsigned int configDjuiScale;
// other // other
extern unsigned int configRulesVersion; extern unsigned int configRulesVersion;
extern bool configCompressOnStartup;
// secrets
extern bool configExCoopTheme;
void enable_queued_mods(void); void enable_queued_mods(void);
void enable_queued_dynos_packs(void); void enable_queued_dynos_packs(void);

View file

@ -20,7 +20,7 @@ static void djui_font_normal_render_char(char* c) {
} }
static f32 djui_font_normal_char_width(char* c) { static f32 djui_font_normal_char_width(char* c) {
if (*c == ' ') { return 0.30f; } if (*c == ' ') { return configExCoopTheme ? 6 / 32.0f : 0.30f; }
extern const f32 font_normal_widths[]; extern const f32 font_normal_widths[];
return djui_unicode_get_sprite_width(c, font_normal_widths, 32.0f); return djui_unicode_get_sprite_width(c, font_normal_widths, 32.0f);
} }
@ -62,7 +62,7 @@ static f32 djui_font_title_char_width(char* text) {
if (c == ' ') { return 0.30f; } if (c == ' ') { return 0.30f; }
c = djui_unicode_get_base_char(text); c = djui_unicode_get_base_char(text);
extern const f32 font_title_widths[]; extern const f32 font_title_widths[];
return font_title_widths[(u8)c - '!'] * 1.1f; return font_title_widths[(u8)c - '!'] * (configExCoopTheme ? 1.0f : 1.1f);
} }
static const struct DjuiFont sDjuiFontTitle = { static const struct DjuiFont sDjuiFontTitle = {

View file

@ -235,15 +235,18 @@ bool djui_interactable_on_key_down(int scancode) {
} }
} }
if ((gDjuiPlayerList != NULL || gDjuiModList != NULL) && gServerSettings.enablePlayerList) { if ((gDjuiPlayerList != NULL || gDjuiModList != NULL)) {
for (int i = 0; i < MAX_BINDS; i++) { for (int i = 0; i < MAX_BINDS; i++) {
if (scancode == (int)configKeyPlayerList[i] && !gDjuiInMainMenu && gNetworkType != NT_NONE) { if (scancode == (int)configKeyPlayerList[i] && !gDjuiInMainMenu && gNetworkType != NT_NONE) {
if (gServerSettings.enablePlayerList) {
if (gDjuiPlayerList != NULL) { if (gDjuiPlayerList != NULL) {
djui_base_set_visible(&gDjuiPlayerList->base, true); djui_base_set_visible(&gDjuiPlayerList->base, true);
} }
if (gDjuiModList != NULL) { if (gDjuiModList != NULL) {
djui_base_set_visible(&gDjuiModList->base, true); djui_base_set_visible(&gDjuiModList->base, true);
} }
}
gAttemptingToOpenPlayerlist = true;
break; break;
} }
if (gDjuiPlayerList->base.visible) { if (gDjuiPlayerList->base.visible) {
@ -295,6 +298,7 @@ void djui_interactable_on_key_up(int scancode) {
if (gDjuiModList != NULL) { if (gDjuiModList != NULL) {
djui_base_set_visible(&gDjuiModList->base, false); djui_base_set_visible(&gDjuiModList->base, false);
} }
gAttemptingToOpenPlayerlist = false;
break; break;
} }
} }
@ -405,17 +409,15 @@ void djui_interactable_update(void) {
if (gInteractableFocus) { if (gInteractableFocus) {
u16 mainButtons = PAD_BUTTON_A | PAD_BUTTON_B; u16 mainButtons = PAD_BUTTON_A | PAD_BUTTON_B;
if ((mouseButtons & MOUSE_BUTTON_1) && !(sLastMouseButtons && MOUSE_BUTTON_1) && !djui_cursor_inside_base(gInteractableFocus)) { if ((mouseButtons & MOUSE_BUTTON_1) && !(sLastMouseButtons && MOUSE_BUTTON_1) && !djui_cursor_inside_base(gInteractableFocus)) {
// clicked outside of focused // clicked outside of focus
// if (!gDjuiChatBoxFocus && gDjuiChatBox != NULL && gInteractableFocus != &gDjuiChatBox->chatInput->base) { if (!gDjuiChatBoxFocus) {
// djui_interactable_set_input_focus(NULL);
// }
djui_interactable_set_input_focus(NULL); djui_interactable_set_input_focus(NULL);
}
} else if ((padButtons & mainButtons) && !(sLastInteractablePad.button & mainButtons)) { } else if ((padButtons & mainButtons) && !(sLastInteractablePad.button & mainButtons)) {
// pressed main face button // pressed main face button
// if (!gDjuiChatBoxFocus && gDjuiChatBox != NULL && gInteractableFocus != &gDjuiChatBox->chatInput->base) { if (!gDjuiChatBoxFocus) {
// djui_interactable_set_input_focus(NULL);
// }
djui_interactable_set_input_focus(NULL); djui_interactable_set_input_focus(NULL);
}
} else { } else {
djui_interactable_on_focus(gInteractableFocus); djui_interactable_on_focus(gInteractableFocus);
} }

View file

@ -58,6 +58,7 @@ struct DjuiPanel* djui_panel_add(struct DjuiBase* caller, struct DjuiThreePanel*
panel->defaultElementBase = defaultElementBase; panel->defaultElementBase = defaultElementBase;
panel->on_back = threePanel->on_back; panel->on_back = threePanel->on_back;
panel->on_panel_destroy = NULL; panel->on_panel_destroy = NULL;
panel->temporary = threePanel->temporary;
sPanelList = panel; sPanelList = panel;
// find better defaultElementBase // find better defaultElementBase
@ -118,6 +119,7 @@ void djui_panel_back(void) {
// set the previous active // set the previous active
sPanelList = sPanelList->parent; sPanelList = sPanelList->parent;
if (sPanelList->temporary) { sPanelList = sPanelList->parent; }
// reset move amount // reset move amount
sMoveAmount = 0; sMoveAmount = 0;

View file

@ -25,10 +25,11 @@ static void djui_panel_main_quit(struct DjuiBase* caller) {
} }
void djui_panel_main_create(struct DjuiBase* caller) { void djui_panel_main_create(struct DjuiBase* caller) {
struct DjuiThreePanel* panel = djui_panel_menu_create("", false); struct DjuiThreePanel* panel = djui_panel_menu_create(configExCoopTheme ? "\\#ff0800\\SM\\#1be700\\64\\#00b3ff\\EX\n\\#ffef00\\COOP" : "", false);
{ {
struct DjuiBase* body = djui_three_panel_get_body(panel); struct DjuiBase* body = djui_three_panel_get_body(panel);
{ {
if (!configExCoopTheme) {
struct DjuiImage* logo = djui_image_create(body, texture_coopdx_logo, 2048, 1024, 32); struct DjuiImage* logo = djui_image_create(body, texture_coopdx_logo, 2048, 1024, 32);
if (configDjuiThemeCenter) { if (configDjuiThemeCenter) {
djui_base_set_size(&logo->base, 550, 275); djui_base_set_size(&logo->base, 550, 275);
@ -38,17 +39,18 @@ void djui_panel_main_create(struct DjuiBase* caller) {
djui_base_set_alignment(&logo->base, DJUI_HALIGN_CENTER, DJUI_VALIGN_TOP); djui_base_set_alignment(&logo->base, DJUI_HALIGN_CENTER, DJUI_VALIGN_TOP);
djui_base_set_location_type(&logo->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE); djui_base_set_location_type(&logo->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_location(&logo->base, 0, -30); djui_base_set_location(&logo->base, 0, -30);
}
struct DjuiButton* button1 = djui_button_create(body, DLANG(MAIN, HOST), DJUI_BUTTON_STYLE_NORMAL, djui_panel_host_create); struct DjuiButton* button1 = djui_button_create(body, DLANG(MAIN, HOST), DJUI_BUTTON_STYLE_NORMAL, djui_panel_host_create);
djui_base_set_location(&button1->base, 0, -30); if (!configExCoopTheme) { djui_base_set_location(&button1->base, 0, -30); }
djui_cursor_input_controlled_center(&button1->base); djui_cursor_input_controlled_center(&button1->base);
struct DjuiButton* button2 = djui_button_create(body, DLANG(MAIN, JOIN), DJUI_BUTTON_STYLE_NORMAL, djui_panel_join_create); struct DjuiButton* button2 = djui_button_create(body, DLANG(MAIN, JOIN), DJUI_BUTTON_STYLE_NORMAL, djui_panel_join_create);
djui_base_set_location(&button2->base, 0, -30); if (!configExCoopTheme) { djui_base_set_location(&button2->base, 0, -30); }
struct DjuiButton* button3 = djui_button_create(body, DLANG(MAIN, OPTIONS), DJUI_BUTTON_STYLE_NORMAL, djui_panel_options_create); struct DjuiButton* button3 = djui_button_create(body, DLANG(MAIN, OPTIONS), DJUI_BUTTON_STYLE_NORMAL, djui_panel_options_create);
djui_base_set_location(&button3->base, 0, -30); if (!configExCoopTheme) { djui_base_set_location(&button3->base, 0, -30); }
struct DjuiButton* button4 = djui_button_create(body, DLANG(MAIN, QUIT), DJUI_BUTTON_STYLE_BACK, djui_panel_main_quit); struct DjuiButton* button4 = djui_button_create(body, DLANG(MAIN, QUIT), DJUI_BUTTON_STYLE_BACK, djui_panel_main_quit);
djui_base_set_location(&button4->base, 0, -30); if (!configExCoopTheme) { djui_base_set_location(&button4->base, 0, -30); }
} }
// these two cannot co-exist for some reason // these two cannot co-exist for some reason

View file

@ -13,6 +13,13 @@ char* sRainbowColors[] = {
"\\#ffef40\\", "\\#ffef40\\",
}; };
char* sExCoopRainbowColors[] = {
"\\#ff0800\\",
"\\#1be700\\",
"\\#00b3ff\\",
"\\#ffef00\\",
};
char sRainbowText[RAINBOW_TEXT_LEN + 1] = { 0 }; char sRainbowText[RAINBOW_TEXT_LEN + 1] = { 0 };
static void generate_rainbow_text(char* text) { static void generate_rainbow_text(char* text) {
@ -28,7 +35,7 @@ static void generate_rainbow_text(char* text) {
} }
s32 restrictSize = RAINBOW_TEXT_LEN - (s32)(dst - sRainbowText); s32 restrictSize = RAINBOW_TEXT_LEN - (s32)(dst - sRainbowText);
if (restrictSize <= 0) { break; } if (restrictSize <= 0) { break; }
snprintf(dst, restrictSize, "%s", sRainbowColors[i++ % 4]); snprintf(dst, restrictSize, "%s", configExCoopTheme ? sExCoopRainbowColors[i++ % 4] : sRainbowColors[i++ % 4]);
dst = &sRainbowText[strlen(sRainbowText)]; dst = &sRainbowText[strlen(sRainbowText)];
restrictSize = RAINBOW_TEXT_LEN - (s32)(dst - sRainbowText); restrictSize = RAINBOW_TEXT_LEN - (s32)(dst - sRainbowText);
@ -75,7 +82,11 @@ struct DjuiThreePanel* djui_panel_menu_create(char* headerText, bool forcedLeftS
djui_base_set_location(&header->base, 0, DJUI_PANEL_HEADER_OFFSET); djui_base_set_location(&header->base, 0, DJUI_PANEL_HEADER_OFFSET);
djui_text_set_alignment(header, DJUI_HALIGN_CENTER, DJUI_VALIGN_BOTTOM); djui_text_set_alignment(header, DJUI_HALIGN_CENTER, DJUI_VALIGN_BOTTOM);
djui_text_set_font(header, hudFontHeader ? gDjuiFonts[2] : gDjuiFonts[1]); djui_text_set_font(header, hudFontHeader ? gDjuiFonts[2] : gDjuiFonts[1]);
if (configExCoopTheme) {
djui_text_set_font_scale(header, gDjuiFonts[1]->defaultFontScale);
} else {
djui_text_set_font_scale(header, gDjuiFonts[1]->defaultFontScale * (hudFontHeader ? 0.7f : 1.0f) * (strlen(headerText) > 15 ? 0.9f : 1.0f)); djui_text_set_font_scale(header, gDjuiFonts[1]->defaultFontScale * (hudFontHeader ? 0.7f : 1.0f) * (strlen(headerText) > 15 ? 0.9f : 1.0f));
}
struct DjuiFlowLayout* body = djui_flow_layout_create(&panel->base); struct DjuiFlowLayout* body = djui_flow_layout_create(&panel->base);
djui_base_set_alignment(&body->base, DJUI_HALIGN_CENTER, DJUI_VALIGN_CENTER); djui_base_set_alignment(&body->base, DJUI_HALIGN_CENTER, DJUI_VALIGN_CENTER);

View file

@ -11,6 +11,7 @@
#include "pc/utils/misc.h" #include "pc/utils/misc.h"
struct DjuiThreePanel* gDjuiPlayerList = NULL; struct DjuiThreePanel* gDjuiPlayerList = NULL;
bool gAttemptingToOpenPlayerlist = false;
static struct DjuiFlowLayout* djuiRow[MAX_PLAYERS] = { 0 }; static struct DjuiFlowLayout* djuiRow[MAX_PLAYERS] = { 0 };
static struct DjuiImage* djuiImages[MAX_PLAYERS] = { 0 }; static struct DjuiImage* djuiImages[MAX_PLAYERS] = { 0 };

View file

@ -2,6 +2,7 @@
#include "djui.h" #include "djui.h"
extern struct DjuiThreePanel* gDjuiPlayerList; extern struct DjuiThreePanel* gDjuiPlayerList;
extern bool gAttemptingToOpenPlayerlist;
extern const u8 sPlayerListSize; extern const u8 sPlayerListSize;
extern u8 sPageIndex; extern u8 sPageIndex;

View file

@ -21,16 +21,7 @@ void djui_panel_rules_create(struct DjuiBase* caller) {
struct DjuiThreePanel* panel = djui_panel_menu_create(DLANG(RULES, RULES_TITLE), false); struct DjuiThreePanel* panel = djui_panel_menu_create(DLANG(RULES, RULES_TITLE), false);
struct DjuiBase* body = djui_three_panel_get_body(panel); struct DjuiBase* body = djui_three_panel_get_body(panel);
{ {
snprintf(sRules, 512, "%s\n\ snprintf(sRules, 512, "%s\n%s\n%s\n%s\n%s", DLANG(RULES, RULE_1), DLANG(RULES, RULE_2), DLANG(RULES, RULE_3), DLANG(RULES, RULE_4), DLANG(RULES, RULE_5));
%s\n\
%s\n\
%s\n\
%s",
DLANG(RULES, RULE_1),
DLANG(RULES, RULE_2),
DLANG(RULES, RULE_3),
DLANG(RULES, RULE_4),
DLANG(RULES, RULE_5));
struct DjuiText* text1 = djui_text_create(body, sRules); struct DjuiText* text1 = djui_text_create(body, sRules);
djui_base_set_location(&text1->base, 0, 0); djui_base_set_location(&text1->base, 0, 0);
@ -65,6 +56,7 @@ DLANG(RULES, RULE_5));
} }
panel->temporary = true;
djui_panel_add(caller, panel, NULL); djui_panel_add(caller, panel, NULL);
} }
#endif #endif

View file

@ -2,7 +2,7 @@
void djui_progress_bar_render_pre(struct DjuiBase* base, UNUSED bool* unused) { void djui_progress_bar_render_pre(struct DjuiBase* base, UNUSED bool* unused) {
struct DjuiProgressBar* progress = (struct DjuiProgressBar*)base; struct DjuiProgressBar* progress = (struct DjuiProgressBar*)base;
progress->smoothValue = progress->smoothValue * 0.95f + *progress->value * 0.05f; progress->smoothValue = progress->smoothValue * progress->smoothenHigh + *progress->value * progress->smoothenLow;
float min = progress->min; float min = progress->min;
float max = progress->max; float max = progress->max;
djui_base_set_size(&progress->rectValue->base, ((f32)progress->smoothValue - min) / ((f32)max - min), 1.0f); djui_base_set_size(&progress->rectValue->base, ((f32)progress->smoothValue - min) / ((f32)max - min), 1.0f);
@ -13,7 +13,7 @@ void djui_progress_bar_render_pre_infinite(struct DjuiBase* base, UNUSED bool* u
float min = progress->min; float min = progress->min;
float max = progress->max; float max = progress->max;
progress->smoothValue = progress->smoothValue * 0.95f + *progress->value * 0.05f; progress->smoothValue = progress->smoothValue * progress->smoothenHigh + *progress->value * progress->smoothenLow;
float modValue = progress->smoothValue - ((int)progress->smoothValue); float modValue = progress->smoothValue - ((int)progress->smoothValue);
float x = (modValue - min - 0.25f) / (max - min - 0.25f); float x = (modValue - min - 0.25f) / (max - min - 0.25f);
float w = 0.25f; float w = 0.25f;
@ -43,6 +43,8 @@ struct DjuiProgressBar* djui_progress_bar_create(struct DjuiBase* parent, float*
progress->smoothValue = *value; progress->smoothValue = *value;
progress->min = min; progress->min = min;
progress->max = max; progress->max = max;
progress->smoothenHigh = 0.95f;
progress->smoothenLow = 0.05f;
djui_base_init(parent, base, NULL, djui_progress_bar_destroy); djui_base_init(parent, base, NULL, djui_progress_bar_destroy);
djui_base_set_size_type(base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE); djui_base_set_size_type(base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);

View file

@ -9,6 +9,8 @@ struct DjuiProgressBar {
float smoothValue; float smoothValue;
float min; float min;
float max; float max;
float smoothenHigh;
float smoothenLow;
}; };
struct DjuiProgressBar* djui_progress_bar_create(struct DjuiBase* parent, float* value, float min, float max, bool infinite); struct DjuiProgressBar* djui_progress_bar_create(struct DjuiBase* parent, float* value, float min, float max, bool infinite);

View file

@ -6,6 +6,7 @@ struct DjuiThreePanel {
struct DjuiScreenValue minHeaderSize; struct DjuiScreenValue minHeaderSize;
struct DjuiScreenValue bodySize; struct DjuiScreenValue bodySize;
struct DjuiScreenValue minFooterSize; struct DjuiScreenValue minFooterSize;
bool temporary;
bool (*on_back)(struct DjuiBase*); bool (*on_back)(struct DjuiBase*);
}; };

View file

@ -17,6 +17,7 @@ struct LoadingSegment gCurrLoadingSegment = { "", 0 };
struct LoadingScreen { struct LoadingScreen {
struct DjuiBase base; struct DjuiBase base;
struct DjuiImage* splashImage; struct DjuiImage* splashImage;
struct DjuiText* splashText;
struct DjuiText* loadingDesc; struct DjuiText* loadingDesc;
struct DjuiProgressBar *loadingBar; struct DjuiProgressBar *loadingBar;
}; };
@ -32,6 +33,10 @@ void loading_screen_set_segment_text(const char* text) {
snprintf(gCurrLoadingSegment.str, 256, text); snprintf(gCurrLoadingSegment.str, 256, text);
} }
void loading_screen_reset_progress_bar(void) {
sLoading->loadingBar->smoothValue = 0;
}
static void loading_screen_produce_frame_callback(void) { static void loading_screen_produce_frame_callback(void) {
if (sLoading) { djui_base_render(&sLoading->base); } if (sLoading) { djui_base_render(&sLoading->base); }
} }
@ -49,12 +54,19 @@ static bool loading_screen_on_render(struct DjuiBase* base) {
windowWidth /= scale; windowWidth /= scale;
windowHeight /= scale; windowHeight /= scale;
f32 loadingDescY1 = windowHeight * 0.5f + sLoading->splashImage->base.height.value * 0.25f; f32 loadingDescY1 = windowHeight * 0.5f - sLoading->loadingDesc->base.height.value * 0.5f;
f32 loadingDescY2 = windowHeight * 0.5f + sLoading->splashImage->base.height.value * 0.55f; f32 loadingDescY2 = windowHeight * 0.5f + sLoading->loadingDesc->base.height.value * 0.5f;
// fill the screen // fill the screen
djui_base_set_size(base, windowWidth, windowHeight); djui_base_set_size(base, windowWidth, windowHeight);
// splash logo
if (configExCoopTheme) {
djui_base_set_location(&sLoading->splashText->base, 0, loadingDescY1 - sLoading->splashText->base.height.value);
} else {
djui_base_set_location(&sLoading->splashImage->base, 0, loadingDescY1 - sLoading->splashImage->base.height.value);
}
{ {
// loading text description // loading text description
char buffer[256] = ""; char buffer[256] = "";
@ -73,7 +85,7 @@ static bool loading_screen_on_render(struct DjuiBase* base) {
} }
// loading bar // loading bar
djui_base_set_location(&sLoading->loadingBar->base, windowWidth / 4, loadingDescY2); djui_base_set_location(&sLoading->loadingBar->base, windowWidth / 4, loadingDescY2 + 64);
djui_base_set_visible(&sLoading->loadingBar->base, gCurrLoadingSegment.percentage > 0 && strlen(gCurrLoadingSegment.str) > 0); djui_base_set_visible(&sLoading->loadingBar->base, gCurrLoadingSegment.percentage > 0 && strlen(gCurrLoadingSegment.str) > 0);
djui_base_compute(base); djui_base_compute(base);
@ -95,12 +107,26 @@ static void init_loading_screen(void) {
djui_base_init(NULL, base, loading_screen_on_render, loading_screen_destroy); djui_base_init(NULL, base, loading_screen_on_render, loading_screen_destroy);
{ // splash text (easter egg)
if (configExCoopTheme) {
struct DjuiText* splashDjuiText = djui_text_create(base, "\\#ff0800\\SM\\#1be700\\64\\#00b3ff\\EX\n\\#ffef00\\COOP");
djui_base_set_location_type(&splashDjuiText->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_location(&splashDjuiText->base, 0, 0);
djui_text_set_font(splashDjuiText, gDjuiFonts[1]);
djui_text_set_font_scale(splashDjuiText, gDjuiFonts[1]->defaultFontScale);
djui_text_set_alignment(splashDjuiText, DJUI_HALIGN_CENTER, DJUI_VALIGN_CENTER);
djui_base_set_size_type(&splashDjuiText->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&splashDjuiText->base, 1.0f, gDjuiFonts[1]->defaultFontScale * 3.0f);
load->splashText = splashDjuiText;
// splash image // splash image
} else {
struct DjuiImage* splashImage = djui_image_create(base, texture_coopdx_logo, 2048, 1024, 32); struct DjuiImage* splashImage = djui_image_create(base, texture_coopdx_logo, 2048, 1024, 32);
djui_base_set_location_type(&splashImage->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_alignment(&splashImage->base, DJUI_HALIGN_CENTER, DJUI_VALIGN_TOP);
djui_base_set_location(&splashImage->base, 0, -100); djui_base_set_location(&splashImage->base, 0, -100);
djui_base_set_alignment(&splashImage->base, DJUI_HALIGN_CENTER, DJUI_VALIGN_CENTER); djui_base_set_size(&splashImage->base, 512, 256);
djui_base_set_size(&splashImage->base, 1024, 512);
load->splashImage = splashImage; load->splashImage = splashImage;
} }
@ -112,11 +138,11 @@ static void init_loading_screen(void) {
djui_base_set_location(&text->base, 0, 0); djui_base_set_location(&text->base, 0, 0);
djui_base_set_size_type(&text->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE); djui_base_set_size_type(&text->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&text->base, 1.0f, gDjuiFonts[0]->defaultFontScale * 4.5f); // 3 lines djui_base_set_size(&text->base, 1.0f, gDjuiFonts[0]->defaultFontScale * 3.0f);
djui_base_set_color(&text->base, 220, 220, 220, 255); djui_base_set_color(&text->base, 220, 220, 220, 255);
djui_text_set_alignment(text, DJUI_HALIGN_CENTER, DJUI_VALIGN_TOP); djui_text_set_alignment(text, DJUI_HALIGN_CENTER, DJUI_VALIGN_TOP);
djui_text_set_font(text, gDjuiFonts[0]); djui_text_set_font(text, gDjuiFonts[0]);
djui_text_set_font_scale(text, gDjuiFonts[0]->defaultFontScale * 1.5f); djui_text_set_font_scale(text, gDjuiFonts[0]->defaultFontScale);
load->loadingDesc = text; load->loadingDesc = text;
} }
@ -127,7 +153,9 @@ static void init_loading_screen(void) {
djui_base_set_location_type(&progressBar->base, DJUI_SVT_ABSOLUTE, DJUI_SVT_ABSOLUTE); djui_base_set_location_type(&progressBar->base, DJUI_SVT_ABSOLUTE, DJUI_SVT_ABSOLUTE);
djui_base_set_location(&progressBar->base, 0, 0); djui_base_set_location(&progressBar->base, 0, 0);
djui_base_set_visible(&progressBar->base, false); djui_base_set_visible(&progressBar->base, false);
djui_base_set_size(&progressBar->base, 0.5f, 32); progressBar->base.width.value = 0.5;
progressBar->smoothenHigh = 0.75f;
progressBar->smoothenLow = 0.25f;
load->loadingBar = progressBar; load->loadingBar = progressBar;
} }

View file

@ -32,6 +32,7 @@ extern pthread_mutex_t gLoadingThreadMutex;
extern bool gIsThreaded; extern bool gIsThreaded;
void loading_screen_set_segment_text(const char* text); void loading_screen_set_segment_text(const char* text);
void loading_screen_reset_progress_bar(void);
void render_loading_screen(void); void render_loading_screen(void);
void loading_screen_reset(void); void loading_screen_reset(void);
void render_rom_setup_screen(void); void render_rom_setup_screen(void);

View file

@ -1,4 +1,5 @@
#include "smlua.h" #include "smlua.h"
#include "smlua_cobject_map.h"
#include "game/hardcoded.h" #include "game/hardcoded.h"
#include "pc/mods/mods.h" #include "pc/mods/mods.h"
#include "pc/mods/mods_utils.h" #include "pc/mods/mods_utils.h"
@ -281,8 +282,7 @@ static void smlua_load_script(struct Mod* mod, struct ModFile* file, u16 remoteI
void smlua_init(void) { void smlua_init(void) {
smlua_shutdown(); smlua_shutdown();
smlua_cobject_allowlist_init(); smlua_pointer_user_data_init();
smlua_cpointer_allowlist_init();
gLuaState = luaL_newstate(); gLuaState = luaL_newstate();
lua_State* L = gLuaState; lua_State* L = gLuaState;
@ -364,8 +364,7 @@ void smlua_shutdown(void) {
smlua_text_utils_reset_all(); smlua_text_utils_reset_all();
smlua_audio_utils_reset_all(); smlua_audio_utils_reset_all();
audio_custom_shutdown(); audio_custom_shutdown();
smlua_cobject_allowlist_shutdown(); smlua_pointer_user_data_shutdown();
smlua_cpointer_allowlist_shutdown();
smlua_clear_hooks(); smlua_clear_hooks();
smlua_model_util_clear(); smlua_model_util_clear();
smlua_level_util_reset(); smlua_level_util_reset();

View file

@ -9,7 +9,6 @@
#include "types.h" #include "types.h"
#include "smlua_cobject.h" #include "smlua_cobject.h"
#include "smlua_cobject_allowlist.h"
#include "smlua_cobject_autogen.h" #include "smlua_cobject_autogen.h"
#include "smlua_utils.h" #include "smlua_utils.h"
#include "smlua_functions.h" #include "smlua_functions.h"

View file

@ -10,6 +10,7 @@
#include "object_fields.h" #include "object_fields.h"
#include "pc/djui/djui_hud_utils.h" #include "pc/djui/djui_hud_utils.h"
#include "pc/lua/smlua.h" #include "pc/lua/smlua.h"
#include "pc/lua/smlua_cobject_map.h"
#include "pc/lua/utils/smlua_anim_utils.h" #include "pc/lua/utils/smlua_anim_utils.h"
#include "pc/lua/utils/smlua_collision_utils.h" #include "pc/lua/utils/smlua_collision_utils.h"
#include "pc/lua/utils/smlua_obj_utils.h" #include "pc/lua/utils/smlua_obj_utils.h"
@ -381,38 +382,30 @@ struct LuaObjectField* smlua_get_custom_field(lua_State* L, u32 lot, int keyInde
static int smlua__get_field(lua_State* L) { static int smlua__get_field(lua_State* L) {
LUA_STACK_CHECK_BEGIN(); LUA_STACK_CHECK_BEGIN();
if (!smlua_functions_valid_param_count(L, 4)) { return 0; }
enum LuaObjectType lot = smlua_to_integer(L, 1); CObject *cobj = lua_touserdata(L, 1);
if (!gSmLuaConvertSuccess) { return 0; } enum LuaObjectType lot = cobj->lot;
u64 pointer = (u64)(intptr_t) cobj->pointer;
const char *key = smlua_to_string(L, 2);
u64 pointer = smlua_to_integer(L, 2); // Legacy support
if (!gSmLuaConvertSuccess) { return 0; } if (strcmp(key, "_pointer") == 0) {
lua_pushinteger(L, pointer);
const char* key = smlua_to_string(L, 3); return 1;
if (!gSmLuaConvertSuccess) { }
LOG_LUA_LINE("Tried to get a non-string field of cobject"); if (strcmp(key, "_lot") == 0) {
return 0; lua_pushinteger(L, cobj->lot);
return 1;
} }
if (pointer == 0) { if (cobj->freed) {
LOG_LUA_LINE("_get_field on null pointer"); LOG_LUA_LINE("_get_field on freed object");
return 0;
}
if (!smlua_valid_lot(lot)) {
LOG_LUA_LINE("_get_field on invalid LOT '%u'", lot);
return 0;
}
if (!smlua_cobject_allowlist_contains(lot, pointer)) {
LOG_LUA_LINE("_get_field received a pointer not in allow list. '%u', '%llu", lot, (u64)pointer);
return 0; return 0;
} }
struct LuaObjectField* data = smlua_get_object_field(lot, key); struct LuaObjectField* data = smlua_get_object_field(lot, key);
if (data == NULL) { if (data == NULL) {
data = smlua_get_custom_field(L, lot, 3); data = smlua_get_custom_field(L, lot, 2);
} }
if (data == NULL) { if (data == NULL) {
LOG_LUA_LINE("_get_field on invalid key '%s', lot '%d'", key, lot); LOG_LUA_LINE("_get_field on invalid key '%s', lot '%d'", key, lot);
@ -470,38 +463,20 @@ static int smlua__get_field(lua_State* L) {
static int smlua__set_field(lua_State* L) { static int smlua__set_field(lua_State* L) {
LUA_STACK_CHECK_BEGIN(); LUA_STACK_CHECK_BEGIN();
if (!smlua_functions_valid_param_count(L, 5)) { return 0; }
enum LuaObjectType lot = smlua_to_integer(L, 1); CObject *cobj = lua_touserdata(L, 1);
if (!gSmLuaConvertSuccess) { return 0; } enum LuaObjectType lot = cobj->lot;
u64 pointer = (u64)(intptr_t) cobj->pointer;
const char *key = smlua_to_string(L, 2);
u64 pointer = smlua_to_integer(L, 2); if (cobj->freed) {
if (!gSmLuaConvertSuccess) { return 0; } LOG_LUA_LINE("_set_field on freed object");
const char* key = smlua_to_string(L, 3);
if (!gSmLuaConvertSuccess) {
LOG_LUA_LINE("Tried to set a non-string field of cobject");
return 0;
}
if (pointer == 0) {
LOG_LUA_LINE("_set_field on null pointer");
return 0;
}
if (!smlua_valid_lot(lot)) {
LOG_LUA_LINE("_set_field on invalid LOT '%u'", lot);
return 0;
}
if (!smlua_cobject_allowlist_contains(lot, pointer)) {
LOG_LUA_LINE("_set_field received a pointer not in allow list. '%u', '%llu", lot, (u64)pointer);
return 0; return 0;
} }
struct LuaObjectField* data = smlua_get_object_field(lot, key); struct LuaObjectField* data = smlua_get_object_field(lot, key);
if (data == NULL) { if (data == NULL) {
data = smlua_get_custom_field(L, lot, 3); data = smlua_get_custom_field(L, lot, 2);
} }
if (data == NULL) { if (data == NULL) {
@ -517,18 +492,18 @@ static int smlua__set_field(lua_State* L) {
void* valuePointer = NULL; void* valuePointer = NULL;
u8* p = ((u8*)(intptr_t)pointer) + data->valueOffset; u8* p = ((u8*)(intptr_t)pointer) + data->valueOffset;
switch (data->valueType) { switch (data->valueType) {
case LVT_BOOL:*(u8*) p = smlua_to_boolean(L, 4); break; case LVT_BOOL:*(u8*) p = smlua_to_boolean(L, 3); break;
case LVT_U8: *(u8*) p = smlua_to_integer(L, 4); break; case LVT_U8: *(u8*) p = smlua_to_integer(L, 3); break;
case LVT_U16: *(u16*)p = smlua_to_integer(L, 4); break; case LVT_U16: *(u16*)p = smlua_to_integer(L, 3); break;
case LVT_U32: *(u32*)p = smlua_to_integer(L, 4); break; case LVT_U32: *(u32*)p = smlua_to_integer(L, 3); break;
case LVT_S8: *(s8*) p = smlua_to_integer(L, 4); break; case LVT_S8: *(s8*) p = smlua_to_integer(L, 3); break;
case LVT_S16: *(s16*)p = smlua_to_integer(L, 4); break; case LVT_S16: *(s16*)p = smlua_to_integer(L, 3); break;
case LVT_S32: *(s32*)p = smlua_to_integer(L, 4); break; case LVT_S32: *(s32*)p = smlua_to_integer(L, 3); break;
case LVT_F32: *(f32*)p = smlua_to_number(L, 4); break; case LVT_F32: *(f32*)p = smlua_to_number(L, 3); break;
case LVT_U64: *(s64*)p = smlua_to_integer(L, 4); break; case LVT_U64: *(s64*)p = smlua_to_integer(L, 3); break;
case LVT_COBJECT_P: case LVT_COBJECT_P:
valuePointer = smlua_to_cobject(L, 4, data->lot); valuePointer = smlua_to_cobject(L, 3, data->lot);
if (gSmLuaConvertSuccess) { if (gSmLuaConvertSuccess) {
*(u8**)p = valuePointer; *(u8**)p = valuePointer;
} }
@ -548,7 +523,7 @@ static int smlua__set_field(lua_State* L) {
case LVT_OBJECTANIMPOINTER_P: case LVT_OBJECTANIMPOINTER_P:
case LVT_COLLISION_P: case LVT_COLLISION_P:
case LVT_TRAJECTORY_P: case LVT_TRAJECTORY_P:
valuePointer = smlua_to_cpointer(L, 4, data->valueType); valuePointer = smlua_to_cpointer(L, 3, data->valueType);
if (gSmLuaConvertSuccess) { if (gSmLuaConvertSuccess) {
*(u8**)p = valuePointer; *(u8**)p = valuePointer;
} }
@ -567,6 +542,43 @@ static int smlua__set_field(lua_State* L) {
return 1; return 1;
} }
int smlua__eq(lua_State *L) {
CObject *a = lua_touserdata(L, 1);
CObject *b = lua_touserdata(L, 2);
lua_pushboolean(L, a->lot == b->lot && a->pointer == b->pointer);
return 1;
}
int smlua__gc(lua_State *L) {
CObject *cobj = lua_touserdata(L, 1);
if (!cobj->freed) {
switch (cobj->lot) {
case LOT_SURFACE: {
smlua_pointer_user_data_delete((uintptr_t) cobj->pointer);
}
}
}
return 0;
}
static int smlua_cpointer_get(lua_State* L) {
CPointer *cptr = lua_touserdata(L, 1);
const char *key = smlua_to_string(L, 2);
// Legacy support
if (strcmp(key, "_pointer") == 0) {
lua_pushinteger(L, (u64)(intptr_t) cptr->pointer);
return 1;
}
if (strcmp(key, "_lot") == 0) {
lua_pushinteger(L, cptr->lvt);
return 1;
}
return 0;
}
static int smlua_cpointer_set(UNUSED lua_State* L) { return 0; }
////////// //////////
// bind // // bind //
////////// //////////
@ -574,6 +586,27 @@ static int smlua__set_field(lua_State* L) {
void smlua_cobject_init_globals(void) { void smlua_cobject_init_globals(void) {
lua_State* L = gLuaState; lua_State* L = gLuaState;
// Create metatables
luaL_newmetatable(L, "CObject");
luaL_Reg cObjectMethods[] = {
{ "__index", smlua__get_field },
{ "__newindex", smlua__set_field },
{ "__eq", smlua__eq },
{ "__gc", smlua__gc },
{ NULL, NULL }
};
luaL_setfuncs(L, cObjectMethods, 0);
lua_pop(L, 1);
luaL_newmetatable(L, "CPointer");
luaL_Reg cPointerMethods[] = {
{ "__index", smlua_cpointer_get },
{ "__newindex", smlua_cpointer_set },
{ "__eq", smlua__eq },
{ NULL, NULL }
};
luaL_setfuncs(L, cPointerMethods, 0);
lua_pop(L, 1);
#define EXPOSE_GLOBAL_ARRAY(lot, ptr, iterator) \ #define EXPOSE_GLOBAL_ARRAY(lot, ptr, iterator) \
{ \ { \
lua_newtable(L); \ lua_newtable(L); \
@ -662,8 +695,4 @@ void smlua_bind_cobject(void) {
lua_State* L = gLuaState; lua_State* L = gLuaState;
smlua_bind_function(L, "define_custom_obj_fields", smlua_func_define_custom_obj_fields); smlua_bind_function(L, "define_custom_obj_fields", smlua_func_define_custom_obj_fields);
smlua_bind_function(L, "_get_field", smlua__get_field);
smlua_bind_function(L, "_set_field", smlua__set_field);
} }

View file

@ -65,6 +65,18 @@ struct LuaObjectTable {
u16 fieldCount; u16 fieldCount;
}; };
typedef struct {
void *pointer;
u16 lot;
bool freed;
} CObject;
typedef struct {
void *pointer;
u16 lvt;
bool freed;
} CPointer;
bool smlua_valid_lot(u16 lot); bool smlua_valid_lot(u16 lot);
bool smlua_valid_lvt(u16 lvt); bool smlua_valid_lvt(u16 lvt);
struct LuaObjectField* smlua_get_object_field_from_ot(struct LuaObjectTable* ot, const char* key); struct LuaObjectField* smlua_get_object_field_from_ot(struct LuaObjectTable* ot, const char* key);

View file

@ -1,102 +0,0 @@
#include <stdio.h>
#include "smlua.h"
#include "data/dynos_cmap.cpp.h"
#define LOT_COUNT (LOT_MAX + (LOT_AUTOGEN_MAX - LOT_AUTOGEN_MIN))
static void* sObjectAllowList[LOT_COUNT] = { NULL };
static u64 sCachedObjectAllowed[LOT_COUNT] = { 0 };
static u16 smlua_lot_mapping(u16 lot) {
if (lot >= LOT_MAX) {
return LOT_MAX + (lot - LOT_AUTOGEN_MIN);
} else {
return lot;
}
}
void smlua_cobject_allowlist_init(void) {
smlua_cobject_allowlist_shutdown();
}
void smlua_cobject_allowlist_shutdown(void) {
for (s32 i = 0; i < LOT_COUNT; i++) {
sCachedObjectAllowed[i] = 0;
if (sObjectAllowList[i]) {
hmap_clear(sObjectAllowList[i]);
}
}
}
void smlua_cobject_allowlist_add(u16 lot, u64 pointer) {
if (pointer == 0) { return; }
if (!smlua_valid_lot(lot)) { return; }
u16 m = smlua_lot_mapping(lot);
if (sCachedObjectAllowed[m] == pointer) { return; }
sCachedObjectAllowed[m] = pointer;
if (!sObjectAllowList[m]) {
sObjectAllowList[m] = hmap_create();
}
if (!hmap_get(sObjectAllowList[m], pointer)) {
hmap_put(sObjectAllowList[m], pointer, (void*)1);
}
}
bool smlua_cobject_allowlist_contains(u16 lot, u64 pointer) {
if (pointer == 0) { return false; }
if (!smlua_valid_lot(lot)) { return false; }
u16 m = smlua_lot_mapping(lot);
if (sCachedObjectAllowed[m] == pointer) { return true; }
if (!sObjectAllowList[m]) { return false; }
return hmap_get(sObjectAllowList[m], pointer) != 0;
}
/////////////////////////////
static void* sPointerAllowList[LVT_MAX] = { 0 };
static u64 sCachedPointerAllowed[LVT_MAX] = { 0 };
void smlua_cpointer_allowlist_init(void) {
smlua_cpointer_allowlist_shutdown();
}
void smlua_cpointer_allowlist_shutdown(void) {
for (s32 i = 0; i < LVT_MAX; i++) {
sCachedPointerAllowed[i] = 0;
if (sPointerAllowList[i]) {
hmap_clear(sPointerAllowList[i]);
}
}
}
void smlua_cpointer_allowlist_add(u16 lvt, u64 pointer) {
if (pointer == 0) { return; }
if (!smlua_valid_lvt(lvt)) { return; }
if (sCachedPointerAllowed[lvt] == pointer) { return; }
sCachedPointerAllowed[lvt] = pointer;
if (!sPointerAllowList[lvt]) {
sPointerAllowList[lvt] = hmap_create();
}
if (!hmap_get(sPointerAllowList[lvt], pointer)) {
hmap_put(sPointerAllowList[lvt], pointer, (void*)1);
}
}
bool smlua_cpointer_allowlist_contains(u16 lvt, u64 pointer) {
if (pointer == 0) { return false; }
if (!smlua_valid_lvt(lvt)) { return false; }
if (sCachedPointerAllowed[lvt] == pointer) { return true; }
if (!sPointerAllowList[lvt]) { return false; }
return hmap_get(sPointerAllowList[lvt], pointer) != 0;
}

View file

@ -1,14 +0,0 @@
#ifndef SMLUA_COBJECT_ALLOWLIST_H
#define SMLUA_COBJECT_ALLOWLIST_H
void smlua_cobject_allowlist_init(void);
void smlua_cobject_allowlist_shutdown(void);
void smlua_cobject_allowlist_add(u16 lot, u64 pointer);
bool smlua_cobject_allowlist_contains(u16 lot, u64 pointer);
void smlua_cpointer_allowlist_init(void);
void smlua_cpointer_allowlist_shutdown(void);
void smlua_cpointer_allowlist_add(u16 lvt, u64 pointer);
bool smlua_cpointer_allowlist_contains(u16 lvt, u64 pointer);
#endif

View file

@ -0,0 +1,35 @@
#include <stdio.h>
#include "smlua.h"
#include "data/dynos_cmap.cpp.h"
static void* sPointers = NULL;
void smlua_pointer_user_data_shutdown(void) {
hmap_clear(sPointers);
}
void smlua_pointer_user_data_init(void) {
smlua_pointer_user_data_shutdown();
}
void smlua_pointer_user_data_add(uintptr_t pointer, CObject *obj) {
if (pointer == 0) { return; }
if (!sPointers) {
sPointers = hmap_create();
}
if (!hmap_get(sPointers, pointer)) {
hmap_put(sPointers, pointer, obj);
}
}
void smlua_pointer_user_data_delete(uintptr_t pointer) {
if (pointer == 0) { return; }
hmap_del(sPointers, pointer);
}
CObject *smlua_pointer_user_data_get(uintptr_t pointer) {
if (pointer == 0) { return NULL; }
return hmap_get(sPointers, pointer);
}

View file

@ -0,0 +1,10 @@
#ifndef SMLUA_COBJECT_MAP_H
#define SMLUA_COBJECT_MAP_H
void smlua_pointer_user_data_init(void);
void smlua_pointer_user_data_shutdown(void);
void smlua_pointer_user_data_add(uintptr_t pointer, CObject *obj);
void smlua_pointer_user_data_delete(uintptr_t pointer);
CObject *smlua_pointer_user_data_get(uintptr_t pointer);
#endif

View file

@ -1,65 +1,5 @@
char gSmluaConstants[] = "" char gSmluaConstants[] = ""
"math.randomseed(get_time())\n" "math.randomseed(get_time())\n"
"--------------\n"
"-- CObjects --\n"
"--------------\n"
"_CObjectPool = {}\n"
"_CObject = {\n"
" __index = function (t,k)\n"
" return _get_field(t['_lot'], t['_pointer'], k, t)\n"
" end,\n"
" __newindex = function (t,k,v)\n"
" _set_field(t['_lot'], t['_pointer'], k, v, t)\n"
" end,\n"
" __tostring = function(t)\n"
" return 'CObject: ' .. t['_lot'] .. ', [' .. string.format('0x%08X', t['_pointer']) .. ']'\n"
" end,\n"
" __eq = function (a, b)\n"
" return a['_pointer'] == b['_pointer'] and a['_lot'] == b['_lot'] and a['_pointer'] ~= nil and a['_lot'] ~= nil\n"
" end\n"
"}\n"
"function _NewCObject(lot, pointer)\n"
" if _CObjectPool[lot] == nil then\n"
" _CObjectPool[lot] = {}\n"
" end\n"
" if _CObjectPool[lot][pointer] == nil then\n"
" local obj = {}\n"
" rawset(obj, '_pointer', pointer)\n"
" rawset(obj, '_lot', lot)\n"
" setmetatable(obj, _CObject)\n"
" _CObjectPool[lot][pointer] = obj\n"
" return obj\n"
" end\n"
" return _CObjectPool[lot][pointer]\n"
"end\n"
"local _CPointerPool = {}\n"
"_CPointer = {\n"
" __index = function (t,k)\n"
" return nil\n"
" end,\n"
" __newindex = function (t,k,v)\n"
" end,\n"
" __tostring = function(t)\n"
" return 'CPointer: ' .. t['_lvt'] .. ', [' .. string.format('0x%08X', t['_pointer']) .. ']'\n"
" end,\n"
" __eq = function (a, b)\n"
" return a['_pointer'] == b['_pointer'] and a['_pointer'] ~= nil and a['_lvt'] ~= nil\n"
" end\n"
"}\n"
"function _NewCPointer(lvt, pointer)\n"
" if _CPointerPool[lvt] == nil then\n"
" _CPointerPool[lvt] = {}\n"
" end\n"
" if _CPointerPool[lvt][pointer] == nil then\n"
" local obj = {}\n"
" rawset(obj, '_pointer', pointer)\n"
" rawset(obj, '_lvt', lvt)\n"
" setmetatable(obj, _CPointer)\n"
" _CPointerPool[lvt][pointer] = obj\n"
" return obj\n"
" end\n"
" return _CPointerPool[lvt][pointer]\n"
"end\n"
"_SyncTable = {\n" "_SyncTable = {\n"
" __index = function (t,k)\n" " __index = function (t,k)\n"
" local _table = rawget(t, '_table')\n" " local _table = rawget(t, '_table')\n"
@ -1479,6 +1419,7 @@ char gSmluaConstants[] = ""
"INT_HIT_FROM_BELOW = (1 << 7)\n" "INT_HIT_FROM_BELOW = (1 << 7)\n"
"INT_TWIRL = (1 << 8)\n" "INT_TWIRL = (1 << 8)\n"
"INT_GROUND_POUND_OR_TWIRL = (INT_GROUND_POUND | INT_TWIRL)\n" "INT_GROUND_POUND_OR_TWIRL = (INT_GROUND_POUND | INT_TWIRL)\n"
"INT_LUA = (1 << 31)\n"
"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)\n" "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)\n"
"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)\n" "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)\n"
"INT_ATTACK_NOT_WEAK_FROM_ABOVE = (INT_GROUND_POUND_OR_TWIRL | INT_PUNCH | INT_KICK | INT_TRIP | INT_HIT_FROM_BELOW)\n" "INT_ATTACK_NOT_WEAK_FROM_ABOVE = (INT_GROUND_POUND_OR_TWIRL | INT_PUNCH | INT_KICK | INT_TRIP | INT_HIT_FROM_BELOW)\n"
@ -3290,7 +3231,8 @@ char gSmluaConstants[] = ""
"HOOK_ON_ATTACK_OBJECT = 43\n" "HOOK_ON_ATTACK_OBJECT = 43\n"
"HOOK_ON_LANGUAGE_CHANGED = 44\n" "HOOK_ON_LANGUAGE_CHANGED = 44\n"
"HOOK_ON_MODS_LOADED = 45\n" "HOOK_ON_MODS_LOADED = 45\n"
"HOOK_MAX = 46\n" "HOOK_ON_NAMETAGS_RENDER = 46\n"
"HOOK_MAX = 47\n"
"ACTION_HOOK_EVERY_FRAME = 0\n" "ACTION_HOOK_EVERY_FRAME = 0\n"
"ACTION_HOOK_GRAVITY = 1\n" "ACTION_HOOK_GRAVITY = 1\n"
"ACTION_HOOK_MAX = 2\n" "ACTION_HOOK_MAX = 2\n"

View file

@ -29015,6 +29015,21 @@ int smlua_func_camera_freeze(UNUSED lua_State* L) {
return 1; return 1;
} }
int smlua_func_camera_get_checking_surfaces(UNUSED lua_State* L) {
if (L == NULL) { return 0; }
int top = lua_gettop(L);
if (top != 0) {
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "camera_get_checking_surfaces", 0, top);
return 0;
}
lua_pushboolean(L, camera_get_checking_surfaces());
return 1;
}
int smlua_func_camera_is_frozen(UNUSED lua_State* L) { int smlua_func_camera_is_frozen(UNUSED lua_State* L) {
if (L == NULL) { return 0; } if (L == NULL) { return 0; }
@ -29079,6 +29094,23 @@ int smlua_func_camera_romhack_allow_dpad_usage(lua_State* L) {
return 1; return 1;
} }
int smlua_func_camera_set_checking_surfaces(lua_State* L) {
if (L == NULL) { return 0; }
int top = lua_gettop(L);
if (top != 1) {
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "camera_set_checking_surfaces", 1, top);
return 0;
}
bool value = smlua_to_boolean(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "camera_set_checking_surfaces"); return 0; }
camera_set_checking_surfaces(value);
return 1;
}
int smlua_func_camera_set_romhack_override(lua_State* L) { int smlua_func_camera_set_romhack_override(lua_State* L) {
if (L == NULL) { return 0; } if (L == NULL) { return 0; }
@ -30152,6 +30184,21 @@ int smlua_func_deref_s32_pointer(lua_State* L) {
return 1; return 1;
} }
int smlua_func_djui_attempting_to_open_playerlist(UNUSED lua_State* L) {
if (L == NULL) { return 0; }
int top = lua_gettop(L);
if (top != 0) {
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "djui_attempting_to_open_playerlist", 0, top);
return 0;
}
lua_pushboolean(L, djui_attempting_to_open_playerlist());
return 1;
}
int smlua_func_djui_is_playerlist_open(UNUSED lua_State* L) { int smlua_func_djui_is_playerlist_open(UNUSED lua_State* L) {
if (L == NULL) { return 0; } if (L == NULL) { return 0; }
@ -30248,6 +30295,23 @@ int smlua_func_djui_set_popup_disabled_override(lua_State* L) {
return 1; return 1;
} }
int smlua_func_get_coopnet_id(lua_State* L) {
if (L == NULL) { return 0; }
int top = lua_gettop(L);
if (top != 1) {
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "get_coopnet_id", 1, top);
return 0;
}
s8 localIndex = smlua_to_integer(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "get_coopnet_id"); return 0; }
lua_pushstring(L, get_coopnet_id(localIndex));
return 1;
}
int smlua_func_get_current_save_file_num(UNUSED lua_State* L) { int smlua_func_get_current_save_file_num(UNUSED lua_State* L) {
if (L == NULL) { return 0; } if (L == NULL) { return 0; }
@ -34595,10 +34659,12 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "camera_config_set_x_sensitivity", smlua_func_camera_config_set_x_sensitivity); smlua_bind_function(L, "camera_config_set_x_sensitivity", smlua_func_camera_config_set_x_sensitivity);
smlua_bind_function(L, "camera_config_set_y_sensitivity", smlua_func_camera_config_set_y_sensitivity); smlua_bind_function(L, "camera_config_set_y_sensitivity", smlua_func_camera_config_set_y_sensitivity);
smlua_bind_function(L, "camera_freeze", smlua_func_camera_freeze); smlua_bind_function(L, "camera_freeze", smlua_func_camera_freeze);
smlua_bind_function(L, "camera_get_checking_surfaces", smlua_func_camera_get_checking_surfaces);
smlua_bind_function(L, "camera_is_frozen", smlua_func_camera_is_frozen); smlua_bind_function(L, "camera_is_frozen", smlua_func_camera_is_frozen);
smlua_bind_function(L, "camera_reset_overrides", smlua_func_camera_reset_overrides); smlua_bind_function(L, "camera_reset_overrides", smlua_func_camera_reset_overrides);
smlua_bind_function(L, "camera_romhack_allow_centering", smlua_func_camera_romhack_allow_centering); smlua_bind_function(L, "camera_romhack_allow_centering", smlua_func_camera_romhack_allow_centering);
smlua_bind_function(L, "camera_romhack_allow_dpad_usage", smlua_func_camera_romhack_allow_dpad_usage); smlua_bind_function(L, "camera_romhack_allow_dpad_usage", smlua_func_camera_romhack_allow_dpad_usage);
smlua_bind_function(L, "camera_set_checking_surfaces", smlua_func_camera_set_checking_surfaces);
smlua_bind_function(L, "camera_set_romhack_override", smlua_func_camera_set_romhack_override); smlua_bind_function(L, "camera_set_romhack_override", smlua_func_camera_set_romhack_override);
smlua_bind_function(L, "camera_unfreeze", smlua_func_camera_unfreeze); smlua_bind_function(L, "camera_unfreeze", smlua_func_camera_unfreeze);
@ -34668,12 +34734,14 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "allocate_mario_action", smlua_func_allocate_mario_action); smlua_bind_function(L, "allocate_mario_action", smlua_func_allocate_mario_action);
smlua_bind_function(L, "course_is_main_course", smlua_func_course_is_main_course); smlua_bind_function(L, "course_is_main_course", smlua_func_course_is_main_course);
smlua_bind_function(L, "deref_s32_pointer", smlua_func_deref_s32_pointer); smlua_bind_function(L, "deref_s32_pointer", smlua_func_deref_s32_pointer);
smlua_bind_function(L, "djui_attempting_to_open_playerlist", smlua_func_djui_attempting_to_open_playerlist);
smlua_bind_function(L, "djui_is_playerlist_open", smlua_func_djui_is_playerlist_open); smlua_bind_function(L, "djui_is_playerlist_open", smlua_func_djui_is_playerlist_open);
smlua_bind_function(L, "djui_is_popup_disabled", smlua_func_djui_is_popup_disabled); smlua_bind_function(L, "djui_is_popup_disabled", smlua_func_djui_is_popup_disabled);
smlua_bind_function(L, "djui_menu_get_font", smlua_func_djui_menu_get_font); smlua_bind_function(L, "djui_menu_get_font", smlua_func_djui_menu_get_font);
smlua_bind_function(L, "djui_popup_create_global", smlua_func_djui_popup_create_global); smlua_bind_function(L, "djui_popup_create_global", smlua_func_djui_popup_create_global);
smlua_bind_function(L, "djui_reset_popup_disabled_override", smlua_func_djui_reset_popup_disabled_override); smlua_bind_function(L, "djui_reset_popup_disabled_override", smlua_func_djui_reset_popup_disabled_override);
smlua_bind_function(L, "djui_set_popup_disabled_override", smlua_func_djui_set_popup_disabled_override); smlua_bind_function(L, "djui_set_popup_disabled_override", smlua_func_djui_set_popup_disabled_override);
smlua_bind_function(L, "get_coopnet_id", smlua_func_get_coopnet_id);
smlua_bind_function(L, "get_current_save_file_num", smlua_func_get_current_save_file_num); smlua_bind_function(L, "get_current_save_file_num", smlua_func_get_current_save_file_num);
smlua_bind_function(L, "get_date_and_time", smlua_func_get_date_and_time); smlua_bind_function(L, "get_date_and_time", smlua_func_get_date_and_time);
smlua_bind_function(L, "get_dialog_box_state", smlua_func_get_dialog_box_state); smlua_bind_function(L, "get_dialog_box_state", smlua_func_get_dialog_box_state);

View file

@ -16,6 +16,7 @@
#include "pc/chat_commands.h" #include "pc/chat_commands.h"
#include "pc/pc_main.h" #include "pc/pc_main.h"
#include "pc/djui/djui_panel.h" #include "pc/djui/djui_panel.h"
#include "pc/configfile.h"
#include "../mods/mods.h" #include "../mods/mods.h"
#include "game/print.h" #include "game/print.h"
@ -690,6 +691,36 @@ void smlua_call_event_hooks_int_params_ret_int(enum LuaHookedEventType hookType,
} }
} }
void smlua_call_event_hooks_int_params_ret_string(enum LuaHookedEventType hookType, s32 param, char** returnValue) {
lua_State* L = gLuaState;
if (L == NULL) { return; }
struct LuaHookedEvent* hook = &sHookedEvents[hookType];
for (int i = 0; i < hook->count; i++) {
s32 prevTop = lua_gettop(L);
// push the callback onto the stack
lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference[i]);
// push params
lua_pushinteger(L, param);
// call the callback
if (0 != smlua_call_hook(L, 1, 1, 0, hook->mod[i])) {
LOG_LUA("Failed to call the callback: %u", hookType);
continue;
}
// output the return value
if (lua_type(L, -1) == LUA_TSTRING) {
*returnValue = (char *)smlua_to_string(L, -1);
lua_settop(L, prevTop);
return;
} else {
lua_settop(L, prevTop);
}
}
}
void smlua_call_event_hooks_value_param(enum LuaHookedEventType hookType, int modIndex, int valueIndex) { void smlua_call_event_hooks_value_param(enum LuaHookedEventType hookType, int modIndex, int valueIndex) {
lua_State* L = gLuaState; lua_State* L = gLuaState;
if (L == NULL) { return; } if (L == NULL) { return; }
@ -1186,6 +1217,7 @@ int smlua_hook_mario_action(lua_State* L) {
lua_Integer interactionType = 0; lua_Integer interactionType = 0;
if (paramCount >= 3) { if (paramCount >= 3) {
interactionType = smlua_to_integer(L, 3); interactionType = smlua_to_integer(L, 3);
interactionType |= (1 << 31); /* INT_LUA */
if (!gSmLuaConvertSuccess) { if (!gSmLuaConvertSuccess) {
LOG_LUA_LINE("Hook Action: tried to hook invalid interactionType: %lld, %u", interactionType, gSmLuaConvertSuccess); LOG_LUA_LINE("Hook Action: tried to hook invalid interactionType: %lld, %u", interactionType, gSmLuaConvertSuccess);
return 0; return 0;

View file

@ -57,6 +57,7 @@ enum LuaHookedEventType {
HOOK_ON_ATTACK_OBJECT, HOOK_ON_ATTACK_OBJECT,
HOOK_ON_LANGUAGE_CHANGED, HOOK_ON_LANGUAGE_CHANGED,
HOOK_ON_MODS_LOADED, HOOK_ON_MODS_LOADED,
HOOK_ON_NAMETAGS_RENDER,
HOOK_MAX, HOOK_MAX,
}; };
@ -107,6 +108,7 @@ static const char* LuaHookedEventTypeName[] = {
"HOOK_ON_ATTACK_OBJECT", "HOOK_ON_ATTACK_OBJECT",
"HOOK_ON_LANGUAGE_CHANGED", "HOOK_ON_LANGUAGE_CHANGED",
"HOOK_ON_MODS_LOADED", "HOOK_ON_MODS_LOADED",
"HOOK_ON_NAMETAGS_RENDER",
"HOOK_MAX" "HOOK_MAX"
}; };
@ -170,6 +172,7 @@ bool smlua_call_event_hooks_ret_int(enum LuaHookedEventType hookType, s32* retur
void smlua_call_event_hooks_set_camera_mode_params(enum LuaHookedEventType hookType, struct Camera *c, s16 mode, s16 frames, bool* returnValue); void smlua_call_event_hooks_set_camera_mode_params(enum LuaHookedEventType hookType, struct Camera *c, s16 mode, s16 frames, bool* returnValue);
void smlua_call_event_hooks_int_params_ret_bool(enum LuaHookedEventType hookType, s16 param, bool* returnValue); void smlua_call_event_hooks_int_params_ret_bool(enum LuaHookedEventType hookType, s16 param, bool* returnValue);
void smlua_call_event_hooks_int_params_ret_int(enum LuaHookedEventType hookType, s32 param, s32* returnValue); void smlua_call_event_hooks_int_params_ret_int(enum LuaHookedEventType hookType, s32 param, s32* returnValue);
void smlua_call_event_hooks_int_params_ret_string(enum LuaHookedEventType hookType, s32 param, char** returnValue);
void smlua_call_event_hooks_value_param(enum LuaHookedEventType hookType, int modIndex, int valueIndex); void smlua_call_event_hooks_value_param(enum LuaHookedEventType hookType, int modIndex, int valueIndex);
void smlua_call_event_hooks_on_play_sound(enum LuaHookedEventType hookType, s32 soundBits, f32* pos, s32* returnValue); void smlua_call_event_hooks_on_play_sound(enum LuaHookedEventType hookType, s32 soundBits, f32* pos, s32* returnValue);
void smlua_call_event_hooks_use_act_select(enum LuaHookedEventType hookType, int value, bool* foundHook, bool* returnValue); void smlua_call_event_hooks_use_act_select(enum LuaHookedEventType hookType, int value, bool* foundHook, bool* returnValue);

View file

@ -1,4 +1,5 @@
#include "smlua.h" #include "smlua.h"
#include "smlua_cobject_map.h"
#include "pc/mods/mods.h" #include "pc/mods/mods.h"
#include "audio/external.h" #include "audio/external.h"
@ -144,126 +145,62 @@ LuaFunction smlua_to_lua_function(lua_State* L, int index) {
return luaL_ref(L, LUA_REGISTRYINDEX); return luaL_ref(L, LUA_REGISTRYINDEX);
} }
bool smlua_is_cobject(lua_State* L, int index, u16 lot) { bool smlua_is_cobject(lua_State* L, int index, UNUSED u16 lot) {
int top = lua_gettop(L); return lua_isuserdata(L, index);
bool ret = true;
s32 indexType = lua_type(L, index);
if (indexType != LUA_TTABLE) {
ret = false;
goto result;
}
lua_getfield(L, index, "_lot");
if (lua_type(L, -1) != LUA_TNUMBER) {
ret = false;
goto result;
}
enum LuaObjectType objLot = smlua_to_integer(L, -1);
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
ret = false;
goto result;
}
if (lot != objLot) {
ret = false;
goto result;
}
result:
lua_settop(L, top);
return ret;
} }
void* smlua_to_cobject(lua_State* L, int index, u16 lot) { void* smlua_to_cobject(lua_State* L, int index, u16 lot) {
s32 indexType = lua_type(L, index); s32 indexType = lua_type(L, index);
if (indexType == LUA_TNIL) { return NULL; } if (indexType == LUA_TNIL) { return NULL; }
if (indexType != LUA_TTABLE) { if (indexType != LUA_TUSERDATA) {
LOG_LUA_LINE("smlua_to_cobject received improper type '%d'", lua_type(L, index)); LOG_LUA_LINE("smlua_to_cobject received improper type '%d'", indexType);
gSmLuaConvertSuccess = false; gSmLuaConvertSuccess = false;
return 0; return 0;
} }
// get LOT CObject *cobject = luaL_checkudata(L, index, "CObject");
lua_getfield(L, index, "_lot");
enum LuaObjectType objLot = smlua_to_integer(L, -1);
lua_pop(L, 1);
if (!gSmLuaConvertSuccess) { return NULL; }
if (lot != objLot) { if (lot != cobject->lot) {
LOG_LUA_LINE("smlua_to_cobject received improper LOT. Expected '%d', received '%d'", lot, objLot); LOG_LUA_LINE("smlua_to_cobject received improper LOT. Expected '%d', received '%d'", lot, cobject->lot);
gSmLuaConvertSuccess = false; gSmLuaConvertSuccess = false;
return NULL; return NULL;
} }
// get pointer if (cobject->pointer == NULL) {
lua_getfield(L, index, "_pointer");
void* pointer = (void*)(intptr_t)smlua_to_integer(L, -1);
lua_pop(L, 1);
if (!gSmLuaConvertSuccess) { return NULL; }
// check allowlist
if (!smlua_cobject_allowlist_contains(lot, (u64)(intptr_t)pointer)) {
LOG_LUA_LINE("smlua_to_cobject received a pointer not in allow list. '%u', '%llu", lot, (u64)(intptr_t)pointer);
gSmLuaConvertSuccess = false;
return NULL;
}
if (pointer == NULL) {
LOG_LUA_LINE("smlua_to_cobject received null pointer."); LOG_LUA_LINE("smlua_to_cobject received null pointer.");
gSmLuaConvertSuccess = false; gSmLuaConvertSuccess = false;
return NULL; return NULL;
} }
gSmLuaConvertSuccess = true; gSmLuaConvertSuccess = true;
return pointer; return cobject->pointer;
} }
void* smlua_to_cpointer(lua_State* L, int index, u16 lvt) { void* smlua_to_cpointer(lua_State* L, int index, u16 lvt) {
if (lua_type(L, index) == LUA_TNIL) { s32 indexType = lua_type(L, index);
return NULL; if (indexType == LUA_TNIL) { return NULL; }
} if (indexType != LUA_TUSERDATA) {
LOG_LUA_LINE("smlua_to_cpointer received improper type '%d'", indexType);
if (lua_type(L, index) != LUA_TTABLE) {
LOG_LUA_LINE("smlua_to_cpointer received improper type '%d'", lua_type(L, index));
gSmLuaConvertSuccess = false; gSmLuaConvertSuccess = false;
return 0; return 0;
} }
// get LVT CPointer *cpointer = luaL_checkudata(L, index, "CPointer");
lua_getfield(L, index, "_lvt");
enum LuaObjectType objLvt = smlua_to_integer(L, -1);
lua_pop(L, 1);
if (!gSmLuaConvertSuccess) { return NULL; }
if (lvt != objLvt) { if (lvt != cpointer->lvt) {
LOG_LUA_LINE("smlua_to_cpointer received improper LVT. Expected '%d', received '%d'", lvt, objLvt); LOG_LUA_LINE("smlua_to_cpointer received improper LOT. Expected '%d', received '%d'", lvt, cpointer->lvt);
gSmLuaConvertSuccess = false; gSmLuaConvertSuccess = false;
return NULL; return NULL;
} }
// get pointer if (cpointer->pointer == NULL) {
lua_getfield(L, index, "_pointer");
void* pointer = (void*)(intptr_t)smlua_to_integer(L, -1);
lua_pop(L, 1);
if (!gSmLuaConvertSuccess) { return NULL; }
if (!smlua_cpointer_allowlist_contains(lvt, (u64)(intptr_t)pointer)) {
LOG_LUA_LINE("smlua_to_cpointer received a pointer not in allow list. '%u', '%llu", lvt, (u64)(intptr_t)pointer);
gSmLuaConvertSuccess = false;
return NULL;
}
if (pointer == NULL) {
LOG_LUA_LINE("smlua_to_cpointer received null pointer."); LOG_LUA_LINE("smlua_to_cpointer received null pointer.");
gSmLuaConvertSuccess = false; gSmLuaConvertSuccess = false;
return NULL; return NULL;
} }
gSmLuaConvertSuccess = true; gSmLuaConvertSuccess = true;
return pointer; return cpointer->pointer;
} }
struct LSTNetworkType smlua_to_lnt(lua_State* L, int index) { struct LSTNetworkType smlua_to_lnt(lua_State* L, int index) {
@ -418,16 +355,17 @@ void smlua_push_object(lua_State* L, u16 lot, void* p) {
return; return;
} }
// add to allowlist CObject *cobject = lua_newuserdata(L, sizeof(CObject));
smlua_cobject_allowlist_add(lot, (u64)(intptr_t) p); cobject->pointer = p;
cobject->lot = lot;
cobject->freed = false;
luaL_getmetatable(L, "CObject");
lua_setmetatable(L, -2);
// get a cobject from a function switch (lot) {
lua_getglobal(L, "_NewCObject"); // Get the function by its global name case LOT_SURFACE: {
lua_pushinteger(L, lot); smlua_pointer_user_data_add((uintptr_t) p, cobject);
lua_pushinteger(L, (u64)(intptr_t) p); }
if (lua_pcall(L, 2, 1, 0) != LUA_OK) {
LOG_ERROR("Error calling Lua function: %s\n", lua_tostring(L, -1));
} }
} }
@ -437,15 +375,12 @@ void smlua_push_pointer(lua_State* L, u16 lvt, void* p) {
return; return;
} }
smlua_cpointer_allowlist_add(lvt, (u64)(intptr_t) p); CPointer *cpointer = lua_newuserdata(L, sizeof(CPointer));
cpointer->pointer = p;
// get a cpointer from a function cpointer->lvt = lvt;
lua_getglobal(L, "_NewCPointer"); // Get the function by its global name cpointer->freed = false;
lua_pushinteger(L, lvt); luaL_getmetatable(L, "CPointer");
lua_pushinteger(L, (u64)(intptr_t) p); lua_setmetatable(L, -2);
if (lua_pcall(L, 2, 1, 0) != LUA_OK) {
LOG_ERROR("Error calling Lua function: %s\n", lua_tostring(L, -1));
}
} }
void smlua_push_integer_field(int index, const char* name, lua_Integer val) { void smlua_push_integer_field(int index, const char* name, lua_Integer val) {
@ -500,7 +435,7 @@ void smlua_push_lnt(struct LSTNetworkType* lnt) {
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
lua_Integer smlua_get_integer_field(int index, const char* name) { lua_Integer smlua_get_integer_field(int index, const char* name) {
if (lua_type(gLuaState, index) != LUA_TTABLE) { if (lua_type(gLuaState, index) != LUA_TTABLE && lua_type(gLuaState, index) != LUA_TUSERDATA) {
LOG_LUA_LINE("smlua_get_integer_field received improper type '%d'", lua_type(gLuaState, index)); LOG_LUA_LINE("smlua_get_integer_field received improper type '%d'", lua_type(gLuaState, index));
gSmLuaConvertSuccess = false; gSmLuaConvertSuccess = false;
return 0; return 0;
@ -512,7 +447,7 @@ lua_Integer smlua_get_integer_field(int index, const char* name) {
} }
lua_Number smlua_get_number_field(int index, const char* name) { lua_Number smlua_get_number_field(int index, const char* name) {
if (lua_type(gLuaState, index) != LUA_TTABLE) { if (lua_type(gLuaState, index) != LUA_TTABLE && lua_type(gLuaState, index) != LUA_TUSERDATA) {
LOG_LUA_LINE("smlua_get_number_field received improper type '%d'", lua_type(gLuaState, index)); LOG_LUA_LINE("smlua_get_number_field received improper type '%d'", lua_type(gLuaState, index));
gSmLuaConvertSuccess = false; gSmLuaConvertSuccess = false;
return 0; return 0;
@ -524,7 +459,7 @@ lua_Number smlua_get_number_field(int index, const char* name) {
} }
const char* smlua_get_string_field(int index, const char* name) { const char* smlua_get_string_field(int index, const char* name) {
if (lua_type(gLuaState, index) != LUA_TTABLE) { if (lua_type(gLuaState, index) != LUA_TTABLE && lua_type(gLuaState, index) != LUA_TUSERDATA) {
LOG_LUA_LINE("smlua_get_string_field received improper type '%d'", lua_type(gLuaState, index)); LOG_LUA_LINE("smlua_get_string_field received improper type '%d'", lua_type(gLuaState, index));
gSmLuaConvertSuccess = false; gSmLuaConvertSuccess = false;
return 0; return 0;
@ -536,7 +471,7 @@ const char* smlua_get_string_field(int index, const char* name) {
} }
LuaFunction smlua_get_function_field(int index, const char *name) { LuaFunction smlua_get_function_field(int index, const char *name) {
if (lua_type(gLuaState, index) != LUA_TTABLE) { if (lua_type(gLuaState, index) != LUA_TTABLE && lua_type(gLuaState, index) != LUA_TUSERDATA) {
LOG_LUA_LINE("smlua_get_function_field received improper type '%d'", lua_type(gLuaState, index)); LOG_LUA_LINE("smlua_get_function_field received improper type '%d'", lua_type(gLuaState, index));
gSmLuaConvertSuccess = false; gSmLuaConvertSuccess = false;
return 0; return 0;
@ -774,9 +709,37 @@ void smlua_logline(void) {
int level = 0; int level = 0;
while (lua_getstack(L, level, &info)) { while (lua_getstack(L, level, &info)) {
lua_getinfo(L, "nSl", &info); lua_getinfo(L, "nSl", &info);
LOG_LUA(" [%d] %s:%d -- %s [%s]",
level, info.short_src, info.currentline, // Get the folder and file of the crash
// in the format: "folder/file.lua"
const char* src = info.source;
int slashCount = 0;
const char* folderStart = NULL;
for (const char* p = src + strlen(src); p > src; --p) {
if (*p == '/') {
if (++slashCount == 2) {
folderStart = p + 1;
break;
}
}
}
LOG_LUA(" [%d] '%s':%d -- %s [%s]",
level, (folderStart ? folderStart : info.short_src), info.currentline,
(info.name ? info.name : "<unknown>"), info.what); (info.name ? info.name : "<unknown>"), info.what);
++level; ++level;
} }
} }
// If an object is freed that Lua has a CObject to,
// Lua is able to use-after-free that pointer
void smlua_free(void *ptr) {
if (ptr && gLuaState) {
CObject *obj = smlua_pointer_user_data_get((uintptr_t) ptr);
if (obj) {
obj->freed = true;
smlua_pointer_user_data_delete((uintptr_t) ptr);
}
}
free(ptr);
}

View file

@ -54,5 +54,6 @@ void smlua_logline(void);
void smlua_dump_stack(void); void smlua_dump_stack(void);
void smlua_dump_globals(void); void smlua_dump_globals(void);
void smlua_dump_table(int index); void smlua_dump_table(int index);
void smlua_free(void *ptr);
#endif #endif

View file

@ -166,6 +166,15 @@ void smlua_audio_utils_replace_sequence(u8 sequenceId, u8 bankId, u8 defaultVolu
static ma_engine sModAudioEngine; static ma_engine sModAudioEngine;
static struct DynamicPool *sModAudioPool; static struct DynamicPool *sModAudioPool;
static void smlua_audio_custom_init(void) {
sModAudioPool = dynamic_pool_init();
ma_result result = ma_engine_init(NULL, &sModAudioEngine);
if (result != MA_SUCCESS) {
LOG_ERROR("failed to init Miniaudio: %d", result);
}
}
static struct ModAudio* find_mod_audio(struct ModFile* file) { static struct ModAudio* find_mod_audio(struct ModFile* file) {
struct DynamicPoolNode* node = sModAudioPool->tail; struct DynamicPoolNode* node = sModAudioPool->tail;
while (node) { while (node) {
@ -178,8 +187,8 @@ static struct ModAudio* find_mod_audio(struct ModFile* file) {
} }
static bool audio_sanity_check(struct ModAudio* audio, bool isStream, const char* action) { static bool audio_sanity_check(struct ModAudio* audio, bool isStream, const char* action) {
if (audio == NULL || !audio->loaded) { if (!audio || !audio->loaded) {
LOG_LUA_LINE("Tried to %s unloaded audio %s", action, audio->isStream ? "stream" : "sample"); LOG_LUA_LINE("Tried to %s unloaded audio %s", action, audio ? (audio->isStream ? "stream" : "sample") : "(NULL)");
return false; return false;
} }
if (isStream && !audio->isStream) { if (isStream && !audio->isStream) {
@ -194,6 +203,8 @@ static bool audio_sanity_check(struct ModAudio* audio, bool isStream, const char
} }
struct ModAudio* audio_load_internal(const char* filename, bool isStream) { struct ModAudio* audio_load_internal(const char* filename, bool isStream) {
if (!sModAudioPool) { smlua_audio_custom_init(); }
// check file type // check file type
bool validFileType = false; bool validFileType = false;
const char* fileTypes[] = { ".mp3", ".aiff", ".ogg", NULL }; const char* fileTypes[] = { ".mp3", ".aiff", ".ogg", NULL };
@ -568,6 +579,7 @@ void audio_sample_play(struct ModAudio* audio, Vec3f position, f32 volume) {
} }
void audio_custom_update_volume(void) { void audio_custom_update_volume(void) {
if (!sModAudioPool) { return; }
struct DynamicPoolNode* node = sModAudioPool->tail; struct DynamicPoolNode* node = sModAudioPool->tail;
while (node) { while (node) {
struct DynamicPoolNode* prev = node->prev; struct DynamicPoolNode* prev = node->prev;
@ -587,32 +599,18 @@ void audio_custom_shutdown(void) {
while (node) { while (node) {
struct DynamicPoolNode* prev = node->prev; struct DynamicPoolNode* prev = node->prev;
struct ModAudio* audio = node->ptr; struct ModAudio* audio = node->ptr;
if (audio->isStream) {
if (audio->loaded) { ma_sound_uninit(&audio->sound); }
dynamic_pool_free(sModAudioPool, audio);
} else {
if (audio->loaded) { if (audio->loaded) {
if (audio->sampleCopiesTail) { if (!audio->isStream && audio->sampleCopiesTail) {
audio_sample_destroy_copies(audio); audio_sample_destroy_copies(audio);
} }
ma_sound_uninit(&audio->sound); ma_sound_uninit(&audio->sound);
} }
dynamic_pool_free(sModAudioPool, audio); dynamic_pool_free(sModAudioPool, audio);
}
node = prev; node = prev;
} }
dynamic_pool_free_pool(sModAudioPool); dynamic_pool_free_pool(sModAudioPool);
} }
void smlua_audio_custom_init(void) {
sModAudioPool = dynamic_pool_init();
ma_result result = ma_engine_init(NULL, &sModAudioEngine);
if (result != MA_SUCCESS) {
LOG_ERROR("failed to init Miniaudio: %d", result);
}
}
void smlua_audio_custom_deinit(void) { void smlua_audio_custom_deinit(void) {
if (sModAudioPool) { if (sModAudioPool) {
audio_custom_shutdown(); audio_custom_shutdown();

View file

@ -55,7 +55,6 @@ void audio_custom_update_volume(void);
void audio_custom_shutdown(void); void audio_custom_shutdown(void);
void smlua_audio_custom_init(void);
void smlua_audio_custom_deinit(void); void smlua_audio_custom_deinit(void);
#endif #endif

View file

@ -1,5 +1,6 @@
#include "smlua_camera_utils.h" #include "smlua_camera_utils.h"
#include "game/bettercamera.h" #include "game/bettercamera.h"
#include "game/object_list_processor.h"
static struct CameraOverride sOverrideCameraXSens = { 0 }; static struct CameraOverride sOverrideCameraXSens = { 0 };
static struct CameraOverride sOverrideCameraYSens = { 0 }; static struct CameraOverride sOverrideCameraYSens = { 0 };
@ -152,3 +153,11 @@ void camera_config_set_deceleration(u32 value) {
sOverrideCameraDegrade.override = true; sOverrideCameraDegrade.override = true;
newcam_init_settings(); newcam_init_settings();
} }
bool camera_get_checking_surfaces(void) {
return gCheckingSurfaceCollisionsForCamera;
}
void camera_set_checking_surfaces(bool value) {
gCheckingSurfaceCollisionsForCamera = value;
}

View file

@ -40,4 +40,7 @@ void camera_config_set_aggression(u32 value);
void camera_config_set_pan_level(u32 value); void camera_config_set_pan_level(u32 value);
void camera_config_set_deceleration(u32 value); void camera_config_set_deceleration(u32 value);
bool camera_get_checking_surfaces(void);
void camera_set_checking_surfaces(bool value);
#endif #endif

View file

@ -32,6 +32,10 @@
#include "pc/discord/discord.h" #include "pc/discord/discord.h"
#endif #endif
#ifdef COOPNET
#include "pc/network/coopnet/coopnet.h"
#endif
static struct DateTime sDateTime; static struct DateTime sDateTime;
/// ///
@ -91,6 +95,10 @@ bool djui_is_playerlist_open(void) {
return gDjuiPlayerList->base.visible; return gDjuiPlayerList->base.visible;
} }
bool djui_attempting_to_open_playerlist(void) {
return gAttemptingToOpenPlayerlist;
}
enum DjuiFontType djui_menu_get_font(void) { enum DjuiFontType djui_menu_get_font(void) {
return configDjuiThemeFont == 0 ? FONT_NORMAL : FONT_ALIASED; return configDjuiThemeFont == 0 ? FONT_NORMAL : FONT_ALIASED;
} }
@ -422,6 +430,18 @@ const char* get_local_discord_id(void) {
#endif #endif
} }
const char* get_coopnet_id(UNUSED s8 localIndex) {
#ifdef COOPNET
if (!gNetworkSystem || gNetworkSystem != &gNetworkSystemCoopNet) { return "-1"; }
if (localIndex < 0 || localIndex >= MAX_PLAYERS) { return "-1"; }
struct NetworkPlayer* np = &gNetworkPlayers[localIndex];
if (np == NULL || !np->connected) { return "-1"; }
return gNetworkSystem->get_id_str(np->localIndex);
#else
return "-1";
#endif
}
/// ///
f32 get_volume_master(void) { f32 get_volume_master(void) {

View file

@ -50,6 +50,7 @@ bool djui_is_popup_disabled(void);
void djui_set_popup_disabled_override(bool value); void djui_set_popup_disabled_override(bool value);
void djui_reset_popup_disabled_override(void); void djui_reset_popup_disabled_override(void);
bool djui_is_playerlist_open(void); bool djui_is_playerlist_open(void);
bool djui_attempting_to_open_playerlist(void);
enum DjuiFontType djui_menu_get_font(void); enum DjuiFontType djui_menu_get_font(void);
s8 get_dialog_box_state(void); s8 get_dialog_box_state(void);
@ -111,6 +112,7 @@ u32 get_global_timer(void);
s32 get_dialog_response(void); s32 get_dialog_response(void);
const char* get_local_discord_id(void); const char* get_local_discord_id(void);
const char* get_coopnet_id(s8 localIndex);
f32 get_volume_master(void); f32 get_volume_master(void);
f32 get_volume_level(void); f32 get_volume_level(void);

View file

@ -272,6 +272,7 @@ void smlua_text_utils_act_name_reset(s16 courseNum, u8 actNum) {
void smlua_text_utils_secret_star_replace(s16 courseNum, const char* courseName) { void smlua_text_utils_secret_star_replace(s16 courseNum, const char* courseName) {
if (courseNum <= COURSE_RR || courseNum > COURSE_COUNT) { return; } if (courseNum <= COURSE_RR || courseNum > COURSE_COUNT) { return; }
/*
s16 courseOffset = courseNum - 1; s16 courseOffset = courseNum - 1;
void **courseNameTbl = get_course_name_table(); void **courseNameTbl = get_course_name_table();
@ -282,6 +283,11 @@ void smlua_text_utils_secret_star_replace(s16 courseNum, const char* courseName)
courseNameTbl[courseOffset] = smlua_text_utils_convert(courseName); courseNameTbl[courseOffset] = smlua_text_utils_convert(courseName);
sReplacedCourseName[courseOffset] = true; sReplacedCourseName[courseOffset] = true;
*/
struct CourseName* courseActNames = gReplacedActNameTable[courseNum];
snprintf(courseActNames->name, 256, "%s", courseName + 3);
courseActNames->modIndex = gLuaActiveMod->index;
} }
void smlua_text_utils_castle_secret_stars_replace(const char* name) { void smlua_text_utils_castle_secret_stars_replace(const char* name) {

View file

@ -9,6 +9,7 @@
#include "mods_utils.h" #include "mods_utils.h"
#include "pc/utils/md5.h" #include "pc/utils/md5.h"
#include "pc/lua/smlua_hooks.h" #include "pc/lua/smlua_hooks.h"
#include "pc/loading.h"
#define MOD_CACHE_FILENAME "mod.cache" #define MOD_CACHE_FILENAME "mod.cache"
#define MOD_CACHE_VERSION 7 #define MOD_CACHE_VERSION 7
@ -255,6 +256,8 @@ void mod_cache_update(struct Mod* mod, struct ModFile* file) {
} }
void mod_cache_load(void) { void mod_cache_load(void) {
LOADING_SCREEN_MUTEX(loading_screen_set_segment_text("Loading Mod Cache"));
mod_cache_shutdown(); mod_cache_shutdown();
LOG_INFO("Loading mod cache"); LOG_INFO("Loading mod cache");

View file

@ -252,7 +252,10 @@ static void mods_load(struct Mods* mods, char* modsBasePath, UNUSED bool isUserM
} }
UNUSED f32 count = (f32) mods_count_directory(modsBasePath); UNUSED f32 count = (f32) mods_count_directory(modsBasePath);
LOADING_SCREEN_MUTEX(snprintf(gCurrLoadingSegment.str, 256, "Loading Mods In %s Mod Path:\n\\#808080\\%s", isUserModPath ? "User" : "Local", modsBasePath)); LOADING_SCREEN_MUTEX(
loading_screen_reset_progress_bar();
snprintf(gCurrLoadingSegment.str, 256, "Loading Mods In %s Mod Path:\n\\#808080\\%s", isUserModPath ? "User" : "Local", modsBasePath);
);
// iterate // iterate
char path[SYS_MAX_PATH] = { 0 }; char path[SYS_MAX_PATH] = { 0 };
@ -276,6 +279,7 @@ static void mods_load(struct Mods* mods, char* modsBasePath, UNUSED bool isUserM
} }
void mods_refresh_local(void) { void mods_refresh_local(void) {
LOADING_SCREEN_MUTEX(loading_screen_set_segment_text("Refreshing Mod Cache"));
mods_local_store_enabled(); mods_local_store_enabled();
// figure out user path // figure out user path
@ -324,7 +328,6 @@ void mods_enable(char* relativePath) {
} }
void mods_init(void) { void mods_init(void) {
LOADING_SCREEN_MUTEX(loading_screen_set_segment_text("Caching Mods"));
// load mod cache // load mod cache
mod_cache_load(); mod_cache_load();

View file

@ -18,7 +18,7 @@
#else #else
#include <sys/mman.h> #include <sys/mman.h>
#include <fcntl.h> /* For O_* constants */ #include <fcntl.h> /* For O_* constants */
#include <libc.h> #include <unistd.h>
#endif // _WIN32 #endif // _WIN32
struct LinkedMem *lm = NULL; struct LinkedMem *lm = NULL;

View file

@ -8,6 +8,7 @@
#include "game/camera.h" #include "game/camera.h"
#include "pc/lua/utils/smlua_math_utils.h" #include "pc/lua/utils/smlua_math_utils.h"
#include "pc/lua/utils/smlua_misc_utils.h" #include "pc/lua/utils/smlua_misc_utils.h"
#include "pc/lua/smlua_hooks.h"
#define NAMETAG_MAX_SCALE 0.32f #define NAMETAG_MAX_SCALE 0.32f
#define NAMETAG_DIST 7000.0f #define NAMETAG_DIST 7000.0f
@ -93,8 +94,14 @@ void nametags_render(void) {
} }
char name[MAX_CONFIG_STRING]; char name[MAX_CONFIG_STRING];
char* hookedString = NULL;
smlua_call_event_hooks_int_params_ret_string(HOOK_ON_NAMETAGS_RENDER, i, &hookedString);
if (hookedString) {
snprintf(name, MAX_CONFIG_STRING, "%s", hookedString);
} else {
snprintf(name, MAX_CONFIG_STRING, "%s", np->name); snprintf(name, MAX_CONFIG_STRING, "%s", np->name);
name_without_hex(name); name_without_hex(name);
}
Color color = { Color color = {
np->overridePalette.parts[CAP][0], np->overridePalette.parts[CAP][0],
np->overridePalette.parts[CAP][1], np->overridePalette.parts[CAP][1],

View file

@ -54,7 +54,7 @@ const char* network_get_player_text_color_string(u8 localIndex) {
extern s16 gMenuMode; extern s16 gMenuMode;
bool network_check_singleplayer_pause(void) { bool network_check_singleplayer_pause(void) {
return gMenuMode != -1 && network_player_connected_count() == 1 && mods_get_all_pausable() && !gDjuiInPlayerMenu; return gMenuMode != -1 && !gServerSettings.pauseAnywhere && network_player_connected_count() == 1 && mods_get_all_pausable() && !gDjuiInPlayerMenu;
} }
const char* network_discord_id_from_local_index(u8 localIndex) { const char* network_discord_id_from_local_index(u8 localIndex) {

View file

@ -345,7 +345,6 @@ void* main_game_init(UNUSED void* dummy) {
audio_init(); audio_init();
sound_init(); sound_init();
smlua_audio_custom_init();
network_player_init(); network_player_init();
gGameInited = true; gGameInited = true;

View file

@ -10,15 +10,9 @@ then
exit 1 exit 1
fi fi
# Make sure this is a git repository
if [ ! -d .git ]
then
echo 'Error: The current directory is not a Git repository.'
exit 1
fi
# 'git diff' is stupid and doesn't show new untracked files, so we must add them first. # 'git diff' is stupid and doesn't show new untracked files, so we must add them first.
git add . # Also make sure this is a valid git repository, throw an error otherwise ( || exit 1 )
git add . || exit 1
# Generate the patch. # Generate the patch.
git diff -p --staged > "$1" git diff -p --staged > "$1"
# Undo the 'git add'. # Undo the 'git add'.

View file

@ -744,52 +744,85 @@ static int parse_arguments(int argc, char *argv[], graphics_config *config)
if (argv[i][0] == '-') { if (argv[i][0] == '-') {
switch (argv[i][1]) { switch (argv[i][1]) {
case 'c': case 'c':
if (++i >= argc) return 0; if (++i >= argc) {
ERROR("Not enough arguments after 'c'\n");
return 0;
}
if (!parse_format(&config->pal_format, argv[i])) { if (!parse_format(&config->pal_format, argv[i])) {
ERROR("Error parsing 'c' format");
return 0; return 0;
} }
break; break;
case 'e': case 'e':
if (++i >= argc) return 0; if (++i >= argc) {
ERROR("Not enough arguments after 'e'\n");
return 0;
}
config->bin_filename = argv[i]; config->bin_filename = argv[i];
config->mode = MODE_EXPORT; config->mode = MODE_EXPORT;
break; break;
case 'f': case 'f':
if (++i >= argc) return 0; if (++i >= argc) {
ERROR("Not enough arguments after 'f'\n");
return 0;
}
if (!parse_format(&config->format, argv[i])) { if (!parse_format(&config->format, argv[i])) {
ERROR("Error parsing format after 'f'");
return 0; return 0;
} }
break; break;
case 'g': case 'g':
if (++i >= argc) return 0; if (++i >= argc) {
ERROR("Not enough arguments after 'g'\n");
return 0;
}
config->img_filename = argv[i]; config->img_filename = argv[i];
break; break;
case 'h': case 'h':
if (++i >= argc) return 0; if (++i >= argc) {
ERROR("Not enough arguments after 'h'\n");
return 0;
}
config->height = strtoul(argv[i], NULL, 0); config->height = strtoul(argv[i], NULL, 0);
break; break;
case 'i': case 'i':
if (++i >= argc) return 0; if (++i >= argc) {
ERROR("Not enough arguments after 'i'\n");
return 0;
}
config->bin_filename = argv[i]; config->bin_filename = argv[i];
config->mode = MODE_IMPORT; config->mode = MODE_IMPORT;
break; break;
case 'o': case 'o':
if (++i >= argc) return 0; if (++i >= argc) {
ERROR("Not enough arguments after 'o'\n");
return 0;
}
config->bin_offset = strtoul(argv[i], NULL, 0); config->bin_offset = strtoul(argv[i], NULL, 0);
config->bin_truncate = 0; config->bin_truncate = 0;
break; break;
case 'p': case 'p':
if (++i >= argc) return 0; if (++i >= argc) {
ERROR("Not enough arguments after 'p'\n");
return 0;
}
config->pal_filename = argv[i]; config->pal_filename = argv[i];
break; break;
case 'P': case 'P':
if (++i >= argc) return 0; if (++i >= argc) {
ERROR("Not enough arguments after 'P'\n");
return 0;
}
config->pal_offset = strtoul(argv[i], NULL, 0); config->pal_offset = strtoul(argv[i], NULL, 0);
config->pal_truncate = 0; config->pal_truncate = 0;
break; break;
case 's': case 's':
if (++i >= argc) return 0; if (++i >= argc) {
ERROR("Not enough arguments after 's'\n");
return 0;
}
if (!parse_encoding(&config->encoding, argv[i])) { if (!parse_encoding(&config->encoding, argv[i])) {
ERROR("Error parsing 's' encoding\n");
return 0; return 0;
} }
break; break;
@ -801,14 +834,19 @@ static int parse_arguments(int argc, char *argv[], graphics_config *config)
exit(0); exit(0);
break; break;
case 'w': case 'w':
if (++i >= argc) return 0; if (++i >= argc) {
ERROR("Not enough arguments after 'w'\n");
return 0;
}
config->width = strtoul(argv[i], NULL, 0); config->width = strtoul(argv[i], NULL, 0);
break; break;
default: default:
ERROR("Error parsing arguments (default)\n");
return 0; return 0;
break; break;
} }
} else { } else {
ERROR("Error parsing arguments (else case)\n");
return 0; return 0;
} }
} }
@ -819,11 +857,13 @@ static int parse_arguments(int argc, char *argv[], graphics_config *config)
static int valid_config(const graphics_config *config) static int valid_config(const graphics_config *config)
{ {
if (!config->bin_filename || !config->img_filename) { if (!config->bin_filename || !config->img_filename) {
ERROR("Invalid bin filename or img filename\n");
return 0; return 0;
} }
if (config->format.format == IMG_FORMAT_CI) { if (config->format.format == IMG_FORMAT_CI) {
if (!config->pal_filename || (config->pal_format.depth != 16) || if (!config->pal_filename || (config->pal_format.depth != 16) ||
(config->pal_format.format != IMG_FORMAT_RGBA && config->pal_format.format != IMG_FORMAT_IA)) { (config->pal_format.format != IMG_FORMAT_RGBA && config->pal_format.format != IMG_FORMAT_IA)) {
ERROR("Invalid format issue\n");
return 0; return 0;
} }
} }
@ -844,6 +884,12 @@ int main(int argc, char *argv[])
int valid = parse_arguments(argc, argv, &config); int valid = parse_arguments(argc, argv, &config);
if (!valid || !valid_config(&config)) { if (!valid || !valid_config(&config)) {
if (!valid){
ERROR("Invalid arguments were given\n");
}
else {
ERROR("The config is invalid\n");
}
print_usage(); print_usage();
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }