Fixed several crashes and errors found in static analysis

This commit is contained in:
MysterD 2023-05-15 01:15:20 -07:00
parent fc60571b2e
commit 2083242b66
56 changed files with 591 additions and 287 deletions

View File

@ -218,6 +218,20 @@ def translate_type_to_lua(ptype):
return ptype, None
def translate_type_to_rnd(ltype):
if 'enum ' in ltype:
ltype = 'integer'
elif '[' in ltype:
ltype = 'null'
elif '{' in ltype:
ltype = 'null'
elif '}' in ltype:
ltype = 'null'
elif 'void*' in ltype:
ltype = 'null'
return 'rnd_' + ltype.strip().replace('`', '').replace(' ', '').split('<')[-1].split('>')[0].split('(')[0].split('[')[0].split('*')[0] + '()'
def gen_comment_header(f):
comment_h = "// " + f + " //"
comment_l = "/" * len(comment_h)

View File

@ -80,7 +80,7 @@ override_allowed_functions = {
override_disallowed_functions = {
"src/audio/external.h": [ " func_" ],
"src/engine/math_util.h": [ "atan2s", "atan2f", "vec3s_sub" ],
"src/engine/surface_load.h", [ "alloc_surface_poools" ],
"src/engine/surface_load.h": [ "alloc_surface_poools" ],
"src/engine/surface_collision.h": [ " debug_", "f32_find_wall_collision" ],
"src/game/mario_actions_airborne.c": [ "^[us]32 act_.*" ],
"src/game/mario_actions_automatic.c": [ "^[us]32 act_.*" ],
@ -800,6 +800,8 @@ def process_files():
############################################################################
fuzz_from = '/home/djoslin/.local/share/sm64ex-coop/mods/test-fuzz.lua'
fuzz_to = '/home/djoslin/.local/share/sm64ex-coop/mods/test-fuzz.lua'
fuzz_functions = ""
def output_fuzz_function(fname, function):
@ -819,9 +821,10 @@ def output_fuzz_function(fname, function):
ptype = param['type']
ptype, plink = translate_type_to_lua(ptype)
if 'enum ' in ptype:
ptype = 'integer'
line += 'rnd_' + ptype.strip().replace('`', '').replace(' ', '').split('<')[-1].split('>')[0].split('(')[0] + '()'
if '(' in pid or '[' in pid or ']' in pid:
continue
line += translate_type_to_rnd(ptype)
comment += ptype
@ -836,9 +839,9 @@ def output_fuzz_function(fname, function):
def output_fuzz_file():
global fuzz_functions
with open('./autogen/fuzz_template.lua') as f:
with open(fuzz_from) as f:
file_str = f.read()
with open('/home/djoslin/.local/share/sm64ex-coop/mods/test-fuzz.lua', 'w') as f:
with open(fuzz_to, 'w') as f:
f.write(file_str.replace('-- $[FUNCS]', fuzz_functions))
############################################################################

View File

@ -83,27 +83,29 @@ override_field_invisible = {
}
override_field_immutable = {
"MarioState": [ "playerIndex", "controller", "marioObj", "marioBodyState", "statusForCamera" ],
"MarioState": [ "playerIndex", "controller", "marioObj", "marioBodyState", "statusForCamera", "area" ],
"MarioAnimation": [ "animDmaTable" ],
"ObjectNode": [ "next", "prev" ],
"Character": [ "*" ],
"NetworkPlayer": [ "*" ],
"TextureInfo": [ "*" ],
"Object": ["oSyncID", "coopFlags"],
"Object": ["oSyncID", "coopFlags", "oChainChompSegments", "oWigglerSegments", "oHauntedChairUnk100", "oTTCTreadmillBigSurface", "oTTCTreadmillSmallSurface", "bhvStackIndex", "respawnInfoType" ],
"GlobalObjectAnimations": [ "*"],
"SpawnParticlesInfo": [ "model" ],
"MarioBodyState": [ "updateTorsoTime" ],
"Area": [ "localAreaTimer", "nextSyncID" ],
"Area": [ "localAreaTimer", "nextSyncID", "unk04" ],
"Mod": [ "*" ],
"ModFile": [ "*" ],
"BassAudio": [ "*" ],
"Painting": [ "id", "imageCount", "textureType", "textureWidth", "textureHeight" ],
"SpawnInfo": [ "syncID" ],
"SpawnInfo": [ "syncID", "next", "unk18" ],
"CustomLevelInfo": [ "next" ],
"GraphNode": [ "next", "prev", "parent" ],
"GraphNode": [ "*" ],
"GraphNodeObject": [ "*" ],
"ObjectWarpNode": [ "next "],
"SpawnInfo": [ "next" ],
"Animation": [ "length" ],
"AnimationTable": [ "count" ],
"Controller": [ "controllerData", "statusData" ],
}
override_field_version_excludes = {
@ -242,9 +244,34 @@ def parse_structs(extracted):
############################################################################
def output_fuzz_struct(struct):
fuzz_from = './autogen/fuzz_template.lua'
fuzz_to = '/home/djoslin/.local/share/sm64ex-coop/mods/test-fuzz.lua'
fuzz_structs = ""
fuzz_structs_calls = ""
fuzz_template_str = None
def output_fuzz_struct_calls(struct):
sid = struct['identifier']
print('function Nuke' + sid + "(struct)")
global fuzz_template_str
if fuzz_template_str == None:
with open(fuzz_from) as f:
fuzz_template_str = f.read()
global fuzz_structs_calls
rnd_call = 'rnd_' + sid + '()'
if rnd_call in fuzz_template_str:
fuzz_structs_calls += ' function() Fuzz' + sid + '(rnd_' + sid + '()) end,\n'
else:
fuzz_structs_calls += ' -- function() Fuzz' + sid + '(rnd_' + sid + '()) end,\n'
def output_fuzz_struct(struct):
output_fuzz_struct_calls(struct)
sid = struct['identifier']
s_out = 'function Fuzz' + sid + "(struct)\n"
s_out += ' local funcs = {\n'
for field in struct['fields']:
fid, ftype, fimmutable, lvt, lot = get_struct_field_info(struct, field)
if fimmutable == 'true':
@ -252,14 +279,48 @@ def output_fuzz_struct(struct):
if sid in override_field_invisible:
if fid in override_field_invisible[sid]:
continue
if '(' in fid or '[' in fid or ']' in fid:
continue
ptype, plink = translate_type_to_lua(ftype)
rnd_line = translate_type_to_rnd(ptype)
s_out += ' function() '
if lvt == 'LVT_COBJECT':
print(' Fuzz' + ftype.replace('struct ', '') + '(struct.' + fid + ')')
s_out += 'Fuzz' + ftype.replace('struct ', '') + '(struct.' + fid + ')'
elif lvt == 'LVT_COBJECT_P':
print(' struct.' + fid + ' = nil')
s_out += 'struct.' + fid + ' = ' + rnd_line + ''
else:
print(' struct.' + fid + ' = 0')
print('end')
print('')
s_out += 'struct.' + fid + ' = ' + rnd_line + ''
s_out += ' end,\n'
s_out += ' }\n'
s_out += """
for i = #funcs, 2, -1 do
local j = math.random(i)
funcs[i], funcs[j] = funcs[j], funcs[i]
end
for k,v in pairs(funcs) do
v()
end
"""
s_out += 'end\n\n'
global fuzz_structs
fuzz_structs += s_out
def output_fuzz_file():
global fuzz_structs
global fuzz_structs_calls
with open(fuzz_from) as f:
file_str = f.read()
with open(fuzz_to, 'w') as f:
f.write(file_str.replace('-- $[STRUCTS]', fuzz_structs).replace('-- $[FUZZ-STRUCTS]', fuzz_structs_calls))
############################################################################
@ -561,6 +622,9 @@ def build_files():
doc_structs(parsed)
def_structs(parsed)
if len(sys.argv) >= 2 and sys.argv[1] == 'fuzz':
output_fuzz_file()
global total_structs
global total_fields

File diff suppressed because one or more lines are too long

View File

@ -11502,6 +11502,9 @@ COOP_OBJ_FLAG_NON_SYNC = (1 << 2)
--- @type integer
MAX_PLAYERS = 16
--- @type integer
OBJECT_MAX_BHV_STACK = 16
--- @type integer
PLAY_MODE_CHANGE_AREA = 3

View File

@ -1845,6 +1845,9 @@
--- @field public offsetY number
--- @field public radius number
--- @field public unused integer
--- @field public x number
--- @field public y number
--- @field public z number
--- @class WarpNode
--- @field public destArea integer

View File

@ -930,7 +930,7 @@ static void ParseGfxSymbol(GfxData* aGfxData, DataNode<Gfx>* aNode, Gfx*& aHead,
gDPLoadBlock(aHead++, G_TX_LOADTILE, 0, 0, (((_Arg3) * (_Arg4) + arg2_1) >> arg2_2) - 1, CALC_DXT(_Arg3, arg2_3));
gDPPipeSync(aHead++);
gDPSetTile(aHead++, _Arg1, _Arg2, ((((_Arg3) * arg2_4) + 7) >> 3), 0, G_TX_RENDERTILE, _Arg5, _Arg7, _Arg9, _ArgB, _Arg6, _Arg8, _ArgA);
gDPSetTileSize(aHead++, G_TX_RENDERTILE, 0, 0, ((_Arg3) - 1) << G_TEXTURE_IMAGE_FRAC, ((_Arg4) - 1) << G_TEXTURE_IMAGE_FRAC);
gDPSetTileSize(aHead++, G_TX_RENDERTILE, 0, 0, (((u64)_Arg3) - 1) << G_TEXTURE_IMAGE_FRAC, (((u64)_Arg4) - 1) << G_TEXTURE_IMAGE_FRAC);
return;
}

View File

@ -59,12 +59,13 @@ void DynOS_Actor_AddCustom(const SysPath &aFilename, const char *aActorName) {
// Add to custom actors
if (georef == NULL) {
DynosCustomActors().Add({ actorName, geoLayout });
DynosCustomActors().Add({ strdup(actorName), geoLayout });
georef = geoLayout;
}
// Add to list
DynOS_Actor_Valid(georef, actorGfx);
free(actorName);
}
const void *DynOS_Actor_GetLayoutFromName(const char *aActorName) {

View File

@ -25,7 +25,7 @@ static void ScanPackBins(struct PackData* aPack) {
if (length > 4 && !strncmp(&_PackEnt->d_name[length - 4], ".bin", 4)) {
String _ActorName = _PackEnt->d_name;
_ActorName[length - 4] = '\0';
DynOS_Actor_LoadFromBinary(aPack->mPath, strdup(_ActorName.begin()), _FileName, true);
DynOS_Actor_LoadFromBinary(aPack->mPath, _ActorName.begin(), _FileName, true);
}
// check for textures
@ -209,7 +209,7 @@ void DynOS_Pack_AddActor(PackData* aPackData, const char* aActorName, GfxData* a
}
s32 index = aPackData->mGfxData.Count();
aPackData->mGfxData.Add({ aActorName, aGfxData });
aPackData->mGfxData.Add({ strdup(aActorName), aGfxData });
if (aPackData->mEnabled) {
DynOS_Pack_ActivateActor(aPackData->mIndex, aPackData->mGfxData[index]);

View File

@ -113,30 +113,6 @@ s32 DynOS_String_Width(const u8 *aStr64) {
return _Width;
}
//
// Geo
//
static void _RelocateGraphNodePointers(struct GraphNode *aHead, u64 aOffset) {
struct GraphNode *_Node = aHead;
do {
if (_Node->prev) {
_Node->prev = (struct GraphNode *) ((u64) _Node->prev + aOffset);
}
if (_Node->next) {
_Node->next = (struct GraphNode *) ((u64) _Node->next + aOffset);
}
if (_Node->parent) {
_Node->parent = (struct GraphNode *) ((u64) _Node->parent + aOffset);
}
if (_Node->children) {
_Node->children = (struct GraphNode *) ((u64) _Node->children + aOffset);
_RelocateGraphNodePointers(_Node->children, aOffset);
}
_Node = _Node->next;
} while (_Node != aHead);
}
//
// Scroll Targets
//

View File

@ -1,2 +1,2 @@
#!/bin/bash
make clean ; scan-build -disable-checker deadcode.DeadStores make BETTERCAMERA=1 NODRAWINGDISTANCE=1 DEBUG=1 IMMEDIATELOAD=1 DEVELOPMENT=1 STRICT=1 EXTRA_INCLUDES="-IC:/msys64/mingw64/include" -j
make clean ; scan-build -disable-checker deadcode.DeadStores make DEBUG=1 DEVELOPMENT=1 COMPILER=clang EXTRA_INCLUDES="-IC:/msys64/mingw64/include" -j

View File

@ -4072,6 +4072,7 @@
- COOP_OBJ_FLAG_NETWORK
- COOP_OBJ_FLAG_NON_SYNC
- MAX_PLAYERS
- OBJECT_MAX_BHV_STACK
- PLAY_MODE_CHANGE_AREA
- PLAY_MODE_CHANGE_LEVEL
- PLAY_MODE_FRAME_ADVANCE

View File

@ -810,13 +810,13 @@
| Field | Type | Access |
| ----- | ---- | ------ |
| children | [GraphNode](structs.md#GraphNode) | |
| extraFlags | `integer` | |
| flags | `integer` | |
| children | [GraphNode](structs.md#GraphNode) | read-only |
| extraFlags | `integer` | read-only |
| flags | `integer` | read-only |
| next | [GraphNode](structs.md#GraphNode) | read-only |
| parent | [GraphNode](structs.md#GraphNode) | read-only |
| prev | [GraphNode](structs.md#GraphNode) | read-only |
| type | `integer` | |
| type | `integer` | read-only |
[:arrow_up_small:](#)
@ -826,32 +826,32 @@
| Field | Type | Access |
| ----- | ---- | ------ |
| activeAreaIndex | `integer` | |
| activeAreaIndex | `integer` | read-only |
| angle | [Vec3s](structs.md#Vec3s) | read-only |
| animInfo | [AnimInfo](structs.md#AnimInfo) | read-only |
| areaIndex | `integer` | |
| areaIndex | `integer` | read-only |
| cameraToObject | [Vec3f](structs.md#Vec3f) | read-only |
| disableAutomaticShadowPos | `boolean` | |
| disableAutomaticShadowPos | `boolean` | read-only |
| node | [GraphNode](structs.md#GraphNode) | read-only |
| pos | [Vec3f](structs.md#Vec3f) | read-only |
| prevAngle | [Vec3s](structs.md#Vec3s) | read-only |
| prevPos | [Vec3f](structs.md#Vec3f) | read-only |
| prevScale | [Vec3f](structs.md#Vec3f) | read-only |
| prevScaleTimestamp | `integer` | |
| prevScaleTimestamp | `integer` | read-only |
| prevShadowPos | [Vec3f](structs.md#Vec3f) | read-only |
| prevShadowPosTimestamp | `integer` | |
| prevShadowPosTimestamp | `integer` | read-only |
| prevThrowMatrix | `Mat4` | read-only |
| prevThrowMatrixTimestamp | `integer` | |
| prevTimestamp | `integer` | |
| prevThrowMatrixTimestamp | `integer` | read-only |
| prevTimestamp | `integer` | read-only |
| scale | [Vec3f](structs.md#Vec3f) | read-only |
| shadowInvisible | `boolean` | |
| shadowInvisible | `boolean` | read-only |
| shadowPos | [Vec3f](structs.md#Vec3f) | read-only |
| sharedChild | [GraphNode](structs.md#GraphNode) | |
| skipInViewCheck | `boolean` | |
| skipInterpolationTimestamp | `integer` | |
| throwMatrix | `Pointer` <`Mat4`> | |
| throwMatrixPrev | `Pointer` <`Mat4`> | |
| unk4C | [SpawnInfo](structs.md#SpawnInfo) | |
| sharedChild | [GraphNode](structs.md#GraphNode) | read-only |
| skipInViewCheck | `boolean` | read-only |
| skipInterpolationTimestamp | `integer` | read-only |
| throwMatrix | `Pointer` <`Mat4`> | read-only |
| throwMatrixPrev | `Pointer` <`Mat4`> | read-only |
| unk4C | [SpawnInfo](structs.md#SpawnInfo) | read-only |
[:arrow_up_small:](#)
@ -1046,7 +1046,7 @@
| actionTimer | `integer` | |
| angleVel | [Vec3s](structs.md#Vec3s) | read-only |
| animation | [MarioAnimation](structs.md#MarioAnimation) | |
| area | [Area](structs.md#Area) | |
| area | [Area](structs.md#Area) | read-only |
| bounceSquishTimer | `integer` | |
| bubbleObj | [Object](structs.md#Object) | |
| cap | `integer` | |
@ -1220,7 +1220,7 @@
| areaTimerType | [enum AreaTimerType](constants.md#enum-AreaTimerType) | |
| behavior | `Pointer` <`BehaviorScript`> | read-only |
| bhvDelayTimer | `integer` | |
| bhvStackIndex | `integer` | |
| bhvStackIndex | `integer` | read-only |
| collidedObjInteractTypes | `integer` | |
| collisionData | `Pointer` <`Collision`> | |
| coopFlags | `integer` | read-only |
@ -1239,7 +1239,7 @@
| parentObj | [Object](structs.md#Object) | |
| platform | [Object](structs.md#Object) | |
| prevObj | [Object](structs.md#Object) | |
| respawnInfoType | `integer` | |
| respawnInfoType | `integer` | read-only |
| setHome | `integer` | |
| transform | `Mat4` | read-only |
| unused1 | `integer` | |
@ -1467,7 +1467,7 @@
| oCannonPlayerIndex | `integer` | |
| oCapUnkF4 | `integer` | |
| oCapUnkF8 | `integer` | |
| oChainChompSegments | [ChainSegment](structs.md#ChainSegment) | |
| oChainChompSegments | [ChainSegment](structs.md#ChainSegment) | read-only |
| oChainChompMaxDistFromPivotPerChainPart | `number` | |
| oChainChompMaxDistBetweenChainParts | `number` | |
| oChainChompDistToPivot | `number` | |
@ -1961,7 +1961,7 @@
| oStrongWindParticlePenguinObj | [Object](structs.md#Object) | |
| oWhompShakeVal | `integer` | |
| oWigglerFallThroughFloorsHeight | `number` | |
| oWigglerSegments | [ChainSegment](structs.md#ChainSegment) | |
| oWigglerSegments | [ChainSegment](structs.md#ChainSegment) | read-only |
| oWigglerWalkAnimSpeed | `number` | |
| oWigglerSquishSpeed | `number` | |
| oWigglerTimeUntilRandomTurn | `integer` | |
@ -2228,8 +2228,8 @@
| next | [SpawnInfo](structs.md#SpawnInfo) | read-only |
| startAngle | [Vec3s](structs.md#Vec3s) | read-only |
| startPos | [Vec3s](structs.md#Vec3s) | read-only |
| syncID | `integer` | |
| unk18 | [GraphNode](structs.md#GraphNode) | |
| syncID | `integer` | read-only |
| unk18 | [GraphNode](structs.md#GraphNode) | read-only |
[:arrow_up_small:](#)
@ -2407,6 +2407,9 @@
| offsetY | `number` | |
| radius | `number` | |
| unused | `integer` | |
| x | `number` | |
| y | `number` | |
| z | `number` | |
[:arrow_up_small:](#)

39
grind.log Normal file
View File

@ -0,0 +1,39 @@
==899764== exp-sgcheck, a stack and global array overrun detector
==899764== NOTE: This is an Experimental-Class Valgrind Tool
==899764== Copyright (C) 2003-2017, and GNU GPL'd, by OpenWorks Ltd et al.
==899764== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==899764== Command: ./build/us_pc/sm64.us.f3dex2e
==899764== Parent PID: 10640
==899764==
--899764-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x93
--899764-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x93
--899764-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x93
--899764-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x93
--899764-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x93
--899764-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x93
--899764-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x93
--899764-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x93
parse DIE(readdwarf3.c:3123): confused by:
<0><19f35>: Abbrev Number: 1 (DW_TAG_compile_unit)
DW_AT_producer : (indirect string, offset: 0x6663): clang LLVM (rustc version 1.39.0-nightly (6ef275e6c 2019-09-24))
DW_AT_language : 28
DW_AT_name : (indirect string, offset: 0x66a4): src/libstd/lib.rs
DW_AT_stmt_list : 46860
DW_AT_comp_dir : (indirect string, offset: 0x66b6): /rustc/6ef275e6c3cb1384ec78128eceeb4963ff788dca/
DW_AT_??? : 1
DW_AT_low_pc : 0x0
DW_AT_ranges : 240976
parse_type_DIE:
--899764-- WARNING: Serious error when reading debug info
--899764-- When reading debug info from /home/djoslin/sm64ex-coop/lib/discordsdk/libdiscord_game_sdk.so:
--899764-- confused by the above DIE
==899764== Warning: noted but unhandled ioctl 0x6444 with no size/direction hints.
==899764== This could cause spurious value errors to appear.
==899764== See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
==899764== Warning: unimplemented fcntl command: 1033
==899764== Warning: unimplemented fcntl command: 1033
==899764== Warning: bogus DWARF3 info: overlapping stack blocks
==899764== Warning: bogus DWARF3 info: overlapping stack blocks
==899764== Warning: bogus DWARF3 info: overlapping stack blocks
==899764== Further instances of this message will not be shown

View File

@ -19,6 +19,8 @@
#define BAD_RETURN(cmd) cmd
#endif
#define OBJECT_MAX_BHV_STACK 16
struct Controller
{
/*0x00*/ s16 rawStickX; //
@ -211,7 +213,7 @@ struct Object
/*0x1C8*/ u32 unused1;
/*0x1CC*/ const BehaviorScript *curBhvCommand;
/*0x1D0*/ u32 bhvStackIndex;
/*0x1D4*/ uintptr_t bhvStack[8];
/*0x1D4*/ uintptr_t bhvStack[OBJECT_MAX_BHV_STACK];
/*0x1F4*/ s16 bhvDelayTimer;
/*0x1F6*/ s16 respawnInfoType;
/*0x1F8*/ f32 hitboxRadius;

View File

@ -128,18 +128,20 @@ void obj_update_gfx_pos_and_angle(struct Object *obj) {
// Push the address of a behavior command to the object's behavior stack.
static void cur_obj_bhv_stack_push(uintptr_t bhvAddr) {
gCurrentObject->bhvStack[gCurrentObject->bhvStackIndex] = bhvAddr;
if (gCurrentObject->bhvStackIndex < OBJECT_MAX_BHV_STACK) {
gCurrentObject->bhvStack[gCurrentObject->bhvStackIndex] = bhvAddr;
}
gCurrentObject->bhvStackIndex++;
if (gCurrentObject->bhvStackIndex >= 8) { gCurrentObject->bhvStackIndex = 8 - 1; }
}
// Retrieve the last behavior command address from the object's behavior stack.
static uintptr_t cur_obj_bhv_stack_pop(void) {
uintptr_t bhvAddr;
uintptr_t bhvAddr = 0;
gCurrentObject->bhvStackIndex--;
if (gCurrentObject->bhvStackIndex >= 8) { gCurrentObject->bhvStackIndex = 0; }
bhvAddr = gCurrentObject->bhvStack[gCurrentObject->bhvStackIndex];
if (gCurrentObject->bhvStackIndex < OBJECT_MAX_BHV_STACK) {
bhvAddr = gCurrentObject->bhvStack[gCurrentObject->bhvStackIndex];
}
return bhvAddr;
}
@ -1287,7 +1289,7 @@ void cur_obj_update(void) {
// catch up the timer in total loop increments
if (gCurrentObject->areaTimerType == AREA_TIMER_TYPE_LOOP) {
u32 difference = (gNetworkAreaTimer - gCurrentObject->areaTimer);
if (difference >= gCurrentObject->areaTimerDuration) {
if (difference >= gCurrentObject->areaTimerDuration && gCurrentObject->areaTimerDuration) {
u32 catchup = difference / gCurrentObject->areaTimerDuration;
catchup *= gCurrentObject->areaTimerDuration;
gCurrentObject->areaTimer += catchup;

View File

@ -196,7 +196,7 @@ void *vec3f_rotate_zxy(Vec3f dest, Vec3s rotate) {
dest[1] = v[0] * (cx * sz) + v[1] * (cx * cz) + v[2] * -sx;
dest[2] = v[0] * ((cysz * sx) - sycz) + v[1] * ((cycz * sx) + sysz) + v[2] * (cx * cy);
return &dest;
return dest;
}
#pragma GCC diagnostic pop

View File

@ -17,7 +17,9 @@
struct WallCollisionData
{
/*0x00*/ f32 x, y, z;
/*0x00*/ f32 x;
/*????*/ f32 y;
/*????*/ f32 z;
/*0x0C*/ f32 offsetY;
/*0x10*/ f32 radius;
/*0x14*/ s16 unused;

View File

@ -187,6 +187,7 @@ void bobomb_free_loop(void) {
}
void bobomb_held_loop(void) {
if (o->heldByPlayerIndex >= MAX_PLAYERS) { return; }
o->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
cur_obj_init_animation(1);
struct Object* player = gMarioStates[o->heldByPlayerIndex].marioObj;

View File

@ -1223,6 +1223,7 @@ void bowser_free_update(void) {
}
void bowser_held_update(void) {
if (o->heldByPlayerIndex >= MAX_PLAYERS) { return; }
struct MarioState* marioState = &gMarioStates[o->heldByPlayerIndex];
struct Object* player = marioState->marioObj;

View File

@ -53,7 +53,7 @@ void opened_cannon_act_4(void) {
o->oPosZ += (f32)((o->oTimer / 2 & 1) - 0.5) * 4;
o->oAction = 6;
}
if (o->oCannonPlayerIndex != 0 && o->oCannonPlayerIndex < MAX_PLAYERS) {
if (o->oCannonPlayerIndex > 0 && o->oCannonPlayerIndex < MAX_PLAYERS) {
struct MarioState* controlledBy = &gMarioStates[o->oCannonPlayerIndex];
if (controlledBy && controlledBy->marioObj != NULL) {
controlledBy->marioObj->oMarioCannonObjectYaw = o->oMoveAngleYaw;

View File

@ -11,7 +11,7 @@ void bhv_punch_tiny_triangle_loop(void) {
if (o->oTimer == 0) {
sp1E = o->oMoveAngleYaw;
o->oCollisionParticleUnkF4 = 1.28f;
cur_obj_set_pos_relative(o->parentObj, 0.0f, 60.0f, 100.0f);
if (o->parentObj) { cur_obj_set_pos_relative(o->parentObj, 0.0f, 60.0f, 100.0f); }
o->oMoveAngleYaw = sp1E;
}
cur_obj_move_using_fvel_and_gravity();
@ -29,7 +29,7 @@ void bhv_punch_tiny_triangle_init(void) {
for (i = 0; i < 6; i++) {
triangle = spawn_object(o, MODEL_DIRT_ANIMATION, bhvPunchTinyTriangle);
if (triangle == NULL) { continue; }
triangle->oMoveAngleYaw = o->parentObj->oMoveAngleYaw + D_8032F2CC[2 * i] + 0x8000;
if (o->parentObj) { triangle->oMoveAngleYaw = o->parentObj->oMoveAngleYaw + D_8032F2CC[2 * i] + 0x8000; }
triangle->oVelY = sins(D_8032F2CC[2 * i + 1]) * 25.0f;
triangle->oForwardVel = coss(D_8032F2CC[2 * i + 1]) * 25.0f;
}
@ -40,7 +40,7 @@ void bhv_wall_tiny_star_particle_loop(void) {
if (o->oTimer == 0) {
sp1E = o->oMoveAngleYaw;
o->oCollisionParticleUnkF4 = 0.28f;
cur_obj_set_pos_relative(o->parentObj, 0.0f, 30.0f, 110.0f);
if (o->parentObj) { cur_obj_set_pos_relative(o->parentObj, 0.0f, 30.0f, 110.0f); }
o->oMoveAngleYaw = sp1E;
}
cur_obj_move_using_fvel_and_gravity();

View File

@ -30,7 +30,7 @@ u8 door_allow_walk_through(void) {
}
s32 cur = o->header.gfx.animInfo.animFrame;
s32 max = o->header.gfx.animInfo.curAnim->loopEnd - 2;
s32 max = o->header.gfx.animInfo.curAnim ? (o->header.gfx.animInfo.curAnim->loopEnd - 2) : 1;
s32 min = max / 4;
// make non-solid immediately for local actions so the camera doesn't glitch out

View File

@ -50,7 +50,7 @@ static void fly_guy_act_idle(void) {
o->oFlyGuyIdleTimer = 0;
o->oAction = FLY_GUY_ACT_APPROACH_MARIO;
} else {
o->oFlyGuyUnusedJitter = o->oMoveAngleYaw + sFlyGuyJitterAmounts[o->oFlyGuyIdleTimer];
o->oFlyGuyUnusedJitter = o->oMoveAngleYaw + BHV_ARR(sFlyGuyJitterAmounts, o->oFlyGuyIdleTimer, s16);
o->oFlyGuyIdleTimer += 1;
}
}

View File

@ -92,6 +92,7 @@ void hoot_free_step(s16 fastOscY, s32 speed) {
}
void hoot_player_set_yaw(void) {
if (o->heldByPlayerIndex >= MAX_PLAYERS) { return; }
struct MarioState* marioState = &gMarioStates[o->heldByPlayerIndex];
s16 stickX = marioState->controller->rawStickX;
s16 stickY = marioState->controller->rawStickY;
@ -147,7 +148,9 @@ void hoot_surface_collision(f32 xPrev, UNUSED f32 yPrev, f32 zPrev) {
o->oPosY = hitbox.y;
o->oPosZ = hitbox.z;
gMarioStates[o->heldByPlayerIndex].marioObj->oInteractStatus |= INT_STATUS_MARIO_UNK7; /* bit 7 */
if (o->heldByPlayerIndex < MAX_PLAYERS) {
gMarioStates[o->heldByPlayerIndex].marioObj->oInteractStatus |= INT_STATUS_MARIO_UNK7; /* bit 7 */
}
}
floorY = find_floor_height_and_data(o->oPosX, o->oPosY, o->oPosZ, &sp44);
@ -223,8 +226,11 @@ void hoot_action_loop(void) {
hoot_carry_step(20, xPrev, zPrev);
if (o->oTimer >= 61)
gMarioStates[o->heldByPlayerIndex].marioObj->oInteractStatus |= INT_STATUS_MARIO_UNK7; /* bit 7 */
if (o->oTimer >= 61) {
if (o->heldByPlayerIndex < MAX_PLAYERS) {
gMarioStates[o->heldByPlayerIndex].marioObj->oInteractStatus |= INT_STATUS_MARIO_UNK7; /* bit 7 */
}
}
break;
}

View File

@ -55,7 +55,9 @@ void bhv_jumping_box_loop(void) {
jumping_box_free_update();
break;
case HELD_HELD:
obj_copy_pos(o, gMarioStates[o->heldByPlayerIndex].marioObj);
if (o->heldByPlayerIndex < MAX_PLAYERS) {
obj_copy_pos(o, gMarioStates[o->heldByPlayerIndex].marioObj);
}
cur_obj_set_model(smlua_model_util_load(E_MODEL_BREAKABLE_BOX_SMALL));
cur_obj_unrender_and_reset_state(-1, 0);
break;

View File

@ -16,11 +16,13 @@ void koopa_shell_spawn_water_drop(void) {
UNUSED s32 unused;
struct Object *drop;
spawn_object(o, MODEL_WAVE_TRAIL, bhvObjectWaveTrail);
if (gMarioStates[o->heldByPlayerIndex].forwardVel > 10.0f) {
drop = spawn_object_with_scale(o, MODEL_WHITE_PARTICLE_SMALL, bhvWaterDroplet, 1.5f);
if (drop != NULL) {
drop->oVelY = random_float() * 30.0f;
obj_translate_xz_random(drop, 110.0f);
if (o->heldByPlayerIndex < MAX_PLAYERS) {
if (gMarioStates[o->heldByPlayerIndex].forwardVel > 10.0f) {
drop = spawn_object_with_scale(o, MODEL_WHITE_PARTICLE_SMALL, bhvWaterDroplet, 1.5f);
if (drop != NULL) {
drop->oVelY = random_float() * 30.0f;
obj_translate_xz_random(drop, 110.0f);
}
}
}
}
@ -79,28 +81,30 @@ void bhv_koopa_shell_loop(void) {
koopa_shell_spawn_sparkles(10.0f);
break;
case 1:
player = gMarioStates[o->heldByPlayerIndex].marioObj;
if (player) {
obj_copy_pos(o, player);
}
sp34 = cur_obj_update_floor_height_and_get_floor();
if (absf(find_water_level(o->oPosX, o->oPosZ) - o->oPosY) < 10.0f)
koopa_shell_spawn_water_drop();
else if (5.0f > absf(o->oPosY - o->oFloorHeight)) {
if (sp34 != NULL && sp34->type == 1)
bhv_koopa_shell_flame_spawn();
else
if (o->heldByPlayerIndex < MAX_PLAYERS) {
player = gMarioStates[o->heldByPlayerIndex].marioObj;
if (player) {
obj_copy_pos(o, player);
}
sp34 = cur_obj_update_floor_height_and_get_floor();
if (absf(find_water_level(o->oPosX, o->oPosZ) - o->oPosY) < 10.0f)
koopa_shell_spawn_water_drop();
else if (5.0f > absf(o->oPosY - o->oFloorHeight)) {
if (sp34 != NULL && sp34->type == 1)
bhv_koopa_shell_flame_spawn();
else
koopa_shell_spawn_sparkles(10.0f);
} else
koopa_shell_spawn_sparkles(10.0f);
} else
koopa_shell_spawn_sparkles(10.0f);
if (player) {
o->oFaceAngleYaw = player->oMoveAngleYaw;
}
if (o->oInteractStatus & INT_STATUS_STOP_RIDING) {
o->heldByPlayerIndex = 0;
obj_mark_for_deletion(o);
spawn_mist_particles();
o->oAction = 0;
if (player) {
o->oFaceAngleYaw = player->oMoveAngleYaw;
}
if (o->oInteractStatus & INT_STATUS_STOP_RIDING) {
o->heldByPlayerIndex = 0;
obj_mark_for_deletion(o);
spawn_mist_particles();
o->oAction = 0;
}
}
break;
}

View File

@ -152,7 +152,7 @@ void bhv_mips_act_follow_path(void) {
// Retrieve current waypoint.
pathBase = segmented_to_virtual(sMipsPaths[0]);
s32 length = get_trajectory_length((Trajectory*)pathBase);
if (o->oMipsStartWaypointIndex >= length) { return; }
if (o->oMipsStartWaypointIndex >= length || o->oMipsStartWaypointIndex < 0) { return; }
waypoint = segmented_to_virtual(pathBase[o->oMipsStartWaypointIndex]);
// Set start waypoint and follow the path from there.
@ -267,6 +267,7 @@ static u8 bhv_mips_held_continue_dialog(void) {
void bhv_mips_held(void) {
s16 dialogID;
if (o->heldByPlayerIndex >= MAX_PLAYERS) { return; }
struct Object* player = gMarioStates[o->heldByPlayerIndex].marioObj;
o->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;

View File

@ -37,7 +37,7 @@ static s16 sTTC2DRotatorTimeBetweenTurns[][4] = {
* Init function for bhvTTC2DRotator.
*/
void bhv_ttc_2d_rotator_init(void) {
if (o->oBehParams2ndByte < 2 && gTTCSpeedSetting < 4) {
if (o->oBehParams2ndByte >= 0 && o->oBehParams2ndByte < 2 && gTTCSpeedSetting >= 0 && gTTCSpeedSetting < 4) {
o->oTTC2DRotatorMinTimeUntilNextTurn = sTTC2DRotatorTimeBetweenTurns[o->oBehParams2ndByte][gTTCSpeedSetting];
o->oTTC2DRotatorIncrement = o->oTTC2DRotatorSpeed = sTTC2DRotatorSpeeds[o->oBehParams2ndByte];
}

View File

@ -67,12 +67,12 @@ void bhv_ttc_pit_block_update(void) {
if (clamp_f32(&o->oPosY, o->oHomeY, o->oTTCPitBlockPeakY)) {
o->oTTCPitBlockDir = o->oTTCPitBlockDir ^ 0x1;
if (gTTCSpeedSetting < 4) {
if (gTTCSpeedSetting >= 0 && gTTCSpeedSetting < 4) {
if ((o->oTTCPitBlockWaitTime = sTTCPitBlockProperties[gTTCSpeedSetting][o->oTTCPitBlockDir & 0x1].waitTime) < 0) {
o->oTTCPitBlockWaitTime = random_mod_offset(10, 20, 6);
}
if (o->oTTCPitBlockDir < 2) {
if (o->oTTCPitBlockDir >= 0 && o->oTTCPitBlockDir < 2) {
o->oVelY = sTTCPitBlockProperties[gTTCSpeedSetting][o->oTTCPitBlockDir].speed;
}
}

View File

@ -70,5 +70,7 @@ void bhv_ttc_treadmill_update(void) {
}
}
o->oForwardVel = 0.084f * *o->oTTCTreadmillBigSurface;
if (o->oTTCTreadmillBigSurface) {
o->oForwardVel = 0.084f * *o->oTTCTreadmillBigSurface;
}
}

View File

@ -167,9 +167,11 @@ void bhv_tuxies_mother_loop(void) {
}
void small_penguin_dive_with_mario(void) {
if (mario_is_dive_sliding(&gMarioStates[o->heldByPlayerIndex])) {
o->oSmallPenguinUnk100 = o->oAction;
o->oAction = 3;
if (o->heldByPlayerIndex < MAX_PLAYERS) {
if (mario_is_dive_sliding(&gMarioStates[o->heldByPlayerIndex])) {
o->oSmallPenguinUnk100 = o->oAction;
o->oAction = 3;
}
}
}
@ -212,9 +214,11 @@ void small_penguin_act_3(void) {
if (o->oTimer == 6)
cur_obj_play_sound_2(SOUND_OBJ_BABY_PENGUIN_DIVE);
cur_obj_init_animation_with_sound(1);
if (o->oTimer > 25)
if (!mario_is_dive_sliding(&gMarioStates[o->heldByPlayerIndex]))
if (o->oTimer > 25) {
if (o->heldByPlayerIndex < MAX_PLAYERS && !mario_is_dive_sliding(&gMarioStates[o->heldByPlayerIndex])) {
o->oAction = 4;
}
}
}
}
@ -304,15 +308,18 @@ void bhv_small_penguin_loop(void) {
break;
case HELD_HELD:
cur_obj_unrender_and_reset_state(0, 0);
if (cur_obj_has_behavior(bhvPenguinBaby))
if (cur_obj_has_behavior(bhvPenguinBaby)) {
obj_set_behavior(o, bhvSmallPenguin);
obj_copy_pos(o, gMarioStates[o->heldByPlayerIndex].marioObj);
if (gGlobalTimer % 30 == 0)
}
if (o->heldByPlayerIndex < MAX_PLAYERS) {
obj_copy_pos(o, gMarioStates[o->heldByPlayerIndex].marioObj);
if (gGlobalTimer % 30 == 0)
#ifndef VERSION_JP
play_sound(SOUND_OBJ2_BABY_PENGUIN_YELL, gMarioStates[o->heldByPlayerIndex].marioObj->header.gfx.cameraToObject);
play_sound(SOUND_OBJ2_BABY_PENGUIN_YELL, gMarioStates[o->heldByPlayerIndex].marioObj->header.gfx.cameraToObject);
#else
play_sound(SOUND_OBJ2_BABY_PENGUIN_YELL, o->header.gfx.cameraToObject);
play_sound(SOUND_OBJ2_BABY_PENGUIN_YELL, o->header.gfx.cameraToObject);
#endif
}
break;
case HELD_THROWN:
cur_obj_get_thrown_or_placed(0, 0, 0);

View File

@ -542,6 +542,7 @@ static u8 cage_ukiki_held_default_continue_dialog(void) {
* Called by the main behavior function for the cage ukiki whenever it is held.
*/
void cage_ukiki_held_loop(void) {
if (o->heldByPlayerIndex >= MAX_PLAYERS) { return; }
struct MarioState* heldByMario = &gMarioStates[o->heldByPlayerIndex];
if (heldByMario->playerIndex != 0) { return; }
@ -593,6 +594,7 @@ u8 hat_ukiki_held_loop_2(void) { return o->oHeldState == HELD_HELD && o->oUkikiT
* Called by the main behavior function for the cap ukiki whenever it is held.
*/
void cap_ukiki_held_loop(void) {
if (o->heldByPlayerIndex >= MAX_PLAYERS) { return; }
struct MarioState* heldByMario = &gMarioStates[o->heldByPlayerIndex];
if (heldByMario->playerIndex != 0) { return; }
@ -664,7 +666,6 @@ void bhv_ukiki_init(void) {
* dependent on the held state and whick ukiki it is (cage or cap).
*/
void bhv_ukiki_loop(void) {
struct Object* heldByPlayer = gMarioStates[o->heldByPlayerIndex].marioObj;
switch(o->oHeldState) {
case HELD_FREE:
@ -675,7 +676,10 @@ void bhv_ukiki_loop(void) {
case HELD_HELD:
cur_obj_unrender_and_reset_state(UKIKI_ANIM_HELD, 0);
obj_copy_pos(o, heldByPlayer);
if (o->heldByPlayerIndex < MAX_PLAYERS) {
struct Object* heldByPlayer = gMarioStates[o->heldByPlayerIndex].marioObj;
obj_copy_pos(o, heldByPlayer);
}
if (o->oBehParams2ndByte == UKIKI_CAP) {
cap_ukiki_held_loop();

View File

@ -71,7 +71,9 @@ void bhv_small_water_wave_loop(void) {
}
void bhv_bubble_player_loop(void) {
if (o->heldByPlayerIndex >= MAX_PLAYERS) { return; }
struct MarioState* marioState = &gMarioStates[o->heldByPlayerIndex];
if (!marioState) { return; }
// set position
o->oPosX = marioState->pos[0];

View File

@ -270,7 +270,6 @@ struct BehaviorValues gBehaviorValues = { 0 };
struct PaintingValues gDefaultPaintingValues = {
.cotmc_painting = &cotmc_painting,
.bob_painting = &bob_painting,
.ccm_painting = &ccm_painting,
.wf_painting = &wf_painting,
@ -285,7 +284,6 @@ struct PaintingValues gDefaultPaintingValues = {
.ttc_painting = &ttc_painting,
.sl_painting = &sl_painting,
.thi_huge_painting = &thi_huge_painting,
.ttm_slide_painting = &ttm_slide_painting,
};

View File

@ -614,6 +614,7 @@ void warp_credits(void) {
}
void check_instant_warp(void) {
if (!gCurrentArea) { return; }
s16 cameraAngle;
struct Surface *floor;
@ -628,8 +629,7 @@ void check_instant_warp(void) {
if ((floor = gMarioStates[0].floor) != NULL) {
s32 index = floor->type - SURFACE_INSTANT_WARP_1B;
if (index >= INSTANT_WARP_INDEX_START && index < INSTANT_WARP_INDEX_STOP
&& gCurrentArea->instantWarps != NULL) {
if (index >= INSTANT_WARP_INDEX_START && index < INSTANT_WARP_INDEX_STOP && gCurrentArea->instantWarps != NULL) {
struct InstantWarp *warp = &gCurrentArea->instantWarps[index];
if (warp->id != 0) {
if (gRejectInstantWarp > 0) {
@ -1161,7 +1161,7 @@ static void start_demo(void) {
gChangeLevel = gCurrLevelNum;
}
if (sDemoNumber <= 6 || sDemoNumber > -1) {
if (sDemoNumber <= 6 && sDemoNumber > -1) {
gCurrDemoInput = NULL;
alloc_anim_dma_table(&gDemo, gDemoInputs, gDemoTargetAnim);
load_patchable_table(&gDemo, sDemoNumber);
@ -1201,7 +1201,7 @@ s32 play_mode_normal(void) {
}
} else {
if (gDjuiInMainMenu && gCurrDemoInput == NULL && configMenuDemos && !gInPlayerMenu) {
if ((++gDemoCountdown) == PRESS_START_DEMO_TIMER && (find_demo_number() && (sDemoNumber <= 6 || sDemoNumber > -1))) {
if ((++gDemoCountdown) == PRESS_START_DEMO_TIMER && (find_demo_number() && (sDemoNumber <= 6 && sDemoNumber > -1))) {
start_demo();
}
}

View File

@ -89,6 +89,7 @@ s16 set_mario_animation(struct MarioState *m, s32 targetAnimID) {
struct Object *o = m->marioObj;
if (!o || !m->animation) { return 0; }
struct Animation *targetAnim = m->animation->targetAnim;
if (!targetAnim) { return 0; }
if (load_patchable_table(m->animation, targetAnimID)) {
targetAnim->values = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->values);
@ -124,6 +125,7 @@ s16 set_mario_anim_with_accel(struct MarioState *m, s32 targetAnimID, s32 accel)
struct Object *o = m->marioObj;
if (!o || !m->animation) { return 0; }
struct Animation *targetAnim = m->animation->targetAnim;
if (!targetAnim) { return 0; }
if (load_patchable_table(m->animation, targetAnimID)) {
targetAnim->values = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->values);

View File

@ -368,7 +368,7 @@ s32 apply_landing_accel(struct MarioState *m, f32 frictionFactor) {
}
void update_shell_speed(struct MarioState *m) {
if (!m) { return; }
if (!m || !m->floor) { return; }
f32 maxTargetSpeed;
f32 targetSpeed;
@ -538,7 +538,7 @@ s32 begin_braking_action(struct MarioState *m) {
return set_mario_action(m, ACT_STANDING_AGAINST_WALL, 0);
}
if (m->forwardVel >= 16.0f && m->floor->normal.y >= 0.17364818f) {
if (m->forwardVel >= 16.0f && m->floor && m->floor->normal.y >= 0.17364818f) {
return set_mario_action(m, ACT_BRAKING, 0);
}
@ -694,6 +694,9 @@ void anim_and_audio_for_hold_walk(struct MarioState *m) {
val08 = FALSE;
}
break;
default:
break;
}
}
}
@ -1281,7 +1284,7 @@ s32 act_riding_shell_ground(struct MarioState *m) {
}
tilt_body_ground_shell(m, startYaw);
if (m->floor->type == SURFACE_BURNING) {
if (m->floor && m->floor->type == SURFACE_BURNING) {
play_sound(SOUND_MOVING_RIDING_SHELL_LAVA, m->marioObj->header.gfx.cameraToObject);
} else {
play_sound(SOUND_MOVING_TERRAIN_RIDING_SHELL + m->terrainSoundAddend,
@ -1827,7 +1830,7 @@ u32 common_landing_action(struct MarioState *m, s16 animation, u32 airAction) {
set_mario_animation(m, animation);
play_mario_landing_sound_once(m, SOUND_ACTION_TERRAIN_LANDING);
if (m->floor->type >= SURFACE_SHALLOW_QUICKSAND && m->floor->type <= SURFACE_MOVING_QUICKSAND) {
if (m->floor && m->floor->type >= SURFACE_SHALLOW_QUICKSAND && m->floor->type <= SURFACE_MOVING_QUICKSAND) {
m->quicksandDepth += (4 - m->actionTimer) * 3.5f - 0.5f;
}
@ -1840,7 +1843,7 @@ s32 common_landing_cancels(struct MarioState *m, struct LandingAction *landingAc
//! Everything here, including floor steepness, is checked before checking
// if Mario is actually on the floor. This leads to e.g. remote sliding.
if (m->floor->normal.y < 0.2923717f) {
if (m->floor && m->floor->normal.y < 0.2923717f) {
return mario_push_off_steep_floor(m, landingAction->verySteepAction, 0);
}

View File

@ -25,7 +25,7 @@
s32 check_common_idle_cancels(struct MarioState *m) {
if (!m) { return 0; }
mario_drop_held_object(m);
if (m->floor->normal.y < 0.29237169f) {
if (m->floor && m->floor->normal.y < 0.29237169f) {
return mario_push_off_steep_floor(m, ACT_FREEFALL, 0);
}

View File

@ -139,7 +139,7 @@ void apply_water_current(struct MarioState *m, Vec3f step) {
s32 i;
f32 whirlpoolRadius = 2000.0f;
if (m->floor->type == SURFACE_FLOWING_WATER) {
if (m->floor && m->floor->type == SURFACE_FLOWING_WATER) {
s16 currentAngle = m->floor->force << 8;
f32 currentSpeed = sWaterCurrentSpeeds[m->floor->force >> 8];

View File

@ -220,7 +220,7 @@ s32 load_patchable_table(struct MarioAnimation *a, u32 index) {
u8* addr = sp20->srcAddr + sp20->anim[index].offset;
u32 size = sp20->anim[index].size;
if (a->currentAnimAddr != addr) {
if (a->targetAnim && a->currentAnimAddr != addr) {
memcpy(a->targetAnim, addr, size);
a->currentAnimAddr = addr;
return TRUE;

View File

@ -121,7 +121,7 @@ void obj_set_dist_from_home(f32 distFromHome) {
}
s32 obj_is_near_to_and_facing_mario(struct MarioState* m, f32 maxDist, s16 maxAngleDiff) {
if (!o) { return 0; }
if (!o || !m) { return 0; }
struct Object* player = m->marioObj;
s32 distanceToPlayer = dist_between_objects(o, player);
s32 angleToPlayer = obj_angle_to_object(o, player);
@ -159,15 +159,14 @@ static BAD_RETURN(u32) obj_perform_position_op(s32 op) {
void platform_on_track_update_pos_or_spawn_ball(s32 ballIndex, f32 x, f32 y, f32 z) {
if (!o) { return; }
struct Object *trackBall;
struct Waypoint *initialPrevWaypoint;
struct Waypoint *nextWaypoint;
struct Waypoint *prevWaypoint;
UNUSED s32 unused;
f32 amountToMove;
f32 dx;
f32 dy;
f32 dz;
struct Object *trackBall = NULL;
struct Waypoint *initialPrevWaypoint = NULL;
struct Waypoint *nextWaypoint = NULL;
struct Waypoint *prevWaypoint = NULL;
f32 amountToMove = 0;
f32 dx = 0;
f32 dy = 0;
f32 dz = 0;
f32 distToNextWaypoint = 100;
if (ballIndex == 0 || ((u16)(o->oBehParams >> 16) & 0x0080)) {

View File

@ -2050,7 +2050,7 @@ f32 cur_obj_abs_y_dist_to_home(void) {
s32 cur_obj_advance_looping_anim(void) {
if (!o) { return 0; }
s32 animFrame = o->header.gfx.animInfo.animFrame;
s32 loopEnd = o->header.gfx.animInfo.curAnim->loopEnd;
s32 loopEnd = o->header.gfx.animInfo.curAnim ? o->header.gfx.animInfo.curAnim->loopEnd : 1;
s32 result;
if (animFrame < 0) {
@ -2060,7 +2060,7 @@ s32 cur_obj_advance_looping_anim(void) {
} else {
animFrame++;
}
if (loopEnd == 0) { loopEnd = 1; }
result = (animFrame << 16) / loopEnd;
return result;
@ -3070,7 +3070,7 @@ void clear_time_stop_flags(s32 flags) {
}
s32 cur_obj_can_mario_activate_textbox(struct MarioState* m, f32 radius, f32 height, UNUSED s32 unused) {
if (!o) { return 0; }
if (!o || !m) { return 0; }
if (!m->visibleToEnemies) { return FALSE; }
if (o->oDistanceToMario < 1500.0f) {
f32 latDistToMario = lateral_dist_between_objects(o, m->marioObj);
@ -3092,7 +3092,7 @@ s32 cur_obj_can_mario_activate_textbox_2(struct MarioState* m, f32 radius, f32 h
}
void cur_obj_end_dialog(struct MarioState* m, s32 dialogFlags, s32 dialogResult) {
if (!o) { return; }
if (!o || !m) { return; }
if (m->playerIndex != 0) { return; }
o->oDialogResponse = dialogResult;
@ -3104,7 +3104,7 @@ void cur_obj_end_dialog(struct MarioState* m, s32 dialogFlags, s32 dialogResult)
}
s32 cur_obj_update_dialog(struct MarioState* m, s32 actionArg, s32 dialogFlags, s32 dialogID, UNUSED s32 unused, u8 (*inContinueDialogFunction)(void)) {
if (!o) { return 0; }
if (!o || !m) { return 0; }
s32 dialogResponse = 0;
UNUSED s32 doneTurning = TRUE;
@ -3184,7 +3184,7 @@ s32 cur_obj_update_dialog(struct MarioState* m, s32 actionArg, s32 dialogFlags,
}
s32 cur_obj_update_dialog_with_cutscene(struct MarioState* m, s32 actionArg, s32 dialogFlags, s32 cutsceneTable, s32 dialogID, u8 (*inContinueDialogFunction)(void)) {
if (!o) { return 0; }
if (!o || !m) { return 0; }
s32 dialogResponse = 0;
s32 doneTurning = TRUE;

View File

@ -270,7 +270,7 @@ void bhv_mario_update(void) {
// set mario state to the current player
s32 stateIndex = (gCurrentObject->oBehParams - 1);
if (stateIndex > MAX_PLAYERS) { return; }
if (stateIndex >= MAX_PLAYERS || stateIndex < 0) { return; }
gMarioState = &gMarioStates[stateIndex];
// sanity check torsoPos, it isn't updated off-screen otherwise
@ -477,7 +477,7 @@ void set_object_respawn_info_bits(struct Object *obj, u8 bits) {
u16 *info16;
u8 oldRespawnInfoBits = 0;
u8 newRespawnInfoBits = 0;
if (!obj) { return; }
if (!obj || !obj->respawnInfo) { return; }
switch (obj->respawnInfoType) {
case RESPAWN_INFO_TYPE_32:

View File

@ -81,6 +81,7 @@ struct ScrollTarget* find_or_create_scroll_targets(u32 id) {
*/
void add_vtx_scroll_target(u32 id, Vtx *vtx, u32 size) {
struct ScrollTarget *scroll = find_or_create_scroll_targets(id);
if (!scroll || !scroll->vertices) { return; }
Vtx* *newArray;
u32 oldSize = sizeof(void*) * scroll->size;
u32 newSize = oldSize + (sizeof(void*) * size);

View File

@ -18,7 +18,7 @@
void exec_anim_sound_state(struct SoundState *soundStates, u16 maxSoundStates) {
if (!gCurrentObject) { return; }
s32 stateIdx = gCurrentObject->oSoundStateID;
if (stateIdx >= maxSoundStates) { return; }
if (stateIdx < 0 || stateIdx >= maxSoundStates) { return; }
switch (soundStates[stateIdx].playSound) {
// since we have an array of sound states corresponding to

View File

@ -1097,7 +1097,8 @@ ConfigRet ConfigRead(FILE *fp, Config **cfg)
else {
if ((ret = GetKeyVal(_cfg, p, &key, &val)) != CONFIG_OK)
goto error;
if (!sect)
goto error;
if ((ret = ConfigAddString(_cfg, sect->name, key, val)) != CONFIG_OK)
goto error;
}

View File

@ -382,6 +382,7 @@ static bool gfx_texture_cache_lookup(int tile, struct TextureHashmapNode **n, co
node = &gfx_texture_cache.hashmap[hash];
// puts("Clearing texture cache");
}
if (!node) { return false; }
*node = &gfx_texture_cache.pool[gfx_texture_cache.pool_pos++];
if ((*node)->texture_addr == NULL) {
(*node)->texture_id = gfx_rapi->new_texture();

View File

@ -80,6 +80,7 @@ struct LuaObjectField* smlua_get_object_field_from_ot(struct LuaObjectTable* ot,
s32 max = ot->fieldCount - 1;
s32 i = (min + max) / 2;
while (true) {
if (!ot->fields[i].key) { return NULL; }
s32 rc = strcmp(key, ot->fields[i].key);
if (rc == 0) {
return &ot->fields[i];

View File

@ -77,7 +77,7 @@ static struct LuaObjectField sAreaFields[LUA_AREA_FIELD_COUNT] = {
{ "surfaceRooms", LVT_S8_P, offsetof(struct Area, surfaceRooms), true, LOT_POINTER },
{ "terrainData", LVT_S16_P, offsetof(struct Area, terrainData), true, LOT_POINTER },
{ "terrainType", LVT_U16, offsetof(struct Area, terrainType), false, LOT_NONE },
// { "unk04", LVT_COBJECT_P, offsetof(struct Area, unk04), false, LOT_??? }, <--- UNIMPLEMENTED
// { "unk04", LVT_COBJECT_P, offsetof(struct Area, unk04), true, LOT_??? }, <--- UNIMPLEMENTED
// { "unused28", LVT_COBJECT_P, offsetof(struct Area, unused28), false, LOT_??? }, <--- UNIMPLEMENTED
{ "warpNodes", LVT_COBJECT_P, offsetof(struct Area, warpNodes), false, LOT_OBJECTWARPNODE },
// { "whirlpools", LOT_???, offsetof(struct Area, whirlpools), false, LOT_??? }, <--- UNIMPLEMENTED
@ -388,13 +388,13 @@ static struct LuaObjectField sCharacterFields[LUA_CHARACTER_FIELD_COUNT] = {
static struct LuaObjectField sControllerFields[LUA_CONTROLLER_FIELD_COUNT] = {
{ "buttonDown", LVT_U16, offsetof(struct Controller, buttonDown), false, LOT_NONE },
{ "buttonPressed", LVT_U16, offsetof(struct Controller, buttonPressed), false, LOT_NONE },
// { "controllerData", LVT_???, offsetof(struct Controller, controllerData), false, LOT_??? }, <--- UNIMPLEMENTED
// { "controllerData", LVT_???, offsetof(struct Controller, controllerData), true, LOT_??? }, <--- UNIMPLEMENTED
{ "extStickX", LVT_S16, offsetof(struct Controller, extStickX), false, LOT_NONE },
{ "extStickY", LVT_S16, offsetof(struct Controller, extStickY), false, LOT_NONE },
{ "port", LVT_S32, offsetof(struct Controller, port), false, LOT_NONE },
{ "rawStickX", LVT_S16, offsetof(struct Controller, rawStickX), false, LOT_NONE },
{ "rawStickY", LVT_S16, offsetof(struct Controller, rawStickY), false, LOT_NONE },
// { "statusData", LVT_???, offsetof(struct Controller, statusData), false, LOT_??? }, <--- UNIMPLEMENTED
// { "statusData", LVT_???, offsetof(struct Controller, statusData), true, LOT_??? }, <--- UNIMPLEMENTED
{ "stickMag", LVT_F32, offsetof(struct Controller, stickMag), false, LOT_NONE },
{ "stickX", LVT_F32, offsetof(struct Controller, stickX), false, LOT_NONE },
{ "stickY", LVT_F32, offsetof(struct Controller, stickY), false, LOT_NONE },
@ -632,44 +632,44 @@ static struct LuaObjectField sGlobalTexturesFields[LUA_GLOBAL_TEXTURES_FIELD_COU
#define LUA_GRAPH_NODE_FIELD_COUNT 7
static struct LuaObjectField sGraphNodeFields[LUA_GRAPH_NODE_FIELD_COUNT] = {
{ "children", LVT_COBJECT_P, offsetof(struct GraphNode, children), false, LOT_GRAPHNODE },
{ "extraFlags", LVT_U8, offsetof(struct GraphNode, extraFlags), false, LOT_NONE },
{ "flags", LVT_S16, offsetof(struct GraphNode, flags), false, LOT_NONE },
// { "georef", LVT_???, offsetof(struct GraphNode, georef), true, LOT_??? }, <--- UNIMPLEMENTED
{ "next", LVT_COBJECT_P, offsetof(struct GraphNode, next), true, LOT_GRAPHNODE },
{ "parent", LVT_COBJECT_P, offsetof(struct GraphNode, parent), true, LOT_GRAPHNODE },
{ "prev", LVT_COBJECT_P, offsetof(struct GraphNode, prev), true, LOT_GRAPHNODE },
{ "type", LVT_S16, offsetof(struct GraphNode, type), false, LOT_NONE },
{ "children", LVT_COBJECT_P, offsetof(struct GraphNode, children), true, LOT_GRAPHNODE },
{ "extraFlags", LVT_U8, offsetof(struct GraphNode, extraFlags), true, LOT_NONE },
{ "flags", LVT_S16, offsetof(struct GraphNode, flags), true, LOT_NONE },
// { "georef", LVT_???, offsetof(struct GraphNode, georef), true, LOT_??? }, <--- UNIMPLEMENTED
{ "next", LVT_COBJECT_P, offsetof(struct GraphNode, next), true, LOT_GRAPHNODE },
{ "parent", LVT_COBJECT_P, offsetof(struct GraphNode, parent), true, LOT_GRAPHNODE },
{ "prev", LVT_COBJECT_P, offsetof(struct GraphNode, prev), true, LOT_GRAPHNODE },
{ "type", LVT_S16, offsetof(struct GraphNode, type), true, LOT_NONE },
};
#define LUA_GRAPH_NODE_OBJECT_FIELD_COUNT 26
static struct LuaObjectField sGraphNodeObjectFields[LUA_GRAPH_NODE_OBJECT_FIELD_COUNT] = {
{ "activeAreaIndex", LVT_S8, offsetof(struct GraphNodeObject, activeAreaIndex), false, LOT_NONE },
{ "angle", LVT_COBJECT, offsetof(struct GraphNodeObject, angle), true, LOT_VEC3S },
{ "animInfo", LVT_COBJECT, offsetof(struct GraphNodeObject, animInfo), true, LOT_ANIMINFO },
{ "areaIndex", LVT_S8, offsetof(struct GraphNodeObject, areaIndex), false, LOT_NONE },
{ "cameraToObject", LVT_COBJECT, offsetof(struct GraphNodeObject, cameraToObject), true, LOT_VEC3F },
{ "disableAutomaticShadowPos", LVT_BOOL, offsetof(struct GraphNodeObject, disableAutomaticShadowPos), false, LOT_NONE },
{ "node", LVT_COBJECT, offsetof(struct GraphNodeObject, node), true, LOT_GRAPHNODE },
{ "pos", LVT_COBJECT, offsetof(struct GraphNodeObject, pos), true, LOT_VEC3F },
{ "prevAngle", LVT_COBJECT, offsetof(struct GraphNodeObject, prevAngle), true, LOT_VEC3S },
{ "prevPos", LVT_COBJECT, offsetof(struct GraphNodeObject, prevPos), true, LOT_VEC3F },
{ "prevScale", LVT_COBJECT, offsetof(struct GraphNodeObject, prevScale), true, LOT_VEC3F },
{ "prevScaleTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevScaleTimestamp), false, LOT_NONE },
{ "prevShadowPos", LVT_COBJECT, offsetof(struct GraphNodeObject, prevShadowPos), true, LOT_VEC3F },
{ "prevShadowPosTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevShadowPosTimestamp), false, LOT_NONE },
{ "prevThrowMatrix", LVT_COBJECT, offsetof(struct GraphNodeObject, prevThrowMatrix), true, LOT_MAT4 },
{ "prevThrowMatrixTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevThrowMatrixTimestamp), false, LOT_NONE },
{ "prevTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevTimestamp), false, LOT_NONE },
{ "scale", LVT_COBJECT, offsetof(struct GraphNodeObject, scale), true, LOT_VEC3F },
{ "shadowInvisible", LVT_BOOL, offsetof(struct GraphNodeObject, shadowInvisible), false, LOT_NONE },
{ "shadowPos", LVT_COBJECT, offsetof(struct GraphNodeObject, shadowPos), true, LOT_VEC3F },
{ "sharedChild", LVT_COBJECT_P, offsetof(struct GraphNodeObject, sharedChild), false, LOT_GRAPHNODE },
{ "skipInViewCheck", LVT_BOOL, offsetof(struct GraphNodeObject, skipInViewCheck), false, LOT_NONE },
{ "skipInterpolationTimestamp", LVT_U32, offsetof(struct GraphNodeObject, skipInterpolationTimestamp), false, LOT_NONE },
{ "throwMatrix", LVT_COBJECT_P, offsetof(struct GraphNodeObject, throwMatrix), false, LOT_POINTER },
{ "throwMatrixPrev", LVT_COBJECT_P, offsetof(struct GraphNodeObject, throwMatrixPrev), false, LOT_POINTER },
{ "unk4C", LVT_COBJECT_P, offsetof(struct GraphNodeObject, unk4C), false, LOT_SPAWNINFO },
{ "activeAreaIndex", LVT_S8, offsetof(struct GraphNodeObject, activeAreaIndex), true, LOT_NONE },
{ "angle", LVT_COBJECT, offsetof(struct GraphNodeObject, angle), true, LOT_VEC3S },
{ "animInfo", LVT_COBJECT, offsetof(struct GraphNodeObject, animInfo), true, LOT_ANIMINFO },
{ "areaIndex", LVT_S8, offsetof(struct GraphNodeObject, areaIndex), true, LOT_NONE },
{ "cameraToObject", LVT_COBJECT, offsetof(struct GraphNodeObject, cameraToObject), true, LOT_VEC3F },
{ "disableAutomaticShadowPos", LVT_BOOL, offsetof(struct GraphNodeObject, disableAutomaticShadowPos), true, LOT_NONE },
{ "node", LVT_COBJECT, offsetof(struct GraphNodeObject, node), true, LOT_GRAPHNODE },
{ "pos", LVT_COBJECT, offsetof(struct GraphNodeObject, pos), true, LOT_VEC3F },
{ "prevAngle", LVT_COBJECT, offsetof(struct GraphNodeObject, prevAngle), true, LOT_VEC3S },
{ "prevPos", LVT_COBJECT, offsetof(struct GraphNodeObject, prevPos), true, LOT_VEC3F },
{ "prevScale", LVT_COBJECT, offsetof(struct GraphNodeObject, prevScale), true, LOT_VEC3F },
{ "prevScaleTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevScaleTimestamp), true, LOT_NONE },
{ "prevShadowPos", LVT_COBJECT, offsetof(struct GraphNodeObject, prevShadowPos), true, LOT_VEC3F },
{ "prevShadowPosTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevShadowPosTimestamp), true, LOT_NONE },
{ "prevThrowMatrix", LVT_COBJECT, offsetof(struct GraphNodeObject, prevThrowMatrix), true, LOT_MAT4 },
{ "prevThrowMatrixTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevThrowMatrixTimestamp), true, LOT_NONE },
{ "prevTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevTimestamp), true, LOT_NONE },
{ "scale", LVT_COBJECT, offsetof(struct GraphNodeObject, scale), true, LOT_VEC3F },
{ "shadowInvisible", LVT_BOOL, offsetof(struct GraphNodeObject, shadowInvisible), true, LOT_NONE },
{ "shadowPos", LVT_COBJECT, offsetof(struct GraphNodeObject, shadowPos), true, LOT_VEC3F },
{ "sharedChild", LVT_COBJECT_P, offsetof(struct GraphNodeObject, sharedChild), true, LOT_GRAPHNODE },
{ "skipInViewCheck", LVT_BOOL, offsetof(struct GraphNodeObject, skipInViewCheck), true, LOT_NONE },
{ "skipInterpolationTimestamp", LVT_U32, offsetof(struct GraphNodeObject, skipInterpolationTimestamp), true, LOT_NONE },
{ "throwMatrix", LVT_COBJECT_P, offsetof(struct GraphNodeObject, throwMatrix), true, LOT_POINTER },
{ "throwMatrixPrev", LVT_COBJECT_P, offsetof(struct GraphNodeObject, throwMatrixPrev), true, LOT_POINTER },
{ "unk4C", LVT_COBJECT_P, offsetof(struct GraphNodeObject, unk4C), true, LOT_SPAWNINFO },
};
#define LUA_GRAPH_NODE_802_A45_E4_FIELD_COUNT 6
@ -793,7 +793,7 @@ static struct LuaObjectField sLinearTransitionPointFields[LUA_LINEAR_TRANSITION_
#define LUA_MARIO_ANIMATION_FIELD_COUNT 2
static struct LuaObjectField sMarioAnimationFields[LUA_MARIO_ANIMATION_FIELD_COUNT] = {
// { "animDmaTable", LVT_COBJECT_P, offsetof(struct MarioAnimation, animDmaTable), false, LOT_??? }, <--- UNIMPLEMENTED
// { "animDmaTable", LVT_COBJECT_P, offsetof(struct MarioAnimation, animDmaTable), true, LOT_??? }, <--- UNIMPLEMENTED
{ "currentAnimAddr", LVT_U8_P, offsetof(struct MarioAnimation, currentAnimAddr), true, LOT_POINTER },
// { "padding", LOT_???, offsetof(struct MarioAnimation, padding), false, LOT_??? }, <--- UNIMPLEMENTED
{ "targetAnim", LVT_COBJECT_P, offsetof(struct MarioAnimation, targetAnim), false, LOT_ANIMATION },
@ -826,7 +826,7 @@ static struct LuaObjectField sMarioStateFields[LUA_MARIO_STATE_FIELD_COUNT] = {
{ "actionTimer", LVT_U16, offsetof(struct MarioState, actionTimer), false, LOT_NONE },
{ "angleVel", LVT_COBJECT, offsetof(struct MarioState, angleVel), true, LOT_VEC3S },
{ "animation", LVT_COBJECT_P, offsetof(struct MarioState, animation), false, LOT_MARIOANIMATION },
{ "area", LVT_COBJECT_P, offsetof(struct MarioState, area), false, LOT_AREA },
{ "area", LVT_COBJECT_P, offsetof(struct MarioState, area), true, LOT_AREA },
{ "bounceSquishTimer", LVT_U8, offsetof(struct MarioState, bounceSquishTimer), false, LOT_NONE },
{ "bubbleObj", LVT_COBJECT_P, offsetof(struct MarioState, bubbleObj), false, LOT_OBJECT },
{ "cap", LVT_U32, offsetof(struct MarioState, cap), false, LOT_NONE },
@ -983,7 +983,7 @@ static struct LuaObjectField sObjectFields[LUA_OBJECT_FIELD_COUNT] = {
{ "behavior", LVT_BEHAVIORSCRIPT_P, offsetof(struct Object, behavior), true, LOT_POINTER },
{ "bhvDelayTimer", LVT_S16, offsetof(struct Object, bhvDelayTimer), false, LOT_NONE },
// { "bhvStack", LOT_???, offsetof(struct Object, bhvStack), false, LOT_??? }, <--- UNIMPLEMENTED
{ "bhvStackIndex", LVT_U32, offsetof(struct Object, bhvStackIndex), false, LOT_NONE },
{ "bhvStackIndex", LVT_U32, offsetof(struct Object, bhvStackIndex), true, LOT_NONE },
{ "collidedObjInteractTypes", LVT_U32, offsetof(struct Object, collidedObjInteractTypes), false, LOT_NONE },
// { "collidedObjs", LOT_???, offsetof(struct Object, collidedObjs), false, LOT_??? }, <--- UNIMPLEMENTED
{ "collisionData", LVT_COLLISION_P, offsetof(struct Object, collisionData), false, LOT_POINTER },
@ -1147,7 +1147,7 @@ static struct LuaObjectField sObjectFields[LUA_OBJECT_FIELD_COUNT] = {
{ "oChainChompNumLunges", LVT_S32, offsetof(struct Object, oChainChompNumLunges), false, LOT_NONE },
{ "oChainChompReleaseStatus", LVT_S32, offsetof(struct Object, oChainChompReleaseStatus), false, LOT_NONE },
{ "oChainChompRestrictedByChain", LVT_S32, offsetof(struct Object, oChainChompRestrictedByChain), false, LOT_NONE },
{ "oChainChompSegments", LVT_COBJECT_P, offsetof(struct Object, oChainChompSegments), false, LOT_CHAINSEGMENT },
{ "oChainChompSegments", LVT_COBJECT_P, offsetof(struct Object, oChainChompSegments), true, LOT_CHAINSEGMENT },
{ "oChainChompTargetPitch", LVT_S32, offsetof(struct Object, oChainChompTargetPitch), false, LOT_NONE },
{ "oChainChompUnk104", LVT_F32, offsetof(struct Object, oChainChompUnk104), false, LOT_NONE },
{ "oCheckerBoardPlatformUnk1AC", LVT_F32, offsetof(struct Object, oCheckerBoardPlatformUnk1AC), false, LOT_NONE },
@ -1721,7 +1721,7 @@ static struct LuaObjectField sObjectFields[LUA_OBJECT_FIELD_COUNT] = {
{ "oWhitePuffUnkFC", LVT_S32, offsetof(struct Object, oWhitePuffUnkFC), false, LOT_NONE },
{ "oWhompShakeVal", LVT_S32, offsetof(struct Object, oWhompShakeVal), false, LOT_NONE },
{ "oWigglerFallThroughFloorsHeight", LVT_F32, offsetof(struct Object, oWigglerFallThroughFloorsHeight), false, LOT_NONE },
{ "oWigglerSegments", LVT_COBJECT_P, offsetof(struct Object, oWigglerSegments), false, LOT_CHAINSEGMENT },
{ "oWigglerSegments", LVT_COBJECT_P, offsetof(struct Object, oWigglerSegments), true, LOT_CHAINSEGMENT },
{ "oWigglerSquishSpeed", LVT_F32, offsetof(struct Object, oWigglerSquishSpeed), false, LOT_NONE },
{ "oWigglerTargetYaw", LVT_S32, offsetof(struct Object, oWigglerTargetYaw), false, LOT_NONE },
{ "oWigglerTextStatus", LVT_S16, offsetof(struct Object, oWigglerTextStatus), false, LOT_NONE },
@ -1743,7 +1743,7 @@ static struct LuaObjectField sObjectFields[LUA_OBJECT_FIELD_COUNT] = {
// { "ptrData", LOT_???, offsetof(struct Object, ptrData), false, LOT_??? }, <--- UNIMPLEMENTED
// { "rawData", LOT_???, offsetof(struct Object, rawData), false, LOT_??? }, <--- UNIMPLEMENTED
// { "respawnInfo", LVT_???, offsetof(struct Object, respawnInfo), false, LOT_??? }, <--- UNIMPLEMENTED
{ "respawnInfoType", LVT_S16, offsetof(struct Object, respawnInfoType), false, LOT_NONE },
{ "respawnInfoType", LVT_S16, offsetof(struct Object, respawnInfoType), true, LOT_NONE },
{ "setHome", LVT_U8, offsetof(struct Object, setHome), false, LOT_NONE },
{ "transform", LVT_COBJECT, offsetof(struct Object, transform), true, LOT_MAT4 },
{ "unused1", LVT_U32, offsetof(struct Object, unused1), false, LOT_NONE },
@ -1931,8 +1931,8 @@ static struct LuaObjectField sSpawnInfoFields[LUA_SPAWN_INFO_FIELD_COUNT] = {
{ "next", LVT_COBJECT_P, offsetof(struct SpawnInfo, next), true, LOT_SPAWNINFO },
{ "startAngle", LVT_COBJECT, offsetof(struct SpawnInfo, startAngle), true, LOT_VEC3S },
{ "startPos", LVT_COBJECT, offsetof(struct SpawnInfo, startPos), true, LOT_VEC3S },
{ "syncID", LVT_U32, offsetof(struct SpawnInfo, syncID), false, LOT_NONE },
{ "unk18", LVT_COBJECT_P, offsetof(struct SpawnInfo, unk18), false, LOT_GRAPHNODE },
{ "syncID", LVT_U32, offsetof(struct SpawnInfo, syncID), true, LOT_NONE },
{ "unk18", LVT_COBJECT_P, offsetof(struct SpawnInfo, unk18), true, LOT_GRAPHNODE },
};
#define LUA_SPAWN_PARTICLES_INFO_FIELD_COUNT 12
@ -2038,7 +2038,7 @@ static struct LuaObjectField sTransitionInfoFields[LUA_TRANSITION_INFO_FIELD_COU
{ "posYaw", LVT_S16, offsetof(struct TransitionInfo, posYaw), false, LOT_NONE },
};
#define LUA_WALL_COLLISION_DATA_FIELD_COUNT 6
#define LUA_WALL_COLLISION_DATA_FIELD_COUNT 9
static struct LuaObjectField sWallCollisionDataFields[LUA_WALL_COLLISION_DATA_FIELD_COUNT] = {
{ "normalAddition", LVT_COBJECT, offsetof(struct WallCollisionData, normalAddition), true, LOT_VEC3F },
{ "normalCount", LVT_U8, offsetof(struct WallCollisionData, normalCount), false, LOT_NONE },
@ -2047,7 +2047,9 @@ static struct LuaObjectField sWallCollisionDataFields[LUA_WALL_COLLISION_DATA_FI
{ "radius", LVT_F32, offsetof(struct WallCollisionData, radius), false, LOT_NONE },
{ "unused", LVT_S16, offsetof(struct WallCollisionData, unused), false, LOT_NONE },
// { "walls", LOT_???, offsetof(struct WallCollisionData, walls), false, LOT_??? }, <--- UNIMPLEMENTED
// { "z", LVT_???, offsetof(struct WallCollisionData, z), false, LOT_??? }, <--- UNIMPLEMENTED
{ "x", LVT_F32, offsetof(struct WallCollisionData, x), false, LOT_NONE },
{ "y", LVT_F32, offsetof(struct WallCollisionData, y), false, LOT_NONE },
{ "z", LVT_F32, offsetof(struct WallCollisionData, z), false, LOT_NONE },
};
#define LUA_WARP_NODE_FIELD_COUNT 4

View File

@ -3998,6 +3998,7 @@ char gSmluaConstants[] = ""
"TERRAIN_WATER = 0x0005\n"
"TERRAIN_SLIDE = 0x0006\n"
"TERRAIN_MASK = 0x0007\n"
"OBJECT_MAX_BHV_STACK = 16\n"
"SPTASK_STATE_NOT_STARTED = 0\n"
"SPTASK_STATE_RUNNING = 1\n"
"SPTASK_STATE_INTERRUPTED = 2\n"

View File

@ -602,6 +602,7 @@ s32 smlua_func_level_script_parse_callback(u8 type, void *cmd) {
LOG_LUA("Failed to call the callback behaviors: %u", type);
return 0;
}
return 0;
}
void smlua_func_level_script_parse(lua_State* L) {
@ -667,10 +668,18 @@ static u16 *smlua_to_u16_list(lua_State* L, int index) {
int indexValue = lua_gettop(L) - 0;
s32 key = smlua_to_integer(L, indexKey);
if (!gSmLuaConvertSuccess) { LOG_LUA("smlua_to_u16_list: Failed to convert table key"); return 0; }
if (!gSmLuaConvertSuccess) {
LOG_LUA("smlua_to_u16_list: Failed to convert table key");
free(values);
return 0;
}
u16 value = smlua_to_integer(L, indexValue);
if (!gSmLuaConvertSuccess) { LOG_LUA("smlua_to_u16_list: Failed to convert table value"); return 0; }
if (!gSmLuaConvertSuccess) {
LOG_LUA("smlua_to_u16_list: Failed to convert table value");
free(values);
return 0;
}
values[key - 1] = value;
lua_settop(L, top);
@ -683,28 +692,28 @@ int smlua_func_smlua_anim_util_register_animation(lua_State* L) {
if (!smlua_functions_valid_param_count(L, 8)) { return 0; }
const char *name = smlua_to_string(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("smlua_anim_util_register_animation: Failed to convert parameter 'name'"); return 0; }
if (!gSmLuaConvertSuccess) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "name"); return 0; }
s16 flags = smlua_to_integer(L, 2);
if (!gSmLuaConvertSuccess) { LOG_LUA("smlua_anim_util_register_animation: Failed to convert parameter 'flags'"); return 0; }
if (!gSmLuaConvertSuccess) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "flags"); return 0; }
s16 animYTransDivisor = smlua_to_integer(L, 3);
if (!gSmLuaConvertSuccess) { LOG_LUA("smlua_anim_util_register_animation: Failed to convert parameter 'animYTransDivisor'"); return 0; }
if (!gSmLuaConvertSuccess) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "animYTransDivisor"); return 0; }
s16 startFrame = smlua_to_integer(L, 4);
if (!gSmLuaConvertSuccess) { LOG_LUA("smlua_anim_util_register_animation: Failed to convert parameter 'startFrame'"); return 0; }
if (!gSmLuaConvertSuccess) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "startFrame"); return 0; }
s16 loopStart = smlua_to_integer(L, 5);
if (!gSmLuaConvertSuccess) { LOG_LUA("smlua_anim_util_register_animation: Failed to convert parameter 'loopStart'"); return 0; }
if (!gSmLuaConvertSuccess) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "loopStart"); return 0; }
s16 loopEnd = smlua_to_integer(L, 6);
if (!gSmLuaConvertSuccess) { LOG_LUA("smlua_anim_util_register_animation: Failed to convert parameter 'loopEnd'"); return 0; }
if (!gSmLuaConvertSuccess) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "loopEnd"); return 0; }
s16 *values = (s16 *) smlua_to_u16_list(L, 7);
if (!values) { LOG_LUA("smlua_anim_util_register_animation: Failed to convert parameter 'values'"); return 0; }
if (!values) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "values"); return 0; }
u16 *index = (u16 *) smlua_to_u16_list(L, 8);
if (!index) { LOG_LUA("smlua_anim_util_register_animation: Failed to convert parameter 'index'"); return 0; }
if (!index) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "index"); free(values); return 0; }
smlua_anim_util_register_animation(name, flags, animYTransDivisor, startFrame, loopStart, loopEnd, values, index);

View File

@ -129,17 +129,21 @@ void smlua_anim_util_reset() {
sCustomAnimationHead = NULL;
}
void smlua_anim_util_register_animation(const char *name, s16 flags, s16 animYTransDivisor, s16 startFrame, s16 loopStart, s16 loopEnd, const s16 *values, const u16 *index) {
void smlua_anim_util_register_animation(const char *name, s16 flags, s16 animYTransDivisor, s16 startFrame, s16 loopStart, s16 loopEnd, s16 *values, u16 *index) {
// NULL-checks
if (!name) {
LOG_LUA_LINE("smlua_anim_util_register_animation: Parameter 'name' is NULL");
free(values);
free(index);
return;
}
// Check if the name is not already taken
if (get_custom_animation_node(name)) {
LOG_LUA_LINE("smlua_anim_util_register_animation: An animation named '%s' already exists", name);
free(values);
free(index);
return;
}

View File

@ -67,7 +67,7 @@ struct GlobalObjectAnimations {
extern struct GlobalObjectAnimations gGlobalObjectAnimations;
void smlua_anim_util_reset();
void smlua_anim_util_register_animation(const char *name, s16 flags, s16 animYTransDivisor, s16 startFrame, s16 loopStart, s16 loopEnd, const s16 *values, const u16 *index);
void smlua_anim_util_register_animation(const char *name, s16 flags, s16 animYTransDivisor, s16 startFrame, s16 loopStart, s16 loopEnd, s16 *values, u16 *index);
void smlua_anim_util_set_animation(struct Object *obj, const char *name);
const char *smlua_anim_util_get_current_animation_name(struct Object *obj);

View File

@ -125,14 +125,18 @@ struct ModCacheEntry* mod_cache_get_from_path(const char* path, bool validate) {
return NULL;
}
void mod_cache_add_internal(u8* dataHash, u64 lastLoaded, const char* path) {
void mod_cache_add_internal(u8* dataHash, u64 lastLoaded, char* inPath) {
char* path = strdup(inPath);
// sanity check
if (path == NULL || strlen(path) == 0) {
LOG_ERROR("Invalid path");
free(path);
return;
}
if (!fs_sys_file_exists(path)) {
LOG_ERROR("File does not exist: %s", path);
free(path);
return;
}
normalize_path((char*)path);
@ -146,6 +150,7 @@ void mod_cache_add_internal(u8* dataHash, u64 lastLoaded, const char* path) {
}
if (!foundNonZero) {
LOG_ERROR("Hash was all zeros for path '%s'", path);
free(path);
return;
}
@ -215,13 +220,13 @@ void mod_cache_add(struct Mod* mod, struct ModFile* file, bool useFilePath) {
struct ModCacheEntry* entry = mod_cache_get_from_path(file->cachedPath, false);
if (useFilePath && entry) {
memcpy(file->dataHash, entry->dataHash, 16);
mod_cache_add_internal(file->dataHash, 0, strdup(file->cachedPath));
mod_cache_add_internal(file->dataHash, 0, (char*)file->cachedPath);
return;
}
// hash and cache
mod_cache_md5(file->cachedPath, file->dataHash);
mod_cache_add_internal(file->dataHash, 0, strdup(file->cachedPath));
mod_cache_add_internal(file->dataHash, 0, (char*)file->cachedPath);
}
void mod_cache_update(struct Mod* mod, struct ModFile* file) {
@ -244,7 +249,7 @@ void mod_cache_update(struct Mod* mod, struct ModFile* file) {
// hash and cache
mod_cache_md5(file->cachedPath, file->dataHash);
mod_cache_add_internal(file->dataHash, 0, strdup(file->cachedPath));
mod_cache_add_internal(file->dataHash, 0, (char*)file->cachedPath);
}
void mod_cache_load(void) {
@ -280,10 +285,12 @@ void mod_cache_load(void) {
fread(&lastLoaded, sizeof(u64), 1, fp);
fread(&pathLen, sizeof(u16), 1, fp);
const char* path = calloc(pathLen + 1, sizeof(char*));
fread((char*)path, sizeof(char*), pathLen + 1, fp);
char* path = calloc(pathLen + 1, sizeof(char));
fread((char*)path, sizeof(char), pathLen + 1, fp);
mod_cache_add_internal(dataHash, lastLoaded, path);
mod_cache_add_internal(dataHash, lastLoaded, (char*)path);
free((void*)path);
count++;
}
LOG_INFO("Loading mod cache complete");

View File

@ -64,7 +64,7 @@ u32 key_count(char* filename) {
return lines - 4;
}
char *mod_storage_get_filename(char* dest) {
void mod_storage_get_filename(char* dest) {
const char *path = sys_user_path(); // get base sm64ex-coop appdata dir
snprintf(dest, SYS_MAX_PATH - 1, "%s/sav/%s", path, gLuaActiveMod->relativePath); // append sav folder
strdelete(dest, ".lua"); // delete ".lua" from sav name