mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-24 21:15:12 +00:00
fixes, clean up and some new features (#259)
- Only inited `smlua_audio_utils` if needed, since there will probably be plenty of people who play without ever using mods with custom audio. - Fixed the pause anywhere setting - this ended up not being fully accurate to ex-coop, which it was originally intended to be. - Stopped regenerating dynos collision bin on start up every time therefore giving a slight start up speed boost for some people. - Added a config file setting that lets people choose to compress dynos bins on startup (disabled by default). - Fixed a warning that shows on non macs during compiling. - Properly fixed the chat box focus. - Made the public lobby rules panel "temporary". - Added a cleaner loading screen design. - Added an ex-coop theme easter egg, can only be activated from the config file. - Cleaned up the Lua traceback logging, now shows the folder and file the error occurred in, rather than the full path. - Added a way to set `gCheckingSurfaceCollisionsForCamera`, so mods can specify to surface finding functions to ignore `SURFACE_FLAG_NO_CAM_COLLISION` internally. - Rewrote the way smlua pushes CObjects/CPointers to Lua. Now using the C Lua API entirely to connect to Lua. - Fixed a use-after-free bug that could easily crash the game through Lua (explained further in one of my comments below). - Fixed a common crash in `audio_sanity_check`.
This commit is contained in:
parent
c3d3f8545a
commit
4aa2a20f72
48 changed files with 550 additions and 630 deletions
6
Makefile
6
Makefile
|
@ -66,8 +66,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
|
||||||
|
|
||||||
|
@ -122,6 +120,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
|
||||||
|
|
|
@ -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" ],
|
||||||
|
|
|
@ -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')
|
||||||
|
|
|
@ -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')
|
||||||
|
|
|
@ -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)
|
||||||
-- ...
|
-- ...
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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");
|
||||||
|
@ -754,6 +777,28 @@ void configfile_save(const char *filename) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
for (unsigned int i = 0; i < ARRAY_LEN(functionOptions); i++) {
|
for (unsigned int i = 0; i < ARRAY_LEN(functionOptions); i++) {
|
||||||
functionOptions[i].write(file);
|
functionOptions[i].write(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);
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -409,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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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*);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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, (u64)(intptr_t) cobj->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((u64)(intptr_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);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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
|
|
35
src/pc/lua/smlua_cobject_map.c
Normal file
35
src/pc/lua/smlua_cobject_map.c
Normal 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_init(void) {
|
||||||
|
smlua_pointer_user_data_shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void smlua_pointer_user_data_shutdown(void) {
|
||||||
|
hmap_clear(sPointers);
|
||||||
|
}
|
||||||
|
|
||||||
|
void smlua_pointer_user_data_add(u64 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(u64 pointer) {
|
||||||
|
if (pointer == 0) { return; }
|
||||||
|
hmap_del(sPointers, pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
CObject *smlua_pointer_user_data_get(u64 pointer) {
|
||||||
|
if (pointer == 0) { return NULL; }
|
||||||
|
return hmap_get(sPointers, pointer);
|
||||||
|
}
|
10
src/pc/lua/smlua_cobject_map.h
Normal file
10
src/pc/lua/smlua_cobject_map.h
Normal 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(u64 pointer, CObject *obj);
|
||||||
|
void smlua_pointer_user_data_delete(u64 pointer);
|
||||||
|
CObject *smlua_pointer_user_data_get(u64 pointer);
|
||||||
|
|
||||||
|
#endif
|
|
@ -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"
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
||||||
|
@ -34610,10 +34642,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);
|
||||||
|
|
||||||
|
|
|
@ -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((u64)(intptr_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((u64)(intptr_t) ptr);
|
||||||
|
if (obj) {
|
||||||
|
obj->freed = true;
|
||||||
|
smlua_pointer_user_data_delete((u64)(intptr_t) ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
@ -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 };
|
||||||
|
@ -587,32 +598,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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue