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 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): def gen_comment_header(f):
comment_h = "// " + f + " //" comment_h = "// " + f + " //"
comment_l = "/" * len(comment_h) comment_l = "/" * len(comment_h)

View file

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

View file

@ -83,27 +83,29 @@ override_field_invisible = {
} }
override_field_immutable = { override_field_immutable = {
"MarioState": [ "playerIndex", "controller", "marioObj", "marioBodyState", "statusForCamera" ], "MarioState": [ "playerIndex", "controller", "marioObj", "marioBodyState", "statusForCamera", "area" ],
"MarioAnimation": [ "animDmaTable" ],
"ObjectNode": [ "next", "prev" ], "ObjectNode": [ "next", "prev" ],
"Character": [ "*" ], "Character": [ "*" ],
"NetworkPlayer": [ "*" ], "NetworkPlayer": [ "*" ],
"TextureInfo": [ "*" ], "TextureInfo": [ "*" ],
"Object": ["oSyncID", "coopFlags"], "Object": ["oSyncID", "coopFlags", "oChainChompSegments", "oWigglerSegments", "oHauntedChairUnk100", "oTTCTreadmillBigSurface", "oTTCTreadmillSmallSurface", "bhvStackIndex", "respawnInfoType" ],
"GlobalObjectAnimations": [ "*"], "GlobalObjectAnimations": [ "*"],
"SpawnParticlesInfo": [ "model" ], "SpawnParticlesInfo": [ "model" ],
"MarioBodyState": [ "updateTorsoTime" ], "MarioBodyState": [ "updateTorsoTime" ],
"Area": [ "localAreaTimer", "nextSyncID" ], "Area": [ "localAreaTimer", "nextSyncID", "unk04" ],
"Mod": [ "*" ], "Mod": [ "*" ],
"ModFile": [ "*" ], "ModFile": [ "*" ],
"BassAudio": [ "*" ], "BassAudio": [ "*" ],
"Painting": [ "id", "imageCount", "textureType", "textureWidth", "textureHeight" ], "Painting": [ "id", "imageCount", "textureType", "textureWidth", "textureHeight" ],
"SpawnInfo": [ "syncID" ], "SpawnInfo": [ "syncID", "next", "unk18" ],
"CustomLevelInfo": [ "next" ], "CustomLevelInfo": [ "next" ],
"GraphNode": [ "next", "prev", "parent" ], "GraphNode": [ "*" ],
"GraphNodeObject": [ "*" ],
"ObjectWarpNode": [ "next "], "ObjectWarpNode": [ "next "],
"SpawnInfo": [ "next" ],
"Animation": [ "length" ], "Animation": [ "length" ],
"AnimationTable": [ "count" ], "AnimationTable": [ "count" ],
"Controller": [ "controllerData", "statusData" ],
} }
override_field_version_excludes = { 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'] 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']: for field in struct['fields']:
fid, ftype, fimmutable, lvt, lot = get_struct_field_info(struct, field) fid, ftype, fimmutable, lvt, lot = get_struct_field_info(struct, field)
if fimmutable == 'true': if fimmutable == 'true':
@ -252,14 +279,48 @@ def output_fuzz_struct(struct):
if sid in override_field_invisible: if sid in override_field_invisible:
if fid in override_field_invisible[sid]: if fid in override_field_invisible[sid]:
continue 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': if lvt == 'LVT_COBJECT':
print(' Fuzz' + ftype.replace('struct ', '') + '(struct.' + fid + ')') s_out += 'Fuzz' + ftype.replace('struct ', '') + '(struct.' + fid + ')'
elif lvt == 'LVT_COBJECT_P': elif lvt == 'LVT_COBJECT_P':
print(' struct.' + fid + ' = nil') s_out += 'struct.' + fid + ' = ' + rnd_line + ''
else: else:
print(' struct.' + fid + ' = 0') s_out += 'struct.' + fid + ' = ' + rnd_line + ''
print('end')
print('') 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) doc_structs(parsed)
def_structs(parsed) def_structs(parsed)
if len(sys.argv) >= 2 and sys.argv[1] == 'fuzz':
output_fuzz_file()
global total_structs global total_structs
global total_fields 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 --- @type integer
MAX_PLAYERS = 16 MAX_PLAYERS = 16
--- @type integer
OBJECT_MAX_BHV_STACK = 16
--- @type integer --- @type integer
PLAY_MODE_CHANGE_AREA = 3 PLAY_MODE_CHANGE_AREA = 3

View file

@ -1845,6 +1845,9 @@
--- @field public offsetY number --- @field public offsetY number
--- @field public radius number --- @field public radius number
--- @field public unused integer --- @field public unused integer
--- @field public x number
--- @field public y number
--- @field public z number
--- @class WarpNode --- @class WarpNode
--- @field public destArea integer --- @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)); gDPLoadBlock(aHead++, G_TX_LOADTILE, 0, 0, (((_Arg3) * (_Arg4) + arg2_1) >> arg2_2) - 1, CALC_DXT(_Arg3, arg2_3));
gDPPipeSync(aHead++); gDPPipeSync(aHead++);
gDPSetTile(aHead++, _Arg1, _Arg2, ((((_Arg3) * arg2_4) + 7) >> 3), 0, G_TX_RENDERTILE, _Arg5, _Arg7, _Arg9, _ArgB, _Arg6, _Arg8, _ArgA); 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; return;
} }

View file

@ -59,12 +59,13 @@ void DynOS_Actor_AddCustom(const SysPath &aFilename, const char *aActorName) {
// Add to custom actors // Add to custom actors
if (georef == NULL) { if (georef == NULL) {
DynosCustomActors().Add({ actorName, geoLayout }); DynosCustomActors().Add({ strdup(actorName), geoLayout });
georef = geoLayout; georef = geoLayout;
} }
// Add to list // Add to list
DynOS_Actor_Valid(georef, actorGfx); DynOS_Actor_Valid(georef, actorGfx);
free(actorName);
} }
const void *DynOS_Actor_GetLayoutFromName(const char *aActorName) { 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)) { if (length > 4 && !strncmp(&_PackEnt->d_name[length - 4], ".bin", 4)) {
String _ActorName = _PackEnt->d_name; String _ActorName = _PackEnt->d_name;
_ActorName[length - 4] = '\0'; _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 // check for textures
@ -209,7 +209,7 @@ void DynOS_Pack_AddActor(PackData* aPackData, const char* aActorName, GfxData* a
} }
s32 index = aPackData->mGfxData.Count(); s32 index = aPackData->mGfxData.Count();
aPackData->mGfxData.Add({ aActorName, aGfxData }); aPackData->mGfxData.Add({ strdup(aActorName), aGfxData });
if (aPackData->mEnabled) { if (aPackData->mEnabled) {
DynOS_Pack_ActivateActor(aPackData->mIndex, aPackData->mGfxData[index]); DynOS_Pack_ActivateActor(aPackData->mIndex, aPackData->mGfxData[index]);

View file

@ -113,30 +113,6 @@ s32 DynOS_String_Width(const u8 *aStr64) {
return _Width; 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 // Scroll Targets
// //

View file

@ -1,2 +1,2 @@
#!/bin/bash #!/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_NETWORK
- COOP_OBJ_FLAG_NON_SYNC - COOP_OBJ_FLAG_NON_SYNC
- MAX_PLAYERS - MAX_PLAYERS
- OBJECT_MAX_BHV_STACK
- PLAY_MODE_CHANGE_AREA - PLAY_MODE_CHANGE_AREA
- PLAY_MODE_CHANGE_LEVEL - PLAY_MODE_CHANGE_LEVEL
- PLAY_MODE_FRAME_ADVANCE - PLAY_MODE_FRAME_ADVANCE

View file

@ -810,13 +810,13 @@
| Field | Type | Access | | Field | Type | Access |
| ----- | ---- | ------ | | ----- | ---- | ------ |
| children | [GraphNode](structs.md#GraphNode) | | | children | [GraphNode](structs.md#GraphNode) | read-only |
| extraFlags | `integer` | | | extraFlags | `integer` | read-only |
| flags | `integer` | | | flags | `integer` | read-only |
| next | [GraphNode](structs.md#GraphNode) | read-only | | next | [GraphNode](structs.md#GraphNode) | read-only |
| parent | [GraphNode](structs.md#GraphNode) | read-only | | parent | [GraphNode](structs.md#GraphNode) | read-only |
| prev | [GraphNode](structs.md#GraphNode) | read-only | | prev | [GraphNode](structs.md#GraphNode) | read-only |
| type | `integer` | | | type | `integer` | read-only |
[:arrow_up_small:](#) [:arrow_up_small:](#)
@ -826,32 +826,32 @@
| Field | Type | Access | | Field | Type | Access |
| ----- | ---- | ------ | | ----- | ---- | ------ |
| activeAreaIndex | `integer` | | | activeAreaIndex | `integer` | read-only |
| angle | [Vec3s](structs.md#Vec3s) | read-only | | angle | [Vec3s](structs.md#Vec3s) | read-only |
| animInfo | [AnimInfo](structs.md#AnimInfo) | read-only | | animInfo | [AnimInfo](structs.md#AnimInfo) | read-only |
| areaIndex | `integer` | | | areaIndex | `integer` | read-only |
| cameraToObject | [Vec3f](structs.md#Vec3f) | read-only | | cameraToObject | [Vec3f](structs.md#Vec3f) | read-only |
| disableAutomaticShadowPos | `boolean` | | | disableAutomaticShadowPos | `boolean` | read-only |
| node | [GraphNode](structs.md#GraphNode) | read-only | | node | [GraphNode](structs.md#GraphNode) | read-only |
| pos | [Vec3f](structs.md#Vec3f) | read-only | | pos | [Vec3f](structs.md#Vec3f) | read-only |
| prevAngle | [Vec3s](structs.md#Vec3s) | read-only | | prevAngle | [Vec3s](structs.md#Vec3s) | read-only |
| prevPos | [Vec3f](structs.md#Vec3f) | read-only | | prevPos | [Vec3f](structs.md#Vec3f) | read-only |
| prevScale | [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 | | prevShadowPos | [Vec3f](structs.md#Vec3f) | read-only |
| prevShadowPosTimestamp | `integer` | | | prevShadowPosTimestamp | `integer` | read-only |
| prevThrowMatrix | `Mat4` | read-only | | prevThrowMatrix | `Mat4` | read-only |
| prevThrowMatrixTimestamp | `integer` | | | prevThrowMatrixTimestamp | `integer` | read-only |
| prevTimestamp | `integer` | | | prevTimestamp | `integer` | read-only |
| scale | [Vec3f](structs.md#Vec3f) | read-only | | scale | [Vec3f](structs.md#Vec3f) | read-only |
| shadowInvisible | `boolean` | | | shadowInvisible | `boolean` | read-only |
| shadowPos | [Vec3f](structs.md#Vec3f) | read-only | | shadowPos | [Vec3f](structs.md#Vec3f) | read-only |
| sharedChild | [GraphNode](structs.md#GraphNode) | | | sharedChild | [GraphNode](structs.md#GraphNode) | read-only |
| skipInViewCheck | `boolean` | | | skipInViewCheck | `boolean` | read-only |
| skipInterpolationTimestamp | `integer` | | | skipInterpolationTimestamp | `integer` | read-only |
| throwMatrix | `Pointer` <`Mat4`> | | | throwMatrix | `Pointer` <`Mat4`> | read-only |
| throwMatrixPrev | `Pointer` <`Mat4`> | | | throwMatrixPrev | `Pointer` <`Mat4`> | read-only |
| unk4C | [SpawnInfo](structs.md#SpawnInfo) | | | unk4C | [SpawnInfo](structs.md#SpawnInfo) | read-only |
[:arrow_up_small:](#) [:arrow_up_small:](#)
@ -1046,7 +1046,7 @@
| actionTimer | `integer` | | | actionTimer | `integer` | |
| angleVel | [Vec3s](structs.md#Vec3s) | read-only | | angleVel | [Vec3s](structs.md#Vec3s) | read-only |
| animation | [MarioAnimation](structs.md#MarioAnimation) | | | animation | [MarioAnimation](structs.md#MarioAnimation) | |
| area | [Area](structs.md#Area) | | | area | [Area](structs.md#Area) | read-only |
| bounceSquishTimer | `integer` | | | bounceSquishTimer | `integer` | |
| bubbleObj | [Object](structs.md#Object) | | | bubbleObj | [Object](structs.md#Object) | |
| cap | `integer` | | | cap | `integer` | |
@ -1220,7 +1220,7 @@
| areaTimerType | [enum AreaTimerType](constants.md#enum-AreaTimerType) | | | areaTimerType | [enum AreaTimerType](constants.md#enum-AreaTimerType) | |
| behavior | `Pointer` <`BehaviorScript`> | read-only | | behavior | `Pointer` <`BehaviorScript`> | read-only |
| bhvDelayTimer | `integer` | | | bhvDelayTimer | `integer` | |
| bhvStackIndex | `integer` | | | bhvStackIndex | `integer` | read-only |
| collidedObjInteractTypes | `integer` | | | collidedObjInteractTypes | `integer` | |
| collisionData | `Pointer` <`Collision`> | | | collisionData | `Pointer` <`Collision`> | |
| coopFlags | `integer` | read-only | | coopFlags | `integer` | read-only |
@ -1239,7 +1239,7 @@
| parentObj | [Object](structs.md#Object) | | | parentObj | [Object](structs.md#Object) | |
| platform | [Object](structs.md#Object) | | | platform | [Object](structs.md#Object) | |
| prevObj | [Object](structs.md#Object) | | | prevObj | [Object](structs.md#Object) | |
| respawnInfoType | `integer` | | | respawnInfoType | `integer` | read-only |
| setHome | `integer` | | | setHome | `integer` | |
| transform | `Mat4` | read-only | | transform | `Mat4` | read-only |
| unused1 | `integer` | | | unused1 | `integer` | |
@ -1467,7 +1467,7 @@
| oCannonPlayerIndex | `integer` | | | oCannonPlayerIndex | `integer` | |
| oCapUnkF4 | `integer` | | | oCapUnkF4 | `integer` | |
| oCapUnkF8 | `integer` | | | oCapUnkF8 | `integer` | |
| oChainChompSegments | [ChainSegment](structs.md#ChainSegment) | | | oChainChompSegments | [ChainSegment](structs.md#ChainSegment) | read-only |
| oChainChompMaxDistFromPivotPerChainPart | `number` | | | oChainChompMaxDistFromPivotPerChainPart | `number` | |
| oChainChompMaxDistBetweenChainParts | `number` | | | oChainChompMaxDistBetweenChainParts | `number` | |
| oChainChompDistToPivot | `number` | | | oChainChompDistToPivot | `number` | |
@ -1961,7 +1961,7 @@
| oStrongWindParticlePenguinObj | [Object](structs.md#Object) | | | oStrongWindParticlePenguinObj | [Object](structs.md#Object) | |
| oWhompShakeVal | `integer` | | | oWhompShakeVal | `integer` | |
| oWigglerFallThroughFloorsHeight | `number` | | | oWigglerFallThroughFloorsHeight | `number` | |
| oWigglerSegments | [ChainSegment](structs.md#ChainSegment) | | | oWigglerSegments | [ChainSegment](structs.md#ChainSegment) | read-only |
| oWigglerWalkAnimSpeed | `number` | | | oWigglerWalkAnimSpeed | `number` | |
| oWigglerSquishSpeed | `number` | | | oWigglerSquishSpeed | `number` | |
| oWigglerTimeUntilRandomTurn | `integer` | | | oWigglerTimeUntilRandomTurn | `integer` | |
@ -2228,8 +2228,8 @@
| next | [SpawnInfo](structs.md#SpawnInfo) | read-only | | next | [SpawnInfo](structs.md#SpawnInfo) | read-only |
| startAngle | [Vec3s](structs.md#Vec3s) | read-only | | startAngle | [Vec3s](structs.md#Vec3s) | read-only |
| startPos | [Vec3s](structs.md#Vec3s) | read-only | | startPos | [Vec3s](structs.md#Vec3s) | read-only |
| syncID | `integer` | | | syncID | `integer` | read-only |
| unk18 | [GraphNode](structs.md#GraphNode) | | | unk18 | [GraphNode](structs.md#GraphNode) | read-only |
[:arrow_up_small:](#) [:arrow_up_small:](#)
@ -2407,6 +2407,9 @@
| offsetY | `number` | | | offsetY | `number` | |
| radius | `number` | | | radius | `number` | |
| unused | `integer` | | | unused | `integer` | |
| x | `number` | |
| y | `number` | |
| z | `number` | |
[:arrow_up_small:](#) [: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 #define BAD_RETURN(cmd) cmd
#endif #endif
#define OBJECT_MAX_BHV_STACK 16
struct Controller struct Controller
{ {
/*0x00*/ s16 rawStickX; // /*0x00*/ s16 rawStickX; //
@ -211,7 +213,7 @@ struct Object
/*0x1C8*/ u32 unused1; /*0x1C8*/ u32 unused1;
/*0x1CC*/ const BehaviorScript *curBhvCommand; /*0x1CC*/ const BehaviorScript *curBhvCommand;
/*0x1D0*/ u32 bhvStackIndex; /*0x1D0*/ u32 bhvStackIndex;
/*0x1D4*/ uintptr_t bhvStack[8]; /*0x1D4*/ uintptr_t bhvStack[OBJECT_MAX_BHV_STACK];
/*0x1F4*/ s16 bhvDelayTimer; /*0x1F4*/ s16 bhvDelayTimer;
/*0x1F6*/ s16 respawnInfoType; /*0x1F6*/ s16 respawnInfoType;
/*0x1F8*/ f32 hitboxRadius; /*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. // Push the address of a behavior command to the object's behavior stack.
static void cur_obj_bhv_stack_push(uintptr_t bhvAddr) { 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++; gCurrentObject->bhvStackIndex++;
if (gCurrentObject->bhvStackIndex >= 8) { gCurrentObject->bhvStackIndex = 8 - 1; }
} }
// Retrieve the last behavior command address from the object's behavior stack. // Retrieve the last behavior command address from the object's behavior stack.
static uintptr_t cur_obj_bhv_stack_pop(void) { static uintptr_t cur_obj_bhv_stack_pop(void) {
uintptr_t bhvAddr; uintptr_t bhvAddr = 0;
gCurrentObject->bhvStackIndex--; gCurrentObject->bhvStackIndex--;
if (gCurrentObject->bhvStackIndex >= 8) { gCurrentObject->bhvStackIndex = 0; } if (gCurrentObject->bhvStackIndex < OBJECT_MAX_BHV_STACK) {
bhvAddr = gCurrentObject->bhvStack[gCurrentObject->bhvStackIndex]; bhvAddr = gCurrentObject->bhvStack[gCurrentObject->bhvStackIndex];
}
return bhvAddr; return bhvAddr;
} }
@ -1287,7 +1289,7 @@ void cur_obj_update(void) {
// catch up the timer in total loop increments // catch up the timer in total loop increments
if (gCurrentObject->areaTimerType == AREA_TIMER_TYPE_LOOP) { if (gCurrentObject->areaTimerType == AREA_TIMER_TYPE_LOOP) {
u32 difference = (gNetworkAreaTimer - gCurrentObject->areaTimer); u32 difference = (gNetworkAreaTimer - gCurrentObject->areaTimer);
if (difference >= gCurrentObject->areaTimerDuration) { if (difference >= gCurrentObject->areaTimerDuration && gCurrentObject->areaTimerDuration) {
u32 catchup = difference / gCurrentObject->areaTimerDuration; u32 catchup = difference / gCurrentObject->areaTimerDuration;
catchup *= gCurrentObject->areaTimerDuration; catchup *= gCurrentObject->areaTimerDuration;
gCurrentObject->areaTimer += catchup; 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[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); dest[2] = v[0] * ((cysz * sx) - sycz) + v[1] * ((cycz * sx) + sysz) + v[2] * (cx * cy);
return &dest; return dest;
} }
#pragma GCC diagnostic pop #pragma GCC diagnostic pop

View file

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

View file

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

View file

@ -1223,6 +1223,7 @@ void bowser_free_update(void) {
} }
void bowser_held_update(void) { void bowser_held_update(void) {
if (o->heldByPlayerIndex >= MAX_PLAYERS) { return; }
struct MarioState* marioState = &gMarioStates[o->heldByPlayerIndex]; struct MarioState* marioState = &gMarioStates[o->heldByPlayerIndex];
struct Object* player = marioState->marioObj; 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->oPosZ += (f32)((o->oTimer / 2 & 1) - 0.5) * 4;
o->oAction = 6; 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]; struct MarioState* controlledBy = &gMarioStates[o->oCannonPlayerIndex];
if (controlledBy && controlledBy->marioObj != NULL) { if (controlledBy && controlledBy->marioObj != NULL) {
controlledBy->marioObj->oMarioCannonObjectYaw = o->oMoveAngleYaw; controlledBy->marioObj->oMarioCannonObjectYaw = o->oMoveAngleYaw;

View file

@ -11,7 +11,7 @@ void bhv_punch_tiny_triangle_loop(void) {
if (o->oTimer == 0) { if (o->oTimer == 0) {
sp1E = o->oMoveAngleYaw; sp1E = o->oMoveAngleYaw;
o->oCollisionParticleUnkF4 = 1.28f; 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; o->oMoveAngleYaw = sp1E;
} }
cur_obj_move_using_fvel_and_gravity(); cur_obj_move_using_fvel_and_gravity();
@ -29,7 +29,7 @@ void bhv_punch_tiny_triangle_init(void) {
for (i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
triangle = spawn_object(o, MODEL_DIRT_ANIMATION, bhvPunchTinyTriangle); triangle = spawn_object(o, MODEL_DIRT_ANIMATION, bhvPunchTinyTriangle);
if (triangle == NULL) { continue; } 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->oVelY = sins(D_8032F2CC[2 * i + 1]) * 25.0f;
triangle->oForwardVel = coss(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) { if (o->oTimer == 0) {
sp1E = o->oMoveAngleYaw; sp1E = o->oMoveAngleYaw;
o->oCollisionParticleUnkF4 = 0.28f; 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; o->oMoveAngleYaw = sp1E;
} }
cur_obj_move_using_fvel_and_gravity(); 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 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; s32 min = max / 4;
// make non-solid immediately for local actions so the camera doesn't glitch out // 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->oFlyGuyIdleTimer = 0;
o->oAction = FLY_GUY_ACT_APPROACH_MARIO; o->oAction = FLY_GUY_ACT_APPROACH_MARIO;
} else { } else {
o->oFlyGuyUnusedJitter = o->oMoveAngleYaw + sFlyGuyJitterAmounts[o->oFlyGuyIdleTimer]; o->oFlyGuyUnusedJitter = o->oMoveAngleYaw + BHV_ARR(sFlyGuyJitterAmounts, o->oFlyGuyIdleTimer, s16);
o->oFlyGuyIdleTimer += 1; o->oFlyGuyIdleTimer += 1;
} }
} }

View file

@ -92,6 +92,7 @@ void hoot_free_step(s16 fastOscY, s32 speed) {
} }
void hoot_player_set_yaw(void) { void hoot_player_set_yaw(void) {
if (o->heldByPlayerIndex >= MAX_PLAYERS) { return; }
struct MarioState* marioState = &gMarioStates[o->heldByPlayerIndex]; struct MarioState* marioState = &gMarioStates[o->heldByPlayerIndex];
s16 stickX = marioState->controller->rawStickX; s16 stickX = marioState->controller->rawStickX;
s16 stickY = marioState->controller->rawStickY; 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->oPosY = hitbox.y;
o->oPosZ = hitbox.z; 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); 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); hoot_carry_step(20, xPrev, zPrev);
if (o->oTimer >= 61) if (o->oTimer >= 61) {
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 */
}
}
break; break;
} }

View file

@ -55,7 +55,9 @@ void bhv_jumping_box_loop(void) {
jumping_box_free_update(); jumping_box_free_update();
break; break;
case HELD_HELD: 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_set_model(smlua_model_util_load(E_MODEL_BREAKABLE_BOX_SMALL));
cur_obj_unrender_and_reset_state(-1, 0); cur_obj_unrender_and_reset_state(-1, 0);
break; break;

View file

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

View file

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

View file

@ -37,7 +37,7 @@ static s16 sTTC2DRotatorTimeBetweenTurns[][4] = {
* Init function for bhvTTC2DRotator. * Init function for bhvTTC2DRotator.
*/ */
void bhv_ttc_2d_rotator_init(void) { 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->oTTC2DRotatorMinTimeUntilNextTurn = sTTC2DRotatorTimeBetweenTurns[o->oBehParams2ndByte][gTTCSpeedSetting];
o->oTTC2DRotatorIncrement = o->oTTC2DRotatorSpeed = sTTC2DRotatorSpeeds[o->oBehParams2ndByte]; 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)) { if (clamp_f32(&o->oPosY, o->oHomeY, o->oTTCPitBlockPeakY)) {
o->oTTCPitBlockDir = o->oTTCPitBlockDir ^ 0x1; o->oTTCPitBlockDir = o->oTTCPitBlockDir ^ 0x1;
if (gTTCSpeedSetting < 4) { if (gTTCSpeedSetting >= 0 && gTTCSpeedSetting < 4) {
if ((o->oTTCPitBlockWaitTime = sTTCPitBlockProperties[gTTCSpeedSetting][o->oTTCPitBlockDir & 0x1].waitTime) < 0) { if ((o->oTTCPitBlockWaitTime = sTTCPitBlockProperties[gTTCSpeedSetting][o->oTTCPitBlockDir & 0x1].waitTime) < 0) {
o->oTTCPitBlockWaitTime = random_mod_offset(10, 20, 6); 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; 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) { void small_penguin_dive_with_mario(void) {
if (mario_is_dive_sliding(&gMarioStates[o->heldByPlayerIndex])) { if (o->heldByPlayerIndex < MAX_PLAYERS) {
o->oSmallPenguinUnk100 = o->oAction; if (mario_is_dive_sliding(&gMarioStates[o->heldByPlayerIndex])) {
o->oAction = 3; o->oSmallPenguinUnk100 = o->oAction;
o->oAction = 3;
}
} }
} }
@ -212,9 +214,11 @@ void small_penguin_act_3(void) {
if (o->oTimer == 6) if (o->oTimer == 6)
cur_obj_play_sound_2(SOUND_OBJ_BABY_PENGUIN_DIVE); cur_obj_play_sound_2(SOUND_OBJ_BABY_PENGUIN_DIVE);
cur_obj_init_animation_with_sound(1); cur_obj_init_animation_with_sound(1);
if (o->oTimer > 25) if (o->oTimer > 25) {
if (!mario_is_dive_sliding(&gMarioStates[o->heldByPlayerIndex])) if (o->heldByPlayerIndex < MAX_PLAYERS && !mario_is_dive_sliding(&gMarioStates[o->heldByPlayerIndex])) {
o->oAction = 4; o->oAction = 4;
}
}
} }
} }
@ -304,15 +308,18 @@ void bhv_small_penguin_loop(void) {
break; break;
case HELD_HELD: case HELD_HELD:
cur_obj_unrender_and_reset_state(0, 0); 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_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 #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 #else
play_sound(SOUND_OBJ2_BABY_PENGUIN_YELL, o->header.gfx.cameraToObject); play_sound(SOUND_OBJ2_BABY_PENGUIN_YELL, o->header.gfx.cameraToObject);
#endif #endif
}
break; break;
case HELD_THROWN: case HELD_THROWN:
cur_obj_get_thrown_or_placed(0, 0, 0); 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. * Called by the main behavior function for the cage ukiki whenever it is held.
*/ */
void cage_ukiki_held_loop(void) { void cage_ukiki_held_loop(void) {
if (o->heldByPlayerIndex >= MAX_PLAYERS) { return; }
struct MarioState* heldByMario = &gMarioStates[o->heldByPlayerIndex]; struct MarioState* heldByMario = &gMarioStates[o->heldByPlayerIndex];
if (heldByMario->playerIndex != 0) { return; } 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. * Called by the main behavior function for the cap ukiki whenever it is held.
*/ */
void cap_ukiki_held_loop(void) { void cap_ukiki_held_loop(void) {
if (o->heldByPlayerIndex >= MAX_PLAYERS) { return; }
struct MarioState* heldByMario = &gMarioStates[o->heldByPlayerIndex]; struct MarioState* heldByMario = &gMarioStates[o->heldByPlayerIndex];
if (heldByMario->playerIndex != 0) { return; } 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). * dependent on the held state and whick ukiki it is (cage or cap).
*/ */
void bhv_ukiki_loop(void) { void bhv_ukiki_loop(void) {
struct Object* heldByPlayer = gMarioStates[o->heldByPlayerIndex].marioObj;
switch(o->oHeldState) { switch(o->oHeldState) {
case HELD_FREE: case HELD_FREE:
@ -675,7 +676,10 @@ void bhv_ukiki_loop(void) {
case HELD_HELD: case HELD_HELD:
cur_obj_unrender_and_reset_state(UKIKI_ANIM_HELD, 0); 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) { if (o->oBehParams2ndByte == UKIKI_CAP) {
cap_ukiki_held_loop(); cap_ukiki_held_loop();

View file

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

View file

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

View file

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

View file

@ -89,6 +89,7 @@ s16 set_mario_animation(struct MarioState *m, s32 targetAnimID) {
struct Object *o = m->marioObj; struct Object *o = m->marioObj;
if (!o || !m->animation) { return 0; } if (!o || !m->animation) { return 0; }
struct Animation *targetAnim = m->animation->targetAnim; struct Animation *targetAnim = m->animation->targetAnim;
if (!targetAnim) { return 0; }
if (load_patchable_table(m->animation, targetAnimID)) { if (load_patchable_table(m->animation, targetAnimID)) {
targetAnim->values = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->values); 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; struct Object *o = m->marioObj;
if (!o || !m->animation) { return 0; } if (!o || !m->animation) { return 0; }
struct Animation *targetAnim = m->animation->targetAnim; struct Animation *targetAnim = m->animation->targetAnim;
if (!targetAnim) { return 0; }
if (load_patchable_table(m->animation, targetAnimID)) { if (load_patchable_table(m->animation, targetAnimID)) {
targetAnim->values = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->values); 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) { void update_shell_speed(struct MarioState *m) {
if (!m) { return; } if (!m || !m->floor) { return; }
f32 maxTargetSpeed; f32 maxTargetSpeed;
f32 targetSpeed; f32 targetSpeed;
@ -538,7 +538,7 @@ s32 begin_braking_action(struct MarioState *m) {
return set_mario_action(m, ACT_STANDING_AGAINST_WALL, 0); 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); return set_mario_action(m, ACT_BRAKING, 0);
} }
@ -694,6 +694,9 @@ void anim_and_audio_for_hold_walk(struct MarioState *m) {
val08 = FALSE; val08 = FALSE;
} }
break; break;
default:
break;
} }
} }
} }
@ -1281,7 +1284,7 @@ s32 act_riding_shell_ground(struct MarioState *m) {
} }
tilt_body_ground_shell(m, startYaw); 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); play_sound(SOUND_MOVING_RIDING_SHELL_LAVA, m->marioObj->header.gfx.cameraToObject);
} else { } else {
play_sound(SOUND_MOVING_TERRAIN_RIDING_SHELL + m->terrainSoundAddend, 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); set_mario_animation(m, animation);
play_mario_landing_sound_once(m, SOUND_ACTION_TERRAIN_LANDING); 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; 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 //! Everything here, including floor steepness, is checked before checking
// if Mario is actually on the floor. This leads to e.g. remote sliding. // 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); return mario_push_off_steep_floor(m, landingAction->verySteepAction, 0);
} }

View file

@ -25,7 +25,7 @@
s32 check_common_idle_cancels(struct MarioState *m) { s32 check_common_idle_cancels(struct MarioState *m) {
if (!m) { return 0; } if (!m) { return 0; }
mario_drop_held_object(m); 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); 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; s32 i;
f32 whirlpoolRadius = 2000.0f; 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; s16 currentAngle = m->floor->force << 8;
f32 currentSpeed = sWaterCurrentSpeeds[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; u8* addr = sp20->srcAddr + sp20->anim[index].offset;
u32 size = sp20->anim[index].size; u32 size = sp20->anim[index].size;
if (a->currentAnimAddr != addr) { if (a->targetAnim && a->currentAnimAddr != addr) {
memcpy(a->targetAnim, addr, size); memcpy(a->targetAnim, addr, size);
a->currentAnimAddr = addr; a->currentAnimAddr = addr;
return TRUE; 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) { 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; struct Object* player = m->marioObj;
s32 distanceToPlayer = dist_between_objects(o, player); s32 distanceToPlayer = dist_between_objects(o, player);
s32 angleToPlayer = obj_angle_to_object(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) { void platform_on_track_update_pos_or_spawn_ball(s32 ballIndex, f32 x, f32 y, f32 z) {
if (!o) { return; } if (!o) { return; }
struct Object *trackBall; struct Object *trackBall = NULL;
struct Waypoint *initialPrevWaypoint; struct Waypoint *initialPrevWaypoint = NULL;
struct Waypoint *nextWaypoint; struct Waypoint *nextWaypoint = NULL;
struct Waypoint *prevWaypoint; struct Waypoint *prevWaypoint = NULL;
UNUSED s32 unused; f32 amountToMove = 0;
f32 amountToMove; f32 dx = 0;
f32 dx; f32 dy = 0;
f32 dy; f32 dz = 0;
f32 dz;
f32 distToNextWaypoint = 100; f32 distToNextWaypoint = 100;
if (ballIndex == 0 || ((u16)(o->oBehParams >> 16) & 0x0080)) { 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) { s32 cur_obj_advance_looping_anim(void) {
if (!o) { return 0; } if (!o) { return 0; }
s32 animFrame = o->header.gfx.animInfo.animFrame; 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; s32 result;
if (animFrame < 0) { if (animFrame < 0) {
@ -2060,7 +2060,7 @@ s32 cur_obj_advance_looping_anim(void) {
} else { } else {
animFrame++; animFrame++;
} }
if (loopEnd == 0) { loopEnd = 1; }
result = (animFrame << 16) / loopEnd; result = (animFrame << 16) / loopEnd;
return result; 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) { 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 (!m->visibleToEnemies) { return FALSE; }
if (o->oDistanceToMario < 1500.0f) { if (o->oDistanceToMario < 1500.0f) {
f32 latDistToMario = lateral_dist_between_objects(o, m->marioObj); 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) { void cur_obj_end_dialog(struct MarioState* m, s32 dialogFlags, s32 dialogResult) {
if (!o) { return; } if (!o || !m) { return; }
if (m->playerIndex != 0) { return; } if (m->playerIndex != 0) { return; }
o->oDialogResponse = dialogResult; 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)) { 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; s32 dialogResponse = 0;
UNUSED s32 doneTurning = TRUE; 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)) { 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 dialogResponse = 0;
s32 doneTurning = TRUE; s32 doneTurning = TRUE;

View file

@ -270,7 +270,7 @@ void bhv_mario_update(void) {
// set mario state to the current player // set mario state to the current player
s32 stateIndex = (gCurrentObject->oBehParams - 1); s32 stateIndex = (gCurrentObject->oBehParams - 1);
if (stateIndex > MAX_PLAYERS) { return; } if (stateIndex >= MAX_PLAYERS || stateIndex < 0) { return; }
gMarioState = &gMarioStates[stateIndex]; gMarioState = &gMarioStates[stateIndex];
// sanity check torsoPos, it isn't updated off-screen otherwise // 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; u16 *info16;
u8 oldRespawnInfoBits = 0; u8 oldRespawnInfoBits = 0;
u8 newRespawnInfoBits = 0; u8 newRespawnInfoBits = 0;
if (!obj) { return; } if (!obj || !obj->respawnInfo) { return; }
switch (obj->respawnInfoType) { switch (obj->respawnInfoType) {
case RESPAWN_INFO_TYPE_32: 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) { void add_vtx_scroll_target(u32 id, Vtx *vtx, u32 size) {
struct ScrollTarget *scroll = find_or_create_scroll_targets(id); struct ScrollTarget *scroll = find_or_create_scroll_targets(id);
if (!scroll || !scroll->vertices) { return; }
Vtx* *newArray; Vtx* *newArray;
u32 oldSize = sizeof(void*) * scroll->size; u32 oldSize = sizeof(void*) * scroll->size;
u32 newSize = oldSize + (sizeof(void*) * size); u32 newSize = oldSize + (sizeof(void*) * size);

View file

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

View file

@ -1097,7 +1097,8 @@ ConfigRet ConfigRead(FILE *fp, Config **cfg)
else { else {
if ((ret = GetKeyVal(_cfg, p, &key, &val)) != CONFIG_OK) if ((ret = GetKeyVal(_cfg, p, &key, &val)) != CONFIG_OK)
goto error; goto error;
if (!sect)
goto error;
if ((ret = ConfigAddString(_cfg, sect->name, key, val)) != CONFIG_OK) if ((ret = ConfigAddString(_cfg, sect->name, key, val)) != CONFIG_OK)
goto error; 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]; node = &gfx_texture_cache.hashmap[hash];
// puts("Clearing texture cache"); // puts("Clearing texture cache");
} }
if (!node) { return false; }
*node = &gfx_texture_cache.pool[gfx_texture_cache.pool_pos++]; *node = &gfx_texture_cache.pool[gfx_texture_cache.pool_pos++];
if ((*node)->texture_addr == NULL) { if ((*node)->texture_addr == NULL) {
(*node)->texture_id = gfx_rapi->new_texture(); (*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 max = ot->fieldCount - 1;
s32 i = (min + max) / 2; s32 i = (min + max) / 2;
while (true) { while (true) {
if (!ot->fields[i].key) { return NULL; }
s32 rc = strcmp(key, ot->fields[i].key); s32 rc = strcmp(key, ot->fields[i].key);
if (rc == 0) { if (rc == 0) {
return &ot->fields[i]; 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 }, { "surfaceRooms", LVT_S8_P, offsetof(struct Area, surfaceRooms), true, LOT_POINTER },
{ "terrainData", LVT_S16_P, offsetof(struct Area, terrainData), true, LOT_POINTER }, { "terrainData", LVT_S16_P, offsetof(struct Area, terrainData), true, LOT_POINTER },
{ "terrainType", LVT_U16, offsetof(struct Area, terrainType), false, LOT_NONE }, { "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 // { "unused28", LVT_COBJECT_P, offsetof(struct Area, unused28), false, LOT_??? }, <--- UNIMPLEMENTED
{ "warpNodes", LVT_COBJECT_P, offsetof(struct Area, warpNodes), false, LOT_OBJECTWARPNODE }, { "warpNodes", LVT_COBJECT_P, offsetof(struct Area, warpNodes), false, LOT_OBJECTWARPNODE },
// { "whirlpools", LOT_???, offsetof(struct Area, whirlpools), false, LOT_??? }, <--- UNIMPLEMENTED // { "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] = { static struct LuaObjectField sControllerFields[LUA_CONTROLLER_FIELD_COUNT] = {
{ "buttonDown", LVT_U16, offsetof(struct Controller, buttonDown), false, LOT_NONE }, { "buttonDown", LVT_U16, offsetof(struct Controller, buttonDown), false, LOT_NONE },
{ "buttonPressed", LVT_U16, offsetof(struct Controller, buttonPressed), 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 }, { "extStickX", LVT_S16, offsetof(struct Controller, extStickX), false, LOT_NONE },
{ "extStickY", LVT_S16, offsetof(struct Controller, extStickY), false, LOT_NONE }, { "extStickY", LVT_S16, offsetof(struct Controller, extStickY), false, LOT_NONE },
{ "port", LVT_S32, offsetof(struct Controller, port), false, LOT_NONE }, { "port", LVT_S32, offsetof(struct Controller, port), false, LOT_NONE },
{ "rawStickX", LVT_S16, offsetof(struct Controller, rawStickX), false, LOT_NONE }, { "rawStickX", LVT_S16, offsetof(struct Controller, rawStickX), false, LOT_NONE },
{ "rawStickY", LVT_S16, offsetof(struct Controller, rawStickY), 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 }, { "stickMag", LVT_F32, offsetof(struct Controller, stickMag), false, LOT_NONE },
{ "stickX", LVT_F32, offsetof(struct Controller, stickX), false, LOT_NONE }, { "stickX", LVT_F32, offsetof(struct Controller, stickX), false, LOT_NONE },
{ "stickY", LVT_F32, offsetof(struct Controller, stickY), 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 #define LUA_GRAPH_NODE_FIELD_COUNT 7
static struct LuaObjectField sGraphNodeFields[LUA_GRAPH_NODE_FIELD_COUNT] = { static struct LuaObjectField sGraphNodeFields[LUA_GRAPH_NODE_FIELD_COUNT] = {
{ "children", LVT_COBJECT_P, offsetof(struct GraphNode, children), false, LOT_GRAPHNODE }, { "children", LVT_COBJECT_P, offsetof(struct GraphNode, children), true, LOT_GRAPHNODE },
{ "extraFlags", LVT_U8, offsetof(struct GraphNode, extraFlags), false, LOT_NONE }, { "extraFlags", LVT_U8, offsetof(struct GraphNode, extraFlags), true, LOT_NONE },
{ "flags", LVT_S16, offsetof(struct GraphNode, flags), false, LOT_NONE }, { "flags", LVT_S16, offsetof(struct GraphNode, flags), true, LOT_NONE },
// { "georef", LVT_???, offsetof(struct GraphNode, georef), true, LOT_??? }, <--- UNIMPLEMENTED // { "georef", LVT_???, offsetof(struct GraphNode, georef), true, LOT_??? }, <--- UNIMPLEMENTED
{ "next", LVT_COBJECT_P, offsetof(struct GraphNode, next), true, LOT_GRAPHNODE }, { "next", LVT_COBJECT_P, offsetof(struct GraphNode, next), true, LOT_GRAPHNODE },
{ "parent", LVT_COBJECT_P, offsetof(struct GraphNode, parent), 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 }, { "prev", LVT_COBJECT_P, offsetof(struct GraphNode, prev), true, LOT_GRAPHNODE },
{ "type", LVT_S16, offsetof(struct GraphNode, type), false, LOT_NONE }, { "type", LVT_S16, offsetof(struct GraphNode, type), true, LOT_NONE },
}; };
#define LUA_GRAPH_NODE_OBJECT_FIELD_COUNT 26 #define LUA_GRAPH_NODE_OBJECT_FIELD_COUNT 26
static struct LuaObjectField sGraphNodeObjectFields[LUA_GRAPH_NODE_OBJECT_FIELD_COUNT] = { static struct LuaObjectField sGraphNodeObjectFields[LUA_GRAPH_NODE_OBJECT_FIELD_COUNT] = {
{ "activeAreaIndex", LVT_S8, offsetof(struct GraphNodeObject, activeAreaIndex), false, LOT_NONE }, { "activeAreaIndex", LVT_S8, offsetof(struct GraphNodeObject, activeAreaIndex), true, LOT_NONE },
{ "angle", LVT_COBJECT, offsetof(struct GraphNodeObject, angle), true, LOT_VEC3S }, { "angle", LVT_COBJECT, offsetof(struct GraphNodeObject, angle), true, LOT_VEC3S },
{ "animInfo", LVT_COBJECT, offsetof(struct GraphNodeObject, animInfo), true, LOT_ANIMINFO }, { "animInfo", LVT_COBJECT, offsetof(struct GraphNodeObject, animInfo), true, LOT_ANIMINFO },
{ "areaIndex", LVT_S8, offsetof(struct GraphNodeObject, areaIndex), false, LOT_NONE }, { "areaIndex", LVT_S8, offsetof(struct GraphNodeObject, areaIndex), true, LOT_NONE },
{ "cameraToObject", LVT_COBJECT, offsetof(struct GraphNodeObject, cameraToObject), true, LOT_VEC3F }, { "cameraToObject", LVT_COBJECT, offsetof(struct GraphNodeObject, cameraToObject), true, LOT_VEC3F },
{ "disableAutomaticShadowPos", LVT_BOOL, offsetof(struct GraphNodeObject, disableAutomaticShadowPos), false, LOT_NONE }, { "disableAutomaticShadowPos", LVT_BOOL, offsetof(struct GraphNodeObject, disableAutomaticShadowPos), true, LOT_NONE },
{ "node", LVT_COBJECT, offsetof(struct GraphNodeObject, node), true, LOT_GRAPHNODE }, { "node", LVT_COBJECT, offsetof(struct GraphNodeObject, node), true, LOT_GRAPHNODE },
{ "pos", LVT_COBJECT, offsetof(struct GraphNodeObject, pos), true, LOT_VEC3F }, { "pos", LVT_COBJECT, offsetof(struct GraphNodeObject, pos), true, LOT_VEC3F },
{ "prevAngle", LVT_COBJECT, offsetof(struct GraphNodeObject, prevAngle), true, LOT_VEC3S }, { "prevAngle", LVT_COBJECT, offsetof(struct GraphNodeObject, prevAngle), true, LOT_VEC3S },
{ "prevPos", LVT_COBJECT, offsetof(struct GraphNodeObject, prevPos), true, LOT_VEC3F }, { "prevPos", LVT_COBJECT, offsetof(struct GraphNodeObject, prevPos), true, LOT_VEC3F },
{ "prevScale", LVT_COBJECT, offsetof(struct GraphNodeObject, prevScale), true, LOT_VEC3F }, { "prevScale", LVT_COBJECT, offsetof(struct GraphNodeObject, prevScale), true, LOT_VEC3F },
{ "prevScaleTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevScaleTimestamp), false, LOT_NONE }, { "prevScaleTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevScaleTimestamp), true, LOT_NONE },
{ "prevShadowPos", LVT_COBJECT, offsetof(struct GraphNodeObject, prevShadowPos), true, LOT_VEC3F }, { "prevShadowPos", LVT_COBJECT, offsetof(struct GraphNodeObject, prevShadowPos), true, LOT_VEC3F },
{ "prevShadowPosTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevShadowPosTimestamp), false, LOT_NONE }, { "prevShadowPosTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevShadowPosTimestamp), true, LOT_NONE },
{ "prevThrowMatrix", LVT_COBJECT, offsetof(struct GraphNodeObject, prevThrowMatrix), true, LOT_MAT4 }, { "prevThrowMatrix", LVT_COBJECT, offsetof(struct GraphNodeObject, prevThrowMatrix), true, LOT_MAT4 },
{ "prevThrowMatrixTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevThrowMatrixTimestamp), false, LOT_NONE }, { "prevThrowMatrixTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevThrowMatrixTimestamp), true, LOT_NONE },
{ "prevTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevTimestamp), false, LOT_NONE }, { "prevTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevTimestamp), true, LOT_NONE },
{ "scale", LVT_COBJECT, offsetof(struct GraphNodeObject, scale), true, LOT_VEC3F }, { "scale", LVT_COBJECT, offsetof(struct GraphNodeObject, scale), true, LOT_VEC3F },
{ "shadowInvisible", LVT_BOOL, offsetof(struct GraphNodeObject, shadowInvisible), false, LOT_NONE }, { "shadowInvisible", LVT_BOOL, offsetof(struct GraphNodeObject, shadowInvisible), true, LOT_NONE },
{ "shadowPos", LVT_COBJECT, offsetof(struct GraphNodeObject, shadowPos), true, LOT_VEC3F }, { "shadowPos", LVT_COBJECT, offsetof(struct GraphNodeObject, shadowPos), true, LOT_VEC3F },
{ "sharedChild", LVT_COBJECT_P, offsetof(struct GraphNodeObject, sharedChild), false, LOT_GRAPHNODE }, { "sharedChild", LVT_COBJECT_P, offsetof(struct GraphNodeObject, sharedChild), true, LOT_GRAPHNODE },
{ "skipInViewCheck", LVT_BOOL, offsetof(struct GraphNodeObject, skipInViewCheck), false, LOT_NONE }, { "skipInViewCheck", LVT_BOOL, offsetof(struct GraphNodeObject, skipInViewCheck), true, LOT_NONE },
{ "skipInterpolationTimestamp", LVT_U32, offsetof(struct GraphNodeObject, skipInterpolationTimestamp), false, LOT_NONE }, { "skipInterpolationTimestamp", LVT_U32, offsetof(struct GraphNodeObject, skipInterpolationTimestamp), true, LOT_NONE },
{ "throwMatrix", LVT_COBJECT_P, offsetof(struct GraphNodeObject, throwMatrix), false, LOT_POINTER }, { "throwMatrix", LVT_COBJECT_P, offsetof(struct GraphNodeObject, throwMatrix), true, LOT_POINTER },
{ "throwMatrixPrev", LVT_COBJECT_P, offsetof(struct GraphNodeObject, throwMatrixPrev), false, LOT_POINTER }, { "throwMatrixPrev", LVT_COBJECT_P, offsetof(struct GraphNodeObject, throwMatrixPrev), true, LOT_POINTER },
{ "unk4C", LVT_COBJECT_P, offsetof(struct GraphNodeObject, unk4C), false, LOT_SPAWNINFO }, { "unk4C", LVT_COBJECT_P, offsetof(struct GraphNodeObject, unk4C), true, LOT_SPAWNINFO },
}; };
#define LUA_GRAPH_NODE_802_A45_E4_FIELD_COUNT 6 #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 #define LUA_MARIO_ANIMATION_FIELD_COUNT 2
static struct LuaObjectField sMarioAnimationFields[LUA_MARIO_ANIMATION_FIELD_COUNT] = { 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 }, { "currentAnimAddr", LVT_U8_P, offsetof(struct MarioAnimation, currentAnimAddr), true, LOT_POINTER },
// { "padding", LOT_???, offsetof(struct MarioAnimation, padding), false, LOT_??? }, <--- UNIMPLEMENTED // { "padding", LOT_???, offsetof(struct MarioAnimation, padding), false, LOT_??? }, <--- UNIMPLEMENTED
{ "targetAnim", LVT_COBJECT_P, offsetof(struct MarioAnimation, targetAnim), false, LOT_ANIMATION }, { "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 }, { "actionTimer", LVT_U16, offsetof(struct MarioState, actionTimer), false, LOT_NONE },
{ "angleVel", LVT_COBJECT, offsetof(struct MarioState, angleVel), true, LOT_VEC3S }, { "angleVel", LVT_COBJECT, offsetof(struct MarioState, angleVel), true, LOT_VEC3S },
{ "animation", LVT_COBJECT_P, offsetof(struct MarioState, animation), false, LOT_MARIOANIMATION }, { "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 }, { "bounceSquishTimer", LVT_U8, offsetof(struct MarioState, bounceSquishTimer), false, LOT_NONE },
{ "bubbleObj", LVT_COBJECT_P, offsetof(struct MarioState, bubbleObj), false, LOT_OBJECT }, { "bubbleObj", LVT_COBJECT_P, offsetof(struct MarioState, bubbleObj), false, LOT_OBJECT },
{ "cap", LVT_U32, offsetof(struct MarioState, cap), false, LOT_NONE }, { "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 }, { "behavior", LVT_BEHAVIORSCRIPT_P, offsetof(struct Object, behavior), true, LOT_POINTER },
{ "bhvDelayTimer", LVT_S16, offsetof(struct Object, bhvDelayTimer), false, LOT_NONE }, { "bhvDelayTimer", LVT_S16, offsetof(struct Object, bhvDelayTimer), false, LOT_NONE },
// { "bhvStack", LOT_???, offsetof(struct Object, bhvStack), false, LOT_??? }, <--- UNIMPLEMENTED // { "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 }, { "collidedObjInteractTypes", LVT_U32, offsetof(struct Object, collidedObjInteractTypes), false, LOT_NONE },
// { "collidedObjs", LOT_???, offsetof(struct Object, collidedObjs), false, LOT_??? }, <--- UNIMPLEMENTED // { "collidedObjs", LOT_???, offsetof(struct Object, collidedObjs), false, LOT_??? }, <--- UNIMPLEMENTED
{ "collisionData", LVT_COLLISION_P, offsetof(struct Object, collisionData), false, LOT_POINTER }, { "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 }, { "oChainChompNumLunges", LVT_S32, offsetof(struct Object, oChainChompNumLunges), false, LOT_NONE },
{ "oChainChompReleaseStatus", LVT_S32, offsetof(struct Object, oChainChompReleaseStatus), false, LOT_NONE }, { "oChainChompReleaseStatus", LVT_S32, offsetof(struct Object, oChainChompReleaseStatus), false, LOT_NONE },
{ "oChainChompRestrictedByChain", LVT_S32, offsetof(struct Object, oChainChompRestrictedByChain), 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 }, { "oChainChompTargetPitch", LVT_S32, offsetof(struct Object, oChainChompTargetPitch), false, LOT_NONE },
{ "oChainChompUnk104", LVT_F32, offsetof(struct Object, oChainChompUnk104), false, LOT_NONE }, { "oChainChompUnk104", LVT_F32, offsetof(struct Object, oChainChompUnk104), false, LOT_NONE },
{ "oCheckerBoardPlatformUnk1AC", LVT_F32, offsetof(struct Object, oCheckerBoardPlatformUnk1AC), 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 }, { "oWhitePuffUnkFC", LVT_S32, offsetof(struct Object, oWhitePuffUnkFC), false, LOT_NONE },
{ "oWhompShakeVal", LVT_S32, offsetof(struct Object, oWhompShakeVal), false, LOT_NONE }, { "oWhompShakeVal", LVT_S32, offsetof(struct Object, oWhompShakeVal), false, LOT_NONE },
{ "oWigglerFallThroughFloorsHeight", LVT_F32, offsetof(struct Object, oWigglerFallThroughFloorsHeight), 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 }, { "oWigglerSquishSpeed", LVT_F32, offsetof(struct Object, oWigglerSquishSpeed), false, LOT_NONE },
{ "oWigglerTargetYaw", LVT_S32, offsetof(struct Object, oWigglerTargetYaw), false, LOT_NONE }, { "oWigglerTargetYaw", LVT_S32, offsetof(struct Object, oWigglerTargetYaw), false, LOT_NONE },
{ "oWigglerTextStatus", LVT_S16, offsetof(struct Object, oWigglerTextStatus), 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 // { "ptrData", LOT_???, offsetof(struct Object, ptrData), false, LOT_??? }, <--- UNIMPLEMENTED
// { "rawData", LOT_???, offsetof(struct Object, rawData), false, LOT_??? }, <--- UNIMPLEMENTED // { "rawData", LOT_???, offsetof(struct Object, rawData), false, LOT_??? }, <--- UNIMPLEMENTED
// { "respawnInfo", LVT_???, offsetof(struct Object, respawnInfo), 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 }, { "setHome", LVT_U8, offsetof(struct Object, setHome), false, LOT_NONE },
{ "transform", LVT_COBJECT, offsetof(struct Object, transform), true, LOT_MAT4 }, { "transform", LVT_COBJECT, offsetof(struct Object, transform), true, LOT_MAT4 },
{ "unused1", LVT_U32, offsetof(struct Object, unused1), false, LOT_NONE }, { "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 }, { "next", LVT_COBJECT_P, offsetof(struct SpawnInfo, next), true, LOT_SPAWNINFO },
{ "startAngle", LVT_COBJECT, offsetof(struct SpawnInfo, startAngle), true, LOT_VEC3S }, { "startAngle", LVT_COBJECT, offsetof(struct SpawnInfo, startAngle), true, LOT_VEC3S },
{ "startPos", LVT_COBJECT, offsetof(struct SpawnInfo, startPos), true, LOT_VEC3S }, { "startPos", LVT_COBJECT, offsetof(struct SpawnInfo, startPos), true, LOT_VEC3S },
{ "syncID", LVT_U32, offsetof(struct SpawnInfo, syncID), false, LOT_NONE }, { "syncID", LVT_U32, offsetof(struct SpawnInfo, syncID), true, LOT_NONE },
{ "unk18", LVT_COBJECT_P, offsetof(struct SpawnInfo, unk18), false, LOT_GRAPHNODE }, { "unk18", LVT_COBJECT_P, offsetof(struct SpawnInfo, unk18), true, LOT_GRAPHNODE },
}; };
#define LUA_SPAWN_PARTICLES_INFO_FIELD_COUNT 12 #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 }, { "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] = { static struct LuaObjectField sWallCollisionDataFields[LUA_WALL_COLLISION_DATA_FIELD_COUNT] = {
{ "normalAddition", LVT_COBJECT, offsetof(struct WallCollisionData, normalAddition), true, LOT_VEC3F }, { "normalAddition", LVT_COBJECT, offsetof(struct WallCollisionData, normalAddition), true, LOT_VEC3F },
{ "normalCount", LVT_U8, offsetof(struct WallCollisionData, normalCount), false, LOT_NONE }, { "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 }, { "radius", LVT_F32, offsetof(struct WallCollisionData, radius), false, LOT_NONE },
{ "unused", LVT_S16, offsetof(struct WallCollisionData, unused), false, LOT_NONE }, { "unused", LVT_S16, offsetof(struct WallCollisionData, unused), false, LOT_NONE },
// { "walls", LOT_???, offsetof(struct WallCollisionData, walls), false, LOT_??? }, <--- UNIMPLEMENTED // { "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 #define LUA_WARP_NODE_FIELD_COUNT 4

View file

@ -3998,6 +3998,7 @@ char gSmluaConstants[] = ""
"TERRAIN_WATER = 0x0005\n" "TERRAIN_WATER = 0x0005\n"
"TERRAIN_SLIDE = 0x0006\n" "TERRAIN_SLIDE = 0x0006\n"
"TERRAIN_MASK = 0x0007\n" "TERRAIN_MASK = 0x0007\n"
"OBJECT_MAX_BHV_STACK = 16\n"
"SPTASK_STATE_NOT_STARTED = 0\n" "SPTASK_STATE_NOT_STARTED = 0\n"
"SPTASK_STATE_RUNNING = 1\n" "SPTASK_STATE_RUNNING = 1\n"
"SPTASK_STATE_INTERRUPTED = 2\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); LOG_LUA("Failed to call the callback behaviors: %u", type);
return 0; return 0;
} }
return 0;
} }
void smlua_func_level_script_parse(lua_State* L) { 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; int indexValue = lua_gettop(L) - 0;
s32 key = smlua_to_integer(L, indexKey); 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); 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; values[key - 1] = value;
lua_settop(L, top); 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; } if (!smlua_functions_valid_param_count(L, 8)) { return 0; }
const char *name = smlua_to_string(L, 1); 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); 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); 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); 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); 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); 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); 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); 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); 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; 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 // NULL-checks
if (!name) { if (!name) {
LOG_LUA_LINE("smlua_anim_util_register_animation: Parameter 'name' is NULL"); LOG_LUA_LINE("smlua_anim_util_register_animation: Parameter 'name' is NULL");
free(values);
free(index);
return; return;
} }
// Check if the name is not already taken // Check if the name is not already taken
if (get_custom_animation_node(name)) { if (get_custom_animation_node(name)) {
LOG_LUA_LINE("smlua_anim_util_register_animation: An animation named '%s' already exists", name); LOG_LUA_LINE("smlua_anim_util_register_animation: An animation named '%s' already exists", name);
free(values);
free(index);
return; return;
} }

View file

@ -67,7 +67,7 @@ struct GlobalObjectAnimations {
extern struct GlobalObjectAnimations gGlobalObjectAnimations; extern struct GlobalObjectAnimations gGlobalObjectAnimations;
void smlua_anim_util_reset(); 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); void smlua_anim_util_set_animation(struct Object *obj, const char *name);
const char *smlua_anim_util_get_current_animation_name(struct Object *obj); 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; 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 // sanity check
if (path == NULL || strlen(path) == 0) { if (path == NULL || strlen(path) == 0) {
LOG_ERROR("Invalid path"); LOG_ERROR("Invalid path");
free(path);
return; return;
} }
if (!fs_sys_file_exists(path)) { if (!fs_sys_file_exists(path)) {
LOG_ERROR("File does not exist: %s", path); LOG_ERROR("File does not exist: %s", path);
free(path);
return; return;
} }
normalize_path((char*)path); normalize_path((char*)path);
@ -146,6 +150,7 @@ void mod_cache_add_internal(u8* dataHash, u64 lastLoaded, const char* path) {
} }
if (!foundNonZero) { if (!foundNonZero) {
LOG_ERROR("Hash was all zeros for path '%s'", path); LOG_ERROR("Hash was all zeros for path '%s'", path);
free(path);
return; 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); struct ModCacheEntry* entry = mod_cache_get_from_path(file->cachedPath, false);
if (useFilePath && entry) { if (useFilePath && entry) {
memcpy(file->dataHash, entry->dataHash, 16); 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; return;
} }
// hash and cache // hash and cache
mod_cache_md5(file->cachedPath, file->dataHash); 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) { 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 // hash and cache
mod_cache_md5(file->cachedPath, file->dataHash); 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) { void mod_cache_load(void) {
@ -280,10 +285,12 @@ void mod_cache_load(void) {
fread(&lastLoaded, sizeof(u64), 1, fp); fread(&lastLoaded, sizeof(u64), 1, fp);
fread(&pathLen, sizeof(u16), 1, fp); fread(&pathLen, sizeof(u16), 1, fp);
const char* path = calloc(pathLen + 1, sizeof(char*)); char* path = calloc(pathLen + 1, sizeof(char));
fread((char*)path, sizeof(char*), pathLen + 1, fp); 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++; count++;
} }
LOG_INFO("Loading mod cache complete"); LOG_INFO("Loading mod cache complete");

View file

@ -64,7 +64,7 @@ u32 key_count(char* filename) {
return lines - 4; 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 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 snprintf(dest, SYS_MAX_PATH - 1, "%s/sav/%s", path, gLuaActiveMod->relativePath); // append sav folder
strdelete(dest, ".lua"); // delete ".lua" from sav name strdelete(dest, ".lua"); // delete ".lua" from sav name