Add OoT's namefixer.py (#775)

* Add OoT's namefixer.py

* Absorb actorfixer into namefixer

* Merge remote-tracking branch 'upstream/master' into namefixer

* Remove problematic functions

* Add sanity check

* Review
This commit is contained in:
EllipticEllipsis 2022-04-17 20:35:35 +01:00 committed by GitHub
parent 578e36cdbd
commit ad42edb034
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,12 +1,24 @@
#!/usr/bin/env python3
import argparse, os
import os
import argparse
# There are a few commented out entries that would produce unexpected renames.
# They are left as a comment so people can just grab them.
# all occurrences of keys will be replaced by associated value
simpleReplace = {
# "Math_Rand_":"Rand_",
# "ACTORTYPE":"ACTORCAT",
# "DistToLink":"DistToPlayer",
# "HitItem":"HitInfo",
}
# "old": "new"
animdict = {
# all occurrences of keys will be replaced by associated value,
# if the occurence is the whole word
# for example, if there is a space before and an open parenthesis after,
# like for a function call: ` func_8002E4B4(`
#
# Custom behaviour can be enabled by using a tuple as the value (see
# explanation in replace_single below)
wordReplace = {
"Actor_GetSwitchFlag": "Flags_GetSwitch",
"atan_flip": "Math_Acot2F",
"atans": "Math_Atan2S",
@ -88,25 +100,25 @@ animdict = {
"func_801A89A8": "Audio_QueueSeqCmd",
"func_8019F1C0": "Audio_PlaySfxAtPos",
"func_801A72CC": "Audio_StopSfxByPos",
"SkelAnime_LodDrawLimb(": "SkelAnime_DrawLimbLod(",
"SkelAnime_LodDraw(": "SkelAnime_DrawLod(",
"SkelAnime_LodDrawLimbSV(": "SkelAnime_DrawFlexLimbLod(",
"SkelAnime_LodDrawSV(": "SkelAnime_DrawFlexLod(",
#"SkelAnime_DrawLimb(": "SkelAnime_DrawLimbOpa(",
#"SkelAnime_Draw(": "SkelAnime_DrawOpa(",
"SkelAnime_DrawLimbSV(": "SkelAnime_DrawFlexLimbOpa(",
"SkelAnime_DrawSV(": "SkelAnime_DrawFlexOpa(",
#"SkelAnime_AnimateFrame(": "SkelAnime_GetFrameData(",
"SkelAnime_GetTotalFrames(": "Animation_GetLength(",
"SkelAnime_GetFrameCount(": "Animation_GetLastFrame(",
"SkelAnime_Draw2Limb(": "SkelAnime_DrawLimb(",
"SkelAnime_Draw2(": "SkelAnime_Draw(",
"SkelAnime_DrawLimbSV2(": "SkelAnime_DrawFlexLimb(",
"SkelAnime_DrawSV2(": "SkelAnime_DrawFlex(",
"SkelAnime_LodDrawLimb": "SkelAnime_DrawLimbLod",
"SkelAnime_LodDraw": "SkelAnime_DrawLod",
"SkelAnime_LodDrawLimbSV": "SkelAnime_DrawFlexLimbLod",
"SkelAnime_LodDrawSV": "SkelAnime_DrawFlexLod",
# "SkelAnime_DrawLimb": "SkelAnime_DrawLimbOpa", # A different function is called this now
# "SkelAnime_Draw": "SkelAnime_DrawOpa", # A different function is called this now
"SkelAnime_DrawLimbSV": "SkelAnime_DrawFlexLimbOpa",
"SkelAnime_DrawSV": "SkelAnime_DrawFlexOpa",
# "SkelAnime_AnimateFrame": "SkelAnime_GetFrameData", # A different function is called this now
"SkelAnime_GetTotalFrames": "Animation_GetLength",
"SkelAnime_GetFrameCount": "Animation_GetLastFrame",
"SkelAnime_Draw2Limb": "SkelAnime_DrawLimb",
"SkelAnime_Draw2": "SkelAnime_Draw",
"SkelAnime_DrawLimbSV2": "SkelAnime_DrawFlexLimb",
"SkelAnime_DrawSV2": "SkelAnime_DrawFlex",
"func_80134FFC": "SkelAnime_GetFrameData2",
"func_801353D4": "Animation_GetLimbCount2",
"SkelAnime_GetTotalFrames2(": "Animation_GetLength2(",
"SkelAnime_GetFrameCount2(": "Animation_GetLastFrame2(",
"SkelAnime_GetTotalFrames2": "Animation_GetLength2",
"SkelAnime_GetFrameCount2": "Animation_GetLastFrame2",
"SkelAnime_InterpolateVec3s": "SkelAnime_InterpFrameTable",
"SkelAnime_AnimationCtxReset": "AnimationContext_Reset",
"func_801358D4": "AnimationContext_SetNextQueue",
@ -125,7 +137,7 @@ animdict = {
"SkelAnime_AnimationType4Loaded": "AnimationContext_CopyFalse",
"SkelAnime_AnimationType5Loaded": "AnimationContext_MoveActor",
"func_80135EE8": "AnimationContext_Update",
"SkelAnime_InitLinkAnimetion(": "SkelAnime_InitLink(",
"SkelAnime_InitLinkAnimetion": "SkelAnime_InitLink",
"func_801360A8": "LinkAnimation_SetUpdateFunction",
"func_801360E0": "LinkAnimation_Update",
"func_80136104": "LinkAnimation_Morph",
@ -158,7 +170,7 @@ animdict = {
"func_801370B0": "SkelAnime_LoopPartial",
"func_8013713C": "SkelAnime_Once",
"SkelAnime_ChangeAnimImpl": "Animation_ChangeImpl",
"SkelAnime_ChangeAnim(": "Animation_Change(",
"SkelAnime_ChangeAnim": "Animation_Change",
"SkelAnime_ChangeAnimDefaultStop": "Animation_PlayOnce",
"SkelAnime_ChangeAnimTransitionStop": "Animation_MorphToPlayOnce",
"SkelAnime_ChangeAnimPlaybackStop": "Animation_PlayOnceSetSpeed",
@ -188,12 +200,12 @@ animdict = {
"Actor_SetChestFlag": "Flags_SetTreasure",
"Actor_SetAllChestFlag": "Flags_SetAllTreasure",
"Actor_GetAllChestFlag": "Flags_GetAllTreasure",
"Actor_GetRoomCleared(": "Flags_GetClear(",
"Actor_SetRoomCleared(": "Flags_SetClear(",
"Actor_UnsetRoomCleared(": "Flags_UnsetClear(",
"Actor_GetRoomClearedTemp(": "Flags_GetClearTemp(",
"Actor_SetRoomClearedTemp(": "Flags_SetClearTemp(",
"Actor_UnsetRoomClearedTemp(": "Flags_UnsetTempClear(",
"Actor_GetRoomCleared": "Flags_GetClear",
"Actor_SetRoomCleared": "Flags_SetClear",
"Actor_UnsetRoomCleared": "Flags_UnsetClear",
"Actor_GetRoomClearedTemp": "Flags_GetClearTemp",
"Actor_SetRoomClearedTemp": "Flags_SetClearTemp",
"Actor_UnsetRoomClearedTemp": "Flags_UnsetTempClear",
"Actor_GetCollectibleFlag": "Flags_GetCollectible",
"Actor_SetCollectibleFlag": "Flags_SetCollectible",
"func_800B8A1C": "Actor_PickUp",
@ -214,7 +226,7 @@ animdict = {
"Actor_TitleCardCreate": "TitleCard_InitBossName",
"func_800B867C": "Actor_TextboxIsClosing",
"func_800BDC5C": "Actor_ChangeAnimationByInfo",
"Actor_ChangeAnimation(": "Actor_ChangeAnimationByInfo(",
"Actor_ChangeAnimation": "Actor_ChangeAnimationByInfo",
"func_80152498": "Message_GetState",
"func_800B8898": "Actor_GetScreenPos",
"Audio_PlayActorSound2": "Actor_PlaySfxAtPos",
@ -222,8 +234,8 @@ animdict = {
"Actor_IsFacingPlayerAndWithinRange": "Actor_IsFacingAndNearPlayer",
"func_800BC8B8": "Actor_DrawDoorLock",
"func_800B86C8": "Actor_ChangeFocus",
"zelda_malloc(": "ZeldaArena_Malloc(",
"zelda_mallocR(": "ZeldaArena_MallocR(",
"zelda_malloc": "ZeldaArena_Malloc",
"zelda_mallocR": "ZeldaArena_MallocR",
"zelda_realloc": "ZeldaArena_Realloc",
"zelda_free": "ZeldaArena_Free",
"zelda_calloc": "ZeldaArena_Calloc",
@ -234,9 +246,9 @@ animdict = {
"MainHeap_IsInitialized": "ZeldaArena_IsInitialized",
"func_80138300": "Skin_GetLimbPos",
"func_8013835C": "Skin_GetVertexPos",
# "BgCheck_RelocateMeshHeader": "CollisionHeader_GetVirtual",
# "BgCheck_AddActorMesh": "DynaPoly_SetBgActor",
# "BgCheck_RemoveActorMesh": "DynaPoly_DeleteBgActor",
"BgCheck_RelocateMeshHeader": "CollisionHeader_GetVirtual",
"BgCheck_AddActorMesh": "DynaPoly_SetBgActor",
"BgCheck_RemoveActorMesh": "DynaPoly_DeleteBgActor",
"BgCheck_PolygonLinkedListNodeInit": "SSNode_SetValue",
"BgCheck_PolygonLinkedListResetHead": "SSList_SetNull",
"BgCheck_ScenePolygonListsNodeInsert": "SSNodeList_SetSSListHead",
@ -265,7 +277,7 @@ animdict = {
"BgCheck_GetIsDefaultSpecialScene": "BgCheck_IsSmallMemScene",
"BgCheck_GetSpecialSceneMaxMemory": "BgCheck_TryGetCustomMemsize",
"BgCheck_CalcSubdivisionSize": "BgCheck_SetSubdivisionDimension",
"BgCheck_Init(": "BgCheck_Allocate(",
"BgCheck_Init": "BgCheck_Allocate",
"func_800C3C00": "BgCheck_SetContextFlags",
"func_800C3C14": "BgCheck_UnsetContextFlags",
"BgCheck_GetActorMeshHeader": "BgCheck_GetCollisionHeader",
@ -379,7 +391,7 @@ animdict = {
"func_8017CEF0": "Math3D_TriChkPointParaZIntersect",
"func_8017D020": "Math3D_TriChkLineSegParaZIntersect",
"Math3D_ColSphereLineSeg": "Math3D_LineVsSph",
"Math3D_ColSphereSphere(": "Math3D_SphVsSph(",
"Math3D_ColSphereSphere": "Math3D_SphVsSph",
"func_8017F9C0": "Math3D_XZInSphere",
"func_8017FA34": "Math3D_XYInSphere",
"func_8017FAA8": "Math3D_YZInSphere",
@ -484,7 +496,7 @@ animdict = {
"func_8015E750": "Message_FindCreditsMessage",
# Structs members
# Struct members
"skelAnime.unk03": "skelAnime.taper",
"skelAnime.animCurrentSeg": "skelAnime.animation",
"skelAnime.initialFrame": "skelAnime.startFrame",
@ -505,6 +517,7 @@ animdict = {
"actor.minVelocityY": "actor.terminalVelocity",
"actor.yDistToWater": "actor.depthInWater",
"actor.yDistToPlayer": "actor.playerHeightRel",
"gSaveContext.weekEventReg": "gSaveContext.save.weekEventReg",
"gSaveContext.playerForm": "gSaveContext.save.playerForm",
"gSaveContext.day": "gSaveContext.save.day",
@ -529,6 +542,11 @@ animdict = {
"gSaveContext.permanentSceneFlags": "gSaveContext.save.permanentSceneFlags",
"gSaveContext.bomberCode": "gSaveContext.save.bomberCode",
"gSaveContext.skullTokenCount": "gSaveContext.save.skullTokenCount",
"gSaveContext.cutscene": "gSaveContext.save.cutscene",
"gSaveContext.health": "gSaveContext.save.playerData.health",
"gSaveContext.unk_1016": "gSaveContext.jinxTimer",
"gSaveContext.unk_3F58": "gSaveContext.sunsSongState",
"player->unk_A87": "player->exchangeItemId",
"player->leftHandActor": "player->heldActor",
"player->unk_384": "player->getItemId",
@ -547,8 +565,7 @@ animdict = {
"globalCtx->envCtx.unk_E6": "globalCtx->envCtx.screenFillColor",
"globalCtx->envCtx.unk_C3": "globalCtx->envCtx.lightSettingOverride",
"globalCtx->envCtx.unk_DC": "globalCtx->envCtx.lightBlend",
"gSaveContext.unk_1016": "gSaveContext.jinxTimer",
"gSaveContext.unk_3F58": "gSaveContext.sunsSongState",
"globalCtx->msgCtx.unk1202A": "globalCtx->msgCtx.ocarinaMode",
"globalCtx->msgCtx.unk1202C": "globalCtx->msgCtx.ocarinaAction",
"globalCtx->msgCtx.unk11F22": "globalCtx->msgCtx.msgMode",
@ -572,65 +589,107 @@ animdict = {
"CUR_UPG_VALUE_VOID": "GET_CUR_UPG_VALUE",
"ICHAIN_F32_DIV1000(minVelocityY,": "ICHAIN_F32_DIV1000(terminalVelocity,",
"ICHAIN_F32(minVelocityY,": "ICHAIN_F32(terminalVelocity,",
# Example of custom behaviour:
# "PLAYER": ("GET_PLAYER(globalCtx)", {"ignore": (-1, '"PLAYER"')}), # ignore "PLAYER" in sSoundBankNames
}
def replace_anim(file):
with open(file, 'r', encoding='utf-8') as infile:
# [a-zA-Z0-9_]
def is_word_char(c):
return (c >= 'a' and c <= 'z') or (c >= 'A' and c <= 'Z') or (c >= '0' and c <= '9') or c == '_'
def replace_single(file):
with open(file, 'r', encoding = 'utf-8') as infile:
srcdata = infile.read()
funcs = list(animdict.keys())
fixes = 0
for func in funcs:
newfunc = animdict.get(func)
if(newfunc is None):
print("How did this happen?")
return -1
if(func in srcdata):
fixes += 1
print(func)
srcdata = srcdata.replace(func, newfunc)
changesCount = 0
if(fixes > 0):
print('Changed', fixes,'entr' + ('y' if fixes == 1 else 'ies') + ' in',file)
for old, new in simpleReplace.items():
# replace `old` with `new`
if old in srcdata:
changesCount += 1
print(old, "->", new)
srcdata = srcdata.replace(old, new)
for old, new in wordReplace.items():
# `new` can be a tuple where the first element is what to replace `old` with,
# and the second element is a dict containing "custom behavior" properties.
if isinstance(new, tuple):
custom_behavior = True
new, custom_behavior_data = new
# The "ignore" data is a tuple where the first element is an offset relative to
# where `old` was found, and the string from that index must differ from the
# tuple's second element for the replacement to be done.
custom_behavior_ignore_data = custom_behavior_data.get("ignore")
custom_behavior_ignore = custom_behavior_ignore_data is not None
if custom_behavior_ignore:
custom_behavior_ignore_offset, custom_behavior_ignore_match = custom_behavior_ignore_data
else:
custom_behavior = False
# replace `old` with `new` if the occurence of `old` is the whole word
oldStartIdx = srcdata.find(old)
if oldStartIdx >= 0:
old_start_as_word = is_word_char(old[0])
old_end_as_word = is_word_char(old[-1])
replaceCount = 0
while oldStartIdx >= 0:
replace = True
if old_start_as_word:
if oldStartIdx == 0:
pass
elif is_word_char(srcdata[oldStartIdx-1]):
replace = False
if old_end_as_word:
oldEndIdx = oldStartIdx + len(old)
if oldEndIdx >= len(srcdata):
pass
elif is_word_char(srcdata[oldEndIdx]):
replace = False
if replace and custom_behavior and custom_behavior_ignore:
if srcdata[oldStartIdx + custom_behavior_ignore_offset:].startswith(custom_behavior_ignore_match):
replace = False
if replace:
srcdata = srcdata[:oldStartIdx] + new + srcdata[oldEndIdx:]
replaceCount += 1
oldStartIdx = srcdata.find(old, oldStartIdx + len(new))
if replaceCount > 0:
changesCount += 1
print(old, "->", new)
if changesCount > 0:
print('Changed', changesCount, 'entry' if changesCount == 1 else 'entries', 'in', file)
with open(file, 'w', encoding = 'utf-8', newline = '\n') as outfile:
outfile.write(srcdata)
return 1
def replace_anim_all(repo):
for subdir, dirs, files in os.walk(repo + os.sep + 'src'):
def replace_all(repo):
for subdir, dirs, files in os.walk(os.path.join(repo,'src')):
for filename in files:
if(filename.endswith('.c')):
file = subdir + os.sep + filename
replace_anim(file)
if filename.endswith('.c') or filename.endswith('.h'):
file = os.path.join(subdir,filename)
replace_single(file)
for subdir, dirs, files in os.walk(repo + os.sep + 'asm'):
for subdir, dirs, files in os.walk(os.path.join(repo,'asm')):
for filename in files:
if(filename.endswith('.s')):
file = subdir + os.sep + filename
replace_anim(file)
if filename.endswith('.s'):
file = os.path.join(subdir,filename)
replace_single(file)
for subdir, dirs, files in os.walk(repo + os.sep + 'data'):
for subdir, dirs, files in os.walk(os.path.join(repo,'data')):
for filename in files:
if(filename.endswith('.s')):
file = subdir + os.sep + filename
replace_anim(file)
if filename.endswith('.s'):
file = os.path.join(subdir,filename)
replace_single(file)
for subdir, dirs, files in os.walk(repo + os.sep + 'docs'):
for subdir, dirs, files in os.walk(os.path.join(repo,'docs')):
for filename in files:
if(filename.endswith('.md')):
file = subdir + os.sep + filename
replace_anim(file)
if filename.endswith('.md'):
file = os.path.join(subdir,filename)
replace_single(file)
for subdir, dirs, files in os.walk(repo + os.sep + 'tools' + os.sep + 'sizes'):
for filename in files:
if(filename.endswith('.csv')):
file = subdir + os.sep + filename
replace_anim(file)
return 1
def dictSanityCheck():
keys = animdict.keys()
values = animdict.values()
keys = wordReplace.keys()
values = wordReplace.values()
for k in keys:
if k in values:
print(f"Key '{k}' found in values")
@ -638,15 +697,27 @@ def dictSanityCheck():
print(f"Fix this by removing said key from the dictionary")
exit(-1)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Update to the new animation names')
parser.add_argument('file', help="source file to be processed. use . to process the whole repo", default = None)
keys = simpleReplace.keys()
values = {*wordReplace.values(), *simpleReplace.values()}
for k in keys:
for value in values:
if k in value:
print(f"Key '{k}' found in values")
print(f"This would produce unintended renames")
print(f"Fix this by removing said key from the dictionary")
exit(-1)
def main():
parser = argparse.ArgumentParser(description='Apply function renames to a file')
parser.add_argument('file', help="source file to be processed. use . to process the whole repo")
args = parser.parse_args()
dictSanityCheck()
if(args.file == '.'):
replace_anim_all(os.curdir)
if args.file == '.':
replace_all(os.curdir)
else:
replace_anim(args.file)
replace_single(args.file)
if __name__ == "__main__":
main()