Moving structure to system as zeldaret/botw

Co-authored-by: leoetlino <leo@leolam.fr>
This commit is contained in:
MonsterDruide1 2021-07-13 23:33:25 +02:00
parent 122e4b2f33
commit 72b3d5cdce
117 changed files with 193246 additions and 15 deletions

34
.gitignore vendored
View File

@ -1,15 +1,31 @@
*.o
*.vscode
__pycache__/
*.pyc
*.egg-info/
*.dist-info/
*.so
*.dll
dist/
build/
bin/
.mypy_cache/
.benchmarks/
# ignore compiled files
build
.idea/
.vscode/
# ignore the actual compiler
compiler
# IDA Files
*.id0
*.id1
*.id2
*.idb
*.i64
*.nam
*.til
*.til
main.elf
perf.mData
perf.mData.old
.gdb_history
.DS_Store
tools/aarch64-none-elf-objdump

31
CMakeLists.txt Normal file
View File

@ -0,0 +1,31 @@
cmake_minimum_required(VERSION 3.13)
project(odyssey CXX)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_NINJA_FORCE_RESPONSE_FILE ON)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
add_compile_options(-fdiagnostics-color=always)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_compile_options(-fcolor-diagnostics)
# Required to silence "unused argument" warnings for -stdlib=libc++ when using distcc
add_compile_options(-Wno-unused-command-line-argument)
# Required to fix source paths in debug info when using distcc
add_compile_options(-fdebug-prefix-map=/tmp=${CMAKE_CURRENT_BINARY_DIR})
endif()
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
add_executable(odyssey)
target_include_directories(odyssey PRIVATE src)
target_compile_options(odyssey PRIVATE -fno-rtti -fno-exceptions)
target_compile_options(odyssey PRIVATE -Wall -Wextra -Wdeprecated)
target_compile_options(odyssey PRIVATE -Wno-unused-parameter -Wno-unused-private-field)
target_compile_options(odyssey PRIVATE -fno-strict-aliasing)
target_compile_options(odyssey PRIVATE -Wno-invalid-offsetof)
add_subdirectory(src)
include_directories(include)
include_directories(include/aarch64)
include_directories(include/sead)

0
README.md Normal file → Executable file
View File

46
ToolchainNX64.cmake Normal file
View File

@ -0,0 +1,46 @@
if (NOT DEFINED ENV{UKING_CLANG})
message(FATAL_ERROR "Please define the UKING_CLANG env variable. It should point to a path such that $UKING_CLANG/bin/clang exists")
endif()
if (NOT DEFINED ENV{DEVKITA64})
message(FATAL_ERROR "Please define the DEVKITA64 env variable.")
endif()
set(UKING_CLANG "$ENV{UKING_CLANG}")
set(DEVKITA64 "$ENV{DEVKITA64}")
set(NX64_OPT_FLAGS "-O3 -g")
set(triple aarch64-none-elf)
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_SYSROOT ${UKING_CLANG})
set(CMAKE_C_COMPILER "${UKING_CLANG}/bin/clang")
set(CMAKE_C_COMPILER_TARGET ${triple})
set(CMAKE_CXX_COMPILER "${UKING_CLANG}/bin/clang++")
set(CMAKE_CXX_COMPILER_TARGET ${triple})
set(CMAKE_C_FLAGS_RELEASE ${NX64_OPT_FLAGS})
set(CMAKE_CXX_FLAGS_RELEASE ${NX64_OPT_FLAGS})
set(CMAKE_C_FLAGS_RELWITHDEBINFO ${NX64_OPT_FLAGS})
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO ${NX64_OPT_FLAGS})
set(ARCH "-mcpu=cortex-a57+fp+simd+crypto+crc")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ARCH} -isystem ${DEVKITA64}/aarch64-none-elf/include")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${UKING_CLANG}/include/c++/v1 -D _LIBCPP_HAS_THREAD_API_PTHREAD ${CMAKE_C_FLAGS}")
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -x assembler-with-cpp ${ARCH}")
add_compile_options(-fPIC -stdlib=libc++ -mno-implicit-float)
add_link_options(-B ${DEVKITA64}/bin -fPIC -Wl,-Bsymbolic-functions -shared -nodefaultlibs)
if(EXISTS "${DEVKITA64}/bin/ld.lld")
add_link_options(-fuse-ld=lld -Wl,-z,notext)
endif()
add_definitions(-D SWITCH -D __DEVKITA64__ -D __ELF__)
add_definitions(-D NNSDK)
add_definitions(-D MATCHING_HACK_NX_CLANG)
add_definitions(-D VER_100)
# Helps with matching as this causes Clang to emit debug type info even for dynamic classes
# with undefined vtables.
add_compile_options(-fstandalone-debug)

Binary file not shown.

0
compile.bat Normal file → Executable file
View File

12
compile.py Normal file → Executable file
View File

@ -11,21 +11,21 @@ gameVersion = versions[int(sys.argv[1])]
# todo -- 1.3.0 uses a different optimization method, find it
optimziation = "-O3"
root = pathlib.Path("compiler")
compilerPath = root / "nx/aarch64/bin/clang++.exe"
compilerPath = "../clang-4.0.1/bin/clang++"
compilerCommand = f"{compilerPath} -x c++ -w -std=gnu++14 -fno-strict-aliasing -fno-exceptions -fno-common -fno-short-enums -ffunction-sections -fdata-sections -fPIC -DNN_NINTENDO_SDK -DNN_SDK_BUILD_RELEASE -D{gameVersion} -DNNSDK {optimziation} -fomit-frame-pointer -mcpu=cortex-a57+fp+simd+crypto+crc -g -I include -I include/sead -I compiler/nx/aarch64/include -c "
source_folder = pathlib.Path('source/')
source_folder = pathlib.Path('src/')
cpp_files = list(source_folder.rglob('*.cpp'))
for cpp_file in cpp_files:
compilerCommand += str(cpp_file) + " "
if subprocess.call(compilerCommand) == 1:
if subprocess.call(compilerCommand, shell=True) == 1:
sys.exit(1)
# this all assumes that the user doesn't have a single build folder
if not os.path.isdir("build/VER_100"):
os.mkdir("build")
os.mkdir("build/VER_100")
os.mkdir("build/VER_110")
os.mkdir("build/VER_120")
@ -41,4 +41,4 @@ for o_file in o_files:
shutil.copy(o_file, buildDir)
os.remove(o_file)
print("Done.")
print("Done.")

499
data/data_symbols.csv Executable file
View File

@ -0,0 +1,499 @@
0x00000071023556B0,_ZTVN4sead14SafeStringBaseIcEE
0x0000007102356AF0,_ZTVN4sead22BufferedSafeStringBaseIcEE
0x000000710246F9E0,_ZN4ksys3gdt6detail13sCommonFlags0E
0x00000071024709E0,_ZN4ksys3gdt6detail13sCommonFlags1E
0x00000071024719E0,_ZN4ksys3gdt6detail13sCommonFlags2E
0x00000071024729E0,_ZN4ksys3gdt6detail13sCommonFlags3E
0x00000071024C0F18,_ZTVN3agl3utl13ParameterBaseE
0x00000071024C1060,_ZTVN3agl3utl9ParameterIbEE
0x00000071024C1100,_ZTVN3agl3utl9ParameterIfEE
0x00000071024C11A0,_ZTVN3agl3utl9ParameterIiEE
0x00000071024C1240,_ZTVN3agl3utl9ParameterIjEE
0x00000071024C12E0,_ZTVN3agl3utl9ParameterIN4sead7Vector2IfEEEE
0x00000071024C1380,_ZTVN3agl3utl9ParameterIN4sead7Vector3IfEEEE
0x00000071024C1420,_ZTVN3agl3utl9ParameterIN4sead7Vector4IfEEEE
0x00000071024C14C0,_ZTVN3agl3utl9ParameterIN4sead7Color4fEEE
0x00000071024C1560,_ZTVN3agl3utl9ParameterIN4sead4QuatIfEEEE
0x00000071024C1600,_ZTVN3agl3utl9ParameterIN4sead15FixedSafeStringILi64EEEEE
0x00000071024C16A0,_ZTVN3agl3utl9ParameterIN4sead15FixedSafeStringILi256EEEEE
0x00000071024C1740,_ZTVN3agl3utl9ParameterIN4sead14SafeStringBaseIcEEEE
0x00000071024D8D58,_ZTVN4ksys3act2ai10ActionBaseE
0x00000071025129E0,_ZTVN4ksys3act2ai6ActionE
0x0000007102513268,_ZTVN4ksys3act2ai2AiE
0x00000071025F75B0,pfnc_nvnDeviceBuilderSetDefaults
0x00000071025F75B8,pfnc_nvnDeviceBuilderSetFlags
0x00000071025F75C0,pfnc_nvnDeviceInitialize
0x00000071025F75C8,pfnc_nvnDeviceFinalize
0x00000071025F75D0,pfnc_nvnDeviceSetDebugLabel
0x00000071025F75D8,pfnc_nvnDeviceGetProcAddress
0x00000071025F75E0,pfnc_nvnDeviceGetInteger
0x00000071025F75E8,pfnc_nvnDeviceGetCurrentTimestampInNanoseconds
0x00000071025F75F0,pfnc_nvnDeviceSetIntermediateShaderCache
0x00000071025F75F8,pfnc_nvnDeviceGetTextureHandle
0x00000071025F7600,pfnc_nvnDeviceGetTexelFetchHandle
0x00000071025F7608,pfnc_nvnDeviceGetImageHandle
0x00000071025F7610,pfnc_nvnDeviceInstallDebugCallback
0x00000071025F7618,pfnc_nvnDeviceGenerateDebugDomainId
0x00000071025F7620,pfnc_nvnDeviceSetWindowOriginMode
0x00000071025F7628,pfnc_nvnDeviceSetDepthMode
0x00000071025F7630,pfnc_nvnDeviceRegisterFastClearColor
0x00000071025F7638,pfnc_nvnDeviceRegisterFastClearColori
0x00000071025F7640,pfnc_nvnDeviceRegisterFastClearColorui
0x00000071025F7648,pfnc_nvnDeviceRegisterFastClearDepth
0x00000071025F7650,pfnc_nvnDeviceGetWindowOriginMode
0x00000071025F7658,pfnc_nvnDeviceGetDepthMode
0x00000071025F7660,pfnc_nvnDeviceGetTimestampInNanoseconds
0x00000071025F7668,pfnc_nvnDeviceApplyDeferredFinalizes
0x00000071025F7670,pfnc_nvnDeviceFinalizeCommandHandle
0x00000071025F7678,pfnc_nvnDeviceWalkDebugDatabase
0x00000071025F7680,pfnc_nvnDeviceGetSeparateTextureHandle
0x00000071025F7688,pfnc_nvnDeviceGetSeparateSamplerHandle
0x00000071025F7690,pfnc_nvnDeviceIsExternalDebuggerAttached
0x00000071025F7698,pfnc_nvnQueueGetError
0x00000071025F76A0,pfnc_nvnQueueGetTotalCommandMemoryUsed
0x00000071025F76A8,pfnc_nvnQueueGetTotalControlMemoryUsed
0x00000071025F76B0,pfnc_nvnQueueGetTotalComputeMemoryUsed
0x00000071025F76B8,pfnc_nvnQueueResetMemoryUsageCounts
0x00000071025F76C0,pfnc_nvnQueueBuilderSetDevice
0x00000071025F76C8,pfnc_nvnQueueBuilderSetDefaults
0x00000071025F76D0,pfnc_nvnQueueBuilderSetFlags
0x00000071025F76D8,pfnc_nvnQueueBuilderSetCommandMemorySize
0x00000071025F76E0,pfnc_nvnQueueBuilderSetComputeMemorySize
0x00000071025F76E8,pfnc_nvnQueueBuilderSetControlMemorySize
0x00000071025F76F0,pfnc_nvnQueueBuilderGetQueueMemorySize
0x00000071025F76F8,pfnc_nvnQueueBuilderSetQueueMemory
0x00000071025F7700,pfnc_nvnQueueBuilderSetCommandFlushThreshold
0x00000071025F7708,pfnc_nvnQueueInitialize
0x00000071025F7710,pfnc_nvnQueueFinalize
0x00000071025F7718,pfnc_nvnQueueSetDebugLabel
0x00000071025F7720,pfnc_nvnQueueSubmitCommands
0x00000071025F7728,pfnc_nvnQueueFlush
0x00000071025F7730,pfnc_nvnQueueFinish
0x00000071025F7738,pfnc_nvnQueuePresentTexture
0x00000071025F7740,pfnc_nvnQueueAcquireTexture
0x00000071025F7748,pfnc_nvnWindowBuilderSetDevice
0x00000071025F7750,pfnc_nvnWindowBuilderSetDefaults
0x00000071025F7758,pfnc_nvnWindowBuilderSetNativeWindow
0x00000071025F7760,pfnc_nvnWindowBuilderSetTextures
0x00000071025F7768,pfnc_nvnWindowBuilderSetPresentInterval
0x00000071025F7770,pfnc_nvnWindowBuilderGetNativeWindow
0x00000071025F7778,pfnc_nvnWindowBuilderGetPresentInterval
0x00000071025F7780,pfnc_nvnWindowInitialize
0x00000071025F7788,pfnc_nvnWindowFinalize
0x00000071025F7790,pfnc_nvnWindowSetDebugLabel
0x00000071025F7798,pfnc_nvnWindowAcquireTexture
0x00000071025F77A0,pfnc_nvnWindowGetNativeWindow
0x00000071025F77A8,pfnc_nvnWindowGetPresentInterval
0x00000071025F77B0,pfnc_nvnWindowSetPresentInterval
0x00000071025F77B8,pfnc_nvnWindowSetCrop
0x00000071025F77C0,pfnc_nvnWindowGetCrop
0x00000071025F77C8,pfnc_nvnProgramInitialize
0x00000071025F77D0,pfnc_nvnProgramFinalize
0x00000071025F77D8,pfnc_nvnProgramSetDebugLabel
0x00000071025F77E0,pfnc_nvnProgramSetShaders
0x00000071025F77E8,pfnc_nvnMemoryPoolBuilderSetDevice
0x00000071025F77F0,pfnc_nvnMemoryPoolBuilderSetDefaults
0x00000071025F77F8,pfnc_nvnMemoryPoolBuilderSetStorage
0x00000071025F7800,pfnc_nvnMemoryPoolBuilderSetFlags
0x00000071025F7808,pfnc_nvnMemoryPoolBuilderGetMemory
0x00000071025F7810,pfnc_nvnMemoryPoolBuilderGetSize
0x00000071025F7818,pfnc_nvnMemoryPoolBuilderGetFlags
0x00000071025F7820,pfnc_nvnMemoryPoolInitialize
0x00000071025F7828,pfnc_nvnMemoryPoolSetDebugLabel
0x00000071025F7830,pfnc_nvnMemoryPoolFinalize
0x00000071025F7838,pfnc_nvnMemoryPoolMap
0x00000071025F7840,pfnc_nvnMemoryPoolFlushMappedRange
0x00000071025F7848,pfnc_nvnMemoryPoolInvalidateMappedRange
0x00000071025F7850,pfnc_nvnMemoryPoolGetBufferAddress
0x00000071025F7858,pfnc_nvnMemoryPoolMapVirtual
0x00000071025F7860,pfnc_nvnMemoryPoolGetSize
0x00000071025F7868,pfnc_nvnMemoryPoolGetFlags
0x00000071025F7870,pfnc_nvnTexturePoolInitialize
0x00000071025F7878,pfnc_nvnTexturePoolSetDebugLabel
0x00000071025F7880,pfnc_nvnTexturePoolFinalize
0x00000071025F7888,pfnc_nvnTexturePoolRegisterTexture
0x00000071025F7890,pfnc_nvnTexturePoolRegisterImage
0x00000071025F7898,pfnc_nvnTexturePoolGetMemoryPool
0x00000071025F78A0,pfnc_nvnTexturePoolGetMemoryOffset
0x00000071025F78A8,pfnc_nvnTexturePoolGetSize
0x00000071025F78B0,pfnc_nvnSamplerPoolInitialize
0x00000071025F78B8,pfnc_nvnSamplerPoolSetDebugLabel
0x00000071025F78C0,pfnc_nvnSamplerPoolFinalize
0x00000071025F78C8,pfnc_nvnSamplerPoolRegisterSampler
0x00000071025F78D0,pfnc_nvnSamplerPoolRegisterSamplerBuilder
0x00000071025F78D8,pfnc_nvnSamplerPoolGetMemoryPool
0x00000071025F78E0,pfnc_nvnSamplerPoolGetMemoryOffset
0x00000071025F78E8,pfnc_nvnSamplerPoolGetSize
0x00000071025F78F0,pfnc_nvnBufferBuilderSetDevice
0x00000071025F78F8,pfnc_nvnBufferBuilderSetDefaults
0x00000071025F7900,pfnc_nvnBufferBuilderSetStorage
0x00000071025F7908,pfnc_nvnBufferBuilderGetMemoryPool
0x00000071025F7910,pfnc_nvnBufferBuilderGetMemoryOffset
0x00000071025F7918,pfnc_nvnBufferBuilderGetSize
0x00000071025F7920,pfnc_nvnBufferInitialize
0x00000071025F7928,pfnc_nvnBufferSetDebugLabel
0x00000071025F7930,pfnc_nvnBufferFinalize
0x00000071025F7938,pfnc_nvnBufferMap
0x00000071025F7940,pfnc_nvnBufferGetAddress
0x00000071025F7948,pfnc_nvnBufferFlushMappedRange
0x00000071025F7950,pfnc_nvnBufferInvalidateMappedRange
0x00000071025F7958,pfnc_nvnBufferGetMemoryPool
0x00000071025F7960,pfnc_nvnBufferGetMemoryOffset
0x00000071025F7968,pfnc_nvnBufferGetSize
0x00000071025F7970,pfnc_nvnBufferGetDebugID
0x00000071025F7978,pfnc_nvnTextureBuilderSetDevice
0x00000071025F7980,pfnc_nvnTextureBuilderSetDefaults
0x00000071025F7988,pfnc_nvnTextureBuilderSetFlags
0x00000071025F7990,pfnc_nvnTextureBuilderSetTarget
0x00000071025F7998,pfnc_nvnTextureBuilderSetWidth
0x00000071025F79A0,pfnc_nvnTextureBuilderSetHeight
0x00000071025F79A8,pfnc_nvnTextureBuilderSetDepth
0x00000071025F79B0,pfnc_nvnTextureBuilderSetSize1D
0x00000071025F79B8,pfnc_nvnTextureBuilderSetSize2D
0x00000071025F79C0,pfnc_nvnTextureBuilderSetSize3D
0x00000071025F79C8,pfnc_nvnTextureBuilderSetLevels
0x00000071025F79D0,pfnc_nvnTextureBuilderSetFormat
0x00000071025F79D8,pfnc_nvnTextureBuilderSetSamples
0x00000071025F79E0,pfnc_nvnTextureBuilderSetSwizzle
0x00000071025F79E8,pfnc_nvnTextureBuilderSetDepthStencilMode
0x00000071025F79F0,pfnc_nvnTextureBuilderGetStorageSize
0x00000071025F79F8,pfnc_nvnTextureBuilderGetStorageAlignment
0x00000071025F7A00,pfnc_nvnTextureBuilderSetStorage
0x00000071025F7A08,pfnc_nvnTextureBuilderSetPackagedTextureData
0x00000071025F7A10,pfnc_nvnTextureBuilderSetPackagedTextureLayout
0x00000071025F7A18,pfnc_nvnTextureBuilderSetStride
0x00000071025F7A20,pfnc_nvnTextureBuilderSetGLTextureName
0x00000071025F7A28,pfnc_nvnTextureBuilderGetStorageClass
0x00000071025F7A30,pfnc_nvnTextureBuilderGetFlags
0x00000071025F7A38,pfnc_nvnTextureBuilderGetTarget
0x00000071025F7A40,pfnc_nvnTextureBuilderGetWidth
0x00000071025F7A48,pfnc_nvnTextureBuilderGetHeight
0x00000071025F7A50,pfnc_nvnTextureBuilderGetDepth
0x00000071025F7A58,pfnc_nvnTextureBuilderGetLevels
0x00000071025F7A60,pfnc_nvnTextureBuilderGetFormat
0x00000071025F7A68,pfnc_nvnTextureBuilderGetSamples
0x00000071025F7A70,pfnc_nvnTextureBuilderGetSwizzle
0x00000071025F7A78,pfnc_nvnTextureBuilderGetDepthStencilMode
0x00000071025F7A80,pfnc_nvnTextureBuilderGetPackagedTextureData
0x00000071025F7A88,pfnc_nvnTextureBuilderGetStride
0x00000071025F7A90,pfnc_nvnTextureBuilderGetSparseTileLayout
0x00000071025F7A98,pfnc_nvnTextureBuilderGetGLTextureName
0x00000071025F7AA0,pfnc_nvnTextureBuilderGetZCullStorageSize
0x00000071025F7AA8,pfnc_nvnTextureBuilderGetMemoryPool
0x00000071025F7AB0,pfnc_nvnTextureBuilderGetMemoryOffset
0x00000071025F7AB8,pfnc_nvnTextureViewSetDefaults
0x00000071025F7AC0,pfnc_nvnTextureViewSetLevels
0x00000071025F7AC8,pfnc_nvnTextureViewSetLayers
0x00000071025F7AD0,pfnc_nvnTextureViewSetFormat
0x00000071025F7AD8,pfnc_nvnTextureViewSetSwizzle
0x00000071025F7AE0,pfnc_nvnTextureViewSetDepthStencilMode
0x00000071025F7AE8,pfnc_nvnTextureViewSetTarget
0x00000071025F7AF0,pfnc_nvnTextureViewGetLevels
0x00000071025F7AF8,pfnc_nvnTextureViewGetLayers
0x00000071025F7B00,pfnc_nvnTextureViewGetFormat
0x00000071025F7B08,pfnc_nvnTextureViewGetSwizzle
0x00000071025F7B10,pfnc_nvnTextureViewGetDepthStencilMode
0x00000071025F7B18,pfnc_nvnTextureViewGetTarget
0x00000071025F7B20,pfnc_nvnTextureViewCompare
0x00000071025F7B28,pfnc_nvnTextureInitialize
0x00000071025F7B30,pfnc_nvnTextureGetZCullStorageSize
0x00000071025F7B38,pfnc_nvnTextureFinalize
0x00000071025F7B40,pfnc_nvnTextureSetDebugLabel
0x00000071025F7B48,pfnc_nvnTextureGetStorageClass
0x00000071025F7B50,pfnc_nvnTextureGetViewOffset
0x00000071025F7B58,pfnc_nvnTextureGetFlags
0x00000071025F7B60,pfnc_nvnTextureGetTarget
0x00000071025F7B68,pfnc_nvnTextureGetWidth
0x00000071025F7B70,pfnc_nvnTextureGetHeight
0x00000071025F7B78,pfnc_nvnTextureGetDepth
0x00000071025F7B80,pfnc_nvnTextureGetLevels
0x00000071025F7B88,pfnc_nvnTextureGetFormat
0x00000071025F7B90,pfnc_nvnTextureGetSamples
0x00000071025F7B98,pfnc_nvnTextureGetSwizzle
0x00000071025F7BA0,pfnc_nvnTextureGetDepthStencilMode
0x00000071025F7BA8,pfnc_nvnTextureGetStride
0x00000071025F7BB0,pfnc_nvnTextureGetTextureAddress
0x00000071025F7BB8,pfnc_nvnTextureGetSparseTileLayout
0x00000071025F7BC0,pfnc_nvnTextureWriteTexels
0x00000071025F7BC8,pfnc_nvnTextureWriteTexelsStrided
0x00000071025F7BD0,pfnc_nvnTextureReadTexels
0x00000071025F7BD8,pfnc_nvnTextureReadTexelsStrided
0x00000071025F7BE0,pfnc_nvnTextureFlushTexels
0x00000071025F7BE8,pfnc_nvnTextureInvalidateTexels
0x00000071025F7BF0,pfnc_nvnTextureGetMemoryPool
0x00000071025F7BF8,pfnc_nvnTextureGetMemoryOffset
0x00000071025F7C00,pfnc_nvnTextureGetStorageSize
0x00000071025F7C08,pfnc_nvnTextureCompare
0x00000071025F7C10,pfnc_nvnTextureGetDebugID
0x00000071025F7C18,pfnc_nvnSamplerBuilderSetDevice
0x00000071025F7C20,pfnc_nvnSamplerBuilderSetDefaults
0x00000071025F7C28,pfnc_nvnSamplerBuilderSetMinMagFilter
0x00000071025F7C30,pfnc_nvnSamplerBuilderSetWrapMode
0x00000071025F7C38,pfnc_nvnSamplerBuilderSetLodClamp
0x00000071025F7C40,pfnc_nvnSamplerBuilderSetLodBias
0x00000071025F7C48,pfnc_nvnSamplerBuilderSetCompare
0x00000071025F7C50,pfnc_nvnSamplerBuilderSetBorderColor
0x00000071025F7C58,pfnc_nvnSamplerBuilderSetBorderColori
0x00000071025F7C60,pfnc_nvnSamplerBuilderSetBorderColorui
0x00000071025F7C68,pfnc_nvnSamplerBuilderSetMaxAnisotropy
0x00000071025F7C70,pfnc_nvnSamplerBuilderSetReductionFilter
0x00000071025F7C78,pfnc_nvnSamplerBuilderSetLodSnap
0x00000071025F7C80,pfnc_nvnSamplerBuilderGetMinMagFilter
0x00000071025F7C88,pfnc_nvnSamplerBuilderGetWrapMode
0x00000071025F7C90,pfnc_nvnSamplerBuilderGetLodClamp
0x00000071025F7C98,pfnc_nvnSamplerBuilderGetLodBias
0x00000071025F7CA0,pfnc_nvnSamplerBuilderGetCompare
0x00000071025F7CA8,pfnc_nvnSamplerBuilderGetBorderColor
0x00000071025F7CB0,pfnc_nvnSamplerBuilderGetBorderColori
0x00000071025F7CB8,pfnc_nvnSamplerBuilderGetBorderColorui
0x00000071025F7CC0,pfnc_nvnSamplerBuilderGetMaxAnisotropy
0x00000071025F7CC8,pfnc_nvnSamplerBuilderGetReductionFilter
0x00000071025F7CD0,pfnc_nvnSamplerBuilderGetLodSnap
0x00000071025F7CD8,pfnc_nvnSamplerInitialize
0x00000071025F7CE0,pfnc_nvnSamplerFinalize
0x00000071025F7CE8,pfnc_nvnSamplerSetDebugLabel
0x00000071025F7CF0,pfnc_nvnSamplerGetMinMagFilter
0x00000071025F7CF8,pfnc_nvnSamplerGetWrapMode
0x00000071025F7D00,pfnc_nvnSamplerGetLodClamp
0x00000071025F7D08,pfnc_nvnSamplerGetLodBias
0x00000071025F7D10,pfnc_nvnSamplerGetCompare
0x00000071025F7D18,pfnc_nvnSamplerGetBorderColor
0x00000071025F7D20,pfnc_nvnSamplerGetBorderColori
0x00000071025F7D28,pfnc_nvnSamplerGetBorderColorui
0x00000071025F7D30,pfnc_nvnSamplerGetMaxAnisotropy
0x00000071025F7D38,pfnc_nvnSamplerGetReductionFilter
0x00000071025F7D40,pfnc_nvnSamplerCompare
0x00000071025F7D48,pfnc_nvnSamplerGetDebugID
0x00000071025F7D50,pfnc_nvnBlendStateSetDefaults
0x00000071025F7D58,pfnc_nvnBlendStateSetBlendTarget
0x00000071025F7D60,pfnc_nvnBlendStateSetBlendFunc
0x00000071025F7D68,pfnc_nvnBlendStateSetBlendEquation
0x00000071025F7D70,pfnc_nvnBlendStateSetAdvancedMode
0x00000071025F7D78,pfnc_nvnBlendStateSetAdvancedOverlap
0x00000071025F7D80,pfnc_nvnBlendStateSetAdvancedPremultipliedSrc
0x00000071025F7D88,pfnc_nvnBlendStateSetAdvancedNormalizedDst
0x00000071025F7D90,pfnc_nvnBlendStateGetBlendTarget
0x00000071025F7D98,pfnc_nvnBlendStateGetBlendFunc
0x00000071025F7DA0,pfnc_nvnBlendStateGetBlendEquation
0x00000071025F7DA8,pfnc_nvnBlendStateGetAdvancedMode
0x00000071025F7DB0,pfnc_nvnBlendStateGetAdvancedOverlap
0x00000071025F7DB8,pfnc_nvnBlendStateGetAdvancedPremultipliedSrc
0x00000071025F7DC0,pfnc_nvnBlendStateGetAdvancedNormalizedDst
0x00000071025F7DC8,pfnc_nvnColorStateSetDefaults
0x00000071025F7DD0,pfnc_nvnColorStateSetBlendEnable
0x00000071025F7DD8,pfnc_nvnColorStateSetLogicOp
0x00000071025F7DE0,pfnc_nvnColorStateSetAlphaTest
0x00000071025F7DE8,pfnc_nvnColorStateGetBlendEnable
0x00000071025F7DF0,pfnc_nvnColorStateGetLogicOp
0x00000071025F7DF8,pfnc_nvnColorStateGetAlphaTest
0x00000071025F7E00,pfnc_nvnChannelMaskStateSetDefaults
0x00000071025F7E08,pfnc_nvnChannelMaskStateSetChannelMask
0x00000071025F7E10,pfnc_nvnChannelMaskStateGetChannelMask
0x00000071025F7E18,pfnc_nvnMultisampleStateSetDefaults
0x00000071025F7E20,pfnc_nvnMultisampleStateSetMultisampleEnable
0x00000071025F7E28,pfnc_nvnMultisampleStateSetSamples
0x00000071025F7E30,pfnc_nvnMultisampleStateSetAlphaToCoverageEnable
0x00000071025F7E38,pfnc_nvnMultisampleStateSetAlphaToCoverageDither
0x00000071025F7E40,pfnc_nvnMultisampleStateGetMultisampleEnable
0x00000071025F7E48,pfnc_nvnMultisampleStateGetSamples
0x00000071025F7E50,pfnc_nvnMultisampleStateGetAlphaToCoverageEnable
0x00000071025F7E58,pfnc_nvnMultisampleStateGetAlphaToCoverageDither
0x00000071025F7E60,pfnc_nvnMultisampleStateSetRasterSamples
0x00000071025F7E68,pfnc_nvnMultisampleStateGetRasterSamples
0x00000071025F7E70,pfnc_nvnMultisampleStateSetCoverageModulationMode
0x00000071025F7E78,pfnc_nvnMultisampleStateGetCoverageModulationMode
0x00000071025F7E80,pfnc_nvnMultisampleStateSetCoverageToColorEnable
0x00000071025F7E88,pfnc_nvnMultisampleStateGetCoverageToColorEnable
0x00000071025F7E90,pfnc_nvnMultisampleStateSetCoverageToColorOutput
0x00000071025F7E98,pfnc_nvnMultisampleStateGetCoverageToColorOutput
0x00000071025F7EA0,pfnc_nvnMultisampleStateSetSampleLocationsEnable
0x00000071025F7EA8,pfnc_nvnMultisampleStateGetSampleLocationsEnable
0x00000071025F7EB0,pfnc_nvnMultisampleStateGetSampleLocationsGrid
0x00000071025F7EB8,pfnc_nvnMultisampleStateSetSampleLocationsGridEnable
0x00000071025F7EC0,pfnc_nvnMultisampleStateGetSampleLocationsGridEnable
0x00000071025F7EC8,pfnc_nvnMultisampleStateSetSampleLocations
0x00000071025F7ED0,pfnc_nvnPolygonStateSetDefaults
0x00000071025F7ED8,pfnc_nvnPolygonStateSetCullFace
0x00000071025F7EE0,pfnc_nvnPolygonStateSetFrontFace
0x00000071025F7EE8,pfnc_nvnPolygonStateSetPolygonMode
0x00000071025F7EF0,pfnc_nvnPolygonStateSetPolygonOffsetEnables
0x00000071025F7EF8,pfnc_nvnPolygonStateGetCullFace
0x00000071025F7F00,pfnc_nvnPolygonStateGetFrontFace
0x00000071025F7F08,pfnc_nvnPolygonStateGetPolygonMode
0x00000071025F7F10,pfnc_nvnPolygonStateGetPolygonOffsetEnables
0x00000071025F7F18,pfnc_nvnDepthStencilStateSetDefaults
0x00000071025F7F20,pfnc_nvnDepthStencilStateSetDepthTestEnable
0x00000071025F7F28,pfnc_nvnDepthStencilStateSetDepthWriteEnable
0x00000071025F7F30,pfnc_nvnDepthStencilStateSetDepthFunc
0x00000071025F7F38,pfnc_nvnDepthStencilStateSetStencilTestEnable
0x00000071025F7F40,pfnc_nvnDepthStencilStateSetStencilFunc
0x00000071025F7F48,pfnc_nvnDepthStencilStateSetStencilOp
0x00000071025F7F50,pfnc_nvnDepthStencilStateGetDepthTestEnable
0x00000071025F7F58,pfnc_nvnDepthStencilStateGetDepthWriteEnable
0x00000071025F7F60,pfnc_nvnDepthStencilStateGetDepthFunc
0x00000071025F7F68,pfnc_nvnDepthStencilStateGetStencilTestEnable
0x00000071025F7F70,pfnc_nvnDepthStencilStateGetStencilFunc
0x00000071025F7F78,pfnc_nvnDepthStencilStateGetStencilOp
0x00000071025F7F80,pfnc_nvnVertexAttribStateSetDefaults
0x00000071025F7F88,pfnc_nvnVertexAttribStateSetFormat
0x00000071025F7F90,pfnc_nvnVertexAttribStateSetStreamIndex
0x00000071025F7F98,pfnc_nvnVertexAttribStateGetFormat
0x00000071025F7FA0,pfnc_nvnVertexAttribStateGetStreamIndex
0x00000071025F7FA8,pfnc_nvnVertexStreamStateSetDefaults
0x00000071025F7FB0,pfnc_nvnVertexStreamStateSetStride
0x00000071025F7FB8,pfnc_nvnVertexStreamStateSetDivisor
0x00000071025F7FC0,pfnc_nvnVertexStreamStateGetStride
0x00000071025F7FC8,pfnc_nvnVertexStreamStateGetDivisor
0x00000071025F7FD0,pfnc_nvnCommandBufferInitialize
0x00000071025F7FD8,pfnc_nvnCommandBufferFinalize
0x00000071025F7FE0,pfnc_nvnCommandBufferSetDebugLabel
0x00000071025F7FE8,pfnc_nvnCommandBufferSetMemoryCallback
0x00000071025F7FF0,pfnc_nvnCommandBufferSetMemoryCallbackData
0x00000071025F7FF8,pfnc_nvnCommandBufferAddCommandMemory
0x00000071025F8000,pfnc_nvnCommandBufferAddControlMemory
0x00000071025F8008,pfnc_nvnCommandBufferGetCommandMemorySize
0x00000071025F8010,pfnc_nvnCommandBufferGetCommandMemoryUsed
0x00000071025F8018,pfnc_nvnCommandBufferGetCommandMemoryFree
0x00000071025F8020,pfnc_nvnCommandBufferGetControlMemorySize
0x00000071025F8028,pfnc_nvnCommandBufferGetControlMemoryUsed
0x00000071025F8030,pfnc_nvnCommandBufferGetControlMemoryFree
0x00000071025F8038,pfnc_nvnCommandBufferBeginRecording
0x00000071025F8040,pfnc_nvnCommandBufferEndRecording
0x00000071025F8048,pfnc_nvnCommandBufferCallCommands
0x00000071025F8050,pfnc_nvnCommandBufferCopyCommands
0x00000071025F8058,pfnc_nvnCommandBufferBindBlendState
0x00000071025F8060,pfnc_nvnCommandBufferBindChannelMaskState
0x00000071025F8068,pfnc_nvnCommandBufferBindColorState
0x00000071025F8070,pfnc_nvnCommandBufferBindMultisampleState
0x00000071025F8078,pfnc_nvnCommandBufferBindPolygonState
0x00000071025F8080,pfnc_nvnCommandBufferBindDepthStencilState
0x00000071025F8088,pfnc_nvnCommandBufferBindVertexAttribState
0x00000071025F8090,pfnc_nvnCommandBufferBindVertexStreamState
0x00000071025F8098,pfnc_nvnCommandBufferBindProgram
0x00000071025F80A0,pfnc_nvnCommandBufferBindVertexBuffer
0x00000071025F80A8,pfnc_nvnCommandBufferBindVertexBuffers
0x00000071025F80B0,pfnc_nvnCommandBufferBindUniformBuffer
0x00000071025F80B8,pfnc_nvnCommandBufferBindUniformBuffers
0x00000071025F80C0,pfnc_nvnCommandBufferBindTransformFeedbackBuffer
0x00000071025F80C8,pfnc_nvnCommandBufferBindTransformFeedbackBuffers
0x00000071025F80D0,pfnc_nvnCommandBufferBindStorageBuffer
0x00000071025F80D8,pfnc_nvnCommandBufferBindStorageBuffers
0x00000071025F80E0,pfnc_nvnCommandBufferBindTexture
0x00000071025F80E8,pfnc_nvnCommandBufferBindTextures
0x00000071025F80F0,pfnc_nvnCommandBufferBindImage
0x00000071025F80F8,pfnc_nvnCommandBufferBindImages
0x00000071025F8100,pfnc_nvnCommandBufferSetPatchSize
0x00000071025F8108,pfnc_nvnCommandBufferSetInnerTessellationLevels
0x00000071025F8110,pfnc_nvnCommandBufferSetOuterTessellationLevels
0x00000071025F8118,pfnc_nvnCommandBufferSetPrimitiveRestart
0x00000071025F8120,pfnc_nvnCommandBufferBeginTransformFeedback
0x00000071025F8128,pfnc_nvnCommandBufferEndTransformFeedback
0x00000071025F8130,pfnc_nvnCommandBufferPauseTransformFeedback
0x00000071025F8138,pfnc_nvnCommandBufferResumeTransformFeedback
0x00000071025F8140,pfnc_nvnCommandBufferDrawTransformFeedback
0x00000071025F8148,pfnc_nvnCommandBufferDrawArrays
0x00000071025F8150,pfnc_nvnCommandBufferDrawElements
0x00000071025F8158,pfnc_nvnCommandBufferDrawElementsBaseVertex
0x00000071025F8160,pfnc_nvnCommandBufferDrawArraysInstanced
0x00000071025F8168,pfnc_nvnCommandBufferDrawElementsInstanced
0x00000071025F8170,pfnc_nvnCommandBufferDrawArraysIndirect
0x00000071025F8178,pfnc_nvnCommandBufferDrawElementsIndirect
0x00000071025F8180,pfnc_nvnCommandBufferMultiDrawArraysIndirectCount
0x00000071025F8188,pfnc_nvnCommandBufferMultiDrawElementsIndirectCount
0x00000071025F8190,pfnc_nvnCommandBufferClearColor
0x00000071025F8198,pfnc_nvnCommandBufferClearColori
0x00000071025F81A0,pfnc_nvnCommandBufferClearColorui
0x00000071025F81A8,pfnc_nvnCommandBufferClearDepthStencil
0x00000071025F81B0,pfnc_nvnCommandBufferDispatchCompute
0x00000071025F81B8,pfnc_nvnCommandBufferDispatchComputeIndirect
0x00000071025F81C0,pfnc_nvnCommandBufferSetViewport
0x00000071025F81C8,pfnc_nvnCommandBufferSetViewports
0x00000071025F81D0,pfnc_nvnCommandBufferSetViewportSwizzles
0x00000071025F81D8,pfnc_nvnCommandBufferSetScissor
0x00000071025F81E0,pfnc_nvnCommandBufferSetScissors
0x00000071025F81E8,pfnc_nvnCommandBufferSetDepthRange
0x00000071025F81F0,pfnc_nvnCommandBufferSetDepthBounds
0x00000071025F81F8,pfnc_nvnCommandBufferSetDepthRanges
0x00000071025F8200,pfnc_nvnCommandBufferSetTiledCacheAction
0x00000071025F8208,pfnc_nvnCommandBufferSetTiledCacheTileSize
0x00000071025F8210,pfnc_nvnCommandBufferBindSeparateTexture
0x00000071025F8218,pfnc_nvnCommandBufferBindSeparateSampler
0x00000071025F8220,pfnc_nvnCommandBufferBindSeparateTextures
0x00000071025F8228,pfnc_nvnCommandBufferBindSeparateSamplers
0x00000071025F8230,pfnc_nvnCommandBufferSetStencilValueMask
0x00000071025F8238,pfnc_nvnCommandBufferSetStencilMask
0x00000071025F8240,pfnc_nvnCommandBufferSetStencilRef
0x00000071025F8248,pfnc_nvnCommandBufferSetBlendColor
0x00000071025F8250,pfnc_nvnCommandBufferSetPointSize
0x00000071025F8258,pfnc_nvnCommandBufferSetLineWidth
0x00000071025F8260,pfnc_nvnCommandBufferSetPolygonOffsetClamp
0x00000071025F8268,pfnc_nvnCommandBufferSetAlphaRef
0x00000071025F8270,pfnc_nvnCommandBufferSetSampleMask
0x00000071025F8278,pfnc_nvnCommandBufferSetRasterizerDiscard
0x00000071025F8280,pfnc_nvnCommandBufferSetDepthClamp
0x00000071025F8288,pfnc_nvnCommandBufferSetConservativeRasterEnable
0x00000071025F8290,pfnc_nvnCommandBufferSetConservativeRasterDilate
0x00000071025F8298,pfnc_nvnCommandBufferSetSubpixelPrecisionBias
0x00000071025F82A0,pfnc_nvnCommandBufferCopyBufferToTexture
0x00000071025F82A8,pfnc_nvnCommandBufferCopyTextureToBuffer
0x00000071025F82B0,pfnc_nvnCommandBufferCopyTextureToTexture
0x00000071025F82B8,pfnc_nvnCommandBufferCopyBufferToBuffer
0x00000071025F82C0,pfnc_nvnCommandBufferClearBuffer
0x00000071025F82C8,pfnc_nvnCommandBufferClearTexture
0x00000071025F82D0,pfnc_nvnCommandBufferClearTexturei
0x00000071025F82D8,pfnc_nvnCommandBufferClearTextureui
0x00000071025F82E0,pfnc_nvnCommandBufferUpdateUniformBuffer
0x00000071025F82E8,pfnc_nvnCommandBufferReportCounter
0x00000071025F82F0,pfnc_nvnCommandBufferResetCounter
0x00000071025F82F8,pfnc_nvnCommandBufferReportValue
0x00000071025F8300,pfnc_nvnCommandBufferSetRenderEnable
0x00000071025F8308,pfnc_nvnCommandBufferSetRenderEnableConditional
0x00000071025F8310,pfnc_nvnCommandBufferSetRenderTargets
0x00000071025F8318,pfnc_nvnCommandBufferDiscardColor
0x00000071025F8320,pfnc_nvnCommandBufferDiscardDepthStencil
0x00000071025F8328,pfnc_nvnCommandBufferDownsample
0x00000071025F8330,pfnc_nvnCommandBufferTiledDownsample
0x00000071025F8338,pfnc_nvnCommandBufferDownsampleTextureView
0x00000071025F8340,pfnc_nvnCommandBufferTiledDownsampleTextureView
0x00000071025F8348,pfnc_nvnCommandBufferBarrier
0x00000071025F8350,pfnc_nvnCommandBufferWaitSync
0x00000071025F8358,pfnc_nvnCommandBufferFenceSync
0x00000071025F8360,pfnc_nvnCommandBufferSetTexturePool
0x00000071025F8368,pfnc_nvnCommandBufferSetSamplerPool
0x00000071025F8370,pfnc_nvnCommandBufferSetShaderScratchMemory
0x00000071025F8378,pfnc_nvnCommandBufferSaveZCullData
0x00000071025F8380,pfnc_nvnCommandBufferRestoreZCullData
0x00000071025F8388,pfnc_nvnCommandBufferSetCopyRowStride
0x00000071025F8390,pfnc_nvnCommandBufferSetCopyImageStride
0x00000071025F8398,pfnc_nvnCommandBufferGetCopyRowStride
0x00000071025F83A0,pfnc_nvnCommandBufferGetCopyImageStride
0x00000071025F83A8,pfnc_nvnCommandBufferDrawTexture
0x00000071025F83B0,pfnc_nvnProgramSetSubroutineLinkage
0x00000071025F83B8,pfnc_nvnCommandBufferSetProgramSubroutines
0x00000071025F83C0,pfnc_nvnCommandBufferBindCoverageModulationTable
0x00000071025F83C8,pfnc_nvnCommandBufferResolveDepthBuffer
0x00000071025F83D0,pfnc_nvnCommandBufferPushDebugGroupStatic
0x00000071025F83D8,pfnc_nvnCommandBufferPushDebugGroupDynamic
0x00000071025F83E0,pfnc_nvnCommandBufferPushDebugGroup
0x00000071025F83E8,pfnc_nvnCommandBufferPopDebugGroup
0x00000071025F83F0,pfnc_nvnCommandBufferPopDebugGroupId
0x00000071025F83F8,pfnc_nvnCommandBufferInsertDebugMarkerStatic
0x00000071025F8400,pfnc_nvnCommandBufferInsertDebugMarkerDynamic
0x00000071025F8408,pfnc_nvnCommandBufferInsertDebugMarker
0x00000071025F8410,pfnc_nvnCommandBufferGetMemoryCallback
0x00000071025F8418,pfnc_nvnCommandBufferGetMemoryCallbackData
0x00000071025F8420,pfnc_nvnCommandBufferIsRecording
0x00000071025F8428,pfnc_nvnSyncInitialize
0x00000071025F8430,pfnc_nvnSyncFinalize
0x00000071025F8438,pfnc_nvnSyncSetDebugLabel
0x00000071025F8440,pfnc_nvnQueueFenceSync
0x00000071025F8448,pfnc_nvnSyncWait
0x00000071025F8450,pfnc_nvnQueueWaitSync
0x00000071025F8458,pfnc_nvnEventBuilderSetDefaults
0x00000071025F8460,pfnc_nvnEventBuilderSetStorage
0x00000071025F8468,pfnc_nvnEventInitialize
0x00000071025F8470,pfnc_nvnEventFinalize
0x00000071025F8478,pfnc_nvnEventGetValue
0x00000071025F8480,pfnc_nvnEventSignal
0x00000071025F8488,pfnc_nvnCommandBufferWaitEvent
0x00000071025F8490,pfnc_nvnCommandBufferSignalEvent
1 0x00000071023556B0 _ZTVN4sead14SafeStringBaseIcEE
2 0x0000007102356AF0 _ZTVN4sead22BufferedSafeStringBaseIcEE
3 0x000000710246F9E0 _ZN4ksys3gdt6detail13sCommonFlags0E
4 0x00000071024709E0 _ZN4ksys3gdt6detail13sCommonFlags1E
5 0x00000071024719E0 _ZN4ksys3gdt6detail13sCommonFlags2E
6 0x00000071024729E0 _ZN4ksys3gdt6detail13sCommonFlags3E
7 0x00000071024C0F18 _ZTVN3agl3utl13ParameterBaseE
8 0x00000071024C1060 _ZTVN3agl3utl9ParameterIbEE
9 0x00000071024C1100 _ZTVN3agl3utl9ParameterIfEE
10 0x00000071024C11A0 _ZTVN3agl3utl9ParameterIiEE
11 0x00000071024C1240 _ZTVN3agl3utl9ParameterIjEE
12 0x00000071024C12E0 _ZTVN3agl3utl9ParameterIN4sead7Vector2IfEEEE
13 0x00000071024C1380 _ZTVN3agl3utl9ParameterIN4sead7Vector3IfEEEE
14 0x00000071024C1420 _ZTVN3agl3utl9ParameterIN4sead7Vector4IfEEEE
15 0x00000071024C14C0 _ZTVN3agl3utl9ParameterIN4sead7Color4fEEE
16 0x00000071024C1560 _ZTVN3agl3utl9ParameterIN4sead4QuatIfEEEE
17 0x00000071024C1600 _ZTVN3agl3utl9ParameterIN4sead15FixedSafeStringILi64EEEEE
18 0x00000071024C16A0 _ZTVN3agl3utl9ParameterIN4sead15FixedSafeStringILi256EEEEE
19 0x00000071024C1740 _ZTVN3agl3utl9ParameterIN4sead14SafeStringBaseIcEEEE
20 0x00000071024D8D58 _ZTVN4ksys3act2ai10ActionBaseE
21 0x00000071025129E0 _ZTVN4ksys3act2ai6ActionE
22 0x0000007102513268 _ZTVN4ksys3act2ai2AiE
23 0x00000071025F75B0 pfnc_nvnDeviceBuilderSetDefaults
24 0x00000071025F75B8 pfnc_nvnDeviceBuilderSetFlags
25 0x00000071025F75C0 pfnc_nvnDeviceInitialize
26 0x00000071025F75C8 pfnc_nvnDeviceFinalize
27 0x00000071025F75D0 pfnc_nvnDeviceSetDebugLabel
28 0x00000071025F75D8 pfnc_nvnDeviceGetProcAddress
29 0x00000071025F75E0 pfnc_nvnDeviceGetInteger
30 0x00000071025F75E8 pfnc_nvnDeviceGetCurrentTimestampInNanoseconds
31 0x00000071025F75F0 pfnc_nvnDeviceSetIntermediateShaderCache
32 0x00000071025F75F8 pfnc_nvnDeviceGetTextureHandle
33 0x00000071025F7600 pfnc_nvnDeviceGetTexelFetchHandle
34 0x00000071025F7608 pfnc_nvnDeviceGetImageHandle
35 0x00000071025F7610 pfnc_nvnDeviceInstallDebugCallback
36 0x00000071025F7618 pfnc_nvnDeviceGenerateDebugDomainId
37 0x00000071025F7620 pfnc_nvnDeviceSetWindowOriginMode
38 0x00000071025F7628 pfnc_nvnDeviceSetDepthMode
39 0x00000071025F7630 pfnc_nvnDeviceRegisterFastClearColor
40 0x00000071025F7638 pfnc_nvnDeviceRegisterFastClearColori
41 0x00000071025F7640 pfnc_nvnDeviceRegisterFastClearColorui
42 0x00000071025F7648 pfnc_nvnDeviceRegisterFastClearDepth
43 0x00000071025F7650 pfnc_nvnDeviceGetWindowOriginMode
44 0x00000071025F7658 pfnc_nvnDeviceGetDepthMode
45 0x00000071025F7660 pfnc_nvnDeviceGetTimestampInNanoseconds
46 0x00000071025F7668 pfnc_nvnDeviceApplyDeferredFinalizes
47 0x00000071025F7670 pfnc_nvnDeviceFinalizeCommandHandle
48 0x00000071025F7678 pfnc_nvnDeviceWalkDebugDatabase
49 0x00000071025F7680 pfnc_nvnDeviceGetSeparateTextureHandle
50 0x00000071025F7688 pfnc_nvnDeviceGetSeparateSamplerHandle
51 0x00000071025F7690 pfnc_nvnDeviceIsExternalDebuggerAttached
52 0x00000071025F7698 pfnc_nvnQueueGetError
53 0x00000071025F76A0 pfnc_nvnQueueGetTotalCommandMemoryUsed
54 0x00000071025F76A8 pfnc_nvnQueueGetTotalControlMemoryUsed
55 0x00000071025F76B0 pfnc_nvnQueueGetTotalComputeMemoryUsed
56 0x00000071025F76B8 pfnc_nvnQueueResetMemoryUsageCounts
57 0x00000071025F76C0 pfnc_nvnQueueBuilderSetDevice
58 0x00000071025F76C8 pfnc_nvnQueueBuilderSetDefaults
59 0x00000071025F76D0 pfnc_nvnQueueBuilderSetFlags
60 0x00000071025F76D8 pfnc_nvnQueueBuilderSetCommandMemorySize
61 0x00000071025F76E0 pfnc_nvnQueueBuilderSetComputeMemorySize
62 0x00000071025F76E8 pfnc_nvnQueueBuilderSetControlMemorySize
63 0x00000071025F76F0 pfnc_nvnQueueBuilderGetQueueMemorySize
64 0x00000071025F76F8 pfnc_nvnQueueBuilderSetQueueMemory
65 0x00000071025F7700 pfnc_nvnQueueBuilderSetCommandFlushThreshold
66 0x00000071025F7708 pfnc_nvnQueueInitialize
67 0x00000071025F7710 pfnc_nvnQueueFinalize
68 0x00000071025F7718 pfnc_nvnQueueSetDebugLabel
69 0x00000071025F7720 pfnc_nvnQueueSubmitCommands
70 0x00000071025F7728 pfnc_nvnQueueFlush
71 0x00000071025F7730 pfnc_nvnQueueFinish
72 0x00000071025F7738 pfnc_nvnQueuePresentTexture
73 0x00000071025F7740 pfnc_nvnQueueAcquireTexture
74 0x00000071025F7748 pfnc_nvnWindowBuilderSetDevice
75 0x00000071025F7750 pfnc_nvnWindowBuilderSetDefaults
76 0x00000071025F7758 pfnc_nvnWindowBuilderSetNativeWindow
77 0x00000071025F7760 pfnc_nvnWindowBuilderSetTextures
78 0x00000071025F7768 pfnc_nvnWindowBuilderSetPresentInterval
79 0x00000071025F7770 pfnc_nvnWindowBuilderGetNativeWindow
80 0x00000071025F7778 pfnc_nvnWindowBuilderGetPresentInterval
81 0x00000071025F7780 pfnc_nvnWindowInitialize
82 0x00000071025F7788 pfnc_nvnWindowFinalize
83 0x00000071025F7790 pfnc_nvnWindowSetDebugLabel
84 0x00000071025F7798 pfnc_nvnWindowAcquireTexture
85 0x00000071025F77A0 pfnc_nvnWindowGetNativeWindow
86 0x00000071025F77A8 pfnc_nvnWindowGetPresentInterval
87 0x00000071025F77B0 pfnc_nvnWindowSetPresentInterval
88 0x00000071025F77B8 pfnc_nvnWindowSetCrop
89 0x00000071025F77C0 pfnc_nvnWindowGetCrop
90 0x00000071025F77C8 pfnc_nvnProgramInitialize
91 0x00000071025F77D0 pfnc_nvnProgramFinalize
92 0x00000071025F77D8 pfnc_nvnProgramSetDebugLabel
93 0x00000071025F77E0 pfnc_nvnProgramSetShaders
94 0x00000071025F77E8 pfnc_nvnMemoryPoolBuilderSetDevice
95 0x00000071025F77F0 pfnc_nvnMemoryPoolBuilderSetDefaults
96 0x00000071025F77F8 pfnc_nvnMemoryPoolBuilderSetStorage
97 0x00000071025F7800 pfnc_nvnMemoryPoolBuilderSetFlags
98 0x00000071025F7808 pfnc_nvnMemoryPoolBuilderGetMemory
99 0x00000071025F7810 pfnc_nvnMemoryPoolBuilderGetSize
100 0x00000071025F7818 pfnc_nvnMemoryPoolBuilderGetFlags
101 0x00000071025F7820 pfnc_nvnMemoryPoolInitialize
102 0x00000071025F7828 pfnc_nvnMemoryPoolSetDebugLabel
103 0x00000071025F7830 pfnc_nvnMemoryPoolFinalize
104 0x00000071025F7838 pfnc_nvnMemoryPoolMap
105 0x00000071025F7840 pfnc_nvnMemoryPoolFlushMappedRange
106 0x00000071025F7848 pfnc_nvnMemoryPoolInvalidateMappedRange
107 0x00000071025F7850 pfnc_nvnMemoryPoolGetBufferAddress
108 0x00000071025F7858 pfnc_nvnMemoryPoolMapVirtual
109 0x00000071025F7860 pfnc_nvnMemoryPoolGetSize
110 0x00000071025F7868 pfnc_nvnMemoryPoolGetFlags
111 0x00000071025F7870 pfnc_nvnTexturePoolInitialize
112 0x00000071025F7878 pfnc_nvnTexturePoolSetDebugLabel
113 0x00000071025F7880 pfnc_nvnTexturePoolFinalize
114 0x00000071025F7888 pfnc_nvnTexturePoolRegisterTexture
115 0x00000071025F7890 pfnc_nvnTexturePoolRegisterImage
116 0x00000071025F7898 pfnc_nvnTexturePoolGetMemoryPool
117 0x00000071025F78A0 pfnc_nvnTexturePoolGetMemoryOffset
118 0x00000071025F78A8 pfnc_nvnTexturePoolGetSize
119 0x00000071025F78B0 pfnc_nvnSamplerPoolInitialize
120 0x00000071025F78B8 pfnc_nvnSamplerPoolSetDebugLabel
121 0x00000071025F78C0 pfnc_nvnSamplerPoolFinalize
122 0x00000071025F78C8 pfnc_nvnSamplerPoolRegisterSampler
123 0x00000071025F78D0 pfnc_nvnSamplerPoolRegisterSamplerBuilder
124 0x00000071025F78D8 pfnc_nvnSamplerPoolGetMemoryPool
125 0x00000071025F78E0 pfnc_nvnSamplerPoolGetMemoryOffset
126 0x00000071025F78E8 pfnc_nvnSamplerPoolGetSize
127 0x00000071025F78F0 pfnc_nvnBufferBuilderSetDevice
128 0x00000071025F78F8 pfnc_nvnBufferBuilderSetDefaults
129 0x00000071025F7900 pfnc_nvnBufferBuilderSetStorage
130 0x00000071025F7908 pfnc_nvnBufferBuilderGetMemoryPool
131 0x00000071025F7910 pfnc_nvnBufferBuilderGetMemoryOffset
132 0x00000071025F7918 pfnc_nvnBufferBuilderGetSize
133 0x00000071025F7920 pfnc_nvnBufferInitialize
134 0x00000071025F7928 pfnc_nvnBufferSetDebugLabel
135 0x00000071025F7930 pfnc_nvnBufferFinalize
136 0x00000071025F7938 pfnc_nvnBufferMap
137 0x00000071025F7940 pfnc_nvnBufferGetAddress
138 0x00000071025F7948 pfnc_nvnBufferFlushMappedRange
139 0x00000071025F7950 pfnc_nvnBufferInvalidateMappedRange
140 0x00000071025F7958 pfnc_nvnBufferGetMemoryPool
141 0x00000071025F7960 pfnc_nvnBufferGetMemoryOffset
142 0x00000071025F7968 pfnc_nvnBufferGetSize
143 0x00000071025F7970 pfnc_nvnBufferGetDebugID
144 0x00000071025F7978 pfnc_nvnTextureBuilderSetDevice
145 0x00000071025F7980 pfnc_nvnTextureBuilderSetDefaults
146 0x00000071025F7988 pfnc_nvnTextureBuilderSetFlags
147 0x00000071025F7990 pfnc_nvnTextureBuilderSetTarget
148 0x00000071025F7998 pfnc_nvnTextureBuilderSetWidth
149 0x00000071025F79A0 pfnc_nvnTextureBuilderSetHeight
150 0x00000071025F79A8 pfnc_nvnTextureBuilderSetDepth
151 0x00000071025F79B0 pfnc_nvnTextureBuilderSetSize1D
152 0x00000071025F79B8 pfnc_nvnTextureBuilderSetSize2D
153 0x00000071025F79C0 pfnc_nvnTextureBuilderSetSize3D
154 0x00000071025F79C8 pfnc_nvnTextureBuilderSetLevels
155 0x00000071025F79D0 pfnc_nvnTextureBuilderSetFormat
156 0x00000071025F79D8 pfnc_nvnTextureBuilderSetSamples
157 0x00000071025F79E0 pfnc_nvnTextureBuilderSetSwizzle
158 0x00000071025F79E8 pfnc_nvnTextureBuilderSetDepthStencilMode
159 0x00000071025F79F0 pfnc_nvnTextureBuilderGetStorageSize
160 0x00000071025F79F8 pfnc_nvnTextureBuilderGetStorageAlignment
161 0x00000071025F7A00 pfnc_nvnTextureBuilderSetStorage
162 0x00000071025F7A08 pfnc_nvnTextureBuilderSetPackagedTextureData
163 0x00000071025F7A10 pfnc_nvnTextureBuilderSetPackagedTextureLayout
164 0x00000071025F7A18 pfnc_nvnTextureBuilderSetStride
165 0x00000071025F7A20 pfnc_nvnTextureBuilderSetGLTextureName
166 0x00000071025F7A28 pfnc_nvnTextureBuilderGetStorageClass
167 0x00000071025F7A30 pfnc_nvnTextureBuilderGetFlags
168 0x00000071025F7A38 pfnc_nvnTextureBuilderGetTarget
169 0x00000071025F7A40 pfnc_nvnTextureBuilderGetWidth
170 0x00000071025F7A48 pfnc_nvnTextureBuilderGetHeight
171 0x00000071025F7A50 pfnc_nvnTextureBuilderGetDepth
172 0x00000071025F7A58 pfnc_nvnTextureBuilderGetLevels
173 0x00000071025F7A60 pfnc_nvnTextureBuilderGetFormat
174 0x00000071025F7A68 pfnc_nvnTextureBuilderGetSamples
175 0x00000071025F7A70 pfnc_nvnTextureBuilderGetSwizzle
176 0x00000071025F7A78 pfnc_nvnTextureBuilderGetDepthStencilMode
177 0x00000071025F7A80 pfnc_nvnTextureBuilderGetPackagedTextureData
178 0x00000071025F7A88 pfnc_nvnTextureBuilderGetStride
179 0x00000071025F7A90 pfnc_nvnTextureBuilderGetSparseTileLayout
180 0x00000071025F7A98 pfnc_nvnTextureBuilderGetGLTextureName
181 0x00000071025F7AA0 pfnc_nvnTextureBuilderGetZCullStorageSize
182 0x00000071025F7AA8 pfnc_nvnTextureBuilderGetMemoryPool
183 0x00000071025F7AB0 pfnc_nvnTextureBuilderGetMemoryOffset
184 0x00000071025F7AB8 pfnc_nvnTextureViewSetDefaults
185 0x00000071025F7AC0 pfnc_nvnTextureViewSetLevels
186 0x00000071025F7AC8 pfnc_nvnTextureViewSetLayers
187 0x00000071025F7AD0 pfnc_nvnTextureViewSetFormat
188 0x00000071025F7AD8 pfnc_nvnTextureViewSetSwizzle
189 0x00000071025F7AE0 pfnc_nvnTextureViewSetDepthStencilMode
190 0x00000071025F7AE8 pfnc_nvnTextureViewSetTarget
191 0x00000071025F7AF0 pfnc_nvnTextureViewGetLevels
192 0x00000071025F7AF8 pfnc_nvnTextureViewGetLayers
193 0x00000071025F7B00 pfnc_nvnTextureViewGetFormat
194 0x00000071025F7B08 pfnc_nvnTextureViewGetSwizzle
195 0x00000071025F7B10 pfnc_nvnTextureViewGetDepthStencilMode
196 0x00000071025F7B18 pfnc_nvnTextureViewGetTarget
197 0x00000071025F7B20 pfnc_nvnTextureViewCompare
198 0x00000071025F7B28 pfnc_nvnTextureInitialize
199 0x00000071025F7B30 pfnc_nvnTextureGetZCullStorageSize
200 0x00000071025F7B38 pfnc_nvnTextureFinalize
201 0x00000071025F7B40 pfnc_nvnTextureSetDebugLabel
202 0x00000071025F7B48 pfnc_nvnTextureGetStorageClass
203 0x00000071025F7B50 pfnc_nvnTextureGetViewOffset
204 0x00000071025F7B58 pfnc_nvnTextureGetFlags
205 0x00000071025F7B60 pfnc_nvnTextureGetTarget
206 0x00000071025F7B68 pfnc_nvnTextureGetWidth
207 0x00000071025F7B70 pfnc_nvnTextureGetHeight
208 0x00000071025F7B78 pfnc_nvnTextureGetDepth
209 0x00000071025F7B80 pfnc_nvnTextureGetLevels
210 0x00000071025F7B88 pfnc_nvnTextureGetFormat
211 0x00000071025F7B90 pfnc_nvnTextureGetSamples
212 0x00000071025F7B98 pfnc_nvnTextureGetSwizzle
213 0x00000071025F7BA0 pfnc_nvnTextureGetDepthStencilMode
214 0x00000071025F7BA8 pfnc_nvnTextureGetStride
215 0x00000071025F7BB0 pfnc_nvnTextureGetTextureAddress
216 0x00000071025F7BB8 pfnc_nvnTextureGetSparseTileLayout
217 0x00000071025F7BC0 pfnc_nvnTextureWriteTexels
218 0x00000071025F7BC8 pfnc_nvnTextureWriteTexelsStrided
219 0x00000071025F7BD0 pfnc_nvnTextureReadTexels
220 0x00000071025F7BD8 pfnc_nvnTextureReadTexelsStrided
221 0x00000071025F7BE0 pfnc_nvnTextureFlushTexels
222 0x00000071025F7BE8 pfnc_nvnTextureInvalidateTexels
223 0x00000071025F7BF0 pfnc_nvnTextureGetMemoryPool
224 0x00000071025F7BF8 pfnc_nvnTextureGetMemoryOffset
225 0x00000071025F7C00 pfnc_nvnTextureGetStorageSize
226 0x00000071025F7C08 pfnc_nvnTextureCompare
227 0x00000071025F7C10 pfnc_nvnTextureGetDebugID
228 0x00000071025F7C18 pfnc_nvnSamplerBuilderSetDevice
229 0x00000071025F7C20 pfnc_nvnSamplerBuilderSetDefaults
230 0x00000071025F7C28 pfnc_nvnSamplerBuilderSetMinMagFilter
231 0x00000071025F7C30 pfnc_nvnSamplerBuilderSetWrapMode
232 0x00000071025F7C38 pfnc_nvnSamplerBuilderSetLodClamp
233 0x00000071025F7C40 pfnc_nvnSamplerBuilderSetLodBias
234 0x00000071025F7C48 pfnc_nvnSamplerBuilderSetCompare
235 0x00000071025F7C50 pfnc_nvnSamplerBuilderSetBorderColor
236 0x00000071025F7C58 pfnc_nvnSamplerBuilderSetBorderColori
237 0x00000071025F7C60 pfnc_nvnSamplerBuilderSetBorderColorui
238 0x00000071025F7C68 pfnc_nvnSamplerBuilderSetMaxAnisotropy
239 0x00000071025F7C70 pfnc_nvnSamplerBuilderSetReductionFilter
240 0x00000071025F7C78 pfnc_nvnSamplerBuilderSetLodSnap
241 0x00000071025F7C80 pfnc_nvnSamplerBuilderGetMinMagFilter
242 0x00000071025F7C88 pfnc_nvnSamplerBuilderGetWrapMode
243 0x00000071025F7C90 pfnc_nvnSamplerBuilderGetLodClamp
244 0x00000071025F7C98 pfnc_nvnSamplerBuilderGetLodBias
245 0x00000071025F7CA0 pfnc_nvnSamplerBuilderGetCompare
246 0x00000071025F7CA8 pfnc_nvnSamplerBuilderGetBorderColor
247 0x00000071025F7CB0 pfnc_nvnSamplerBuilderGetBorderColori
248 0x00000071025F7CB8 pfnc_nvnSamplerBuilderGetBorderColorui
249 0x00000071025F7CC0 pfnc_nvnSamplerBuilderGetMaxAnisotropy
250 0x00000071025F7CC8 pfnc_nvnSamplerBuilderGetReductionFilter
251 0x00000071025F7CD0 pfnc_nvnSamplerBuilderGetLodSnap
252 0x00000071025F7CD8 pfnc_nvnSamplerInitialize
253 0x00000071025F7CE0 pfnc_nvnSamplerFinalize
254 0x00000071025F7CE8 pfnc_nvnSamplerSetDebugLabel
255 0x00000071025F7CF0 pfnc_nvnSamplerGetMinMagFilter
256 0x00000071025F7CF8 pfnc_nvnSamplerGetWrapMode
257 0x00000071025F7D00 pfnc_nvnSamplerGetLodClamp
258 0x00000071025F7D08 pfnc_nvnSamplerGetLodBias
259 0x00000071025F7D10 pfnc_nvnSamplerGetCompare
260 0x00000071025F7D18 pfnc_nvnSamplerGetBorderColor
261 0x00000071025F7D20 pfnc_nvnSamplerGetBorderColori
262 0x00000071025F7D28 pfnc_nvnSamplerGetBorderColorui
263 0x00000071025F7D30 pfnc_nvnSamplerGetMaxAnisotropy
264 0x00000071025F7D38 pfnc_nvnSamplerGetReductionFilter
265 0x00000071025F7D40 pfnc_nvnSamplerCompare
266 0x00000071025F7D48 pfnc_nvnSamplerGetDebugID
267 0x00000071025F7D50 pfnc_nvnBlendStateSetDefaults
268 0x00000071025F7D58 pfnc_nvnBlendStateSetBlendTarget
269 0x00000071025F7D60 pfnc_nvnBlendStateSetBlendFunc
270 0x00000071025F7D68 pfnc_nvnBlendStateSetBlendEquation
271 0x00000071025F7D70 pfnc_nvnBlendStateSetAdvancedMode
272 0x00000071025F7D78 pfnc_nvnBlendStateSetAdvancedOverlap
273 0x00000071025F7D80 pfnc_nvnBlendStateSetAdvancedPremultipliedSrc
274 0x00000071025F7D88 pfnc_nvnBlendStateSetAdvancedNormalizedDst
275 0x00000071025F7D90 pfnc_nvnBlendStateGetBlendTarget
276 0x00000071025F7D98 pfnc_nvnBlendStateGetBlendFunc
277 0x00000071025F7DA0 pfnc_nvnBlendStateGetBlendEquation
278 0x00000071025F7DA8 pfnc_nvnBlendStateGetAdvancedMode
279 0x00000071025F7DB0 pfnc_nvnBlendStateGetAdvancedOverlap
280 0x00000071025F7DB8 pfnc_nvnBlendStateGetAdvancedPremultipliedSrc
281 0x00000071025F7DC0 pfnc_nvnBlendStateGetAdvancedNormalizedDst
282 0x00000071025F7DC8 pfnc_nvnColorStateSetDefaults
283 0x00000071025F7DD0 pfnc_nvnColorStateSetBlendEnable
284 0x00000071025F7DD8 pfnc_nvnColorStateSetLogicOp
285 0x00000071025F7DE0 pfnc_nvnColorStateSetAlphaTest
286 0x00000071025F7DE8 pfnc_nvnColorStateGetBlendEnable
287 0x00000071025F7DF0 pfnc_nvnColorStateGetLogicOp
288 0x00000071025F7DF8 pfnc_nvnColorStateGetAlphaTest
289 0x00000071025F7E00 pfnc_nvnChannelMaskStateSetDefaults
290 0x00000071025F7E08 pfnc_nvnChannelMaskStateSetChannelMask
291 0x00000071025F7E10 pfnc_nvnChannelMaskStateGetChannelMask
292 0x00000071025F7E18 pfnc_nvnMultisampleStateSetDefaults
293 0x00000071025F7E20 pfnc_nvnMultisampleStateSetMultisampleEnable
294 0x00000071025F7E28 pfnc_nvnMultisampleStateSetSamples
295 0x00000071025F7E30 pfnc_nvnMultisampleStateSetAlphaToCoverageEnable
296 0x00000071025F7E38 pfnc_nvnMultisampleStateSetAlphaToCoverageDither
297 0x00000071025F7E40 pfnc_nvnMultisampleStateGetMultisampleEnable
298 0x00000071025F7E48 pfnc_nvnMultisampleStateGetSamples
299 0x00000071025F7E50 pfnc_nvnMultisampleStateGetAlphaToCoverageEnable
300 0x00000071025F7E58 pfnc_nvnMultisampleStateGetAlphaToCoverageDither
301 0x00000071025F7E60 pfnc_nvnMultisampleStateSetRasterSamples
302 0x00000071025F7E68 pfnc_nvnMultisampleStateGetRasterSamples
303 0x00000071025F7E70 pfnc_nvnMultisampleStateSetCoverageModulationMode
304 0x00000071025F7E78 pfnc_nvnMultisampleStateGetCoverageModulationMode
305 0x00000071025F7E80 pfnc_nvnMultisampleStateSetCoverageToColorEnable
306 0x00000071025F7E88 pfnc_nvnMultisampleStateGetCoverageToColorEnable
307 0x00000071025F7E90 pfnc_nvnMultisampleStateSetCoverageToColorOutput
308 0x00000071025F7E98 pfnc_nvnMultisampleStateGetCoverageToColorOutput
309 0x00000071025F7EA0 pfnc_nvnMultisampleStateSetSampleLocationsEnable
310 0x00000071025F7EA8 pfnc_nvnMultisampleStateGetSampleLocationsEnable
311 0x00000071025F7EB0 pfnc_nvnMultisampleStateGetSampleLocationsGrid
312 0x00000071025F7EB8 pfnc_nvnMultisampleStateSetSampleLocationsGridEnable
313 0x00000071025F7EC0 pfnc_nvnMultisampleStateGetSampleLocationsGridEnable
314 0x00000071025F7EC8 pfnc_nvnMultisampleStateSetSampleLocations
315 0x00000071025F7ED0 pfnc_nvnPolygonStateSetDefaults
316 0x00000071025F7ED8 pfnc_nvnPolygonStateSetCullFace
317 0x00000071025F7EE0 pfnc_nvnPolygonStateSetFrontFace
318 0x00000071025F7EE8 pfnc_nvnPolygonStateSetPolygonMode
319 0x00000071025F7EF0 pfnc_nvnPolygonStateSetPolygonOffsetEnables
320 0x00000071025F7EF8 pfnc_nvnPolygonStateGetCullFace
321 0x00000071025F7F00 pfnc_nvnPolygonStateGetFrontFace
322 0x00000071025F7F08 pfnc_nvnPolygonStateGetPolygonMode
323 0x00000071025F7F10 pfnc_nvnPolygonStateGetPolygonOffsetEnables
324 0x00000071025F7F18 pfnc_nvnDepthStencilStateSetDefaults
325 0x00000071025F7F20 pfnc_nvnDepthStencilStateSetDepthTestEnable
326 0x00000071025F7F28 pfnc_nvnDepthStencilStateSetDepthWriteEnable
327 0x00000071025F7F30 pfnc_nvnDepthStencilStateSetDepthFunc
328 0x00000071025F7F38 pfnc_nvnDepthStencilStateSetStencilTestEnable
329 0x00000071025F7F40 pfnc_nvnDepthStencilStateSetStencilFunc
330 0x00000071025F7F48 pfnc_nvnDepthStencilStateSetStencilOp
331 0x00000071025F7F50 pfnc_nvnDepthStencilStateGetDepthTestEnable
332 0x00000071025F7F58 pfnc_nvnDepthStencilStateGetDepthWriteEnable
333 0x00000071025F7F60 pfnc_nvnDepthStencilStateGetDepthFunc
334 0x00000071025F7F68 pfnc_nvnDepthStencilStateGetStencilTestEnable
335 0x00000071025F7F70 pfnc_nvnDepthStencilStateGetStencilFunc
336 0x00000071025F7F78 pfnc_nvnDepthStencilStateGetStencilOp
337 0x00000071025F7F80 pfnc_nvnVertexAttribStateSetDefaults
338 0x00000071025F7F88 pfnc_nvnVertexAttribStateSetFormat
339 0x00000071025F7F90 pfnc_nvnVertexAttribStateSetStreamIndex
340 0x00000071025F7F98 pfnc_nvnVertexAttribStateGetFormat
341 0x00000071025F7FA0 pfnc_nvnVertexAttribStateGetStreamIndex
342 0x00000071025F7FA8 pfnc_nvnVertexStreamStateSetDefaults
343 0x00000071025F7FB0 pfnc_nvnVertexStreamStateSetStride
344 0x00000071025F7FB8 pfnc_nvnVertexStreamStateSetDivisor
345 0x00000071025F7FC0 pfnc_nvnVertexStreamStateGetStride
346 0x00000071025F7FC8 pfnc_nvnVertexStreamStateGetDivisor
347 0x00000071025F7FD0 pfnc_nvnCommandBufferInitialize
348 0x00000071025F7FD8 pfnc_nvnCommandBufferFinalize
349 0x00000071025F7FE0 pfnc_nvnCommandBufferSetDebugLabel
350 0x00000071025F7FE8 pfnc_nvnCommandBufferSetMemoryCallback
351 0x00000071025F7FF0 pfnc_nvnCommandBufferSetMemoryCallbackData
352 0x00000071025F7FF8 pfnc_nvnCommandBufferAddCommandMemory
353 0x00000071025F8000 pfnc_nvnCommandBufferAddControlMemory
354 0x00000071025F8008 pfnc_nvnCommandBufferGetCommandMemorySize
355 0x00000071025F8010 pfnc_nvnCommandBufferGetCommandMemoryUsed
356 0x00000071025F8018 pfnc_nvnCommandBufferGetCommandMemoryFree
357 0x00000071025F8020 pfnc_nvnCommandBufferGetControlMemorySize
358 0x00000071025F8028 pfnc_nvnCommandBufferGetControlMemoryUsed
359 0x00000071025F8030 pfnc_nvnCommandBufferGetControlMemoryFree
360 0x00000071025F8038 pfnc_nvnCommandBufferBeginRecording
361 0x00000071025F8040 pfnc_nvnCommandBufferEndRecording
362 0x00000071025F8048 pfnc_nvnCommandBufferCallCommands
363 0x00000071025F8050 pfnc_nvnCommandBufferCopyCommands
364 0x00000071025F8058 pfnc_nvnCommandBufferBindBlendState
365 0x00000071025F8060 pfnc_nvnCommandBufferBindChannelMaskState
366 0x00000071025F8068 pfnc_nvnCommandBufferBindColorState
367 0x00000071025F8070 pfnc_nvnCommandBufferBindMultisampleState
368 0x00000071025F8078 pfnc_nvnCommandBufferBindPolygonState
369 0x00000071025F8080 pfnc_nvnCommandBufferBindDepthStencilState
370 0x00000071025F8088 pfnc_nvnCommandBufferBindVertexAttribState
371 0x00000071025F8090 pfnc_nvnCommandBufferBindVertexStreamState
372 0x00000071025F8098 pfnc_nvnCommandBufferBindProgram
373 0x00000071025F80A0 pfnc_nvnCommandBufferBindVertexBuffer
374 0x00000071025F80A8 pfnc_nvnCommandBufferBindVertexBuffers
375 0x00000071025F80B0 pfnc_nvnCommandBufferBindUniformBuffer
376 0x00000071025F80B8 pfnc_nvnCommandBufferBindUniformBuffers
377 0x00000071025F80C0 pfnc_nvnCommandBufferBindTransformFeedbackBuffer
378 0x00000071025F80C8 pfnc_nvnCommandBufferBindTransformFeedbackBuffers
379 0x00000071025F80D0 pfnc_nvnCommandBufferBindStorageBuffer
380 0x00000071025F80D8 pfnc_nvnCommandBufferBindStorageBuffers
381 0x00000071025F80E0 pfnc_nvnCommandBufferBindTexture
382 0x00000071025F80E8 pfnc_nvnCommandBufferBindTextures
383 0x00000071025F80F0 pfnc_nvnCommandBufferBindImage
384 0x00000071025F80F8 pfnc_nvnCommandBufferBindImages
385 0x00000071025F8100 pfnc_nvnCommandBufferSetPatchSize
386 0x00000071025F8108 pfnc_nvnCommandBufferSetInnerTessellationLevels
387 0x00000071025F8110 pfnc_nvnCommandBufferSetOuterTessellationLevels
388 0x00000071025F8118 pfnc_nvnCommandBufferSetPrimitiveRestart
389 0x00000071025F8120 pfnc_nvnCommandBufferBeginTransformFeedback
390 0x00000071025F8128 pfnc_nvnCommandBufferEndTransformFeedback
391 0x00000071025F8130 pfnc_nvnCommandBufferPauseTransformFeedback
392 0x00000071025F8138 pfnc_nvnCommandBufferResumeTransformFeedback
393 0x00000071025F8140 pfnc_nvnCommandBufferDrawTransformFeedback
394 0x00000071025F8148 pfnc_nvnCommandBufferDrawArrays
395 0x00000071025F8150 pfnc_nvnCommandBufferDrawElements
396 0x00000071025F8158 pfnc_nvnCommandBufferDrawElementsBaseVertex
397 0x00000071025F8160 pfnc_nvnCommandBufferDrawArraysInstanced
398 0x00000071025F8168 pfnc_nvnCommandBufferDrawElementsInstanced
399 0x00000071025F8170 pfnc_nvnCommandBufferDrawArraysIndirect
400 0x00000071025F8178 pfnc_nvnCommandBufferDrawElementsIndirect
401 0x00000071025F8180 pfnc_nvnCommandBufferMultiDrawArraysIndirectCount
402 0x00000071025F8188 pfnc_nvnCommandBufferMultiDrawElementsIndirectCount
403 0x00000071025F8190 pfnc_nvnCommandBufferClearColor
404 0x00000071025F8198 pfnc_nvnCommandBufferClearColori
405 0x00000071025F81A0 pfnc_nvnCommandBufferClearColorui
406 0x00000071025F81A8 pfnc_nvnCommandBufferClearDepthStencil
407 0x00000071025F81B0 pfnc_nvnCommandBufferDispatchCompute
408 0x00000071025F81B8 pfnc_nvnCommandBufferDispatchComputeIndirect
409 0x00000071025F81C0 pfnc_nvnCommandBufferSetViewport
410 0x00000071025F81C8 pfnc_nvnCommandBufferSetViewports
411 0x00000071025F81D0 pfnc_nvnCommandBufferSetViewportSwizzles
412 0x00000071025F81D8 pfnc_nvnCommandBufferSetScissor
413 0x00000071025F81E0 pfnc_nvnCommandBufferSetScissors
414 0x00000071025F81E8 pfnc_nvnCommandBufferSetDepthRange
415 0x00000071025F81F0 pfnc_nvnCommandBufferSetDepthBounds
416 0x00000071025F81F8 pfnc_nvnCommandBufferSetDepthRanges
417 0x00000071025F8200 pfnc_nvnCommandBufferSetTiledCacheAction
418 0x00000071025F8208 pfnc_nvnCommandBufferSetTiledCacheTileSize
419 0x00000071025F8210 pfnc_nvnCommandBufferBindSeparateTexture
420 0x00000071025F8218 pfnc_nvnCommandBufferBindSeparateSampler
421 0x00000071025F8220 pfnc_nvnCommandBufferBindSeparateTextures
422 0x00000071025F8228 pfnc_nvnCommandBufferBindSeparateSamplers
423 0x00000071025F8230 pfnc_nvnCommandBufferSetStencilValueMask
424 0x00000071025F8238 pfnc_nvnCommandBufferSetStencilMask
425 0x00000071025F8240 pfnc_nvnCommandBufferSetStencilRef
426 0x00000071025F8248 pfnc_nvnCommandBufferSetBlendColor
427 0x00000071025F8250 pfnc_nvnCommandBufferSetPointSize
428 0x00000071025F8258 pfnc_nvnCommandBufferSetLineWidth
429 0x00000071025F8260 pfnc_nvnCommandBufferSetPolygonOffsetClamp
430 0x00000071025F8268 pfnc_nvnCommandBufferSetAlphaRef
431 0x00000071025F8270 pfnc_nvnCommandBufferSetSampleMask
432 0x00000071025F8278 pfnc_nvnCommandBufferSetRasterizerDiscard
433 0x00000071025F8280 pfnc_nvnCommandBufferSetDepthClamp
434 0x00000071025F8288 pfnc_nvnCommandBufferSetConservativeRasterEnable
435 0x00000071025F8290 pfnc_nvnCommandBufferSetConservativeRasterDilate
436 0x00000071025F8298 pfnc_nvnCommandBufferSetSubpixelPrecisionBias
437 0x00000071025F82A0 pfnc_nvnCommandBufferCopyBufferToTexture
438 0x00000071025F82A8 pfnc_nvnCommandBufferCopyTextureToBuffer
439 0x00000071025F82B0 pfnc_nvnCommandBufferCopyTextureToTexture
440 0x00000071025F82B8 pfnc_nvnCommandBufferCopyBufferToBuffer
441 0x00000071025F82C0 pfnc_nvnCommandBufferClearBuffer
442 0x00000071025F82C8 pfnc_nvnCommandBufferClearTexture
443 0x00000071025F82D0 pfnc_nvnCommandBufferClearTexturei
444 0x00000071025F82D8 pfnc_nvnCommandBufferClearTextureui
445 0x00000071025F82E0 pfnc_nvnCommandBufferUpdateUniformBuffer
446 0x00000071025F82E8 pfnc_nvnCommandBufferReportCounter
447 0x00000071025F82F0 pfnc_nvnCommandBufferResetCounter
448 0x00000071025F82F8 pfnc_nvnCommandBufferReportValue
449 0x00000071025F8300 pfnc_nvnCommandBufferSetRenderEnable
450 0x00000071025F8308 pfnc_nvnCommandBufferSetRenderEnableConditional
451 0x00000071025F8310 pfnc_nvnCommandBufferSetRenderTargets
452 0x00000071025F8318 pfnc_nvnCommandBufferDiscardColor
453 0x00000071025F8320 pfnc_nvnCommandBufferDiscardDepthStencil
454 0x00000071025F8328 pfnc_nvnCommandBufferDownsample
455 0x00000071025F8330 pfnc_nvnCommandBufferTiledDownsample
456 0x00000071025F8338 pfnc_nvnCommandBufferDownsampleTextureView
457 0x00000071025F8340 pfnc_nvnCommandBufferTiledDownsampleTextureView
458 0x00000071025F8348 pfnc_nvnCommandBufferBarrier
459 0x00000071025F8350 pfnc_nvnCommandBufferWaitSync
460 0x00000071025F8358 pfnc_nvnCommandBufferFenceSync
461 0x00000071025F8360 pfnc_nvnCommandBufferSetTexturePool
462 0x00000071025F8368 pfnc_nvnCommandBufferSetSamplerPool
463 0x00000071025F8370 pfnc_nvnCommandBufferSetShaderScratchMemory
464 0x00000071025F8378 pfnc_nvnCommandBufferSaveZCullData
465 0x00000071025F8380 pfnc_nvnCommandBufferRestoreZCullData
466 0x00000071025F8388 pfnc_nvnCommandBufferSetCopyRowStride
467 0x00000071025F8390 pfnc_nvnCommandBufferSetCopyImageStride
468 0x00000071025F8398 pfnc_nvnCommandBufferGetCopyRowStride
469 0x00000071025F83A0 pfnc_nvnCommandBufferGetCopyImageStride
470 0x00000071025F83A8 pfnc_nvnCommandBufferDrawTexture
471 0x00000071025F83B0 pfnc_nvnProgramSetSubroutineLinkage
472 0x00000071025F83B8 pfnc_nvnCommandBufferSetProgramSubroutines
473 0x00000071025F83C0 pfnc_nvnCommandBufferBindCoverageModulationTable
474 0x00000071025F83C8 pfnc_nvnCommandBufferResolveDepthBuffer
475 0x00000071025F83D0 pfnc_nvnCommandBufferPushDebugGroupStatic
476 0x00000071025F83D8 pfnc_nvnCommandBufferPushDebugGroupDynamic
477 0x00000071025F83E0 pfnc_nvnCommandBufferPushDebugGroup
478 0x00000071025F83E8 pfnc_nvnCommandBufferPopDebugGroup
479 0x00000071025F83F0 pfnc_nvnCommandBufferPopDebugGroupId
480 0x00000071025F83F8 pfnc_nvnCommandBufferInsertDebugMarkerStatic
481 0x00000071025F8400 pfnc_nvnCommandBufferInsertDebugMarkerDynamic
482 0x00000071025F8408 pfnc_nvnCommandBufferInsertDebugMarker
483 0x00000071025F8410 pfnc_nvnCommandBufferGetMemoryCallback
484 0x00000071025F8418 pfnc_nvnCommandBufferGetMemoryCallbackData
485 0x00000071025F8420 pfnc_nvnCommandBufferIsRecording
486 0x00000071025F8428 pfnc_nvnSyncInitialize
487 0x00000071025F8430 pfnc_nvnSyncFinalize
488 0x00000071025F8438 pfnc_nvnSyncSetDebugLabel
489 0x00000071025F8440 pfnc_nvnQueueFenceSync
490 0x00000071025F8448 pfnc_nvnSyncWait
491 0x00000071025F8450 pfnc_nvnQueueWaitSync
492 0x00000071025F8458 pfnc_nvnEventBuilderSetDefaults
493 0x00000071025F8460 pfnc_nvnEventBuilderSetStorage
494 0x00000071025F8468 pfnc_nvnEventInitialize
495 0x00000071025F8470 pfnc_nvnEventFinalize
496 0x00000071025F8478 pfnc_nvnEventGetValue
497 0x00000071025F8480 pfnc_nvnEventSignal
498 0x00000071025F8488 pfnc_nvnCommandBufferWaitEvent
499 0x00000071025F8490 pfnc_nvnCommandBufferSignalEvent

74783
data/odyssey_functions.csv Normal file

File diff suppressed because it is too large Load Diff

112757
data/uking_functions.csv Executable file

File diff suppressed because it is too large Load Diff

1
diff.py Symbolic link
View File

@ -0,0 +1 @@
tools/diff.py

23
diff_settings.py Executable file
View File

@ -0,0 +1,23 @@
#!/usr/bin/env python3
from pathlib import Path
def apply(config, args):
config['arch'] = 'aarch64'
config['baseimg'] = 'data/main.elf'
config['myimg'] = 'build/odyssey'
config['source_directories'] = ['src', 'lib']
config['objdump_executable'] = 'tools/aarch64-none-elf-objdump'
for dir in ('build', 'build/nx64-release'):
if (Path(dir) / 'build.ninja').is_file():
config['make_command'] = ['ninja', '-C', dir]
def map_build_target(make_target: str):
if make_target == "build/odyssey":
return "odyssey"
# TODO: When support for directly diffing object files is added, this needs to strip
# the build/ prefix from the object file targets.
return make_target

View File

@ -0,0 +1,26 @@
#ifndef _BYTESWAP_H
#define _BYTESWAP_H
#include <features.h>
#include <stdint.h>
static __inline uint16_t __bswap_16(uint16_t __x)
{
return __x<<8 | __x>>8;
}
static __inline uint32_t __bswap_32(uint32_t __x)
{
return __x>>24 | __x>>8&0xff00 | __x<<8&0xff0000 | __x<<24;
}
static __inline uint64_t __bswap_64(uint64_t __x)
{
return __bswap_32(__x)+0ULL<<32 | __bswap_32(__x>>32);
}
#define bswap_16(x) __bswap_16(x)
#define bswap_32(x) __bswap_32(x)
#define bswap_64(x) __bswap_64(x)
#endif

View File

@ -0,0 +1,22 @@
#ifndef _NN_FEATURES_H
#define _NN_FEATURES_H
/* libc++ (and or libc++abi) checks for GLIBC
*
* for now pretend MUSL is GLIBC 2.17
* Perhaps someday MUSL will have version information
* and libc++ will check for it
*
* rename original MUSL header to features_musl.h
* and include it here
*/
#include <features_musl.h>
#ifndef __GLIBC_PREREQ
#define __MUSL_GLIBC__ 2
#define __MUSL_GLIBC_MINOR__ 17
#define __GLIBC_PREREQ(maj, min) ((__MUSL_GLIBC__ << 16) + __MUSL_GLIBC_MINOR__ >= ((maj) << 16) + (min))
#endif
#define __MUSL__ 0x10110
#define __NNMUSL__ 1
#endif

View File

@ -0,0 +1,38 @@
#ifndef _FEATURES_H
#define _FEATURES_H
#if defined(_ALL_SOURCE) && !defined(_GNU_SOURCE)
#define _GNU_SOURCE 1
#endif
#if defined(_DEFAULT_SOURCE) && !defined(_BSD_SOURCE)
#define _BSD_SOURCE 1
#endif
#if !defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) \
&& !defined(_XOPEN_SOURCE) && !defined(_GNU_SOURCE) \
&& !defined(_BSD_SOURCE) && !defined(__STRICT_ANSI__)
#define _BSD_SOURCE 1
#define _XOPEN_SOURCE 700
#endif
#if __STDC_VERSION__ >= 199901L
#define __restrict restrict
#elif !defined(__GNUC__)
#define __restrict
#endif
#if __STDC_VERSION__ >= 199901L || defined(__cplusplus)
#define __inline inline
#elif !defined(__GNUC__)
#define __inline
#endif
#if __STDC_VERSION__ >= 201112L
#elif defined(__GNUC__)
#define _Noreturn __attribute__((__noreturn__))
#else
#define _Noreturn
#endif
#endif

0
include/agl/g3d.h Normal file → Executable file
View File

0
include/agl/g3d/g3d_ResFile.h Normal file → Executable file
View File

0
include/nn/g3d.h Normal file → Executable file
View File

0
include/nn/g3d/g3d_ResFile.h Normal file → Executable file
View File

0
include/nn/util/util_AccessorBase.h Normal file → Executable file
View File

0
include/sead/seadBitFlag.h Normal file → Executable file
View File

0
include/sead/seadDisposer.h Normal file → Executable file
View File

0
include/sead/seadFileDevice.h Normal file → Executable file
View File

0
include/sead/seadHeap.h Normal file → Executable file
View File

0
include/sead/seadHostIO.h Normal file → Executable file
View File

0
include/sead/seadListImpl.h Normal file → Executable file
View File

0
include/sead/seadMatrix.h Normal file → Executable file
View File

0
include/sead/seadNamable.h Normal file → Executable file
View File

0
include/sead/seadQuat.h Normal file → Executable file
View File

0
include/sead/seadResource.h Normal file → Executable file
View File

0
include/sead/seadRuntimeTypeInfo.h Normal file → Executable file
View File

0
include/sead/seadSafeString.h Normal file → Executable file
View File

0
include/sead/seadSafeString.hpp Normal file → Executable file
View File

0
include/sead/seadVector.h Normal file → Executable file
View File

1
src/CMakeLists.txt Normal file
View File

@ -0,0 +1 @@
add_subdirectory(al)

9
src/al/CMakeLists.txt Normal file
View File

@ -0,0 +1,9 @@
add_subdirectory(actor)
add_subdirectory(byaml)
add_subdirectory(LiveActor)
add_subdirectory(nerve)
add_subdirectory(pose)
add_subdirectory(resource)
add_subdirectory(sead)
add_subdirectory(sensor)
add_subdirectory(util)

View File

@ -0,0 +1,4 @@
target_sources(odyssey PRIVATE
LiveActor.cpp
LiveActorGroup.cpp
)

View File

View File

@ -0,0 +1,4 @@
target_sources(odyssey PRIVATE
Factory.cpp
Placement.cpp
)

View File

View File

View File

View File

View File

View File

@ -0,0 +1,7 @@
target_sources(odyssey PRIVATE
ByamlContainerHeader.cpp
ByamlData.cpp
ByamlHashPair.cpp
ByamlHeader.cpp
ByamlStringTableIter.cpp
)

View File

@ -0,0 +1,7 @@
target_sources(odyssey PRIVATE
NerveAction.cpp
NerveExecutor.cpp
NerveKeeper.cpp
NerveStateBase.cpp
NerveStateCtrl.cpp
)

View File

View File

View File

View File

View File

View File

View File

@ -0,0 +1,3 @@
target_sources(odyssey PRIVATE
ActorPoseKeeper.cpp
)

View File

@ -0,0 +1,3 @@
target_sources(odyssey PRIVATE
Resource.cpp
)

View File

View File

@ -0,0 +1,3 @@
target_sources(odyssey PRIVATE
seadSafeString.cpp
)

View File

View File

@ -0,0 +1,4 @@
target_sources(odyssey PRIVATE
HitSensor.cpp
SensorHitGroup.cpp
)

View File

View File

View File

@ -0,0 +1,7 @@
target_sources(odyssey PRIVATE
ByamlUtil.cpp
MathUtil.cpp
NerveUtil.cpp
PlacementUtil.cpp
StringUtil.cpp
)

View File

View File

View File

View File

Binary file not shown.

Binary file not shown.

BIN
tools/aarch64-none-elf-objdump Executable file

Binary file not shown.

37
tools/add_missing_functions.py Executable file
View File

@ -0,0 +1,37 @@
#!/usr/bin/env python3
import argparse
import csv
import sys
from pathlib import Path
from typing import Set, List
from util import utils
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("csv_path", help="Path to function CSV to merge")
args = parser.parse_args()
csv_path = Path(args.csv_path)
known_fn_addrs: Set[int] = {func.addr for func in utils.get_functions()}
new_fns: List[utils.FunctionInfo] = []
for func in utils.get_functions(csv_path):
if func.addr not in known_fn_addrs:
new_fns.append(func)
new_fn_list: List[utils.FunctionInfo] = []
new_fn_list.extend(utils.get_functions())
new_fn_list.extend(new_fns)
new_fn_list.sort(key=lambda func: func.addr)
# Output the modified function CSV.
writer = csv.writer(sys.stdout, lineterminator="\n")
for func in new_fn_list:
writer.writerow(func.raw_row)
if __name__ == "__main__":
main()

271
tools/ai_generate_actions.py Executable file
View File

@ -0,0 +1,271 @@
#!/usr/bin/env python3
import enum
import cxxfilt
import zlib
from typing import List, Dict, Iterable, Optional, Set
from pathlib import Path
import textwrap
from util import ai_common, elf
def get_member_name(entry) -> str:
type_ = entry["type"]
if type_ == "dynamic_param":
return f'm{entry["param_name"]}_d'
elif type_ == "dynamic2_param":
return f'm{entry["param_name"]}_d'
elif type_ == "static_param":
return f'm{entry["param_name"]}_s'
elif type_ == "map_unit_param":
return f'm{entry["param_name"]}_m'
elif type_ == "aitree_variable":
return f'm{entry["param_name"]}_a'
else:
assert False
def generate_action_loadparam_body(info: list) -> str:
out = []
for entry in info:
type_ = entry["type"]
if type_ == "dynamic_param":
if entry["param_name"]:
out.append(f'getDynamicParam(&{get_member_name(entry)}, "{entry["param_name"]}");')
elif type_ == "dynamic2_param":
if entry["param_name"]:
out.append(f'getDynamicParam2(&{get_member_name(entry)}, "{entry["param_name"]}");')
elif type_ == "static_param":
if entry["param_name"]:
out.append(f'getStaticParam(&{get_member_name(entry)}, "{entry["param_name"]}");')
elif type_ == "map_unit_param":
if entry["param_name"]:
out.append(f'getMapUnitParam(&{get_member_name(entry)}, "{entry["param_name"]}");')
elif type_ == "aitree_variable":
if entry["param_name"]:
out.append(f'getAITreeVariable(&{get_member_name(entry)}, "{entry["param_name"]}");')
elif type_ == "call":
fn_name: str = entry["fn"]
if fn_name.startswith("_ZN") and fn_name.endswith("11loadParams_Ev"):
parent_class_name = cxxfilt.demangle(fn_name).split("::")[-2]
out.append(f"{parent_class_name}::loadParams_();")
else:
out.append(f"// FIXME: CALL {fn_name} @ {entry['addr']:#x}")
else:
raise AssertionError(f"unknown type: {type_}")
return "\n".join(out)
def generate_action_param_member_vars(parent: str, info: list) -> str:
out = []
# Ignore duplicate calls to getXXXXXParam
params_dict = dict()
for entry in info:
offset: Optional[int] = entry.get("param_offset")
if offset is not None:
params_dict[offset] = entry
params = list(params_dict.values())
params.sort(key=lambda entry: entry["param_offset"])
if not parent and params:
first_offset: int = params[0]["param_offset"]
sizeof_action = 0x20
diff = first_offset - sizeof_action
assert diff >= 0
if diff > 0:
out.append(f"// FIXME: remove this")
out.append(f"u8 pad_0x20[{diff:#x}];")
for entry in params:
if not entry["param_name"]:
continue
out.append(f"// {entry['type']} at offset {entry['param_offset']:#x}")
out.append(f"{entry['param_type']} {get_member_name(entry)}{{}};")
return "\n".join(out)
@enum.unique
class CommonVIndex(enum.IntEnum):
Dtor = 2
OneShot = 10
Init = 11
Enter = 12
Leave = 14
LoadParams = 15
Calc = 31
def generate_action(class_dir: Path, name: str, info: list, parent: str, seen_virtual_functions: Set[int],
vtable: int) -> None:
name = name[0].upper() + name[1:]
if parent:
parent = parent[0].upper() + parent[1:]
cpp_class_name = f"{name}"
header_file_name = f"action{name}.h"
parent_class_name = parent if parent else 'ksys::act::ai::Action'
own_virtual_functions: Set[int] = set()
for i, fn in enumerate(elf.get_vtable_fns_from_base_elf(vtable, 32)):
if i not in CommonVIndex.__members__.values() or fn in seen_virtual_functions:
continue
own_virtual_functions.add(i)
seen_virtual_functions.add(fn)
# Header
out = []
out.append("#pragma once")
out.append("")
if parent:
out.append(f'#include "Game/AI/Action/action{parent}.h"')
out.append('#include "KingSystem/ActorSystem/actAiAction.h"')
out.append("")
out.append("namespace uking::action {")
out.append("")
out.append(f"class {cpp_class_name} : public {parent_class_name} {{")
out.append(f" SEAD_RTTI_OVERRIDE({cpp_class_name}, {parent_class_name})")
out.append("public:")
out.append(f" explicit {cpp_class_name}(const InitArg& arg);")
if CommonVIndex.Dtor in own_virtual_functions:
out.append(f" ~{cpp_class_name}() override;")
out.append("")
if CommonVIndex.Init in own_virtual_functions:
out.append(" bool init_(sead::Heap* heap) override;")
if CommonVIndex.Enter in own_virtual_functions:
out.append(" void enter_(ksys::act::ai::InlineParamPack* params) override;")
if CommonVIndex.Leave in own_virtual_functions:
out.append(" void leave_() override;")
if CommonVIndex.LoadParams in own_virtual_functions:
out.append(" void loadParams_() override;")
out.append("")
out.append("protected:")
if CommonVIndex.Calc in own_virtual_functions:
out.append(" void calc_() override;")
out.append("")
out.append(textwrap.indent(generate_action_param_member_vars(parent, info), " " * 4))
out.append("};") # =================================== end of class
out.append("")
out.append("} // namespace uking::action")
out.append("")
(class_dir / header_file_name).write_text("\n".join(out))
# .cpp
out = []
out.append(f'#include "Game/AI/Action/{header_file_name}"')
out.append("")
out.append("namespace uking::action {")
out.append("")
out.append(f"{cpp_class_name}::{cpp_class_name}(const InitArg& arg) : {parent_class_name}(arg) {{}}")
out.append("")
if CommonVIndex.Dtor in own_virtual_functions:
out.append(f"{cpp_class_name}::~{cpp_class_name}() = default;")
out.append("")
if CommonVIndex.Init in own_virtual_functions:
out.append(f"bool {cpp_class_name}::init_(sead::Heap* heap) {{")
out.append(f" return {parent_class_name}::init_(heap);")
out.append(f"}}")
out.append("")
if CommonVIndex.Enter in own_virtual_functions:
out.append(f"void {cpp_class_name}::enter_(ksys::act::ai::InlineParamPack* params) {{")
out.append(f" {parent_class_name}::enter_(params);")
out.append(f"}}")
out.append("")
if CommonVIndex.Leave in own_virtual_functions:
out.append(f"void {cpp_class_name}::leave_() {{")
out.append(f" {parent_class_name}::leave_();")
out.append(f"}}")
out.append("")
if CommonVIndex.LoadParams in own_virtual_functions:
out.append(f"void {cpp_class_name}::loadParams_() {{")
out.append(textwrap.indent(generate_action_loadparam_body(info), " " * 4))
out.append(f"}}")
out.append("")
if CommonVIndex.Calc in own_virtual_functions:
out.append(f"void {cpp_class_name}::calc_() {{")
out.append(f" {parent_class_name}::calc_();")
out.append(f"}}")
out.append("")
out.append("} // namespace uking::action")
out.append("")
(class_dir / f"action{name}.cpp").write_text("\n".join(out))
def generate_action_factories(class_dir: Path, actions: Iterable[str]) -> None:
out = []
out.append("""\
// DO NOT MAKE MAJOR EDITS. This file is automatically generated.
// For major edits, please edit the generator script (ai_generate_queries.py) instead.
// If edits are made to this file, make sure they are not lost when the generator is re-run.
""")
out.append('#include "Game/AI/aiActionFactories.h"')
out.append('#include <array>')
for name in actions:
name = name[0].upper() + name[1:]
out.append(f'#include "Game/AI/Action/action{name}.h"')
out.append('#include "KingSystem/ActorSystem/actAiAction.h"')
out.append('')
out.append('namespace uking {')
out.append('')
out.append('using Factory = ksys::act::ai::ActionFactory;')
out.append('')
out.append('static Factory sActionFactories[] = {')
for name in sorted(actions, key=lambda name: zlib.crc32(name.encode())):
class_name = "action::" + name[0].upper() + name[1:]
out.append(f' {{0x{zlib.crc32(name.encode()):08x}, Factory::make<{class_name}>}},')
out.append('};')
out.append('')
out.append('void initActionFactories() {')
out.append(' ksys::act::ai::Actions::setFactories(std::size(sActionFactories), sActionFactories);')
out.append('}')
out.append('')
out.append('} // namespace uking')
(class_dir.parent / f"aiActionFactories.cpp").write_text("\n".join(out))
def main() -> None:
src_root = Path(__file__).parent.parent
class_dir = src_root / "src" / "Game" / "AI" / "Action"
class_dir.mkdir(exist_ok=True)
action_vtables: Dict[str, List[int]] = ai_common.get_vtables()["Action"]
action_params = ai_common.get_action_params()
vtable_names = ai_common.get_action_vtable_names()
seen_virtual_functions = set()
seen_virtual_functions.update(elf.get_vtable_fns_from_base_elf(0x24d8d68, 31))
seen_virtual_functions.update(elf.get_vtable_fns_from_base_elf(0x25129f0, 32))
generated = set()
for vtables in action_vtables.values():
vtables = list(dict.fromkeys(vtables))
for i in range(len(vtables)):
# This skips the first base class.
if i == 0:
continue
vtable_parent = vtables[i - 1]
vtable = vtables[i]
# This skips any other base class.
if vtable in ai_common.BaseClasses:
continue
action_name = vtable_names[vtable]
parent_name = vtable_names[vtable_parent]
if vtable_parent in ai_common.BaseClasses:
parent_name = ""
if vtable not in generated:
generated.add(vtable)
generate_action(class_dir, action_name, action_params[action_name], parent_name, seen_virtual_functions,
vtable)
generate_action_factories(class_dir, action_vtables.keys())
if __name__ == '__main__':
main()

272
tools/ai_generate_ais.py Executable file
View File

@ -0,0 +1,272 @@
#!/usr/bin/env python3
import enum
import cxxfilt
import zlib
from typing import List, Dict, Iterable, Optional, Set
from pathlib import Path
import textwrap
from util import ai_common, elf
def get_member_name(entry) -> str:
type_ = entry["type"]
if type_ == "dynamic_param":
return f'm{entry["param_name"]}_d'
elif type_ == "dynamic2_param":
return f'm{entry["param_name"]}_d'
elif type_ == "static_param":
return f'm{entry["param_name"]}_s'
elif type_ == "map_unit_param":
return f'm{entry["param_name"]}_m'
elif type_ == "aitree_variable":
return f'm{entry["param_name"]}_a'
else:
assert False
def generate_ai_loadparam_body(info: list) -> str:
out = []
for entry in info:
type_ = entry["type"]
if type_ == "dynamic_param":
if entry["param_name"]:
out.append(f'getDynamicParam(&{get_member_name(entry)}, "{entry["param_name"]}");')
elif type_ == "dynamic2_param":
if entry["param_name"]:
out.append(f'getDynamicParam2(&{get_member_name(entry)}, "{entry["param_name"]}");')
elif type_ == "static_param":
if entry["param_name"]:
out.append(f'getStaticParam(&{get_member_name(entry)}, "{entry["param_name"]}");')
elif type_ == "map_unit_param":
if entry["param_name"]:
out.append(f'getMapUnitParam(&{get_member_name(entry)}, "{entry["param_name"]}");')
elif type_ == "aitree_variable":
if entry["param_name"]:
out.append(f'getAITreeVariable(&{get_member_name(entry)}, "{entry["param_name"]}");')
elif type_ == "call":
fn_name: str = entry["fn"]
if fn_name.startswith("_ZN") and fn_name.endswith("11loadParams_Ev"):
parent_class_name = cxxfilt.demangle(fn_name).split("::")[-2]
out.append(f"{parent_class_name}::loadParams_();")
else:
out.append(f"// FIXME: CALL {fn_name} @ {entry['addr']:#x}")
else:
raise AssertionError(f"unknown type: {type_}")
return "\n".join(out)
def generate_ai_param_member_vars(parent: str, info: list) -> str:
out = []
# Ignore duplicate calls to getXXXXXParam
params_dict = dict()
for entry in info:
offset: Optional[int] = entry.get("param_offset")
if offset is not None:
params_dict[offset] = entry
params = list(params_dict.values())
params.sort(key=lambda entry: entry["param_offset"])
if not parent and params:
first_offset: int = params[0]["param_offset"]
sizeof_ai = 0x38
diff = first_offset - sizeof_ai
assert diff >= 0
if diff > 0:
out.append(f"// FIXME: remove this")
out.append(f"u8 pad_0x38[{diff:#x}];")
for entry in params:
if not entry["param_name"]:
continue
out.append(f"// {entry['type']} at offset {entry['param_offset']:#x}")
out.append(f"{entry['param_type']} {get_member_name(entry)}{{}};")
return "\n".join(out)
@enum.unique
class CommonVIndex(enum.IntEnum):
Dtor = 2
OneShot = 10
Init = 11
Enter = 12
Leave = 14
LoadParams = 15
Calc = 32
def generate_ai(class_dir: Path, name: str, info: list, parent: str, seen_virtual_functions: Set[int],
vtable: int) -> None:
name = name[0].upper() + name[1:]
if parent:
parent = parent[0].upper() + parent[1:]
cpp_class_name = f"{name}"
header_file_name = f"ai{name}.h"
parent_class_name = parent if parent else 'ksys::act::ai::Ai'
own_virtual_functions: Set[int] = set()
for i, fn in enumerate(elf.get_vtable_fns_from_base_elf(vtable, 32)):
if i not in CommonVIndex.__members__.values() or fn in seen_virtual_functions:
continue
own_virtual_functions.add(i)
seen_virtual_functions.add(fn)
# Header
out = []
out.append("#pragma once")
out.append("")
if parent:
out.append(f'#include "Game/AI/AI/ai{parent}.h"')
out.append('#include "KingSystem/ActorSystem/actAiAi.h"')
out.append("")
out.append("namespace uking::ai {")
out.append("")
out.append(f"class {cpp_class_name} : public {parent_class_name} {{")
out.append(f" SEAD_RTTI_OVERRIDE({cpp_class_name}, {parent_class_name})")
out.append("public:")
out.append(f" explicit {cpp_class_name}(const InitArg& arg);")
if CommonVIndex.Dtor in own_virtual_functions:
out.append(f" ~{cpp_class_name}() override;")
out.append("")
if CommonVIndex.Init in own_virtual_functions:
out.append(" bool init_(sead::Heap* heap) override;")
if CommonVIndex.Enter in own_virtual_functions:
out.append(" void enter_(ksys::act::ai::InlineParamPack* params) override;")
if CommonVIndex.Leave in own_virtual_functions:
out.append(" void leave_() override;")
if CommonVIndex.LoadParams in own_virtual_functions:
out.append(" void loadParams_() override;")
out.append("")
out.append("protected:")
if CommonVIndex.Calc in own_virtual_functions:
out.append(" void calc_() override;")
out.append("")
out.append(textwrap.indent(generate_ai_param_member_vars(parent, info), " " * 4))
out.append("};") # =================================== end of class
out.append("")
out.append("} // namespace uking::ai")
out.append("")
(class_dir / header_file_name).write_text("\n".join(out))
# .cpp
out = []
out.append(f'#include "Game/AI/AI/{header_file_name}"')
out.append("")
out.append("namespace uking::ai {")
out.append("")
out.append(f"{cpp_class_name}::{cpp_class_name}(const InitArg& arg) : {parent_class_name}(arg) {{}}")
out.append("")
if CommonVIndex.Dtor in own_virtual_functions:
out.append(f"{cpp_class_name}::~{cpp_class_name}() = default;")
out.append("")
if CommonVIndex.Init in own_virtual_functions:
out.append(f"bool {cpp_class_name}::init_(sead::Heap* heap) {{")
out.append(f" return {parent_class_name}::init_(heap);")
out.append(f"}}")
out.append("")
if CommonVIndex.Enter in own_virtual_functions:
out.append(f"void {cpp_class_name}::enter_(ksys::act::ai::InlineParamPack* params) {{")
out.append(f" {parent_class_name}::enter_(params);")
out.append(f"}}")
out.append("")
if CommonVIndex.Leave in own_virtual_functions:
out.append(f"void {cpp_class_name}::leave_() {{")
out.append(f" {parent_class_name}::leave_();")
out.append(f"}}")
out.append("")
if CommonVIndex.LoadParams in own_virtual_functions:
out.append(f"void {cpp_class_name}::loadParams_() {{")
out.append(textwrap.indent(generate_ai_loadparam_body(info), " " * 4))
out.append(f"}}")
out.append("")
if CommonVIndex.Calc in own_virtual_functions:
out.append(f"void {cpp_class_name}::calc_() {{")
out.append(f" {parent_class_name}::calc_();")
out.append(f"}}")
out.append("")
out.append("} // namespace uking::ai")
out.append("")
(class_dir / f"ai{name}.cpp").write_text("\n".join(out))
def generate_ai_factories(class_dir: Path, ais: Iterable[str]) -> None:
out = []
out.append("""\
// DO NOT MAKE MAJOR EDITS. This file is automatically generated.
// For major edits, please edit the generator script (ai_generate_ais.py) instead.
// If edits are made to this file, make sure they are not lost when the generator is re-run.
""")
out.append('#include "Game/AI/aiAiFactories.h"')
out.append('#include <array>')
for name in ais:
name = name[0].upper() + name[1:]
out.append(f'#include "Game/AI/AI/ai{name}.h"')
out.append('#include "KingSystem/ActorSystem/actAiAi.h"')
out.append('')
out.append('namespace uking {')
out.append('')
out.append('using Factory = ksys::act::ai::AiFactory;')
out.append('')
out.append('static Factory sAiFactories[] = {')
for name in sorted(ais, key=lambda name: zlib.crc32(name.encode())):
class_name = "ai::" + name[0].upper() + name[1:]
out.append(f' {{0x{zlib.crc32(name.encode()):08x}, Factory::make<{class_name}>}},')
out.append('};')
out.append('')
out.append('void initAiFactories() {')
out.append(' ksys::act::ai::Ais::setFactories(std::size(sAiFactories), sAiFactories);')
out.append('}')
out.append('')
out.append('} // namespace uking')
(class_dir.parent / f"aiAiFactories.cpp").write_text("\n".join(out))
def main() -> None:
src_root = Path(__file__).parent.parent
class_dir = src_root / "src" / "Game" / "AI" / "AI"
class_dir.mkdir(exist_ok=True)
ai_vtables: Dict[str, List[int]] = ai_common.get_vtables()["AI"]
ai_params = ai_common.get_ai_params()
vtable_names = ai_common.get_ai_vtable_names()
seen_virtual_functions = set()
# ai::ActionBase
seen_virtual_functions.update(elf.get_vtable_fns_from_base_elf(0x24d8d68, 31))
# ai::Ai
seen_virtual_functions.update(elf.get_vtable_fns_from_base_elf(0x2513278, 34))
generated = set()
for vtables in ai_vtables.values():
vtables = list(dict.fromkeys(vtables))
for i in range(len(vtables)):
# This skips the first base class.
if i == 0:
continue
vtable_parent = vtables[i - 1]
vtable = vtables[i]
# This skips any other base class.
if vtable in ai_common.BaseClasses:
continue
ai_name = vtable_names[vtable]
parent_name = vtable_names[vtable_parent]
if vtable_parent in ai_common.BaseClasses:
parent_name = ""
if vtable not in generated:
generated.add(vtable)
generate_ai(class_dir, ai_name, ai_params[ai_name], parent_name, seen_virtual_functions, vtable)
generate_ai_factories(class_dir, ai_vtables.keys())
if __name__ == '__main__':
main()

213
tools/ai_generate_queries.py Executable file
View File

@ -0,0 +1,213 @@
#!/usr/bin/env python3
import argparse
import zlib
from typing import List
import oead
from pathlib import Path
import textwrap
def sort_params(params: list) -> list:
def sort_by_type(param):
t = param["Type"]
if t == "String":
return 1
return 0
return sorted(params, key=sort_by_type)
def generate_query_loadparam_body(query: dict, is_evfl: bool) -> str:
if not query:
return ""
out = []
if is_evfl:
for param in sort_params(query.get("DynamicInstParams", [])):
out.append(f"load{param['Type']}(arg.param_accessor, \"{param['Name']}\");")
else:
for param in sort_params(query.get("StaticInstParams", [])):
out.append(f"getStaticParam(&m{param['Name']}, \"{param['Name']}\");")
for param in sort_params(query.get("DynamicInstParams", [])):
out.append(f"getDynamicParam(&m{param['Name']}, \"{param['Name']}\");")
for param in sort_params(query.get("AITreeVariables", [])):
out.append(f"getAITreeVariable(&m{param['Name']}, \"{param['Name']}\");")
return "\n".join(out)
_types_static = {
"Bool": "const bool*",
"Int": "const int*",
"Float": "const float*",
"String": "sead::SafeString",
}
_types_dynamic = {
"Bool": "bool*",
"Int": "int*",
"Float": "float*",
"String": "sead::SafeString",
}
_types_ai_tree_var = {
"String": "sead::SafeString*",
"AITreeVariablePointer": "void*",
}
def generate_query_param_member_vars(query: dict) -> str:
out = []
for param in sort_params(query.get("StaticInstParams", [])):
out.append(f"{_types_static[param['Type']]} m{param['Name']}{{}};")
for param in sort_params(query.get("DynamicInstParams", [])):
out.append(f"{_types_dynamic[param['Type']]} m{param['Name']}{{}};")
for param in sort_params(query.get("AITreeVariables", [])):
out.append(f"{_types_ai_tree_var[param['Type']]} m{param['Name']}{{}};")
return "\n".join(out)
def generate_query(class_dir: Path, name: str, query) -> None:
has_params = False
if query != "":
assert isinstance(query, oead.byml.Hash)
query = dict(query)
has_params = "DynamicInstParams" in query or "StaticInstParams" in query or "AITreeVariables" in query
cpp_class_name = f"{name}"
header_file_name = f"query{name}.h"
# Header
out = []
out.append("#pragma once")
out.append("")
out.append('#include "KingSystem/ActorSystem/actAiQuery.h"')
out.append("")
out.append("namespace uking::query {")
out.append("")
out.append(f"class {cpp_class_name} : public ksys::act::ai::Query {{")
out.append(f" SEAD_RTTI_OVERRIDE({cpp_class_name}, Query)")
out.append("public:")
out.append(f" explicit {cpp_class_name}(const InitArg& arg);")
out.append(f" ~{cpp_class_name}() override;")
out.append(f" int doQuery() override;")
out.append("")
out.append(" void loadParams() override;")
out.append(" void loadParams(const evfl::QueryArg& arg) override;")
if has_params:
out.append("")
out.append("protected:")
out.append(textwrap.indent(generate_query_param_member_vars(query), " " * 4))
out.append("};") # =================================== end of class
out.append("")
out.append("} // namespace uking::query")
out.append("")
(class_dir / header_file_name).write_text("\n".join(out))
# .cpp
out = []
out.append(f'#include "Game/AI/Query/{header_file_name}"')
out.append(f'#include <evfl/query.h>')
out.append("")
out.append("namespace uking::query {")
out.append("")
out.append(f"{cpp_class_name}::{cpp_class_name}(const InitArg& arg) : ksys::act::ai::Query(arg) {{}}")
out.append("")
out.append(f"{cpp_class_name}::~{cpp_class_name}() = default;")
out.append("")
out.append("// FIXME: implement")
out.append(f"int {cpp_class_name}::doQuery() {{ return -1; }}")
out.append("")
out.append(f"void {cpp_class_name}::loadParams(const evfl::QueryArg& arg) {{")
out.append(textwrap.indent(generate_query_loadparam_body(query, is_evfl=True), " " * 4))
out.append(f"}}")
out.append("")
out.append(f"void {cpp_class_name}::loadParams() {{")
out.append(textwrap.indent(generate_query_loadparam_body(query, is_evfl=False), " " * 4))
out.append(f"}}")
out.append("")
out.append("} // namespace uking::query")
out.append("")
(class_dir / f"query{name}.cpp").write_text("\n".join(out))
def generate_query_factories(class_dir: Path, aidef) -> None:
queries: List[str] = []
for query_name, data in aidef["Querys"].items():
if isinstance(data, oead.byml.Hash) and dict(data).get("SystemQuery", False):
continue
queries.append(query_name)
out = []
out.append("""\
// DO NOT MAKE MAJOR EDITS. This file is automatically generated.
// For major edits, please edit the generator script (ai_generate_queries.py) instead.
// If edits are made to this file, make sure they are not lost when the generator is re-run.
""")
out.append('#include "Game/AI/aiQueryFactories.h"')
out.append('#include <array>')
for query_name in queries:
query_name = query_name[0].upper() + query_name[1:]
out.append(f'#include "Game/AI/Query/query{query_name}.h"')
out.append('#include "KingSystem/ActorSystem/actAiQueries.h"')
out.append('#include "KingSystem/ActorSystem/actAiQuery.h"')
out.append('')
out.append('namespace uking {')
out.append('')
out.append('using Factory = ksys::act::ai::QueryFactory;')
out.append('')
out.append('static ksys::act::ai::QueryFactory sQueryFactories[] = {')
for query_name in sorted(queries, key=lambda query: zlib.crc32(query.encode())):
class_name = "query::" + query_name[0].upper() + query_name[1:]
out.append(f' {{0x{zlib.crc32(query_name.encode()):08x}, Factory::make<{class_name}>}},')
out.append('};')
out.append('')
out.append('void initQueryFactories() {')
out.append(' ksys::act::ai::Queries::setFactories(std::size(sQueryFactories), sQueryFactories);')
out.append('}')
out.append('')
out.append('} // namespace uking')
(class_dir.parent / f"aiQueryFactories.cpp").write_text("\n".join(out))
def main() -> None:
src_root = Path(__file__).parent.parent
class_dir = src_root / "src" / "Game" / "AI" / "Query"
class_dir.mkdir(exist_ok=True)
parser = argparse.ArgumentParser(description="Generates stubs for AI queries.")
parser.add_argument("aidef")
args = parser.parse_args()
aidef = oead.byml.from_text(Path(args.aidef).read_text(encoding="utf-8"))
count = 0
keys = set()
for query_name, data in aidef["Querys"].items():
if isinstance(data, oead.byml.Hash) and dict(data).get("SystemQuery", False):
continue
if isinstance(data, oead.byml.Hash):
keys |= set(data.keys())
query_name = query_name[0].upper() + query_name[1:]
generate_query(class_dir, query_name, data)
print(query_name)
count += 1
generate_query_factories(class_dir, aidef)
print()
print(f"{count} queries")
if __name__ == '__main__':
main()

View File

@ -0,0 +1,132 @@
#!/usr/bin/env python3
import argparse
import oead
from colorama import Fore
import cxxfilt
from pathlib import Path
from typing import Dict, Iterable
import util.checker
import util.elf
from util import utils, ai_common
def identify(functions: Dict[str, utils.FunctionInfo], checker: util.checker.FunctionChecker,
new_matches: Dict[int, str], class_names: Iterable[str], get_pairs) -> None:
for name in class_names:
orig_name = name
name = name[0].upper() + name[1:]
pairs = get_pairs(orig_name, name)
for orig_fn_name, fn_name in pairs:
orig_fn_info = functions.get(orig_fn_name, None)
if orig_fn_info is None:
continue
if orig_fn_info.status != utils.FunctionStatus.NotDecompiled:
continue
orig_fn = util.elf.get_fn_from_base_elf(orig_fn_info.addr, orig_fn_info.size)
try:
decomp_fn = util.elf.get_fn_from_my_elf(fn_name)
except KeyError:
continue
if checker.check(orig_fn, decomp_fn):
new_matches[orig_fn_info.addr] = fn_name
utils.print_note(f"new match: {Fore.BLUE}{cxxfilt.demangle(fn_name)}{Fore.RESET}")
def main() -> None:
parser = argparse.ArgumentParser(description="Identifies matching AI class functions.")
parser.add_argument("aidef")
parser.add_argument("--type", choices=["Action", "AI", "Behavior", "Query"], required=True)
args = parser.parse_args()
type_: str = args.type
new_matches: Dict[int, str] = dict()
checker = util.checker.FunctionChecker()
functions: Dict[str, utils.FunctionInfo] = {fn.name: fn for fn in utils.get_functions()}
aidef = oead.byml.from_text(Path(args.aidef).read_text(encoding="utf-8"))
def get_query_pairs(orig_name, name):
prefix = f"AI_Query_{orig_name}::"
return [
(f"{prefix}ctor", f"_ZN5uking5query{len(name)}{name}C1ERKN4ksys3act2ai5Query7InitArgE"),
(f"{prefix}dtor", f"_ZN5uking5query{len(name)}{name}D1Ev"),
(f"{prefix}dtorDelete", f"_ZN5uking5query{len(name)}{name}D0Ev"),
(f"{prefix}m10", f"_ZN5uking5query{len(name)}{name}10loadParamsERKN4evfl8QueryArgE"),
(f"{prefix}loadParams", f"_ZN5uking5query{len(name)}{name}10loadParamsEv"),
(f"{prefix}rtti1",
f"_ZNK5uking5query{len(name)}{name}27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE"),
(f"{prefix}rtti2", f"_ZNK5uking5query{len(name)}{name}18getRuntimeTypeInfoEv"),
(f"AI_F_Query_{orig_name}",
f"_ZN4ksys3act2ai12QueryFactory4makeIN5uking5query{len(name)}{name}EEEPNS1_5QueryERKNS7_7InitArgEPN4sead4HeapE"),
]
def get_action_pairs(orig_name, name):
pairs = []
def add_pair(x):
pairs.append((x, x))
pairs.append(
(f"AI_Action_{orig_name}::ctor",
f"_ZN5uking6action{len(name)}{name}C1ERKN4ksys3act2ai10ActionBase7InitArgE"))
pairs.append(
(f"AI_Action{orig_name}::ctor",
f"_ZN5uking6action{len(name)}{name}C1ERKN4ksys3act2ai10ActionBase7InitArgE"))
pairs.append((f"AI_F_Action_{orig_name}",
f"_ZN4ksys3act2ai13ActionFactory4makeIN5uking6action{len(name)}{name}EEEPNS1_6ActionERKNS1_10ActionBase7InitArgEPN4sead4HeapE"))
add_pair(f"_ZN5uking6action{len(name)}{name}D1Ev")
add_pair(f"_ZN5uking6action{len(name)}{name}D0Ev")
add_pair(f"_ZN5uking6action{len(name)}{name}11loadParams_Ev")
add_pair(f"_ZN5uking6action{len(name)}{name}5init_EPN4sead4HeapE")
add_pair(f"_ZN5uking6action{len(name)}{name}6enter_EPN4ksys3act2ai15InlineParamPackE")
add_pair(f"_ZN5uking6action{len(name)}{name}6leave_Ev")
add_pair(f"_ZN5uking6action{len(name)}{name}5calc_Ev")
add_pair(
f"_ZNK5uking6action{len(name)}{name}27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE")
add_pair(f"_ZNK5uking6action{len(name)}{name}18getRuntimeTypeInfoEv")
return pairs
def get_ai_pairs(orig_name, name):
pairs = []
def add_pair(x):
pairs.append((x, x))
pairs.append(
(f"AI_AI_{orig_name}::ctor", f"_ZN5uking2ai{len(name)}{name}C1ERKN4ksys3act2ai10ActionBase7InitArgE"))
pairs.append(
(f"AI_AI{orig_name}::ctor", f"_ZN5uking2ai{len(name)}{name}C1ERKN4ksys3act2ai10ActionBase7InitArgE"))
pairs.append((f"AI_F_AI_{orig_name}",
f"_ZN4ksys3act2ai9AiFactory4makeIN5uking2ai{len(name)}{name}EEEPNS1_2AiERKNS1_10ActionBase7InitArgEPN4sead4HeapE"))
add_pair(f"_ZN5uking2ai{len(name)}{name}D1Ev")
add_pair(f"_ZN5uking2ai{len(name)}{name}D0Ev")
add_pair(f"_ZN5uking2ai{len(name)}{name}11loadParams_Ev")
add_pair(f"_ZN5uking2ai{len(name)}{name}5init_EPN4sead4HeapE")
add_pair(f"_ZN5uking2ai{len(name)}{name}6enter_EPN4ksys3act2ai15InlineParamPackE")
add_pair(f"_ZN5uking2ai{len(name)}{name}6leave_Ev")
add_pair(f"_ZN5uking2ai{len(name)}{name}5calc_Ev")
add_pair(f"_ZNK5uking2ai{len(name)}{name}27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE")
add_pair(f"_ZNK5uking2ai{len(name)}{name}18getRuntimeTypeInfoEv")
return pairs
if type_ == "Action":
action_vtable_names = ai_common.get_action_vtable_names()
identify(functions, checker, new_matches, action_vtable_names.values(), get_action_pairs)
if type_ == "AI":
ai_vtable_names = ai_common.get_ai_vtable_names()
identify(functions, checker, new_matches, ai_vtable_names.values(), get_ai_pairs)
elif type_ == "Query":
identify(functions, checker, new_matches, aidef["Querys"].keys(), get_query_pairs)
utils.add_decompiled_functions(new_matches)
if __name__ == "__main__":
main()

43
tools/ai_progress.py Executable file
View File

@ -0,0 +1,43 @@
#!/usr/bin/env python3
import argparse
from typing import Dict, Optional
import yaml
from colorama import Fore
from util import utils
# TODO: add behaviors after they have been generated
_TYPES = ("action", "ai", "query")
def main() -> None:
parser = argparse.ArgumentParser("Print AI class decompilation progress.")
parser.add_argument("-t", "--type", help="AI class type", choices=_TYPES)
args = parser.parse_args()
filter_type: Optional[str] = args.type
data_path = utils.get_repo_root() / "data"
for class_type in _TYPES:
if filter_type is not None and class_type != filter_type:
continue
with (data_path / f"status_{class_type}.yml").open() as f:
fns: Dict[str, dict] = yaml.load(f, Loader=yaml.CSafeLoader)
for name, info in fns.items():
status = info["status"]
if status == "done":
color = Fore.GREEN
elif status == "wip":
color = Fore.YELLOW
elif status == "pending":
color = ""
else:
assert False, f"unexpected status {status}"
print(f"{color}{name:<50} {color}{info['status']}{Fore.RESET}")
if __name__ == '__main__':
main()

View File

@ -0,0 +1,114 @@
#!/usr/bin/env python3
import argparse
from pathlib import Path
from typing import Union
import yaml
from util import ai_common
from util.ai_common import BaseClasses
from util.graph import Graph
_known_vtables = {
0x71024d8d68: "ActionBase",
0x71025129f0: "Action",
0x7102513278: "Ai",
0x71024d8ef0: "Behavior",
0x710243c9b8: "Query",
}
def get_name_for_vtable(vtable: Union[str, int]):
if isinstance(vtable, str):
return vtable
known_name = _known_vtables.get(vtable, None)
if known_name is not None:
return f"[V] {known_name}"
return f"[V] {vtable:#x}"
def guess_vtable_names(reverse_graph: Graph):
for u in reverse_graph.nodes:
targets = list(reverse_graph.nodes[u])
known_targets = list(filter(lambda x: isinstance(x, str), targets))
if len(known_targets) == 1:
# Leaves can be named pretty easily.
_known_vtables[u] = known_targets[0]
def build_graph(all_vtables: dict, type_: str, graph: Graph, reverse_graph: Graph):
for name, vtables in all_vtables[type_].items():
classes = [name] + list(reversed(vtables))
# Each class has at least one parent, so the -1 is fine.
for i in range(len(classes) - 1):
from_ = classes[i]
to_ = classes[i + 1]
# Skip base classes to reduce noise.
if to_ in BaseClasses:
break
reverse_graph.add_edge(to_, from_)
guess_vtable_names(reverse_graph)
for name, vtables in all_vtables[type_].items():
classes = [name] + list(reversed(vtables))
for i in range(len(classes) - 1):
if classes[i + 1] in BaseClasses:
break
from_ = get_name_for_vtable(classes[i])
to_ = get_name_for_vtable(classes[i + 1])
graph.add_edge(from_, to_)
def main() -> None:
parser = argparse.ArgumentParser(description="Shows AI classes with non-trivial class hierarchies.")
parser.add_argument("--type", help="AI class type to visualise", choices=["Action", "AI", "Behavior", "Query"],
required=True)
parser.add_argument("--out-names", help="Path to which a vtable -> name map will be written", required=True)
args = parser.parse_args()
all_vtables = ai_common.get_vtables()
graph = Graph()
reverse_graph = Graph()
build_graph(all_vtables, args.type, graph, reverse_graph)
interesting_nodes = set()
node_colors = dict()
colors = ["#c7dcff", "#ffc7c7", "#ceffc7", "#dcc7ff", "#fffdc9", "#c9fff3", "#ffe0cc", "#ffcffe", "#96a8ff"]
components = graph.find_connected_components()
num_nontrivial_cc = 0
for i, comp in enumerate(components):
if len(comp) == 2:
continue
for node in comp:
node_colors[node] = colors[i % len(colors)]
num_nontrivial_cc += 1
interesting_nodes |= set(comp)
print("digraph {")
print("node [shape=rectangle]")
for u in graph.nodes:
if u not in interesting_nodes:
continue
for v in graph.nodes[u]:
shape_u = "shape=component," if "[V]" not in u else ""
shape_v = "shape=component," if "[V]" not in v else ""
print(f'"{u}" [{shape_u}style=filled, fillcolor="{node_colors[u]}"]')
print(f'"{v}" [{shape_v}style=filled, fillcolor="{node_colors[v]}"]')
print(f'"{u}" -> "{v}"')
print("}")
print(f"# {len(components)} connected components")
print(f"# {num_nontrivial_cc} non-trivial connected components")
yaml.add_representer(int, lambda dumper, data: yaml.ScalarNode('tag:yaml.org,2002:int', f"{data:#x}"),
Dumper=yaml.CSafeDumper)
with Path(args.out_names).open("w") as f:
yaml.dump(_known_vtables, f, Dumper=yaml.CSafeDumper)
if __name__ == '__main__':
main()

2
tools/asm-differ/.gitignore vendored Executable file
View File

@ -0,0 +1,2 @@
.mypy_cache/
__pycache__/

40
tools/asm-differ/README.md Executable file
View File

@ -0,0 +1,40 @@
# asm-differ
Nice differ for assembly code (MIPS and AArch64; should be easy to hack to support other instruction sets).
![](screenshot.png)
## Dependencies
- Python >= 3.6
- `python3 -m pip install --user colorama ansiwrap watchdog python-Levenshtein`
## Usage
Create a file `diff-settings.sh` in some directory (see the one in this repo for an example). Then from that directory, run
```
/path/to/diff.sh [flags] (function|rom addr)
```
Recommended flags are `-mwo` (automatically run `make` on source file changes, and include symbols in diff). See `--help` for more details.
### Tab completion
[argcomplete](https://kislyuk.github.io/argcomplete/) can be optionally installed (with `python3 -m pip install argcomplete`) to enable tab completion in a bash shell, completing options and symbol names using the linker map. It also requires a bit more setup:
If invoking the script **exactly** as `./diff.py`, the following should be added to the `.bashrc` according to argcomplete's instructions:
```sh
eval "$(register-python-argcomplete ./diff.py)"
```
If that doesn't work, run `register-python-argcomplete ./diff.py` in your terminal and copy the output to `.bashrc`.
If setup correctly (don't forget to restart the shell), `complete | grep ./diff.py` should output:
```
complete -o bashdefault -o default -o nospace -F _python_argcomplete ./diff.py
```
Note for developers or for general troubleshooting: run `export _ARC_DEBUG=` to enable debug output during tab-completion, it may show otherwise silenced errors. Use `unset _ARC_DEBUG` or restart the terminal to disable.

1607
tools/asm-differ/diff.py Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
def apply(config, args):
config["baseimg"] = "target.bin"
config["myimg"] = "source.bin"
config["mapfile"] = "build.map"
config["source_directories"] = ["."]
#config["arch"] = "mips"
#config["map_format"] = "gnu" # gnu or mw
#config["mw_build_dir"] = "build/" # only needed for mw map format
#config["makeflags"] = []
#config["objdump_executable"] = ""

16
tools/asm-differ/mypy.ini Executable file
View File

@ -0,0 +1,16 @@
[mypy]
check_untyped_defs = True
disallow_any_generics = True
disallow_incomplete_defs = True
disallow_subclassing_any = True
disallow_untyped_calls = True
disallow_untyped_decorators = True
disallow_untyped_defs = True
no_implicit_optional = True
warn_redundant_casts = True
warn_return_any = True
warn_unused_ignores = True
python_version = 3.6
[mypy-diff_settings]
ignore_errors = True

BIN
tools/asm-differ/screenshot.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

68
tools/check.py Executable file
View File

@ -0,0 +1,68 @@
#!/usr/bin/env python3
import sys
from typing import Optional
from colorama import Fore
import util.elf
import util.checker
from util import utils
def check_function(checker: util.checker.FunctionChecker, addr: int, size: int, name: str,
base_fn: Optional[util.elf.Function] = None) -> bool:
if base_fn is None:
try:
base_fn = util.elf.get_fn_from_base_elf(addr, size)
except KeyError:
utils.print_error(f"couldn't find base function 0x{addr:016x} for {utils.format_symbol_name_for_msg(name)}")
return False
my_fn = util.elf.get_fn_from_my_elf(name)
return checker.check(base_fn, my_fn)
def main() -> None:
failed = False
nonmatching_fns_with_dump = {p.stem: util.elf.Function(p.read_bytes(), 0) for p in
(utils.get_repo_root() / "expected").glob("*.bin")}
checker = util.checker.FunctionChecker(log_mismatch_cause=True)
for func in utils.get_functions():
if not func.decomp_name:
continue
try:
util.elf.get_fn_from_my_elf(func.decomp_name)
except KeyError:
utils.warn(f"couldn't find {utils.format_symbol_name_for_msg(func.decomp_name)}")
continue
if func.status == utils.FunctionStatus.Matching:
if not check_function(checker, func.addr, func.size, func.decomp_name):
utils.print_error(
f"function {utils.format_symbol_name_for_msg(func.decomp_name)} is marked as matching but does not match")
a1, a2, reason = checker.get_mismatch()
if a1 != -1:
sys.stderr.write(f" at {a1 | 0x7100000000:#x} : {Fore.CYAN}{reason}{Fore.RESET}\n")
failed = True
elif func.status == utils.FunctionStatus.Equivalent or func.status == utils.FunctionStatus.NonMatching:
if check_function(checker, func.addr, func.size, func.decomp_name):
utils.print_note(
f"function {utils.format_symbol_name_for_msg(func.decomp_name)} is marked as non-matching but matches")
fn_dump = nonmatching_fns_with_dump.get(func.decomp_name, None)
if fn_dump is not None and not check_function(checker, func.addr, len(fn_dump), func.decomp_name, fn_dump):
utils.print_error(
f"function {utils.format_symbol_name_for_msg(func.decomp_name)} does not match expected output")
failed = True
if failed:
sys.exit(1)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,8 @@
import idaapi
import idautils
with open("/tmp/funclist.csv", "w") as f:
for ea in idautils.Functions():
size = idaapi.get_func(ea).size()
name = idaapi.get_func_name(ea)
f.write(",".join(("0x%016lx" % ea, name, str(size), "")) + "\n")

61
tools/diff.py Executable file
View File

@ -0,0 +1,61 @@
#!/usr/bin/env python3
import argparse
import subprocess
import cxxfilt
from colorama import Fore, Style
from util import utils
import util.checker
import check
parser = argparse.ArgumentParser(description="Diff assembly")
parser.add_argument(
"function", help="Name of the function to diff. Pass | to get a WIP function", nargs="?", default="|")
args, unknown = parser.parse_known_args()
find_wip = args.function == "|"
def find_function_info(name: str):
for info in utils.get_functions():
if info.decomp_name == name or (find_wip and info.status == utils.FunctionStatus.Wip):
return info
for info in utils.get_functions():
if name in cxxfilt.demangle(info.decomp_name):
return info
return None
def check_func(info):
checker = util.checker.FunctionChecker(log_mismatch_cause=True)
return check.check_function(checker, info.addr, info.size, info.decomp_name)
info = find_function_info(args.function)
if info is not None:
if not info.decomp_name:
utils.fail(f"{args.function} has not been decompiled")
print("comparing functions...")
if(check_func(info)):
print("matching function!")
else:
print(
f"diffing: {Style.BRIGHT}{Fore.BLUE}{cxxfilt.demangle(info.decomp_name)}{Style.RESET_ALL} {Style.DIM}({info.decomp_name}){Style.RESET_ALL}")
addr_end = info.addr + info.size
subprocess.call(["tools/asm-differ/diff.py", "-I", "-e", info.decomp_name, "0x%016x" %
info.addr, "0x%016x" % addr_end] + unknown)
if info.status == utils.FunctionStatus.NonMatching:
utils.warn(
f"{info.decomp_name} is marked as non-matching and possibly NOT functionally equivalent")
elif info.status == utils.FunctionStatus.Equivalent:
utils.warn(f"{info.decomp_name} is marked as functionally equivalent but non-matching")
else:
if find_wip:
utils.fail("no WIP function")
utils.fail(
f"unknown function '{args.function}'\nfor constructors and destructors, list the complete object constructor (C1) or destructor (D1)")

23
tools/diff_settings.py Executable file
View File

@ -0,0 +1,23 @@
#!/usr/bin/env python3
from pathlib import Path
def apply(config, args):
config['arch'] = 'aarch64'
config['baseimg'] = 'data/main.elf'
config['myimg'] = 'build/odyssey'
config['source_directories'] = ['src', 'lib']
config['objdump_executable'] = 'tools/aarch64-none-elf-objdump'
for dir in ('build', 'build/nx64-release'):
if (Path(dir) / 'build.ninja').is_file():
config['make_command'] = ['ninja', '-C', dir]
def map_build_target(make_target: str):
if make_target == "build/odyssey":
return "odyssey"
# TODO: When support for directly diffing object files is added, this needs to strip
# the build/ prefix from the object file targets.
return make_target

29
tools/dump_function.py Executable file
View File

@ -0,0 +1,29 @@
#!/usr/bin/env python3
import argparse
import util.elf
from util import utils
def dump_fn(name: str) -> None:
expected_dir = utils.get_repo_root() / "expected"
try:
fn = util.elf.get_fn_from_my_elf(name)
path = expected_dir / f"{name}.bin"
path.parent.mkdir(exist_ok=True)
path.write_bytes(fn.data)
except KeyError:
utils.fail("could not find function")
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("function_name", help="Name of the function to dump")
args = parser.parse_args()
dump_fn(args.function_name)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,131 @@
#!/usr/bin/env python3
import argparse
import json
import oead
from pathlib import Path
def _parse_parameter_archive(path: Path) -> oead.aamp.ParameterIO:
data = path.read_bytes()
try:
return oead.aamp.ParameterIO.from_binary(data)
except:
return oead.aamp.ParameterIO.from_text(data)
_AampTypeToAglUtlParameterType = {
oead.aamp.Parameter.Type.Bool: "agl::utl::Parameter<bool>",
oead.aamp.Parameter.Type.F32: "agl::utl::Parameter<f32>",
oead.aamp.Parameter.Type.Int: "agl::utl::Parameter<s32>",
oead.aamp.Parameter.Type.Vec2: "agl::utl::Parameter<sead::Vector2f>",
oead.aamp.Parameter.Type.Vec3: "agl::utl::Parameter<sead::Vector3f>",
oead.aamp.Parameter.Type.Vec4: "agl::utl::Parameter<sead::Vector4f>",
oead.aamp.Parameter.Type.Color: "agl::utl::Parameter<sead::Color4f>",
oead.aamp.Parameter.Type.String32: "agl::utl::Parameter<sead::SafeString>",
oead.aamp.Parameter.Type.String64: "agl::utl::Parameter<sead::SafeString>",
oead.aamp.Parameter.Type.Curve1: "agl::utl::ParameterCurve<1>",
oead.aamp.Parameter.Type.Curve2: "agl::utl::ParameterCurve<2>",
oead.aamp.Parameter.Type.Curve3: "agl::utl::ParameterCurve<3>",
oead.aamp.Parameter.Type.Curve4: "agl::utl::ParameterCurve<4>",
oead.aamp.Parameter.Type.BufferInt: "agl::utl::ParameterBuffer<s32>",
oead.aamp.Parameter.Type.BufferF32: "agl::utl::ParameterBuffer<f32>",
oead.aamp.Parameter.Type.String256: "agl::utl::Parameter<sead::SafeString>",
oead.aamp.Parameter.Type.Quat: "agl::utl::Parameter<sead::Quatf>",
oead.aamp.Parameter.Type.U32: "agl::utl::Parameter<u32>",
oead.aamp.Parameter.Type.BufferU32: "agl::utl::ParameterBuffer<u32>",
oead.aamp.Parameter.Type.BufferBinary: "agl::utl::ParameterBuffer<u8>",
oead.aamp.Parameter.Type.StringRef: "agl::utl::Parameter<sead::SafeString>",
}
def _aamp_type_to_agl_utl_parameter_type(type_: oead.aamp.Parameter.Type) -> str:
return _AampTypeToAglUtlParameterType[type_]
def _represent_float(value: float) -> str:
s = f'{value:g}'
if 'e' not in s and '.' not in s:
s += '.0'
return s
def _get_value_repr(value) -> str:
v = value.v
if isinstance(v, bool):
return "true" if v else "false"
if isinstance(v, oead.FixedSafeString32) or isinstance(v, oead.FixedSafeString64) or isinstance(v, oead.FixedSafeString256) or isinstance(v, str):
return json.dumps(str(v))
if isinstance(v, oead.Vector2f):
return f"{{{_represent_float(v.x)}, {_represent_float(v.y)}}}"
if isinstance(v, oead.Vector3f):
return f"{{{_represent_float(v.x)}, {_represent_float(v.y)}, {_represent_float(v.z)}}}"
if isinstance(v, oead.Vector4f):
return f"{{{_represent_float(v.x)}, {_represent_float(v.y)}, {_represent_float(v.z)}, {_represent_float(v.t)}}}"
if isinstance(v, float):
return _represent_float(v)
return repr(v)
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("bgparamlist_path", type=Path,
help="Path to Dummy.bgparamlist (text or binary)")
parser.add_argument("--object", required=True)
args = parser.parse_args()
name_table = oead.aamp.get_default_name_table()
pio = _parse_parameter_archive(args.bgparamlist_path)
pobj = pio.objects[args.object]
class_name = f"GParamListObject{args.object}"
# Includes
print("""\
#pragma once
#include <agl/Utils/aglParameter.h>
#include "KingSystem/Resource/GeneralParamList/resGParamListObject.h"
#include "KingSystem/Utils/Types.h"
namespace ksys::res {
""")
# Generate the class definition.
print(f"class {class_name} : public GParamListObject {{")
print(f"public:")
print(f" {class_name}();")
print(f' const char* getName() const override {{ return "{args.object}"; }}')
print()
for key, value in pobj.params.items():
name = name_table.get_name(key.hash, 0, 0)
assert name
type_str = _aamp_type_to_agl_utl_parameter_type(value.type())
print(f" {type_str} m{name};")
print("};")
print()
# Generate the constructor now.
print(f"inline {class_name}::{class_name}() {{")
print(" auto* const obj = &mObj;")
print()
for key, value in pobj.params.items():
name = name_table.get_name(key.hash, 0, 0)
assert name
default_value_repr = _get_value_repr(value)
print(f' m{name}.init({default_value_repr}, "{name}", "", obj);')
print("}")
print()
print("} // namespace ksys::res")
if __name__ == "__main__":
main()

View File

@ -0,0 +1,346 @@
#!/usr/bin/env python3
import argparse
from pathlib import Path
import typing as tp
import oead
class FlagTypeInfo(tp.NamedTuple):
def get_getter_fn_name(self) -> str:
return self.getter_fn_name
def get_handle_getter_fn_name(self) -> str:
s = self.getter_fn_name
if self.is_value_array():
s += "Array"
s += "Handle"
return s
def get_setter_fn_name(self) -> str:
return "s" + self.getter_fn_name[1:]
def is_value_inline(self) -> bool:
return self.arg_type in ("bool", "s32", "f32")
def is_value_array(self) -> bool:
return self.is_array
def get_setter_arg_type(self) -> str:
return self.setter_arg_type if self.setter_arg_type else self.arg_type
getter_fn_name: str
arg_type: str
setter_arg_type: str = ""
is_array: bool = False
flag_type_info = {
"bool_data": FlagTypeInfo("getBool", "bool"),
"s32_data": FlagTypeInfo("getS32", "s32"),
"f32_data": FlagTypeInfo("getF32", "f32"),
"string_data": FlagTypeInfo("getStr", "char const*", "const sead::SafeString&"),
"string64_data": FlagTypeInfo("getStr64", "char const*", "const sead::SafeString&"),
"string256_data": FlagTypeInfo("getStr256", "char const*", "const sead::SafeString&"),
"vector2f_data": FlagTypeInfo("getVec2f", "sead::Vector2f", "const sead::Vector2f&"),
"vector3f_data": FlagTypeInfo("getVec3f", "sead::Vector3f", "const sead::Vector3f&"),
"vector4f_data": FlagTypeInfo("getVec4f", "sead::Vector4f", "const sead::Vector4f&"),
"bool_array_data": FlagTypeInfo("getBool", "bool", is_array=True),
"s32_array_data": FlagTypeInfo("getS32", "s32", is_array=True),
"f32_array_data": FlagTypeInfo("getF32", "f32", is_array=True),
"string_array_data": FlagTypeInfo("getStr", "char const*", "const sead::SafeString&", is_array=True),
"string64_array_data": FlagTypeInfo("getStr64", "char const*", "const sead::SafeString&", is_array=True),
"string256_array_data": FlagTypeInfo("getStr256", "char const*", "const sead::SafeString&", is_array=True),
"vector2f_array_data": FlagTypeInfo("getVec2f", "sead::Vector2f", "const sead::Vector2f&", is_array=True),
"vector3f_array_data": FlagTypeInfo("getVec3f", "sead::Vector3f", "const sead::Vector3f&", is_array=True),
"vector4f_array_data": FlagTypeInfo("getVec4f", "sead::Vector4f", "const sead::Vector4f&", is_array=True),
}
def add_development_remnant_flags(flags: tp.Dict[str, str]):
_flags = {
"AoC_DragonFireChallengeRing_Advent": "bool_data",
"AoC_RandomSpawnTreasure_Contents": "string64_array_data",
"AoC_RandomSpawnTreasure_IsRandomized": "bool_data",
"AoC_TestProg_Imoto_Flag_00": "bool_data",
"AoC_TestProg_Imoto_TagCount_00": "s32_data",
"AocTestEx_Omosako_IsPastWorld": "bool_data",
"AocTestEx_Omosako_ReturnToMainField_Position": "vector3f_data",
"AocTestEx_Omosako_ReturnToMainField_Rotation": "f32_data",
"AocTestEx_Omosako_SandOfTime_Num": "s32_data",
"AocTestEx_Omosako_SandOfTime_Rate": "f32_data",
"Location_DarkDungeon01": "s32_data",
"Location_DarkDungeon02": "s32_data",
"Location_DarkDungeon03": "s32_data",
"Location_DarkDungeon04": "s32_data",
"SpurGear_revolve_01": "bool_data",
"SpurGear_revolve_02": "bool_data",
}
flags.update(_flags)
def load_flag_types(root: Path) -> tp.Dict[str, str]:
flag_types: tp.Dict[str, str] = dict()
add_development_remnant_flags(flag_types)
gdt_dir = root / "GameData"
for path in gdt_dir.glob("Flag/*.yml"):
flag_list = oead.byml.from_text(path.read_text(encoding="utf-8"))
keys = list(flag_list.keys())
assert len(keys) == 1
flag_type = keys[0]
for flag in flag_list[flag_type]:
flag_types[flag["DataName"]] = flag_type
return flag_types
def write_struct_chunk(f: tp.TextIO, flags: tp.Collection[str], i: int) -> None:
f.write(f"""\
struct CommonFlags{i} {{
""")
for name in flags:
f.write(f" FlagHandle flag_{name} = InvalidHandle;\n")
f.write(f"""\
u32 _pad = 0;
}};
[[gnu::visibility("hidden")]] extern CommonFlags{i} sCommonFlags{i};
""")
FLAGS_PER_CHUNK = 1023
def chunk_flag_iterator(flags: tp.Iterator[str]):
while True:
chunk = []
for i in range(FLAGS_PER_CHUNK):
try:
chunk.append(next(flags))
except StopIteration:
break
if not chunk:
return
yield chunk
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("root", help="Path to the root of the GameROM source")
parser.add_argument("exe_flag_list", help="Path to a file containing a list of flags")
args = parser.parse_args()
src_root = Path(__file__).parent.parent
src_gdt = src_root / "src" / "KingSystem" / "GameData"
root = Path(args.root)
exe_flag_list = Path(args.exe_flag_list).read_text().splitlines()
flag_types = load_flag_types(root)
with (src_gdt / "gdtCommonFlags.h").open("w") as f:
f.write("""\
#pragma once
// DO NOT EDIT. This file is automatically generated.
#include "KingSystem/GameData/gdtManager.h"
namespace ksys::gdt {
// clang-format off
namespace detail {
""")
for i, chunk in enumerate(chunk_flag_iterator(iter(exe_flag_list))):
write_struct_chunk(f, chunk, i)
f.write("\n")
f.write("""\
} // namespace detail
void initCommonFlags();
""")
for i, name in enumerate(exe_flag_list):
chunk_idx: int = i // FLAGS_PER_CHUNK
f.write(f"inline FlagHandle& flag_{name}() {{ return detail::sCommonFlags{chunk_idx}.flag_{name}; }}\n")
f.write("""\
// clang-format on
} // namespace ksys::gdt
""")
# Generate the implementation.
with (src_gdt / "gdtCommonFlags.cpp").open("w") as f:
f.write("""\
// DO NOT EDIT. This file is automatically generated.
#include "KingSystem/GameData/gdtCommonFlags.h"
namespace ksys::gdt {
namespace detail {
""")
for i in range(len(exe_flag_list) // FLAGS_PER_CHUNK + 1):
f.write(f"CommonFlags{i} sCommonFlags{i};\n")
f.write("""
} // namespace detail
void initCommonFlags_();
void initCommonFlags() {
initCommonFlags_();
}
void initCommonFlags_() {
auto* mgr = Manager::instance();
if (!mgr)
return;
// clang-format off
""")
for flag_name in exe_flag_list:
info = flag_type_info[flag_types[flag_name]]
f.write(f" flag_{flag_name}() = mgr->{info.get_handle_getter_fn_name()}(\"{flag_name}\");\n")
f.write("""\
// clang-format on
}
} // namespace ksys::gdt
""")
# Generate gdtCommonFlagsUtils.h
with (src_gdt / "gdtCommonFlagsUtils.h").open("w") as f:
f.write("""\
#pragma once
// DO NOT EDIT. This file is automatically generated.
#include "KingSystem/GameData/gdtCommonFlags.h"
#include "KingSystem/GameData/gdtFlagUtils.h"
namespace ksys::gdt {
// clang-format off
bool getFlagGenericBool(FlagHandle handle, bool debug = false);
s32 getFlagGenericS32(FlagHandle handle, bool debug = false);
""")
for i, name in enumerate(exe_flag_list):
info = flag_type_info[flag_types[name]]
if info.is_value_array():
# Getter
if info.is_value_inline():
f.write(
f"{info.arg_type} getFlag_{name}(s32 idx, bool debug = false);\n")
else:
f.write(
f"void getFlag_{name}({info.arg_type}* value, s32 idx, bool debug = false);\n")
# Increase function
if info.arg_type == "s32":
f.write(f"void increaseFlag_{name}(s32 value, s32 idx, bool debug = false);\n")
# Setter
f.write(f"void setFlag_{name}({info.get_setter_arg_type()} value, s32 idx, bool debug = false);\n")
# Resetter
f.write(f"void resetFlag_{name}(s32 idx, bool debug = false);\n")
else:
# Getter
if info.is_value_inline():
f.write(
f"{info.arg_type} getFlag_{name}(bool debug = false);\n")
else:
f.write(
f"void getFlag_{name}({info.arg_type}* value, bool debug = false);\n")
# Increase function
if info.arg_type == "s32":
f.write(f"void increaseFlag_{name}(s32 value, bool debug = false);\n")
# Setter
f.write(f"void setFlag_{name}({info.get_setter_arg_type()} value, bool debug = false);\n")
# Resetter
f.write(f"void resetFlag_{name}(bool debug = false);\n")
f.write("""\
// clang-format on
} // namespace ksys::gdt
""")
# Generate gdtCommonFlagsUtils.cpp
with (src_gdt / "gdtCommonFlagsUtils.cpp").open("w") as f:
f.write("""\
// DO NOT EDIT. This file is automatically generated.
#include "KingSystem/GameData/gdtCommonFlagsUtils.h"
namespace ksys::gdt {
// clang-format off
bool getFlagGenericBool(FlagHandle handle, bool debug) { return getBool(handle, debug); }
s32 getFlagGenericS32(FlagHandle handle, bool debug) { return getS32(handle, debug); }
""")
for i, name in enumerate(exe_flag_list):
info = flag_type_info[flag_types[name]]
if info.is_value_array():
# Getter
if info.is_value_inline():
f.write(
f"{info.arg_type} getFlag_{name}(s32 idx, bool debug) {{ return {info.get_getter_fn_name()}(flag_{name}(), idx, debug); }}\n")
else:
f.write(
f"void getFlag_{name}({info.arg_type}* value, s32 idx, bool debug) {{ {info.get_getter_fn_name()}(flag_{name}(), value, idx, debug); }}\n")
# Increase function
if info.arg_type == "s32":
f.write(f"void increaseFlag_{name}(s32 value, s32 idx, bool debug) {{ "
f"increaseS32CommonFlag(value, \"{name}\", idx, debug); }}\n")
# Setter
f.write(
f"void setFlag_{name}({info.get_setter_arg_type()} value, s32 idx, bool debug) {{ "
f"{info.get_setter_fn_name()}(value, flag_{name}(), idx, debug); }}\n")
# Resetter
f.write(
f"void resetFlag_{name}(s32 idx, bool debug) {{ "
f"re{info.get_setter_fn_name()}(flag_{name}(), idx, debug); }}\n")
else:
# Getter
if info.is_value_inline():
f.write(
f"{info.arg_type} getFlag_{name}(bool debug) {{ return {info.get_getter_fn_name()}(flag_{name}(), debug); }}\n")
else:
f.write(
f"void getFlag_{name}({info.arg_type}* value, bool debug) {{ {info.get_getter_fn_name()}(flag_{name}(), value, debug); }}\n")
# Increase function
if info.arg_type == "s32":
f.write(f"void increaseFlag_{name}(s32 value, bool debug) {{ "
f"increaseS32CommonFlag(value, \"{name}\", -1, debug); }}\n")
# Setter
f.write(
f"void setFlag_{name}({info.get_setter_arg_type()} value, bool debug) {{ "
f"{info.get_setter_fn_name()}(value, flag_{name}(), debug); }}\n")
# Resetter
f.write(
f"void resetFlag_{name}(bool debug) {{ re{info.get_setter_fn_name()}(flag_{name}(), debug); }}\n")
f.write("""\
// clang-format on
} // namespace ksys::gdt
""")
if __name__ == "__main__":
main()

View File

@ -0,0 +1,94 @@
import struct
from typing import Dict
from util import utils, ai_common
import idaapi
from util.ai_common import BaseClasses
_vtable_fn_names = [
"_ZNK5uking6action{}27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE",
"_ZNK5uking6action{}18getRuntimeTypeInfoEv",
"_ZN5uking6action{}D2Ev",
"_ZN5uking6action{}D0Ev",
"_ZNK5uking6action{}8isFailedEv",
"_ZNK5uking6action{}10isFinishedEv",
"_ZNK5uking6action{}10isFlag4SetEv",
"_ZN5uking6action{}14hasPreDeleteCbEv",
"_ZN5uking6action{}23hasUpdateForPreDeleteCbEv",
"_ZN5uking6action{}2m9Ev",
"_ZN5uking6action{}8oneShot_Ev",
"_ZN5uking6action{}5init_EPN4sead4HeapE",
"_ZN5uking6action{}6enter_EPN4ksys3act2ai15InlineParamPackE",
"_ZN5uking6action{}8reenter_EPS2_b",
"_ZN5uking6action{}6leave_Ev",
"_ZN5uking6action{}11loadParams_Ev",
"_ZN5uking6action{}14handleMessage_EPN4ksys3mes7MessageE",
"_ZN5uking6action{}15handleMessage2_EPN4ksys3mes7MessageE",
"_ZN5uking6action{}18updateForPreDeleteEv",
"_ZN5uking6action{}11onPreDeleteEv",
"_ZN5uking6action{}4calcEv",
"_ZNK5uking6action{}14getCurrentNameEPN4sead22BufferedSafeStringBaseIcEEPS2_",
"_ZN5uking6action{}11changeChildERKN4sead14SafeStringBaseIcEE",
"_ZNK5uking6action{}9getParamsEPN4ksys3act2ai18ParamNameTypePairsEb",
"_ZNK5uking6action{}14getNumChildrenEv",
"_ZN5uking6action{}12initChildrenERKN4ksys8AIDefSetEPN4sead4HeapE",
"_ZNK5uking6action{}15getCurrentChildEv",
"_ZNK5uking6action{}7getTypeEv",
"_ZN5uking6action{}7reenterEPS2_RKN4sead14SafeStringBaseIcEE",
"_ZN5uking6action{}9postLeaveEv",
"_ZNK5uking6action{}8getChildEi",
"_ZN5uking6action{}5calc_Ev",
]
def format_fn_name(name: str, class_name: str):
return name.format(f"{len(class_name)}{class_name}")
def iterate_vtable(vtable_addr):
ea = vtable_addr
while True:
fn_ea = struct.unpack('<Q', idaapi.get_bytes(ea, 8))[0]
if idaapi.get_name(fn_ea) != "__cxa_pure_virtual" and not idaapi.is_func(idaapi.get_flags(fn_ea)):
return
yield fn_ea
ea += 8
_ida_base = 0x7100000000
def main() -> None:
all_vtables = ai_common.get_vtables()
names = ai_common.get_action_vtable_names()
not_decompiled = {func.addr for func in utils.get_functions() if func.status == utils.FunctionStatus.NotDecompiled}
new_names: Dict[int, str] = dict()
order = ai_common.topologically_sort_vtables(all_vtables, "Action")
for vtable_addr in order:
if vtable_addr in BaseClasses:
continue
class_name = names.get(vtable_addr)
for i, fn_ea in enumerate(iterate_vtable(vtable_addr)):
if idaapi.get_name(fn_ea) == "__cxa_pure_virtual":
continue
real_fn_ea = fn_ea & ~_ida_base
if real_fn_ea not in new_names:
if i < len(_vtable_fn_names):
new_names[real_fn_ea] = format_fn_name(_vtable_fn_names[i], class_name)
else:
# Unknown member function.
new_names[real_fn_ea] = f"uking::action::{class_name}::m{i}"
if real_fn_ea in not_decompiled:
idaapi.set_name(fn_ea, new_names[real_fn_ea])
utils.add_decompiled_functions(dict(), new_names)
if __name__ == '__main__':
main()

96
tools/ida_ai_rename_ai_vfns.py Executable file
View File

@ -0,0 +1,96 @@
import struct
from typing import Dict
from util import utils, ai_common
import idaapi
from util.ai_common import BaseClasses
_vtable_fn_names = [
"_ZNK5uking2ai{}27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE",
"_ZNK5uking2ai{}18getRuntimeTypeInfoEv",
"_ZN5uking2ai{}D2Ev",
"_ZN5uking2ai{}D0Ev",
"_ZNK5uking2ai{}8isFailedEv",
"_ZNK5uking2ai{}10isFinishedEv",
"_ZNK5uking2ai{}10isFlag4SetEv",
"_ZN5uking2ai{}14hasPreDeleteCbEv",
"_ZN5uking2ai{}23hasUpdateForPreDeleteCbEv",
"_ZN5uking2ai{}2m9Ev",
"_ZN5uking2ai{}8oneShot_Ev",
"_ZN5uking2ai{}5init_EPN4sead4HeapE",
"_ZN5uking2ai{}6enter_EPN4ksys3act2ai15InlineParamPackE",
"_ZN5uking2ai{}8reenter_EPS2_b",
"_ZN5uking2ai{}6leave_Ev",
"_ZN5uking2ai{}11loadParams_Ev",
"_ZN5uking2ai{}14handleMessage_EPN4ksys3mes7MessageE",
"_ZN5uking2ai{}15handleMessage2_EPN4ksys3mes7MessageE",
"_ZN5uking2ai{}18updateForPreDeleteEv",
"_ZN5uking2ai{}11onPreDeleteEv",
"_ZN5uking2ai{}4calcEv",
"_ZNK5uking2ai{}14getCurrentNameEPN4sead22BufferedSafeStringBaseIcEEPS2_",
"_ZN5uking2ai{}11changeChildERKN4sead14SafeStringBaseIcEE",
"_ZNK5uking2ai{}9getParamsEPN4ksys3act2ai18ParamNameTypePairsEb",
"_ZNK5uking2ai{}14getNumChildrenEv",
"_ZN5uking2ai{}12initChildrenERKN4ksys8AIDefSetEPN4sead4HeapE",
"_ZNK5uking2ai{}15getCurrentChildEv",
"_ZNK5uking2ai{}7getTypeEv",
"_ZN5uking2ai{}7reenterEPS2_RKN4sead14SafeStringBaseIcEE",
"_ZN5uking2ai{}9postLeaveEv",
"_ZNK5uking2ai{}8getChildEi",
"_ZNK5uking2ai{}8getNamesEPN4sead22BufferedSafeStringBaseIcEE",
"_ZN5uking2ai{}5calc_Ev",
"_ZN5uking2ai{}25handlePendingChildChange_Ev",
]
def format_fn_name(name: str, class_name: str):
return name.format(f"{len(class_name)}{class_name}")
def iterate_vtable(vtable_addr):
ea = vtable_addr
while True:
fn_ea = struct.unpack('<Q', idaapi.get_bytes(ea, 8))[0]
if idaapi.get_name(fn_ea) != "__cxa_pure_virtual" and not idaapi.is_func(idaapi.get_flags(fn_ea)):
return
yield fn_ea
ea += 8
_ida_base = 0x7100000000
def main() -> None:
all_vtables = ai_common.get_vtables()
names = ai_common.get_ai_vtable_names()
not_decompiled = {func.addr for func in utils.get_functions() if func.status == utils.FunctionStatus.NotDecompiled}
new_names: Dict[int, str] = dict()
order = ai_common.topologically_sort_vtables(all_vtables, "AI")
for vtable_addr in order:
if vtable_addr in BaseClasses:
continue
class_name = names.get(vtable_addr)
for i, fn_ea in enumerate(iterate_vtable(vtable_addr)):
if idaapi.get_name(fn_ea) == "__cxa_pure_virtual":
continue
real_fn_ea = fn_ea & ~_ida_base
if real_fn_ea not in new_names:
if i < len(_vtable_fn_names):
new_names[real_fn_ea] = format_fn_name(_vtable_fn_names[i], class_name)
else:
# Unknown member function.
new_names[real_fn_ea] = f"uking::ai::{class_name}::m{i}"
if real_fn_ea in not_decompiled:
idaapi.set_name(fn_ea, new_names[real_fn_ea])
utils.add_decompiled_functions(dict(), new_names)
if __name__ == '__main__':
main()

View File

@ -0,0 +1,31 @@
# This script needs to be compatible with Python 2.7 as it is executed in IDA.
import idaapi
import idautils
import idc
import os
# only valid in 1.5.0
LOAD_SAVEDATA_FUNCTION_START = 0x71008BF8A0
LOAD_SAVEDATA_FUNCTION_END = 0x71008E3DB8
CRC32_FUNCTION_EA = 0x7100B2170C
SAVEDATA_STRUCT = 0x710246F9E0
with open(os.path.dirname(os.path.realpath(__file__)) + "/../build/gdt_common_flags.txt", "w") as file:
struct_offset = 0
for ref in idautils.CodeRefsTo(idc.GetFunctionAttr(CRC32_FUNCTION_EA, idc.FUNCATTR_START), 1):
if not (LOAD_SAVEDATA_FUNCTION_START < ref < LOAD_SAVEDATA_FUNCTION_END):
continue
string_xref = idaapi.get_arg_addrs(ref)[0]
iterator = idautils.XrefsFrom(string_xref, 0)
next(iterator)
string_addr = next(iterator).to
string = idc.GetString(string_addr)
# For some reason the struct includes dummy members that should be skipped.
if idaapi.get_dword(SAVEDATA_STRUCT + struct_offset) == 0:
struct_offset += 4
file.write("%s\n" % string)
struct_offset += 4

View File

@ -0,0 +1,12 @@
import idaapi
for i in range(idaapi.get_fchunk_qty()):
chunk = idaapi.getn_fchunk(i)
if not idaapi.is_func_tail(chunk):
continue
ea = chunk.start_ea
print("removing tail 0x%016x" % ea)
parent = idaapi.get_func(ea)
idaapi.remove_func_tail(parent, ea)
idaapi.add_func(ea)

View File

@ -0,0 +1,80 @@
#!/usr/bin/env python3
import argparse
from colorama import Fore
import csv
import sys
from pathlib import Path
from typing import Dict
import util.checker
import util.elf
from util import utils
def read_candidates(path: Path) -> Dict[str, util.elf.Function]:
candidates: Dict[str, util.elf.Function] = dict()
for candidate in path.read_text().splitlines():
columns = candidate.split()
if len(columns) == 3:
candidate = columns[2]
candidates[candidate] = util.elf.get_fn_from_my_elf(candidate)
return candidates
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("csv_path",
help="Path to a list of functions to identify (in the same format as the main function CSV)")
parser.add_argument("candidates_path",
help="Path to a list of candidates (names only)")
args = parser.parse_args()
csv_path = Path(args.csv_path)
candidates_path = Path(args.candidates_path)
candidates = read_candidates(candidates_path)
new_matches: Dict[int, str] = dict()
checker = util.checker.FunctionChecker()
# Given a list L of functions to identify and a small list of candidates C, this tool will attempt to
# automatically identify matches by checking each function in L against each function in C.
#
# This matching algorithm is quite naive (quadratic time complexity if both lists have about the same size)
# but this should work well enough for short lists of candidates...
for func in utils.get_functions(csv_path):
if func.status != utils.FunctionStatus.NotDecompiled:
continue
match_name = ""
for candidate_name, candidate in candidates.items():
if len(candidate.data) != func.size:
continue
if checker.check(util.elf.get_fn_from_base_elf(func.addr, func.size), candidate):
match_name = candidate_name
break
if match_name:
new_matches[func.addr] = match_name
utils.print_note(
f"found new match: {Fore.BLUE}{match_name}{Fore.RESET} ({func.addr | 0x71_00000000:#018x})")
# This is no longer a candidate.
del candidates[match_name]
else:
utils.warn(f"no match found for {Fore.BLUE}{func.name}{Fore.RESET} ({func.addr | 0x71_00000000:#018x})")
# Output the modified function CSV.
writer = csv.writer(sys.stdout, lineterminator="\n")
for func in utils.get_functions():
if func.status == utils.FunctionStatus.NotDecompiled and func.addr in new_matches:
func.raw_row[3] = new_matches[func.addr]
writer.writerow(func.raw_row)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,92 @@
#!/usr/bin/env python3
from typing import Dict, List
import argparse
import cxxfilt
from colorama import Fore
from util import utils, checker, elf
class Checker(checker.FunctionChecker):
def __init__(self):
super().__init__()
self.checking = ""
self.invalid_call_descriptions: List[str] = []
self.addr_to_symbol = elf.build_addr_to_symbol_table(elf.my_symtab)
self._possible_calls: Dict[int, int] = dict()
def reset(self) -> None:
self._possible_calls.clear()
def get_possible_calls(self) -> Dict[int, int]:
return self._possible_calls
def on_unknown_fn_call(self, orig_addr: int, decomp_addr: int):
existing_addr = self._possible_calls.get(orig_addr)
if existing_addr is not None and existing_addr != decomp_addr:
self.invalid_call_descriptions.append(
f"{orig_addr | 0x7100000000:#x} was mapped to {self.addr_to_symbol[existing_addr]} "
f"({existing_addr:#x}) "
f"but now maps to {self.addr_to_symbol[decomp_addr]} ({decomp_addr:#x})"
f" (while checking {self.checking})")
return
self._possible_calls[orig_addr] = decomp_addr
def main() -> None:
parser = argparse.ArgumentParser("Identifies matching functions by looking at function calls in matching functions")
parser.add_argument("-f", "--fn", help="Functions to analyze", nargs="*")
args = parser.parse_args()
functions_to_analyze = set(args.fn) if args.fn else set()
functions_by_addr: Dict[int, utils.FunctionInfo] = {fn.addr: fn for fn in utils.get_functions()}
fn_checker = Checker()
for fn in functions_by_addr.values():
if functions_to_analyze and fn.decomp_name not in functions_to_analyze:
continue
if fn.status != utils.FunctionStatus.Matching:
continue
base_fn = elf.get_fn_from_base_elf(fn.addr, fn.size)
try:
my_fn = elf.get_fn_from_my_elf(fn.decomp_name)
except KeyError:
utils.warn(f"could not find function {fn.decomp_name}")
continue
fn_checker.checking = fn.decomp_name
fn_checker.check(base_fn, my_fn)
if fn_checker.invalid_call_descriptions:
for x in fn_checker.invalid_call_descriptions:
utils.print_note(x)
utils.fail("invalid calls detected")
new_matches: Dict[int, str] = dict()
calls = fn_checker.get_possible_calls().copy()
for base_target, my_target in calls.items():
target_info = functions_by_addr.get(base_target)
if target_info is None:
continue
if target_info.status != utils.FunctionStatus.NotDecompiled:
continue
base_fn = elf.get_fn_from_base_elf(target_info.addr, target_info.size)
try:
name = fn_checker.addr_to_symbol[my_target]
my_fn = elf.get_fn_from_my_elf(name)
except KeyError:
continue
if fn_checker.check(base_fn, my_fn):
new_matches[base_target] = name
utils.print_note(f"new match: {Fore.BLUE}{cxxfilt.demangle(name)}{Fore.RESET}")
utils.add_decompiled_functions(new_matches)
if __name__ == '__main__':
main()

View File

@ -0,0 +1,84 @@
#!/usr/bin/env python3
import struct
from typing import Dict, Set
import capstone as cs
import cxxfilt
from colorama import Fore
from util import utils, elf
def main() -> None:
new_matches: Dict[int, str] = dict()
functions_by_addr: Dict[int, utils.FunctionInfo] = {fn.addr: fn for fn in utils.get_functions()}
md = cs.Cs(cs.CS_ARCH_ARM64, cs.CS_MODE_ARM)
md.detail = True
decomp_addr_to_symbol = elf.build_addr_to_symbol_table(elf.my_symtab)
decomp_glob_data_table = elf.build_glob_data_table(elf.my_elf)
processed: Set[int] = set()
for fn in functions_by_addr.values():
if fn.status != utils.FunctionStatus.Matching:
continue
if fn.size != 0x5C or (not fn.decomp_name.endswith("8getRuntimeTypeInfoEv") and not fn.name.endswith("rtti2")):
continue
base_fn = elf.get_fn_from_base_elf(fn.addr, fn.size)
try:
my_fn = elf.get_fn_from_my_elf(fn.decomp_name)
except KeyError:
utils.warn(f"could not find function {fn.decomp_name}")
continue
assert len(base_fn.data) == len(my_fn.data)
vtable_ptr1 = 0
vtable_ptr2 = 0
for j, (i1, i2) in enumerate(zip(md.disasm(base_fn.data, base_fn.addr), md.disasm(my_fn.data, my_fn.addr))):
assert i1.mnemonic == i2.mnemonic
if j == 10:
assert i1.mnemonic == "adrp"
assert i1.operands[0].reg == i2.operands[0].reg
vtable_ptr1 = i1.operands[1].imm
vtable_ptr2 = i2.operands[1].imm
elif j == 11:
assert i1.mnemonic == "ldr"
assert i1.operands[0].reg == i2.operands[0].reg
assert i1.operands[1].value.mem.base == i2.operands[1].value.mem.base
vtable_ptr1 += i1.operands[1].value.mem.disp
vtable_ptr2 += i2.operands[1].value.mem.disp
break
assert vtable_ptr1 != 0 and vtable_ptr2 != 0
if vtable_ptr1 in processed:
continue
processed.add(vtable_ptr1)
ptr1, = struct.unpack("<Q", elf.read_from_elf(elf.base_elf, vtable_ptr1, 8))
ptr2 = decomp_glob_data_table[vtable_ptr2]
vtable1 = elf.get_vtable_fns_from_base_elf(ptr1 + 0x10, num_entries=1)
vtable2 = elf.unpack_vtable_fns(elf.read_from_elf(elf.my_elf, addr=ptr2 + 0x10, size=8), num_entries=1)
if functions_by_addr[vtable1[0]].status == utils.FunctionStatus.Matching:
continue
decomp_derive_fn_addr = vtable2[0]
if decomp_derive_fn_addr == 0:
decomp_derive_fn_addr = decomp_glob_data_table.get(ptr2 + 0x10, 0)
if decomp_derive_fn_addr == 0:
raise RuntimeError(f"Derive virtual function pointer is null "
f"(fn: {fn.decomp_name}, decomp vtable at {ptr2:#x})")
name = decomp_addr_to_symbol[decomp_derive_fn_addr]
new_matches[vtable1[0]] = name
utils.print_note(f"new match: {Fore.BLUE}{cxxfilt.demangle(name)}{Fore.RESET} (from {fn.decomp_name})")
# overwrite the original names because they are likely to be incorrect
utils.add_decompiled_functions(new_matches, new_orig_names=new_matches)
if __name__ == '__main__':
main()

58
tools/print_decomp_symbols.py Executable file
View File

@ -0,0 +1,58 @@
#!/usr/bin/env python3
import argparse
from colorama import Fore, Style
import diff_settings
import subprocess
from util import utils
parser = argparse.ArgumentParser(description="Prints build/odyssey.elf symbols")
parser.add_argument("--print-undefined", "-u",
help="Print symbols that are undefined", action="store_true")
parser.add_argument("--print-c2-d2", "-c",
help="Print C2/D2 (base object constructor/destructor) symbols", action="store_true")
parser.add_argument("--hide-unknown", "-H",
help="Hide symbols that are not present in the original game", action="store_true")
parser.add_argument("--all", "-a", action="store_true")
args = parser.parse_args()
listed_decomp_symbols = {info.decomp_name for info in utils.get_functions()}
original_symbols = {info.name for info in utils.get_functions()}
config: dict = dict()
diff_settings.apply(config, {})
myimg: str = config["myimg"]
entries = [x.strip().split() for x in subprocess.check_output(["nm", "-n", myimg], universal_newlines=True).split("\n")]
for entry in entries:
if len(entry) == 3:
addr = int(entry[0], 16)
symbol_type: str = entry[1]
name = entry[2]
if (symbol_type == "t" or symbol_type == "T" or symbol_type == "W") and (
args.all or name not in listed_decomp_symbols):
c1_name = name.replace("C2", "C1")
is_c2_ctor = "C2" in name and c1_name in listed_decomp_symbols and utils.are_demangled_names_equal(
c1_name, name)
d1_name = name.replace("D2", "D1")
is_d2_dtor = "D2" in name and d1_name in listed_decomp_symbols and utils.are_demangled_names_equal(
d1_name, name)
if args.print_c2_d2 or not (is_c2_ctor or is_d2_dtor):
color = Fore.YELLOW
if name in original_symbols:
color = Fore.RED
elif args.hide_unknown:
continue
if is_c2_ctor or is_d2_dtor:
color += Style.DIM
print(f"{color}UNLISTED {Fore.RESET} {utils.format_symbol_name(name)}")
elif len(entry) == 2:
symbol_type = entry[0]
name = entry[1]
if symbol_type.upper() == "U" and args.print_undefined:
print(f"{Fore.CYAN}UNDEFINED{Style.RESET_ALL} {utils.format_symbol_name(name)}")

Some files were not shown because too many files have changed in this diff Show More