Compare commits
125 Commits
45829ecc7e
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 5638734828 | |||
| b5805d39d4 | |||
| 7e68709aec | |||
| 0d35e5af6d | |||
| b6be9b7c09 | |||
| e6c8d527bc | |||
| a8143e6ac0 | |||
| 3537c91324 | |||
| 360df2dfda | |||
| 8b73364db9 | |||
| 72c6656e01 | |||
| c854b78e02 | |||
| 6104238552 | |||
| 892aa30091 | |||
| b19de8b1b7 | |||
| b1dc3a13c2 | |||
| fb30afded9 | |||
| 38b62c4d50 | |||
| 919430c923 | |||
| 599c2f746b | |||
| 7d095623ba | |||
| 080b9f7b8c | |||
| ab0c1473ec | |||
| a559f68de2 | |||
| 010e3825da | |||
| 8c53aa61be | |||
| 0d488e24e3 | |||
| 4dc6fb2176 | |||
| 836c856258 | |||
| 027829659c | |||
| 1bbe4bf3c7 | |||
| 1835eecb49 | |||
| 7186b95de4 | |||
| 3c6c7a6f65 | |||
| ac9879a4aa | |||
| 2423d68e0a | |||
| 66565671b5 | |||
| bd98761921 | |||
| cfb41094d5 | |||
| 743d5aa015 | |||
| 947165067c | |||
| cde5c7c313 | |||
| f6d2ec6efb | |||
| ac92d40671 | |||
| f2606cd72f | |||
| 15ec7bd1f1 | |||
| 3ad0cb5bd1 | |||
| 7a7c907abb | |||
| 6bce41bd2d | |||
| 35b2c67e73 | |||
| 4092af3513 | |||
| e3c19e890f | |||
| 8328a6e8e8 | |||
| 1d305a44c6 | |||
| 36b700f66e | |||
| a723dbd2f9 | |||
| 76915ede69 | |||
| 2c305c7a03 | |||
| af2c8c1384 | |||
| 0187b3943c | |||
| 209d82c172 | |||
| 325219104a | |||
| 891277f15d | |||
| 532c1653c0 | |||
| 1e91d93470 | |||
| f1b346fb0e | |||
| faf2e134f2 | |||
| 7613e37444 | |||
| 0edba96773 | |||
| 556f8339c0 | |||
| 2c104648cd | |||
| acb9d47e0e | |||
| ea677e6de7 | |||
| 4a669d86b7 | |||
| 35a220de3f | |||
| b0b4683f7d | |||
| e7417745fd | |||
| 31ee70e8c0 | |||
| 55438d7380 | |||
| edf6cc5a67 | |||
| ebfc4bf4f4 | |||
| 5ce1a399b1 | |||
| e19a123b94 | |||
| 16e5456079 | |||
| 2791a66b1f | |||
| 45344e2e52 | |||
| 647e3668a0 | |||
| d7de3deb59 | |||
| 7c18d04724 | |||
| 3d40dc7e80 | |||
| 0383ef8f13 | |||
| 58397127e7 | |||
| 560fbe70ce | |||
| db228e64ec | |||
| 836e281b80 | |||
| 8ac8951d8d | |||
| a958b0268e | |||
| ec5d40be0c | |||
| 99aaebba82 | |||
| c9c9e9c6e6 | |||
| c7309d1b29 | |||
| 4070a99bf8 | |||
| 04b92cbd08 | |||
| f2ca59b3b1 | |||
| 84ebde858e | |||
| c2397e8e24 | |||
| c20f540b47 | |||
| fd4546c1f0 | |||
| e4325de092 | |||
| dfe339bcd3 | |||
| cc7964f03e | |||
| fd90916a1f | |||
| 54476f89f0 | |||
| 5223f1c7c1 | |||
| 468866b833 | |||
| 86fb5c8973 | |||
| 1b2694d2e4 | |||
| 376c86051a | |||
| cf51259899 | |||
| 9e52c0147d | |||
| 55aa93eee2 | |||
| 5b8a014013 | |||
| aa93dba62f | |||
| 6e748b6c94 | |||
| 494038ebde |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -19,5 +19,11 @@ headers
|
|||||||
|
|
||||||
ACP_Ray2/
|
ACP_Ray2/
|
||||||
build/
|
build/
|
||||||
|
build_msvc/
|
||||||
# game_re/
|
# game_re/
|
||||||
windows_libs/
|
windows_libs/
|
||||||
|
tooling/build/
|
||||||
|
|
||||||
|
*.code-workspace
|
||||||
|
*.log
|
||||||
|
.edits_backup/
|
||||||
12
.gitmodules
vendored
12
.gitmodules
vendored
@@ -1,3 +1,15 @@
|
|||||||
[submodule "game_re/third_party/spdlog"]
|
[submodule "game_re/third_party/spdlog"]
|
||||||
path = game_re/third_party/spdlog
|
path = game_re/third_party/spdlog
|
||||||
url = https://github.com/gabime/spdlog.git
|
url = https://github.com/gabime/spdlog.git
|
||||||
|
[submodule "tooling2/third_party/tree-sitter"]
|
||||||
|
path = tooling/third_party/tree-sitter
|
||||||
|
url = https://github.com/guusw/tree-sitter.git
|
||||||
|
[submodule "tooling2/third_party/tree-sitter-cpp"]
|
||||||
|
path = tooling/third_party/tree-sitter-cpp
|
||||||
|
url = https://github.com/guusw/tree-sitter-cpp.git
|
||||||
|
[submodule "third_party/hooker"]
|
||||||
|
path = third_party/hooker
|
||||||
|
url = https://github.com/guusw/hooker.git
|
||||||
|
[submodule "third_party/magic_enum"]
|
||||||
|
path = third_party/magic_enum
|
||||||
|
url = https://github.com/Neargye/magic_enum.git
|
||||||
|
|||||||
@@ -1,9 +1,23 @@
|
|||||||
cmake_minimum_required(VERSION 3.26.4)
|
cmake_minimum_required(VERSION 3.26.4)
|
||||||
project(reman3)
|
project(reman3)
|
||||||
|
|
||||||
|
# Build for 32-bit compatibility, until code is binary compatible with 64-bit
|
||||||
|
option(R3_32BIT "Build for 32-bit compatibility" ON)
|
||||||
|
|
||||||
|
if(R3_32BIT)
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||||
|
add_link_options(/machine:x86)
|
||||||
|
else()
|
||||||
|
add_compile_options(-m32)
|
||||||
|
add_link_options(-m32)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
set(GAME_DATA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/game)
|
set(GAME_DATA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/game)
|
||||||
|
|
||||||
|
add_subdirectory(third_party)
|
||||||
add_subdirectory(game_re)
|
add_subdirectory(game_re)
|
||||||
|
add_subdirectory(patcher)
|
||||||
|
|
||||||
# Use highest possible C standard
|
# Use highest possible C standard
|
||||||
set_target_properties(game_re PROPERTIES C_STANDARD 23)
|
set_target_properties(game_re PROPERTIES C_STANDARD 23)
|
||||||
|
|||||||
741
GhidraPlugin/.classpath
Normal file
741
GhidraPlugin/.classpath
Normal file
@@ -0,0 +1,741 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" output="bin/scripts" path="ghidra_scripts"/>
|
||||||
|
<classpathentry kind="src" output="bin/main" path="src/main/help"/>
|
||||||
|
<classpathentry kind="src" output="bin/main" path="src/main/resources"/>
|
||||||
|
<classpathentry kind="src" output="bin/test" path="src/test/java"/>
|
||||||
|
<classpathentry kind="src" output="bin/main" path="src/main/java"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk-21.0.7.6-hotspot"/>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/68000/lib/68000.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/68000/lib/68000-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/8051/lib/8051.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/AARCH64/lib/AARCH64.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/AARCH64/lib/AARCH64-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/ARM/lib/ARM.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/ARM/lib/ARM-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/AnnotationValidator/lib/AnnotationValidator.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/AnnotationValidator/lib/AnnotationValidator-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/Atmel/lib/Atmel.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/Atmel/lib/Atmel-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/BSim/lib/BSim.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/BSim/lib/BSim-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/BSim/lib/commons-dbcp2-2.9.0.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/BSim/lib/commons-logging-1.2.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/BSim/lib/commons-pool2-2.11.1.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/BSim/lib/h2-2.2.220.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/BSim/lib/postgresql-42.7.3.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/BSimFeatureVisualizer/lib/BSimFeatureVisualizer.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/BSimFeatureVisualizer/lib/BSimFeatureVisualizer-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/Base/lib/Base.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/Base/lib/Base-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/Base/lib/biz.aQute.bnd.util-7.0.0.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/Base/lib/biz.aQute.bndlib-7.0.0.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/Base/lib/org.apache.felix.framework-7.0.5.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/Base/lib/org.osgi.util.promise-1.3.0.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/Base/lib/phidias-0.3.7.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/Base/lib/slf4j-api-1.7.25.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/Base/lib/slf4j-nop-1.7.25.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/BytePatterns/lib/BytePatterns.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/BytePatterns/lib/BytePatterns-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/ByteViewer/lib/ByteViewer.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/ByteViewer/lib/ByteViewer-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/CodeCompare/lib/CodeCompare.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/CodeCompare/lib/CodeCompare-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/DATA/lib/DATA.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/DATA/lib/DATA-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/DB/lib/DB.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/DB/lib/DB-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/Dalvik/lib/Dalvik.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/Dalvik/lib/Dalvik-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/DebugUtils/lib/DebugUtils.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/DebugUtils/lib/DebugUtils-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/Debugger/lib/Debugger.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/Debugger/lib/Debugger-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/Debugger-api/lib/Debugger-api.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/Debugger-api/lib/Debugger-api-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/Debugger-isf/lib/Debugger-isf.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/Debugger-isf/lib/Debugger-isf-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/Debugger-jpda/lib/Debugger-jpda.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/Debugger-jpda/lib/Debugger-jpda-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/Debugger-rmi-trace/lib/Debugger-rmi-trace.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/Debugger-rmi-trace/lib/Debugger-rmi-trace-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/Decompiler/lib/Decompiler.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/Decompiler/lib/Decompiler-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/DecompilerDependent/lib/DecompilerDependent.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/DecompilerDependent/lib/DecompilerDependent-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Docking/lib/Docking.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Docking/lib/Docking-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Emulation/lib/asm-9.7.1.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Emulation/lib/asm-analysis-9.7.1.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Emulation/lib/asm-commons-9.7.1.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Emulation/lib/asm-tree-9.7.1.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Emulation/lib/asm-util-9.7.1.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Emulation/lib/Emulation.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Emulation/lib/Emulation-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/FileFormats/lib/AXMLPrinter2.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/FileFormats/lib/baksmali-2.5.2.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/FileFormats/lib/dex-ir-2.4.24.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/FileFormats/lib/dex-reader-2.4.24.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/FileFormats/lib/dex-reader-api-2.4.24.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/FileFormats/lib/dex-translator-2.4.24.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/FileFormats/lib/dexlib2-2.5.2.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/FileFormats/lib/FileFormats.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/FileFormats/lib/FileFormats-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/FileFormats/lib/sevenzipjbinding-16.02-2.01.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/FileFormats/lib/sevenzipjbinding-all-platforms-16.02-2.01.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/FileFormats/lib/util-2.5.2.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/FileSystem/lib/FileSystem.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/FileSystem/lib/FileSystem-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/Framework-AsyncComm/lib/Framework-AsyncComm.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/Framework-AsyncComm/lib/Framework-AsyncComm-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/Framework-AsyncComm/lib/protobuf-java-3.21.8.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/Framework-TraceModeling/lib/Framework-TraceModeling.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/Framework-TraceModeling/lib/Framework-TraceModeling-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/FunctionGraph/lib/FunctionGraph.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/FunctionGraph/lib/FunctionGraph-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/FunctionGraphDecompilerExtension/lib/FunctionGraphDecompilerExtension.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/FunctionGraphDecompilerExtension/lib/FunctionGraphDecompilerExtension-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/FunctionID/lib/FunctionID.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/FunctionID/lib/FunctionID-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Generic/lib/bcpkix-jdk15on-1.69.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Generic/lib/bcprov-jdk15on-1.69.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Generic/lib/bcutil-jdk15on-1.69.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Generic/lib/commons-collections4-4.1.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Generic/lib/commons-compress-1.21.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Generic/lib/commons-io-2.11.0.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Generic/lib/commons-lang3-3.12.0.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Generic/lib/commons-text-1.10.0.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Generic/lib/failureaccess-1.0.1.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Generic/lib/Generic.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Generic/lib/Generic-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Generic/lib/gson-2.9.0.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Generic/lib/guava-32.1.3-jre.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Generic/lib/jdom-legacy-1.1.3.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Generic/lib/log4j-api-2.17.1.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Generic/lib/log4j-core-2.17.1.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/GhidraGo/lib/GhidraGo.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/GhidraGo/lib/GhidraGo-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/GhidraServer/lib/GhidraServer.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/GhidraServer/lib/GhidraServer-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/GnuDemangler/lib/GnuDemangler.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/GnuDemangler/lib/GnuDemangler-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Graph/lib/Graph.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Graph/lib/Graph-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Graph/lib/jgrapht-core-1.5.1.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Graph/lib/jgrapht-io-1.5.1.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Graph/lib/jung-algorithms-2.1.1.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Graph/lib/jung-api-2.1.1.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Graph/lib/jung-graph-impl-2.1.1.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Graph/lib/jung-visualization-2.1.1.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/GraphFunctionCalls/lib/GraphFunctionCalls.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/GraphFunctionCalls/lib/GraphFunctionCalls-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/GraphServices/lib/GraphServices.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/GraphServices/lib/GraphServices-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/GraphServices/lib/jgrapht-core-1.5.1.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/GraphServices/lib/jgrapht-io-1.5.1.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/GraphServices/lib/jheaps-0.13.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/GraphServices/lib/jungrapht-layout-1.4.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/GraphServices/lib/jungrapht-visualization-1.4.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Gui/lib/flatlaf-3.5.4.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Gui/lib/Gui.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Gui/lib/Gui-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/HCS12/lib/HCS12.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/HCS12/lib/HCS12-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Help/lib/Help.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Help/lib/Help-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Help/lib/javahelp-2.0.05.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Help/lib/timingframework-1.0.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/JVM/lib/JVM.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/JVM/lib/JVM-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/Jython/lib/jython-standalone-2.7.4.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/Jython/lib/Jython.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/Jython/lib/Jython-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/Loongarch/lib/Loongarch.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/Loongarch/lib/Loongarch-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/MIPS/lib/MIPS.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/MIPS/lib/MIPS-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/MicrosoftCodeAnalyzer/lib/MicrosoftCodeAnalyzer.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/MicrosoftCodeAnalyzer/lib/MicrosoftCodeAnalyzer-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/MicrosoftDemangler/lib/MicrosoftDemangler.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/MicrosoftDemangler/lib/MicrosoftDemangler-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/MicrosoftDmang/lib/MicrosoftDmang.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/MicrosoftDmang/lib/MicrosoftDmang-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/PDB/lib/PDB.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/PDB/lib/PDB-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/PIC/lib/PIC.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/PIC/lib/PIC-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/PowerPC/lib/PowerPC.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/PowerPC/lib/PowerPC-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/ProgramDiff/lib/ProgramDiff.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/ProgramDiff/lib/ProgramDiff-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/ProgramGraph/lib/ProgramGraph.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/ProgramGraph/lib/ProgramGraph-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Project/lib/Project.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Project/lib/Project-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Project/lib/xz-1.9.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/ProposedUtils/lib/ProposedUtils.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/ProposedUtils/lib/ProposedUtils-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Pty/lib/jna-5.14.0.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Pty/lib/jna-platform-5.14.0.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Pty/lib/Pty.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Pty/lib/Pty-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Configurations/Public_Release/lib/Public_Release.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/PyGhidra/lib/PyGhidra.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/PyGhidra/lib/PyGhidra-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/RISCV/lib/RISCV.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/RISCV/lib/RISCV-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/Recognizers/lib/Recognizers.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/Recognizers/lib/Recognizers-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/Sarif/lib/java-sarif-2.1-modified.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/Sarif/lib/Sarif.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/Sarif/lib/Sarif-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/SoftwareModeling/lib/antlr-runtime-3.5.2.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/SoftwareModeling/lib/isorelax-20050913.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/SoftwareModeling/lib/msv-20050913.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/SoftwareModeling/lib/relaxngDatatype-20050913.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/SoftwareModeling/lib/SoftwareModeling.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/SoftwareModeling/lib/SoftwareModeling-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/SoftwareModeling/lib/xsdlib-20050913.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/SourceCodeLookup/lib/SourceCodeLookup.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/SourceCodeLookup/lib/SourceCodeLookup-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/Sparc/lib/Sparc.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/Sparc/lib/Sparc-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/SuperH4/lib/SuperH4.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/SuperH4/lib/SuperH4-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/SwiftDemangler/lib/SwiftDemangler.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/SwiftDemangler/lib/SwiftDemangler-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/SystemEmulation/lib/SystemEmulation.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/SystemEmulation/lib/SystemEmulation-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/TI_MSP430/lib/TI_MSP430.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/TI_MSP430/lib/TI_MSP430-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/TaintAnalysis/lib/TaintAnalysis.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Debug/TaintAnalysis/lib/TaintAnalysis-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Utility/lib/Utility.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Framework/Utility/lib/Utility-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/V850/lib/V850.jar">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/VersionTracking/lib/VersionTracking.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/VersionTracking/lib/VersionTracking-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/VersionTrackingBSim/lib/VersionTrackingBSim.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/VersionTrackingBSim/lib/VersionTrackingBSim-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/WildcardAssembler/lib/WildcardAssembler.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Features/WildcardAssembler/lib/WildcardAssembler-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Users/Guus/AppData/Roaming/ghidra/ghidra_11.3.2_PUBLIC/Extensions/XEXLoaderWV/lib/XEXLoaderWV.jar" sourcepath="C:/Users/Guus/AppData/Roaming/ghidra/ghidra_11.3.2_PUBLIC/Extensions/XEXLoaderWV/lib/XEXLoaderWV-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/Xtensa/lib/Xtensa.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/Xtensa/lib/Xtensa-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/eBPF/lib/eBPF.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/eBPF/lib/eBPF-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/tricore/lib/tricore.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/tricore/lib/tricore-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/x86/lib/x86.jar" sourcepath="C:/Projects/ghidra_11.3.2_PUBLIC/Ghidra/Processors/x86/lib/x86-src.zip">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="javadoc_location" value="jar:file:/C:\Projects\ghidra_11.3.2_PUBLIC\docs\GhidraAPI_javadoc.zip!/api/"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="output" path="bin/main"/>
|
||||||
|
</classpath>
|
||||||
24
GhidraPlugin/.project
Normal file
24
GhidraPlugin/.project
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>GhidraPlugin</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
<linkedResources>
|
||||||
|
<link>
|
||||||
|
<name>Ghidra</name>
|
||||||
|
<type>2</type>
|
||||||
|
<location>C:/Projects/ghidra_11.3.2_PUBLIC</location>
|
||||||
|
</link>
|
||||||
|
</linkedResources>
|
||||||
|
</projectDescription>
|
||||||
2
GhidraPlugin/.settings/org.eclipse.core.resources.prefs
Normal file
2
GhidraPlugin/.settings/org.eclipse.core.resources.prefs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
encoding/<project>=UTF-8
|
||||||
47
GhidraPlugin/.settings/org.eclipse.jdt.core.prefs
Normal file
47
GhidraPlugin/.settings/org.eclipse.jdt.core.prefs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=21
|
||||||
|
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
|
||||||
|
org.eclipse.jdt.core.compiler.problem.deprecation=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
|
||||||
|
org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
|
||||||
|
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
|
||||||
|
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
|
||||||
|
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
|
||||||
|
org.eclipse.jdt.core.compiler.problem.nullReference=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
|
||||||
|
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
|
||||||
|
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unusedImport=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
|
||||||
|
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
|
||||||
|
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
|
||||||
|
org.eclipse.jdt.core.compiler.source=21
|
||||||
0
GhidraPlugin/Module.manifest
Normal file
0
GhidraPlugin/Module.manifest
Normal file
1
GhidraPlugin/README.md
Normal file
1
GhidraPlugin/README.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# GhidraPlugin
|
||||||
BIN
GhidraPlugin/bin/main/ghidraplugin/GhidraPluginAnalyzer.class
Normal file
BIN
GhidraPlugin/bin/main/ghidraplugin/GhidraPluginAnalyzer.class
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
GhidraPlugin/bin/main/ghidraplugin/GhidraPluginPlugin.class
Normal file
BIN
GhidraPlugin/bin/main/ghidraplugin/GhidraPluginPlugin.class
Normal file
Binary file not shown.
Binary file not shown.
57
GhidraPlugin/bin/main/help/TOC_Source.xml
Normal file
57
GhidraPlugin/bin/main/help/TOC_Source.xml
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<?xml version='1.0' encoding='ISO-8859-1' ?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
This is an XML file intended to be parsed by the Ghidra help system. It is loosely based
|
||||||
|
upon the JavaHelp table of contents document format. The Ghidra help system uses a
|
||||||
|
TOC_Source.xml file to allow a module with help to define how its contents appear in the
|
||||||
|
Ghidra help viewer's table of contents. The main document (in the Base module)
|
||||||
|
defines a basic structure for the
|
||||||
|
Ghidra table of contents system. Other TOC_Source.xml files may use this structure to insert
|
||||||
|
their files directly into this structure (and optionally define a substructure).
|
||||||
|
|
||||||
|
|
||||||
|
In this document, a tag can be either a <tocdef> or a <tocref>. The former is a definition
|
||||||
|
of an XML item that may have a link and may contain other <tocdef> and <tocref> children.
|
||||||
|
<tocdef> items may be referred to in other documents by using a <tocref> tag with the
|
||||||
|
appropriate id attribute value. Using these two tags allows any module to define a place
|
||||||
|
in the table of contents system (<tocdef>), which also provides a place for
|
||||||
|
other TOC_Source.xml files to insert content (<tocref>).
|
||||||
|
|
||||||
|
During the help build time, all TOC_Source.xml files will be parsed and validated to ensure
|
||||||
|
that all <tocref> tags point to valid <tocdef> tags. From these files will be generated
|
||||||
|
<module name>_TOC.xml files, which are table of contents files written in the format
|
||||||
|
desired by the JavaHelp system. Additionally, the genated files will be merged together
|
||||||
|
as they are loaded by the JavaHelp system. In the end, when displaying help in the Ghidra
|
||||||
|
help GUI, there will be on table of contents that has been created from the definitions in
|
||||||
|
all of the modules' TOC_Source.xml files.
|
||||||
|
|
||||||
|
|
||||||
|
Tags and Attributes
|
||||||
|
|
||||||
|
<tocdef>
|
||||||
|
-id - the name of the definition (this must be unique across all TOC_Source.xml files)
|
||||||
|
-text - the display text of the node, as seen in the help GUI
|
||||||
|
-target** - the file to display when the node is clicked in the GUI
|
||||||
|
-sortgroup - this is a string that defines where a given node should appear under a given
|
||||||
|
parent. The string values will be sorted by the JavaHelp system using
|
||||||
|
a javax.text.RulesBasedCollator. If this attribute is not specified, then
|
||||||
|
the text of attribute will be used.
|
||||||
|
|
||||||
|
<tocref>
|
||||||
|
-id - The id of the <tocdef> that this reference points to
|
||||||
|
|
||||||
|
**The URL for the target is relative and should start with 'help/topics'. This text is
|
||||||
|
used by the Ghidra help system to provide a universal starting point for all links so that
|
||||||
|
they can be resolved at runtime, across modules.
|
||||||
|
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
<tocroot>
|
||||||
|
<!-- Uncomment and adjust fields to add help topic to help system's Table of Contents
|
||||||
|
<tocref id="Ghidra Functionality">
|
||||||
|
<tocdef id="HelpAnchor" text="My Feature" target="help/topics/my_topic/help.html" />
|
||||||
|
</tocref>
|
||||||
|
-->
|
||||||
|
</tocroot>
|
||||||
23
GhidraPlugin/bin/main/help/topics/ghidraplugin/help.html
Normal file
23
GhidraPlugin/bin/main/help/topics/ghidraplugin/help.html
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
|
||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<META name="generator" content=
|
||||||
|
"HTML Tidy for Java (vers. 2009-12-01), see jtidy.sourceforge.net">
|
||||||
|
<META http-equiv="Content-Language" content="en-us">
|
||||||
|
<META http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||||
|
<META name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||||
|
<META name="ProgId" content="FrontPage.Editor.Document">
|
||||||
|
|
||||||
|
<TITLE>Skeleton Help File for a Module</TITLE>
|
||||||
|
<LINK rel="stylesheet" type="text/css" href="help/shared/DefaultStyle.css">
|
||||||
|
</HEAD>
|
||||||
|
|
||||||
|
<BODY>
|
||||||
|
<H1><a name="HelpAnchor"></a>Skeleton Help File for a Module</H1>
|
||||||
|
|
||||||
|
<P>This is a simple skeleton help topic. For a better description of what should and should not
|
||||||
|
go in here, see the "sample" Ghidra extension in the Extensions/Ghidra directory, or see your
|
||||||
|
favorite help topic. In general, language modules do not have their own help topics.</P>
|
||||||
|
</BODY>
|
||||||
|
</HTML>
|
||||||
2
GhidraPlugin/bin/main/images/README.txt
Normal file
2
GhidraPlugin/bin/main/images/README.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
The "src/resources/images" directory is intended to hold all image/icon files used by
|
||||||
|
this module.
|
||||||
1
GhidraPlugin/bin/scripts/README.txt
Normal file
1
GhidraPlugin/bin/scripts/README.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Java source directory to hold module-specific Ghidra scripts.
|
||||||
66
GhidraPlugin/build.gradle
Normal file
66
GhidraPlugin/build.gradle
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
// Builds a Ghidra Extension for a given Ghidra installation.
|
||||||
|
//
|
||||||
|
// An absolute path to the Ghidra installation directory must be supplied either by setting the
|
||||||
|
// GHIDRA_INSTALL_DIR environment variable or Gradle project property:
|
||||||
|
//
|
||||||
|
// > export GHIDRA_INSTALL_DIR=<Absolute path to Ghidra>
|
||||||
|
// > gradle
|
||||||
|
//
|
||||||
|
// or
|
||||||
|
//
|
||||||
|
// > gradle -PGHIDRA_INSTALL_DIR=<Absolute path to Ghidra>
|
||||||
|
//
|
||||||
|
// Gradle should be invoked from the directory of the project to build. Please see the
|
||||||
|
// application.gradle.version property in <GHIDRA_INSTALL_DIR>/Ghidra/application.properties
|
||||||
|
// for the correction version of Gradle to use for the Ghidra installation you specify.
|
||||||
|
|
||||||
|
//----------------------START "DO NOT MODIFY" SECTION------------------------------
|
||||||
|
def ghidraInstallDir
|
||||||
|
|
||||||
|
if (System.env.GHIDRA_INSTALL_DIR) {
|
||||||
|
ghidraInstallDir = System.env.GHIDRA_INSTALL_DIR
|
||||||
|
}
|
||||||
|
else if (project.hasProperty("GHIDRA_INSTALL_DIR")) {
|
||||||
|
ghidraInstallDir = project.getProperty("GHIDRA_INSTALL_DIR")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ghidraInstallDir = "<REPLACE>"
|
||||||
|
}
|
||||||
|
|
||||||
|
task distributeExtension {
|
||||||
|
group "Ghidra"
|
||||||
|
|
||||||
|
apply from: new File(ghidraInstallDir).getCanonicalPath() + "/support/buildExtension.gradle"
|
||||||
|
dependsOn ':buildExtension'
|
||||||
|
}
|
||||||
|
//----------------------END "DO NOT MODIFY" SECTION-------------------------------
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
// Declare dependency repositories here. This is not needed if dependencies are manually
|
||||||
|
// dropped into the lib/ directory.
|
||||||
|
// See https://docs.gradle.org/current/userguide/declaring_repositories.html for more info.
|
||||||
|
// Ex: mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// Any external dependencies added here will automatically be copied to the lib/ directory when
|
||||||
|
// this extension is built.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exclude additional files from the built extension
|
||||||
|
// Ex: buildExtension.exclude '.idea/**'
|
||||||
15
GhidraPlugin/data/README.txt
Normal file
15
GhidraPlugin/data/README.txt
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
The "data" directory is intended to hold data files that will be used by this module and will
|
||||||
|
not end up in the .jar file, but will be present in the zip or tar file. Typically, data
|
||||||
|
files are placed here rather than in the resources directory if the user may need to edit them.
|
||||||
|
|
||||||
|
An optional data/languages directory can exist for the purpose of containing various Sleigh language
|
||||||
|
specification files and importer opinion files.
|
||||||
|
|
||||||
|
The data/buildLanguage.xml is used for building the contents of the data/languages directory.
|
||||||
|
|
||||||
|
The skel language definition has been commented-out within the skel.ldefs file so that the
|
||||||
|
skeleton language does not show-up within Ghidra.
|
||||||
|
|
||||||
|
See the Sleigh language documentation (docs/languages/index.html) for details Sleigh language
|
||||||
|
specification syntax.
|
||||||
|
|
||||||
5
GhidraPlugin/extension.properties
Normal file
5
GhidraPlugin/extension.properties
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
name=@extname@
|
||||||
|
description=The extension description can be customized by editing the extension.properties file.
|
||||||
|
author=
|
||||||
|
createdOn=
|
||||||
|
version=@extversion@
|
||||||
1
GhidraPlugin/ghidra_scripts/README.txt
Normal file
1
GhidraPlugin/ghidra_scripts/README.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Java source directory to hold module-specific Ghidra scripts.
|
||||||
3
GhidraPlugin/lib/README.txt
Normal file
3
GhidraPlugin/lib/README.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
The "lib" directory is intended to hold Jar files which this module is dependent upon. Jar files
|
||||||
|
may be placed in this directory manually, or automatically by maven via the dependencies block
|
||||||
|
of this module's build.gradle file.
|
||||||
3
GhidraPlugin/os/linux_x86_64/README.txt
Normal file
3
GhidraPlugin/os/linux_x86_64/README.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
The "os/linux_x86_64" directory is intended to hold Linux native binaries
|
||||||
|
which this module is dependent upon. This directory may be eliminated for a specific
|
||||||
|
module if native binaries are not provided for the corresponding platform.
|
||||||
3
GhidraPlugin/os/mac_x86_64/README.txt
Normal file
3
GhidraPlugin/os/mac_x86_64/README.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
The "os/mac_x86_64" directory is intended to hold macOS (OS X) native binaries
|
||||||
|
which this module is dependent upon. This directory may be eliminated for a specific
|
||||||
|
module if native binaries are not provided for the corresponding platform.
|
||||||
3
GhidraPlugin/os/win_x86_64/README.txt
Normal file
3
GhidraPlugin/os/win_x86_64/README.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
The "os/win_x86_64" directory is intended to hold MS Windows native binaries (.exe)
|
||||||
|
which this module is dependent upon. This directory may be eliminated for a specific
|
||||||
|
module if native binaries are not provided for the corresponding platform.
|
||||||
57
GhidraPlugin/src/main/help/help/TOC_Source.xml
Normal file
57
GhidraPlugin/src/main/help/help/TOC_Source.xml
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<?xml version='1.0' encoding='ISO-8859-1' ?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
This is an XML file intended to be parsed by the Ghidra help system. It is loosely based
|
||||||
|
upon the JavaHelp table of contents document format. The Ghidra help system uses a
|
||||||
|
TOC_Source.xml file to allow a module with help to define how its contents appear in the
|
||||||
|
Ghidra help viewer's table of contents. The main document (in the Base module)
|
||||||
|
defines a basic structure for the
|
||||||
|
Ghidra table of contents system. Other TOC_Source.xml files may use this structure to insert
|
||||||
|
their files directly into this structure (and optionally define a substructure).
|
||||||
|
|
||||||
|
|
||||||
|
In this document, a tag can be either a <tocdef> or a <tocref>. The former is a definition
|
||||||
|
of an XML item that may have a link and may contain other <tocdef> and <tocref> children.
|
||||||
|
<tocdef> items may be referred to in other documents by using a <tocref> tag with the
|
||||||
|
appropriate id attribute value. Using these two tags allows any module to define a place
|
||||||
|
in the table of contents system (<tocdef>), which also provides a place for
|
||||||
|
other TOC_Source.xml files to insert content (<tocref>).
|
||||||
|
|
||||||
|
During the help build time, all TOC_Source.xml files will be parsed and validated to ensure
|
||||||
|
that all <tocref> tags point to valid <tocdef> tags. From these files will be generated
|
||||||
|
<module name>_TOC.xml files, which are table of contents files written in the format
|
||||||
|
desired by the JavaHelp system. Additionally, the genated files will be merged together
|
||||||
|
as they are loaded by the JavaHelp system. In the end, when displaying help in the Ghidra
|
||||||
|
help GUI, there will be on table of contents that has been created from the definitions in
|
||||||
|
all of the modules' TOC_Source.xml files.
|
||||||
|
|
||||||
|
|
||||||
|
Tags and Attributes
|
||||||
|
|
||||||
|
<tocdef>
|
||||||
|
-id - the name of the definition (this must be unique across all TOC_Source.xml files)
|
||||||
|
-text - the display text of the node, as seen in the help GUI
|
||||||
|
-target** - the file to display when the node is clicked in the GUI
|
||||||
|
-sortgroup - this is a string that defines where a given node should appear under a given
|
||||||
|
parent. The string values will be sorted by the JavaHelp system using
|
||||||
|
a javax.text.RulesBasedCollator. If this attribute is not specified, then
|
||||||
|
the text of attribute will be used.
|
||||||
|
|
||||||
|
<tocref>
|
||||||
|
-id - The id of the <tocdef> that this reference points to
|
||||||
|
|
||||||
|
**The URL for the target is relative and should start with 'help/topics'. This text is
|
||||||
|
used by the Ghidra help system to provide a universal starting point for all links so that
|
||||||
|
they can be resolved at runtime, across modules.
|
||||||
|
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
<tocroot>
|
||||||
|
<!-- Uncomment and adjust fields to add help topic to help system's Table of Contents
|
||||||
|
<tocref id="Ghidra Functionality">
|
||||||
|
<tocdef id="HelpAnchor" text="My Feature" target="help/topics/my_topic/help.html" />
|
||||||
|
</tocref>
|
||||||
|
-->
|
||||||
|
</tocroot>
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
|
||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<META name="generator" content=
|
||||||
|
"HTML Tidy for Java (vers. 2009-12-01), see jtidy.sourceforge.net">
|
||||||
|
<META http-equiv="Content-Language" content="en-us">
|
||||||
|
<META http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||||
|
<META name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||||
|
<META name="ProgId" content="FrontPage.Editor.Document">
|
||||||
|
|
||||||
|
<TITLE>Skeleton Help File for a Module</TITLE>
|
||||||
|
<LINK rel="stylesheet" type="text/css" href="help/shared/DefaultStyle.css">
|
||||||
|
</HEAD>
|
||||||
|
|
||||||
|
<BODY>
|
||||||
|
<H1><a name="HelpAnchor"></a>Skeleton Help File for a Module</H1>
|
||||||
|
|
||||||
|
<P>This is a simple skeleton help topic. For a better description of what should and should not
|
||||||
|
go in here, see the "sample" Ghidra extension in the Extensions/Ghidra directory, or see your
|
||||||
|
favorite help topic. In general, language modules do not have their own help topics.</P>
|
||||||
|
</BODY>
|
||||||
|
</HTML>
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidraplugin;
|
||||||
|
|
||||||
|
import ghidra.app.services.AbstractAnalyzer;
|
||||||
|
import ghidra.app.services.AnalyzerType;
|
||||||
|
import ghidra.app.util.importer.MessageLog;
|
||||||
|
import ghidra.framework.options.Options;
|
||||||
|
import ghidra.program.model.address.AddressSetView;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.util.exception.CancelledException;
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide class-level documentation that describes what this analyzer does.
|
||||||
|
*/
|
||||||
|
public class GhidraPluginAnalyzer extends AbstractAnalyzer {
|
||||||
|
|
||||||
|
public GhidraPluginAnalyzer() {
|
||||||
|
|
||||||
|
// Name the analyzer and give it a description.
|
||||||
|
|
||||||
|
super("My Analyzer", "Analyzer description goes here", AnalyzerType.BYTE_ANALYZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getDefaultEnablement(Program program) {
|
||||||
|
|
||||||
|
// Return true if analyzer should be enabled by default
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canAnalyze(Program program) {
|
||||||
|
|
||||||
|
// Examine 'program' to determine of this analyzer should analyze it. Return true
|
||||||
|
// if it can.
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerOptions(Options options, Program program) {
|
||||||
|
|
||||||
|
// If this analyzer has custom options, register them here
|
||||||
|
|
||||||
|
options.registerOption("Option name goes here", false, null,
|
||||||
|
"Option description goes here");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
|
||||||
|
throws CancelledException {
|
||||||
|
|
||||||
|
// Perform analysis when things get added to the 'program'. Return true if the
|
||||||
|
// analysis succeeded.
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
116
GhidraPlugin/src/main/java/ghidraplugin/GhidraPluginPlugin.java
Normal file
116
GhidraPlugin/src/main/java/ghidraplugin/GhidraPluginPlugin.java
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidraplugin;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
import docking.ActionContext;
|
||||||
|
import docking.ComponentProvider;
|
||||||
|
import docking.action.DockingAction;
|
||||||
|
import docking.action.ToolBarData;
|
||||||
|
import ghidra.app.ExamplesPluginPackage;
|
||||||
|
import ghidra.app.plugin.PluginCategoryNames;
|
||||||
|
import ghidra.app.plugin.ProgramPlugin;
|
||||||
|
import ghidra.framework.plugintool.*;
|
||||||
|
import ghidra.framework.plugintool.util.PluginStatus;
|
||||||
|
import ghidra.util.HelpLocation;
|
||||||
|
import ghidra.util.Msg;
|
||||||
|
import resources.Icons;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide class-level documentation that describes what this plugin does.
|
||||||
|
*/
|
||||||
|
//@formatter:off
|
||||||
|
@PluginInfo(
|
||||||
|
status = PluginStatus.STABLE,
|
||||||
|
packageName = ExamplesPluginPackage.NAME,
|
||||||
|
category = PluginCategoryNames.EXAMPLES,
|
||||||
|
shortDescription = "Plugin short description goes here.",
|
||||||
|
description = "Plugin long description goes here."
|
||||||
|
)
|
||||||
|
//@formatter:on
|
||||||
|
public class GhidraPluginPlugin extends ProgramPlugin {
|
||||||
|
|
||||||
|
MyProvider provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin constructor.
|
||||||
|
*
|
||||||
|
* @param tool The plugin tool that this plugin is added to.
|
||||||
|
*/
|
||||||
|
public GhidraPluginPlugin(PluginTool tool) {
|
||||||
|
super(tool);
|
||||||
|
|
||||||
|
// Customize provider (or remove if a provider is not desired)
|
||||||
|
String pluginName = getName();
|
||||||
|
provider = new MyProvider(this, pluginName);
|
||||||
|
|
||||||
|
// Customize help (or remove if help is not desired)
|
||||||
|
String topicName = this.getClass().getPackage().getName();
|
||||||
|
String anchorName = "HelpAnchor";
|
||||||
|
provider.setHelpLocation(new HelpLocation(topicName, anchorName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
super.init();
|
||||||
|
|
||||||
|
// Acquire services if necessary
|
||||||
|
}
|
||||||
|
|
||||||
|
// If provider is desired, it is recommended to move it to its own file
|
||||||
|
private static class MyProvider extends ComponentProvider {
|
||||||
|
|
||||||
|
private JPanel panel;
|
||||||
|
private DockingAction action;
|
||||||
|
|
||||||
|
public MyProvider(Plugin plugin, String owner) {
|
||||||
|
super(plugin.getTool(), "Skeleton Provider", owner);
|
||||||
|
buildPanel();
|
||||||
|
createActions();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Customize GUI
|
||||||
|
private void buildPanel() {
|
||||||
|
panel = new JPanel(new BorderLayout());
|
||||||
|
JTextArea textArea = new JTextArea(5, 25);
|
||||||
|
textArea.setEditable(false);
|
||||||
|
panel.add(new JScrollPane(textArea));
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Customize actions
|
||||||
|
private void createActions() {
|
||||||
|
action = new DockingAction("My Action", getOwner()) {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionContext context) {
|
||||||
|
Msg.showInfo(getClass(), panel, "Custom Action", "Hello!");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
action.setToolBarData(new ToolBarData(Icons.ADD_ICON, null));
|
||||||
|
action.setEnabled(true);
|
||||||
|
action.markHelpUnnecessary();
|
||||||
|
dockingTool.addLocalAction(this, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JComponent getComponent() {
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,409 @@
|
|||||||
|
package ghidraplugin;
|
||||||
|
|
||||||
|
import ghidra.app.plugin.PluginCategoryNames;
|
||||||
|
import ghidra.app.plugin.ProgramPlugin;
|
||||||
|
import ghidra.framework.plugintool.PluginInfo;
|
||||||
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
|
import ghidra.framework.plugintool.util.PluginStatus;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.program.util.ProgramChangeRecord;
|
||||||
|
import ghidra.program.util.ProgramEvent;
|
||||||
|
import ghidra.util.Msg;
|
||||||
|
import ghidra.framework.model.*;
|
||||||
|
import ghidra.program.model.symbol.*;
|
||||||
|
import ghidra.program.model.listing.Data;
|
||||||
|
import ghidra.program.model.listing.Function;
|
||||||
|
import ghidra.program.util.*;
|
||||||
|
import ghidra.framework.cmd.Command;
|
||||||
|
import ghidra.framework.model.TransactionInfo;
|
||||||
|
|
||||||
|
@PluginInfo(
|
||||||
|
status = PluginStatus.STABLE,
|
||||||
|
packageName = "SymbolLogger",
|
||||||
|
category = PluginCategoryNames.COMMON,
|
||||||
|
shortDescription = "Logs symbol and function renames",
|
||||||
|
description = "A plugin that monitors and logs all symbol and function rename events to the console, including undo/redo context",
|
||||||
|
servicesRequired = {},
|
||||||
|
servicesProvided = {}
|
||||||
|
)
|
||||||
|
public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObjectListener {
|
||||||
|
|
||||||
|
public SymbolRenameLoggerPlugin(PluginTool tool) {
|
||||||
|
super(tool);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init() {
|
||||||
|
super.init();
|
||||||
|
Msg.info(this, "SymbolRenameLoggerPlugin initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void programActivated(Program program) {
|
||||||
|
super.programActivated(program);
|
||||||
|
if (program != null) {
|
||||||
|
program.addListener(this);
|
||||||
|
Msg.info(this, "Started listening for rename events in program: " + program.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void programDeactivated(Program program) {
|
||||||
|
if (program != null) {
|
||||||
|
program.removeListener(this);
|
||||||
|
Msg.info(this, "Stopped listening for rename events in program: " + program.getName());
|
||||||
|
}
|
||||||
|
super.programDeactivated(program);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void domainObjectChanged(DomainObjectChangedEvent ev) {
|
||||||
|
for (DomainObjectChangeRecord record : ev) {
|
||||||
|
if (record instanceof ProgramChangeRecord) {
|
||||||
|
ProgramChangeRecord progRecord = (ProgramChangeRecord) record;
|
||||||
|
handleProgramChange(progRecord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the context of the current operation (direct action, undo, or redo)
|
||||||
|
*/
|
||||||
|
private String getOperationContext() {
|
||||||
|
try {
|
||||||
|
Program program = getCurrentProgram();
|
||||||
|
if (program != null) {
|
||||||
|
TransactionInfo currentTransaction = program.getCurrentTransactionInfo();
|
||||||
|
if (currentTransaction != null) {
|
||||||
|
String description = currentTransaction.getDescription();
|
||||||
|
if (description != null) {
|
||||||
|
if (description.startsWith("Undo")) {
|
||||||
|
return "[UNDO] ";
|
||||||
|
} else if (description.startsWith("Redo")) {
|
||||||
|
return "[REDO] ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Silently handle any exceptions in context detection
|
||||||
|
}
|
||||||
|
return ""; // Direct user action (no prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enhanced logging method that includes undo/redo context
|
||||||
|
*/
|
||||||
|
private void logWithContext(String message) {
|
||||||
|
String context = getOperationContext();
|
||||||
|
Msg.info(this, context + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleProgramChange(ProgramChangeRecord record) {
|
||||||
|
ProgramEvent eventType = (ProgramEvent)record.getEventType();
|
||||||
|
|
||||||
|
Msg.info(this, "Event: " + record.toString());
|
||||||
|
|
||||||
|
// Handle symbol rename events
|
||||||
|
if (eventType == ProgramEvent.SYMBOL_RENAMED) {
|
||||||
|
handleSymbolRenamed(record);
|
||||||
|
}
|
||||||
|
// Handle function rename events (functions are also symbols, but we can be more specific)
|
||||||
|
else if (eventType == ProgramEvent.FUNCTION_CHANGED) {
|
||||||
|
handleFunctionChanged(record);
|
||||||
|
}
|
||||||
|
// Handle symbol added events (in case we want to track new symbols)
|
||||||
|
else if (eventType == ProgramEvent.SYMBOL_ADDED) {
|
||||||
|
handleSymbolAdded(record);
|
||||||
|
}
|
||||||
|
// Handle symbol removed events
|
||||||
|
else if (eventType == ProgramEvent.SYMBOL_REMOVED) {
|
||||||
|
handleSymbolRemoved(record);
|
||||||
|
}
|
||||||
|
// Handle data type changes (includes global type definitions, structures, etc.)
|
||||||
|
else if (eventType == ProgramEvent.DATA_TYPE_CHANGED) {
|
||||||
|
handleDataTypeChanged(record);
|
||||||
|
}
|
||||||
|
// Handle data type added events
|
||||||
|
else if (eventType == ProgramEvent.DATA_TYPE_ADDED) {
|
||||||
|
handleDataTypeAdded(record);
|
||||||
|
}
|
||||||
|
// Handle data type removed events
|
||||||
|
else if (eventType == ProgramEvent.DATA_TYPE_REMOVED) {
|
||||||
|
handleDataTypeRemoved(record);
|
||||||
|
}
|
||||||
|
// Handle data type renamed events
|
||||||
|
else if (eventType == ProgramEvent.DATA_TYPE_RENAMED) {
|
||||||
|
handleDataTypeRenamed(record);
|
||||||
|
}
|
||||||
|
// Handle function signature changes (parameters, return types, etc.)
|
||||||
|
else if (eventType == ProgramEvent.FUNCTION_CHANGED) {
|
||||||
|
handleFunctionSignatureChanged(record);
|
||||||
|
}
|
||||||
|
// Handle transaction events for better undo/redo tracking
|
||||||
|
// else if (eventType == ProgramEvent..TRANSACTION_STARTED) {
|
||||||
|
// handleTransactionStarted(record);
|
||||||
|
// }
|
||||||
|
// else if (eventType == ProgramEvent.TRANSACTION_ENDED) {
|
||||||
|
// handleTransactionEnded(record);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleTransactionStarted(ProgramChangeRecord record) {
|
||||||
|
String context = getOperationContext();
|
||||||
|
if (!context.isEmpty()) {
|
||||||
|
logWithContext("TRANSACTION STARTED");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleTransactionEnded(ProgramChangeRecord record) {
|
||||||
|
String context = getOperationContext();
|
||||||
|
if (!context.isEmpty()) {
|
||||||
|
logWithContext("TRANSACTION ENDED");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleSymbolRenamed(ProgramChangeRecord record) {
|
||||||
|
Object newValue = record.getNewValue();
|
||||||
|
Object oldValue = record.getOldValue();
|
||||||
|
|
||||||
|
String newName = (newValue != null) ? newValue.toString() : "null";
|
||||||
|
String oldName = (oldValue != null) ? oldValue.toString() : "null";
|
||||||
|
|
||||||
|
logWithContext(String.format("SYMBOL RENAMED: '%s' -> '%s' at address %s",
|
||||||
|
oldName, newName, record.getStart()));
|
||||||
|
|
||||||
|
// Try to get additional information about the symbol
|
||||||
|
try {
|
||||||
|
Program program = getCurrentProgram();
|
||||||
|
if (program != null) {
|
||||||
|
SymbolTable symbolTable = program.getSymbolTable();
|
||||||
|
Symbol[] symbols = symbolTable.getSymbols(record.getStart());
|
||||||
|
|
||||||
|
for (Symbol symbol : symbols) {
|
||||||
|
if (symbol.getName().equals(newName)) {
|
||||||
|
String symbolType = getSymbolTypeDescription(symbol);
|
||||||
|
logWithContext(String.format(" Symbol type: %s, Namespace: %s",
|
||||||
|
symbolType, symbol.getParentNamespace().getName()));
|
||||||
|
|
||||||
|
// If it's a function, log additional function details
|
||||||
|
if (symbol.getSymbolType() == SymbolType.FUNCTION) {
|
||||||
|
Function function = (Function) symbol.getObject();
|
||||||
|
if (function != null) {
|
||||||
|
logWithContext(String.format(" Function signature: %s",
|
||||||
|
function.getPrototypeString(false, false)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Msg.error(this, "Error getting symbol details: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleFunctionChanged(ProgramChangeRecord record) {
|
||||||
|
// This handles function-specific changes including renames and signature changes
|
||||||
|
Object newValue = record.getNewValue();
|
||||||
|
Object oldValue = record.getOldValue();
|
||||||
|
|
||||||
|
if (newValue instanceof Function && oldValue instanceof Function) {
|
||||||
|
Function newFunc = (Function) newValue;
|
||||||
|
Function oldFunc = (Function) oldValue;
|
||||||
|
|
||||||
|
// Check for name changes
|
||||||
|
if (!newFunc.getName().equals(oldFunc.getName())) {
|
||||||
|
logWithContext(String.format("FUNCTION RENAMED: '%s' -> '%s' at address %s",
|
||||||
|
oldFunc.getName(), newFunc.getName(), newFunc.getEntryPoint()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for signature changes
|
||||||
|
String oldSignature = oldFunc.getPrototypeString(false, false);
|
||||||
|
String newSignature = newFunc.getPrototypeString(false, false);
|
||||||
|
if (!oldSignature.equals(newSignature)) {
|
||||||
|
logWithContext(String.format("FUNCTION SIGNATURE CHANGED at address %s:", newFunc.getEntryPoint()));
|
||||||
|
logWithContext(String.format(" Old: %s", oldSignature));
|
||||||
|
logWithContext(String.format(" New: %s", newSignature));
|
||||||
|
|
||||||
|
// Log specific changes
|
||||||
|
logFunctionSignatureDetails(oldFunc, newFunc);
|
||||||
|
}
|
||||||
|
} else if (newValue instanceof Function) {
|
||||||
|
Function function = (Function) newValue;
|
||||||
|
logWithContext(String.format("FUNCTION MODIFIED: %s at address %s",
|
||||||
|
function.getName(), function.getEntryPoint()));
|
||||||
|
logWithContext(String.format(" Signature: %s", function.getPrototypeString(false, false)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleFunctionSignatureChanged(ProgramChangeRecord record) {
|
||||||
|
// Handle detailed function signature changes
|
||||||
|
handleFunctionChanged(record); // Reuse the existing logic
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleDataTypeChanged(ProgramChangeRecord record) {
|
||||||
|
Object newValue = record.getNewValue();
|
||||||
|
Object oldValue = record.getOldValue();
|
||||||
|
|
||||||
|
logWithContext(String.format("DATA TYPE CHANGED at address %s", record.getStart()));
|
||||||
|
|
||||||
|
if (oldValue != null && newValue != null) {
|
||||||
|
logWithContext(String.format(" Old type: %s", oldValue.toString()));
|
||||||
|
logWithContext(String.format(" New type: %s", newValue.toString()));
|
||||||
|
} else if (newValue != null) {
|
||||||
|
logWithContext(String.format(" Type set to: %s", newValue.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to get more context about the data type change
|
||||||
|
try {
|
||||||
|
Program program = getCurrentProgram();
|
||||||
|
if (program != null && record.getStart() != null) {
|
||||||
|
Data data = program.getListing().getDataAt(record.getStart());
|
||||||
|
if (data != null) {
|
||||||
|
logWithContext(String.format(" Data label: %s", data.getLabel()));
|
||||||
|
logWithContext(String.format(" Data type: %s", data.getDataType().getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Msg.error(this, "Error getting data type details: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleDataTypeAdded(ProgramChangeRecord record) {
|
||||||
|
Object newValue = record.getNewValue();
|
||||||
|
|
||||||
|
logWithContext(String.format("DATA TYPE ADDED at address %s", record.getStart()));
|
||||||
|
if (newValue != null) {
|
||||||
|
logWithContext(String.format(" Type: %s", newValue.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleDataTypeRemoved(ProgramChangeRecord record) {
|
||||||
|
Object oldValue = record.getOldValue();
|
||||||
|
|
||||||
|
logWithContext(String.format("DATA TYPE REMOVED at address %s", record.getStart()));
|
||||||
|
if (oldValue != null) {
|
||||||
|
logWithContext(String.format(" Removed type: %s", oldValue.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleDataTypeRenamed(ProgramChangeRecord record) {
|
||||||
|
Object newValue = record.getNewValue();
|
||||||
|
Object oldValue = record.getOldValue();
|
||||||
|
|
||||||
|
String newName = (newValue != null) ? newValue.toString() : "null";
|
||||||
|
String oldName = (oldValue != null) ? oldValue.toString() : "null";
|
||||||
|
|
||||||
|
logWithContext(String.format("DATA TYPE RENAMED: '%s' -> '%s' at address %s",
|
||||||
|
oldName, newName, record.getStart()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logFunctionSignatureDetails(Function oldFunc, Function newFunc) {
|
||||||
|
try {
|
||||||
|
// Check return type changes
|
||||||
|
if (!oldFunc.getReturnType().equals(newFunc.getReturnType())) {
|
||||||
|
logWithContext(String.format(" Return type changed: %s -> %s",
|
||||||
|
oldFunc.getReturnType().getName(), newFunc.getReturnType().getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check parameter count changes
|
||||||
|
int oldParamCount = oldFunc.getParameterCount();
|
||||||
|
int newParamCount = newFunc.getParameterCount();
|
||||||
|
if (oldParamCount != newParamCount) {
|
||||||
|
logWithContext(String.format(" Parameter count changed: %d -> %d",
|
||||||
|
oldParamCount, newParamCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check individual parameter changes
|
||||||
|
int maxParams = Math.max(oldParamCount, newParamCount);
|
||||||
|
for (int i = 0; i < maxParams; i++) {
|
||||||
|
if (i < oldParamCount && i < newParamCount) {
|
||||||
|
ghidra.program.model.listing.Parameter oldParam = oldFunc.getParameter(i);
|
||||||
|
ghidra.program.model.listing.Parameter newParam = newFunc.getParameter(i);
|
||||||
|
|
||||||
|
if (!oldParam.getDataType().equals(newParam.getDataType())) {
|
||||||
|
logWithContext(String.format(" Parameter %d type changed: %s -> %s",
|
||||||
|
i, oldParam.getDataType().getName(), newParam.getDataType().getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!oldParam.getName().equals(newParam.getName())) {
|
||||||
|
logWithContext(String.format(" Parameter %d name changed: %s -> %s",
|
||||||
|
i, oldParam.getName(), newParam.getName()));
|
||||||
|
}
|
||||||
|
} else if (i < newParamCount) {
|
||||||
|
ghidra.program.model.listing.Parameter newParam = newFunc.getParameter(i);
|
||||||
|
logWithContext(String.format(" Parameter %d added: %s %s",
|
||||||
|
i, newParam.getDataType().getName(), newParam.getName()));
|
||||||
|
} else {
|
||||||
|
ghidra.program.model.listing.Parameter oldParam = oldFunc.getParameter(i);
|
||||||
|
logWithContext(String.format(" Parameter %d removed: %s %s",
|
||||||
|
i, oldParam.getDataType().getName(), oldParam.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check calling convention changes
|
||||||
|
if (!oldFunc.getCallingConventionName().equals(newFunc.getCallingConventionName())) {
|
||||||
|
logWithContext(String.format(" Calling convention changed: %s -> %s",
|
||||||
|
oldFunc.getCallingConventionName(), newFunc.getCallingConventionName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Msg.error(this, "Error logging function signature details: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleSymbolAdded(ProgramChangeRecord record) {
|
||||||
|
Object newValue = record.getNewValue();
|
||||||
|
if (newValue instanceof Symbol) {
|
||||||
|
Symbol symbol = (Symbol) newValue;
|
||||||
|
String symbolType = getSymbolTypeDescription(symbol);
|
||||||
|
logWithContext(String.format("SYMBOL ADDED: '%s' (%s) at address %s",
|
||||||
|
symbol.getName(), symbolType, symbol.getAddress()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleSymbolRemoved(ProgramChangeRecord record) {
|
||||||
|
Object oldValue = record.getOldValue();
|
||||||
|
if (oldValue instanceof Symbol) {
|
||||||
|
Symbol symbol = (Symbol) oldValue;
|
||||||
|
String symbolType = getSymbolTypeDescription(symbol);
|
||||||
|
logWithContext(String.format("SYMBOL REMOVED: '%s' (%s) at address %s",
|
||||||
|
symbol.getName(), symbolType, symbol.getAddress()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getSymbolTypeDescription(Symbol symbol) {
|
||||||
|
SymbolType type = symbol.getSymbolType();
|
||||||
|
|
||||||
|
if (type == SymbolType.FUNCTION) {
|
||||||
|
return "Function";
|
||||||
|
} else if (type == SymbolType.LABEL) {
|
||||||
|
return "Label";
|
||||||
|
} else if (type == SymbolType.CLASS) {
|
||||||
|
return "Class";
|
||||||
|
} else if (type == SymbolType.NAMESPACE) {
|
||||||
|
return "Namespace";
|
||||||
|
} else if (type == SymbolType.PARAMETER) {
|
||||||
|
return "Parameter";
|
||||||
|
} else if (type == SymbolType.LOCAL_VAR) {
|
||||||
|
return "Local Variable";
|
||||||
|
} else if (type == SymbolType.GLOBAL_VAR) {
|
||||||
|
return "Global Variable";
|
||||||
|
} else if (type == SymbolType.LIBRARY) {
|
||||||
|
return "Library";
|
||||||
|
} else {
|
||||||
|
return type.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void dispose() {
|
||||||
|
Program program = getCurrentProgram();
|
||||||
|
if (program != null) {
|
||||||
|
program.removeListener(this);
|
||||||
|
}
|
||||||
|
super.dispose();
|
||||||
|
Msg.info(this, "SymbolRenameLoggerPlugin disposed");
|
||||||
|
}
|
||||||
|
}
|
||||||
2
GhidraPlugin/src/main/resources/images/README.txt
Normal file
2
GhidraPlugin/src/main/resources/images/README.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
The "src/resources/images" directory is intended to hold all image/icon files used by
|
||||||
|
this module.
|
||||||
150
GhidraScripts/CleanupDatabase.java
Normal file
150
GhidraScripts/CleanupDatabase.java
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
// Cleanup the database of all missing files, and report duplicates
|
||||||
|
// @category _Reman3
|
||||||
|
// @menupath Reman3.Cleanup Database
|
||||||
|
// @importpackage org.sqlite
|
||||||
|
|
||||||
|
import ghidra.app.script.GhidraScript;
|
||||||
|
import ghidra.program.model.listing.Function;
|
||||||
|
import re3lib.FunctionDumper;
|
||||||
|
import re3lib.GlobalDumper;
|
||||||
|
import re3lib.RemanConfig;
|
||||||
|
import re3lib.FunctionDatabase;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import ghidra.program.model.address.Address;
|
||||||
|
|
||||||
|
public class CleanupDatabase extends GhidraScript {
|
||||||
|
@Override
|
||||||
|
public void run() throws Exception {
|
||||||
|
RemanConfig.INSTANCE = new RemanConfig(this);
|
||||||
|
RemanConfig.INSTANCE.createDirectories();
|
||||||
|
boolean anyChanges = false;
|
||||||
|
|
||||||
|
try (FunctionDatabase functionDatabase = new FunctionDatabase(this)) {
|
||||||
|
functionDatabase.connect();
|
||||||
|
|
||||||
|
// Step 1: Check for missing files and remove entries
|
||||||
|
anyChanges |= cleanupMissingFiles(functionDatabase);
|
||||||
|
|
||||||
|
// Step 2: Check for duplicate addresses
|
||||||
|
anyChanges |= reportDuplicateAddresses(functionDatabase);
|
||||||
|
|
||||||
|
// Step 3: Check if database names match function names
|
||||||
|
anyChanges |= validateFunctionNames(functionDatabase);
|
||||||
|
|
||||||
|
if (anyChanges) {
|
||||||
|
println("Database cleanup completed with changes - touching CMake timestamp");
|
||||||
|
RemanConfig.INSTANCE.touchCMakeTimestamp();
|
||||||
|
} else {
|
||||||
|
println("Database cleanup completed - no changes needed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cleanupMissingFiles(FunctionDatabase functionDatabase) throws Exception {
|
||||||
|
println("=== Step 1: Checking for missing files ===");
|
||||||
|
boolean madeChanges = false;
|
||||||
|
|
||||||
|
List<FunctionDatabase.FunctionEntry> entries = functionDatabase.loadAllEntries();
|
||||||
|
List<FunctionDatabase.FunctionEntry> entriesToRemove = new ArrayList<>();
|
||||||
|
|
||||||
|
for (FunctionDatabase.FunctionEntry entry : entries) {
|
||||||
|
if (!entry.file.exists()) {
|
||||||
|
println("Missing file: " + entry.file.getAbsolutePath() + " for function " + entry.name);
|
||||||
|
entriesToRemove.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (FunctionDatabase.FunctionEntry entry : entriesToRemove) {
|
||||||
|
println("Removing database entry for missing file: " + entry.file.getAbsolutePath());
|
||||||
|
functionDatabase.removeEntryAt(entry.file.getAbsolutePath());
|
||||||
|
madeChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
println("Removed " + entriesToRemove.size() + " entries for missing files");
|
||||||
|
return madeChanges;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean reportDuplicateAddresses(FunctionDatabase functionDatabase) throws Exception {
|
||||||
|
println("=== Step 2: Checking for duplicate addresses ===");
|
||||||
|
boolean madeChanges = false;
|
||||||
|
|
||||||
|
List<FunctionDatabase.FunctionEntry> entries = functionDatabase.loadAllEntries();
|
||||||
|
Map<Address, List<FunctionDatabase.FunctionEntry>> addressMap = new HashMap<>();
|
||||||
|
|
||||||
|
// Group entries by address
|
||||||
|
for (FunctionDatabase.FunctionEntry entry : entries) {
|
||||||
|
if (entry.type == FunctionDatabase.Type.Ref)
|
||||||
|
continue;
|
||||||
|
if (!addressMap.containsKey(entry.address)) {
|
||||||
|
addressMap.put(entry.address, new ArrayList<>());
|
||||||
|
}
|
||||||
|
addressMap.get(entry.address).add(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for duplicates
|
||||||
|
for (Map.Entry<Address, List<FunctionDatabase.FunctionEntry>> mapEntry : addressMap.entrySet()) {
|
||||||
|
List<FunctionDatabase.FunctionEntry> duplicates = mapEntry.getValue();
|
||||||
|
if (duplicates.size() > 1) {
|
||||||
|
println("Found " + duplicates.size() + " entries for address " + mapEntry.getKey() + ":");
|
||||||
|
|
||||||
|
// Report all entries
|
||||||
|
for (FunctionDatabase.FunctionEntry entry : duplicates) {
|
||||||
|
println(" - " + entry.type + ": " + entry.file.getAbsolutePath() + " (name: " + entry.name + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return madeChanges;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean validateFunctionNames(FunctionDatabase functionDatabase) throws Exception {
|
||||||
|
println("=== Step 3: Validating function names ===");
|
||||||
|
boolean madeChanges = false;
|
||||||
|
|
||||||
|
List<FunctionDatabase.FunctionEntry> entries = functionDatabase.loadAllEntries();
|
||||||
|
List<FunctionDatabase.FunctionEntry> entriesToUpdate = new ArrayList<>();
|
||||||
|
List<FunctionDatabase.FunctionEntry> entriesToRemove = new ArrayList<>();
|
||||||
|
|
||||||
|
for (FunctionDatabase.FunctionEntry entry : entries) {
|
||||||
|
Function function = getFunctionAt(entry.address);
|
||||||
|
|
||||||
|
if (function == null) {
|
||||||
|
println("No function found at address " + entry.address + " for database entry: " + entry.name);
|
||||||
|
println(" Removing orphaned database entry");
|
||||||
|
entriesToRemove.add(entry);
|
||||||
|
} else {
|
||||||
|
String actualName = function.getName();
|
||||||
|
if (!actualName.equals(entry.name)) {
|
||||||
|
println("Name mismatch at " + entry.address + ":");
|
||||||
|
println(" Database name: " + entry.name);
|
||||||
|
println(" Actual name: " + actualName);
|
||||||
|
|
||||||
|
// Update the entry with the correct name
|
||||||
|
entry.name = actualName;
|
||||||
|
entriesToUpdate.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Report orphaned entries
|
||||||
|
for (FunctionDatabase.FunctionEntry entry : entriesToRemove) {
|
||||||
|
println("Found orphaned entry: " + entry.file.getAbsolutePath() + " for function " + entry.name + " at address "
|
||||||
|
+ entry.address);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update entries with corrected names
|
||||||
|
for (FunctionDatabase.FunctionEntry entry : entriesToUpdate) {
|
||||||
|
println("Updating database entry for " + entry.address + " with correct name: " + entry.name);
|
||||||
|
functionDatabase.addEntryAt(entry);
|
||||||
|
madeChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
println("Removed " + entriesToRemove.size() + " orphaned entries");
|
||||||
|
println("Updated " + entriesToUpdate.size() + " entries with corrected names");
|
||||||
|
|
||||||
|
return madeChanges;
|
||||||
|
}
|
||||||
|
}
|
||||||
36
GhidraScripts/DumpCurrentFunction.java
Normal file
36
GhidraScripts/DumpCurrentFunction.java
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
// Script to export decompiled C code for selected function from Ghidra
|
||||||
|
// @category _Reman3
|
||||||
|
// @menupath Reman3.Dump Current Function
|
||||||
|
// @importpackage org.sqlite
|
||||||
|
|
||||||
|
import ghidra.app.script.GhidraScript;
|
||||||
|
import ghidra.program.model.listing.Function;
|
||||||
|
import re3lib.FunctionDumper;
|
||||||
|
import re3lib.GlobalDumper;
|
||||||
|
import re3lib.RemanConfig;
|
||||||
|
import re3lib.FunctionDatabase;
|
||||||
|
|
||||||
|
public class DumpCurrentFunction extends GhidraScript {
|
||||||
|
@Override
|
||||||
|
public void run() throws Exception {
|
||||||
|
RemanConfig.INSTANCE = new RemanConfig(this);
|
||||||
|
RemanConfig.INSTANCE.createDirectories();
|
||||||
|
|
||||||
|
try (FunctionDatabase functionDatabase = new FunctionDatabase(this)) {
|
||||||
|
GlobalDumper globalDumper = new GlobalDumper(this, functionDatabase);
|
||||||
|
FunctionDumper functionDumper = new FunctionDumper(this, functionDatabase, globalDumper);
|
||||||
|
|
||||||
|
Function currentFunction = getFunctionContaining(currentAddress);
|
||||||
|
if (currentFunction != null) {
|
||||||
|
functionDumper.dump(currentFunction);
|
||||||
|
} else {
|
||||||
|
println("No function found at the current address.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (functionDumper.createdFile)
|
||||||
|
RemanConfig.INSTANCE.touchCMakeTimestamp();
|
||||||
|
|
||||||
|
globalDumper.dumpGlobals();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
GhidraScripts/DumpCurrentFunctionFix.java
Normal file
39
GhidraScripts/DumpCurrentFunctionFix.java
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
// Script to export decompiled C code for selected function from Ghidra as Fix type
|
||||||
|
// @category _Reman3
|
||||||
|
// @menupath Reman3.Dump Current Function (Fix)
|
||||||
|
// @importpackage org.sqlite
|
||||||
|
|
||||||
|
import ghidra.app.script.GhidraScript;
|
||||||
|
import ghidra.program.model.listing.Function;
|
||||||
|
import re3lib.FunctionDumper;
|
||||||
|
import re3lib.GlobalDumper;
|
||||||
|
import re3lib.RemanConfig;
|
||||||
|
import re3lib.FunctionDatabase;
|
||||||
|
|
||||||
|
public class DumpCurrentFunctionFix extends GhidraScript {
|
||||||
|
@Override
|
||||||
|
public void run() throws Exception {
|
||||||
|
RemanConfig.INSTANCE = new RemanConfig(this);
|
||||||
|
RemanConfig.INSTANCE.createDirectories();
|
||||||
|
|
||||||
|
try (FunctionDatabase functionDatabase = new FunctionDatabase(this)) {
|
||||||
|
GlobalDumper globalDumper = new GlobalDumper(this, functionDatabase);
|
||||||
|
FunctionDumper functionDumper = new FunctionDumper(this, functionDatabase, globalDumper);
|
||||||
|
|
||||||
|
// Force Fix type instead of Auto
|
||||||
|
functionDumper.forceFixType = true;
|
||||||
|
|
||||||
|
Function currentFunction = getFunctionContaining(currentAddress);
|
||||||
|
if (currentFunction != null) {
|
||||||
|
functionDumper.dump(currentFunction);
|
||||||
|
} else {
|
||||||
|
println("No function found at the current address.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (functionDumper.createdFile)
|
||||||
|
RemanConfig.INSTANCE.touchCMakeTimestamp();
|
||||||
|
|
||||||
|
globalDumper.dumpGlobals();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
112
GhidraScripts/DumpCurrentFunctionN.java
Normal file
112
GhidraScripts/DumpCurrentFunctionN.java
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
// Decompile selected function recursively (until a given number of new functions is reached)
|
||||||
|
// @category _Reman3
|
||||||
|
// @menupath Reman3.Dump N Functions
|
||||||
|
// @importpackage org.sqlite
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import ghidra.app.script.GhidraScript;
|
||||||
|
import ghidra.pcodeCPort.address.Address;
|
||||||
|
import ghidra.program.model.listing.Function;
|
||||||
|
import re3lib.FunctionDatabase;
|
||||||
|
import re3lib.FunctionDumper;
|
||||||
|
import re3lib.GlobalDumper;
|
||||||
|
import re3lib.PCallTracer;
|
||||||
|
import re3lib.RemanConfig;
|
||||||
|
import re3lib.TypeDumper;
|
||||||
|
|
||||||
|
public class DumpCurrentFunctionN extends GhidraScript {
|
||||||
|
final int NumFunctions = 8;
|
||||||
|
|
||||||
|
// class Entry {
|
||||||
|
// Function function;
|
||||||
|
// }
|
||||||
|
// class QueueEntry {
|
||||||
|
// Function function;
|
||||||
|
// List<Function> callees;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// HashSet<Address> visited = new HashSet<>();
|
||||||
|
|
||||||
|
// QueueEntry enter(Function function) {
|
||||||
|
// if (visited.contains(function.getEntryPoint()))
|
||||||
|
// return null;
|
||||||
|
|
||||||
|
// visited.add(function.getEntryPoint());
|
||||||
|
|
||||||
|
// QueueEntry entry = new QueueEntry();
|
||||||
|
// entry.function = function;
|
||||||
|
|
||||||
|
// function.getCalledFunctions(monitor);
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() throws Exception {
|
||||||
|
RemanConfig.INSTANCE = new RemanConfig(this);
|
||||||
|
RemanConfig.INSTANCE.createDirectories();
|
||||||
|
|
||||||
|
try (FunctionDatabase functionDatabase = new FunctionDatabase(this)) {
|
||||||
|
|
||||||
|
GlobalDumper globalDumper = new GlobalDumper(this, functionDatabase);
|
||||||
|
|
||||||
|
FunctionDumper functionDumper = new FunctionDumper(this, functionDatabase, globalDumper);
|
||||||
|
|
||||||
|
PCallTracer tracer = new PCallTracer();
|
||||||
|
tracer.setBlacklist(functionDumper.functionAddrBlackList);
|
||||||
|
tracer.traceCalls(getFunctionContaining(currentAddress));
|
||||||
|
|
||||||
|
List<Address> queue = new ArrayList<>();
|
||||||
|
|
||||||
|
// List<Function> functionsToDump = new ArrayList<>();
|
||||||
|
// List<Function> functionsToDumpNew = new ArrayList<>();
|
||||||
|
// for (Function func : tracer.out) {
|
||||||
|
// if (FunctionDumper.isDumpedFix(func))
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
// println("Dump: " + func.getName());
|
||||||
|
// functionsToDump.add(func);
|
||||||
|
|
||||||
|
// if (!FunctionDumper.isDumpedAuto(func))
|
||||||
|
// functionsToDumpNew.add(func);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!functionsToDump.isEmpty()) {
|
||||||
|
// String newOpt = "Only new (" + functionsToDumpNew.size() + ")";
|
||||||
|
// String okOpt = "Yes (" + functionsToDump.size() + ")";
|
||||||
|
// String choice = askChoice("Confirmation", "About to generate " +
|
||||||
|
// functionsToDump.size() + " functions ("
|
||||||
|
// + functionsToDumpNew.size() + " new), continue?",
|
||||||
|
// new ArrayList<String>() {
|
||||||
|
// {
|
||||||
|
// add(okOpt);
|
||||||
|
// add(newOpt);
|
||||||
|
// add("No");
|
||||||
|
// }
|
||||||
|
// }, okOpt);
|
||||||
|
// if (choice == okOpt) {
|
||||||
|
// } else if (choice == newOpt) {
|
||||||
|
// functionsToDump = functionsToDumpNew;
|
||||||
|
// } else {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (Function func : functionsToDump) {
|
||||||
|
// functionDumper.dump(func);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (functionDumper.createdFile)
|
||||||
|
// RecompileConfig.INSTANCE.touchCMakeTimestamp();
|
||||||
|
|
||||||
|
// globalDumper.dumpGlobals();
|
||||||
|
// globalDumper.saveGlobalManifest();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Dump types
|
||||||
|
// TypeDumper dumper = new TypeDumper(this);
|
||||||
|
// dumper.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
91
GhidraScripts/DumpCurrentFunctionRecursive.java
Normal file
91
GhidraScripts/DumpCurrentFunctionRecursive.java
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
// Decompile selected function recursively
|
||||||
|
// @category _Reman3
|
||||||
|
// @menupath Reman3.Dump Current Function (recursive)
|
||||||
|
// @importpackage org.sqlite
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import ghidra.app.script.GhidraScript;
|
||||||
|
import ghidra.program.model.listing.Function;
|
||||||
|
import re3lib.FunctionDatabase;
|
||||||
|
import re3lib.FunctionDumper;
|
||||||
|
import re3lib.GlobalDumper;
|
||||||
|
import re3lib.PCallTracer;
|
||||||
|
import re3lib.RemanConfig;
|
||||||
|
import re3lib.TypeDumper;
|
||||||
|
|
||||||
|
public class DumpCurrentFunctionRecursive extends GhidraScript {
|
||||||
|
@Override
|
||||||
|
public void run() throws Exception {
|
||||||
|
RemanConfig.INSTANCE = new RemanConfig(this);
|
||||||
|
RemanConfig.INSTANCE.createDirectories();
|
||||||
|
|
||||||
|
try (FunctionDatabase functionDatabase = new FunctionDatabase(this)) {
|
||||||
|
GlobalDumper globalDumper = new GlobalDumper(this, functionDatabase);
|
||||||
|
|
||||||
|
FunctionDumper functionDumper = new FunctionDumper(this, functionDatabase, globalDumper);
|
||||||
|
|
||||||
|
PCallTracer tracer = new PCallTracer();
|
||||||
|
tracer.setBlacklist(functionDumper.functionAddrBlackList);
|
||||||
|
tracer.traceCalls(getFunctionContaining(currentAddress));
|
||||||
|
|
||||||
|
List<Function> functionsToDump = new ArrayList<>();
|
||||||
|
List<Function> functionsToDumpNew = new ArrayList<>();
|
||||||
|
for (Function func : tracer.out) {
|
||||||
|
List<FunctionDatabase.FunctionEntry> entries = functionDatabase.findEntriesByAddress(func.getEntryPoint());
|
||||||
|
boolean shouldDump = true;
|
||||||
|
boolean isNew = true;
|
||||||
|
for (FunctionDatabase.FunctionEntry entry : entries) {
|
||||||
|
if (entry.type == FunctionDatabase.Type.Fix) {
|
||||||
|
shouldDump = false;
|
||||||
|
}
|
||||||
|
if (entry.type == FunctionDatabase.Type.Fix || entry.type == FunctionDatabase.Type.Auto) {
|
||||||
|
isNew = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!shouldDump)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
println("Dump: " + func.getName());
|
||||||
|
functionsToDump.add(func);
|
||||||
|
|
||||||
|
if (isNew)
|
||||||
|
functionsToDumpNew.add(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!functionsToDump.isEmpty()) {
|
||||||
|
String newOpt = "Only new (" + functionsToDumpNew.size() + ")";
|
||||||
|
String okOpt = "Yes (" + functionsToDump.size() + ")";
|
||||||
|
String choice = askChoice("Confirmation", "About to generate " + functionsToDump.size() + " functions ("
|
||||||
|
+ functionsToDumpNew.size() + " new), continue?",
|
||||||
|
new ArrayList<String>() {
|
||||||
|
{
|
||||||
|
add(okOpt);
|
||||||
|
add(newOpt);
|
||||||
|
add("No");
|
||||||
|
}
|
||||||
|
}, okOpt);
|
||||||
|
if (choice == okOpt) {
|
||||||
|
} else if (choice == newOpt) {
|
||||||
|
functionsToDump = functionsToDumpNew;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Function func : functionsToDump) {
|
||||||
|
functionDumper.dump(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (functionDumper.createdFile)
|
||||||
|
RemanConfig.INSTANCE.touchCMakeTimestamp();
|
||||||
|
|
||||||
|
globalDumper.dumpGlobals();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dump types
|
||||||
|
TypeDumper dumper = new TypeDumper(this);
|
||||||
|
dumper.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
GhidraScripts/DumpGlobals.java
Normal file
26
GhidraScripts/DumpGlobals.java
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// Script to refresh all custom globals & types from Ghidra
|
||||||
|
// @category _Reman3
|
||||||
|
// @menupath Reman3.Redump Globals and Types
|
||||||
|
// @importpackage org.sqlite
|
||||||
|
|
||||||
|
import ghidra.app.script.GhidraScript;
|
||||||
|
import re3lib.GlobalDumper;
|
||||||
|
import re3lib.RemanConfig;
|
||||||
|
import re3lib.TypeDumper;
|
||||||
|
import re3lib.FunctionDatabase;
|
||||||
|
|
||||||
|
public class DumpGlobals extends GhidraScript {
|
||||||
|
@Override
|
||||||
|
protected void run() throws Exception {
|
||||||
|
RemanConfig.INSTANCE = new RemanConfig(this);
|
||||||
|
RemanConfig.INSTANCE.createDirectories();
|
||||||
|
|
||||||
|
try (FunctionDatabase functionDatabase = new FunctionDatabase(this)) {
|
||||||
|
GlobalDumper globalDumper = new GlobalDumper(this, functionDatabase);
|
||||||
|
globalDumper.dumpGlobals();
|
||||||
|
|
||||||
|
TypeDumper dumper = new TypeDumper(this);
|
||||||
|
dumper.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
// Script to dump all custom types from Ghidra
|
// Script to dump all custom types from Ghidra
|
||||||
// @category _Reman3
|
// @category _Reman3
|
||||||
// @menupath Reman3.Dump Types
|
// @menupath Reman3.Dump Types
|
||||||
|
// @importpackage org.sqlite
|
||||||
|
|
||||||
import ghidra.app.script.GhidraScript;
|
import ghidra.app.script.GhidraScript;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
// Exports binary read only and data segments to a binary + header file
|
// Exports binary read only and data segments to a binary + header file
|
||||||
// @category _Reman3
|
// @category _Reman3
|
||||||
// @menupath Tools.Reman3.Export Data
|
// @menupath Reman3.Export Data Segment
|
||||||
|
// @importpackage org.sqlite
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import ghidra.app.script.GhidraScript;
|
import ghidra.app.script.GhidraScript;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import re3lib.RecompileConfig;
|
import re3lib.RemanConfig;
|
||||||
|
|
||||||
public class ExportData extends GhidraScript {
|
public class ExportData extends GhidraScript {
|
||||||
|
|
||||||
@@ -16,16 +17,16 @@ public class ExportData extends GhidraScript {
|
|||||||
if (currentProgram == null) {
|
if (currentProgram == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RecompileConfig.INSTANCE = new RecompileConfig(this);
|
RemanConfig.INSTANCE = new RemanConfig(this);
|
||||||
|
|
||||||
String dataFile = new File(RecompileConfig.INSTANCE.outputDir, "gh_datasegment.bin").toString();
|
String dataFile = new File(RemanConfig.INSTANCE.outputDir, "gh_datasegment.bin").toString();
|
||||||
String headerFile = new File(RecompileConfig.INSTANCE.outputDir, "gh_datasegment.h").toString();
|
String headerFile = new File(RemanConfig.INSTANCE.outputDir, "gh_datasegment.h").toString();
|
||||||
|
|
||||||
FileOutputStream dataOutputStream = new FileOutputStream(dataFile);
|
FileOutputStream dataOutputStream = new FileOutputStream(dataFile);
|
||||||
PrintWriter headerWriter = new PrintWriter(headerFile, "UTF-8");
|
PrintWriter headerWriter = new PrintWriter(headerFile, "UTF-8");
|
||||||
|
|
||||||
Address startAddr = RecompileConfig.INSTANCE.staticMemoryBlockStart;
|
Address startAddr = RemanConfig.INSTANCE.staticMemoryBlockStart;
|
||||||
Address endAddr = RecompileConfig.INSTANCE.staticMemoryBlockEnd;
|
Address endAddr = RemanConfig.INSTANCE.staticMemoryBlockEnd;
|
||||||
|
|
||||||
// Dump all the memory to the bin file
|
// Dump all the memory to the bin file
|
||||||
int numBytes = (int) endAddr.subtract(startAddr);
|
int numBytes = (int) endAddr.subtract(startAddr);
|
||||||
448
GhidraScripts/FindRelocations.java
Normal file
448
GhidraScripts/FindRelocations.java
Normal file
@@ -0,0 +1,448 @@
|
|||||||
|
// Script to find hardcoded addresses in the binary that need to be relocated
|
||||||
|
// @category _Reman3
|
||||||
|
// @menupath Reman3.Find and dump Relocations
|
||||||
|
// @importpackage org.sqlite
|
||||||
|
|
||||||
|
import ghidra.app.script.GhidraScript;
|
||||||
|
import ghidra.program.model.listing.*;
|
||||||
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
|
import ghidra.program.model.address.*;
|
||||||
|
import ghidra.program.model.scalar.Scalar;
|
||||||
|
import ghidra.program.model.symbol.Reference;
|
||||||
|
import ghidra.program.model.pcode.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.io.*;
|
||||||
|
import re3lib.RemanConfig;
|
||||||
|
|
||||||
|
public class FindRelocations extends GhidraScript {
|
||||||
|
private Set<String> foundRelocations = new HashSet<>();
|
||||||
|
private PrintWriter outputFile;
|
||||||
|
|
||||||
|
long addrMin, addrMax;
|
||||||
|
|
||||||
|
private void analyzeInstruction(Instruction instruction) {
|
||||||
|
String mnemonic = instruction.getMnemonicString().toLowerCase();
|
||||||
|
|
||||||
|
boolean trace = instruction.getAddress().getOffset() == 0x004ac0f0;
|
||||||
|
if (trace) {
|
||||||
|
println("DEBUG: " + mnemonic + " at " + instruction.getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for instructions that commonly use absolute addresses
|
||||||
|
if (isRelocatableInstruction(mnemonic)) {
|
||||||
|
// Always run both analyses to catch all cases
|
||||||
|
// Pcode analysis is better for complex addressing, reference analysis catches
|
||||||
|
// simple cases
|
||||||
|
Set<String> foundAddresses = new HashSet<>();
|
||||||
|
|
||||||
|
analyzePcodeForConstants(instruction, trace, foundAddresses);
|
||||||
|
analyzeReferences(instruction, trace, foundAddresses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() throws Exception {
|
||||||
|
RemanConfig.INSTANCE = new RemanConfig(this);
|
||||||
|
RemanConfig.INSTANCE.createDirectories();
|
||||||
|
|
||||||
|
addrMin = RemanConfig.INSTANCE.staticMemoryBlockStart.getOffset();
|
||||||
|
addrMax = RemanConfig.INSTANCE.staticMemoryBlockEnd.getOffset();
|
||||||
|
|
||||||
|
// Create output file for relocations
|
||||||
|
File relocFile = new File(RemanConfig.INSTANCE.outputDir, "relocations.def");
|
||||||
|
outputFile = new PrintWriter(new FileWriter(relocFile));
|
||||||
|
|
||||||
|
try {
|
||||||
|
println("Counting instructions and data for progress tracking...");
|
||||||
|
|
||||||
|
// Count total work for progress monitoring
|
||||||
|
long totalInstructions = currentProgram.getListing().getNumInstructions();
|
||||||
|
long totalDataBytes = currentProgram.getMemory().getLoadedAndInitializedAddressSet().getNumAddresses();
|
||||||
|
long totalWork = totalInstructions + (totalDataBytes / currentProgram.getDefaultPointerSize());
|
||||||
|
|
||||||
|
monitor.initialize(totalWork);
|
||||||
|
monitor.setMessage("Scanning for relocations...");
|
||||||
|
|
||||||
|
println("Scanning " + totalInstructions + " instructions and " + totalDataBytes + " data bytes...");
|
||||||
|
|
||||||
|
// Get all instructions in the program
|
||||||
|
InstructionIterator instructions = currentProgram.getListing().getInstructions(true);
|
||||||
|
long processedInstructions = 0;
|
||||||
|
|
||||||
|
while (instructions.hasNext()) {
|
||||||
|
if (monitor.isCancelled()) {
|
||||||
|
println("Operation cancelled by user");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Instruction instruction = instructions.next();
|
||||||
|
analyzeInstruction(instruction);
|
||||||
|
|
||||||
|
// Check if we've gone past the end address
|
||||||
|
if (instruction.getAddress().getOffset() >= 0x00844190) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
processedInstructions++;
|
||||||
|
if (processedInstructions % 1000 == 0) {
|
||||||
|
monitor.setProgress(processedInstructions);
|
||||||
|
monitor.setMessage("Processed " + processedInstructions + "/" + totalInstructions + " instructions...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor.setProgress(totalInstructions);
|
||||||
|
monitor.setMessage("Analyzing data sections...");
|
||||||
|
|
||||||
|
// Also check data references
|
||||||
|
analyzeDataReferences(totalInstructions, totalWork);
|
||||||
|
|
||||||
|
monitor.setMessage("Scan complete");
|
||||||
|
println("Found " + foundRelocations.size() + " potential relocations");
|
||||||
|
println("Results saved to: " + relocFile.getAbsolutePath());
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
if (outputFile != null) {
|
||||||
|
outputFile.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void analyzePcodeForConstants(Instruction instruction, boolean trace, Set<String> foundAddresses) {
|
||||||
|
try {
|
||||||
|
// Get the pcode operations for this instruction
|
||||||
|
PcodeOp[] pcodeOps = instruction.getPcode();
|
||||||
|
|
||||||
|
if (trace) {
|
||||||
|
println("DEBUG: Analyzing pcode for " + instruction.getAddress());
|
||||||
|
for (PcodeOp op : pcodeOps) {
|
||||||
|
println("DEBUG: PcodeOp: " + op.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PcodeOp op : pcodeOps) {
|
||||||
|
// Look for constants in the pcode that look like addresses
|
||||||
|
Varnode[] inputs = op.getInputs();
|
||||||
|
for (Varnode input : inputs) {
|
||||||
|
if (input.isConstant()) {
|
||||||
|
long constantValue = input.getOffset();
|
||||||
|
|
||||||
|
// Check if this constant looks like an address in our target range
|
||||||
|
if (looksLikeAddress(constantValue)) {
|
||||||
|
if (trace) {
|
||||||
|
println("DEBUG: Found constant: 0x" + Long.toHexString(constantValue) + " that looks like an address");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Address targetAddr = currentProgram.getAddressFactory().getDefaultAddressSpace()
|
||||||
|
.getAddress(constantValue);
|
||||||
|
if (isInMainMemorySpace(targetAddr)) {
|
||||||
|
String addrKey = targetAddr.toString();
|
||||||
|
if (!foundAddresses.contains(addrKey)) {
|
||||||
|
// Find where this constant appears in the instruction bytes
|
||||||
|
int operandOffset = findAbsoluteAddressOffset(instruction, targetAddr, trace);
|
||||||
|
if (operandOffset >= 0) {
|
||||||
|
recordRelocation(instruction.getAddress(), targetAddr, instruction.getMnemonicString(),
|
||||||
|
"pcode_constant", operandOffset);
|
||||||
|
foundAddresses.add(addrKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (trace) {
|
||||||
|
println("DEBUG: Invalid address from constant: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Also check for address space references (like *[ram]0x77d4c8)
|
||||||
|
else if (input.isAddress() && input.getAddress() != null) {
|
||||||
|
long addressValue = input.getAddress().getOffset();
|
||||||
|
if (trace) {
|
||||||
|
println("DEBUG: Found address varnode: 0x" + Long.toHexString(addressValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (looksLikeAddress(addressValue)) {
|
||||||
|
try {
|
||||||
|
Address targetAddr = input.getAddress();
|
||||||
|
if (isInMainMemorySpace(targetAddr)) {
|
||||||
|
String addrKey = targetAddr.toString();
|
||||||
|
if (!foundAddresses.contains(addrKey)) {
|
||||||
|
int operandOffset = findAbsoluteAddressOffset(instruction, targetAddr, trace);
|
||||||
|
if (operandOffset >= 0) {
|
||||||
|
recordRelocation(instruction.getAddress(), targetAddr, instruction.getMnemonicString(),
|
||||||
|
"pcode_address", operandOffset);
|
||||||
|
foundAddresses.add(addrKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (trace) {
|
||||||
|
println("DEBUG: Invalid address from varnode: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (trace) {
|
||||||
|
println("DEBUG: Error analyzing pcode: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void analyzeReferences(Instruction instruction, boolean trace, Set<String> foundAddresses) {
|
||||||
|
// Check references from this instruction (original approach)
|
||||||
|
Reference[] refs = instruction.getReferencesFrom();
|
||||||
|
for (Reference ref : refs) {
|
||||||
|
Address toAddr = ref.getToAddress();
|
||||||
|
|
||||||
|
boolean isInMainMemorySpace = isInMainMemorySpace(toAddr);
|
||||||
|
if (trace) {
|
||||||
|
println("DEBUG: Reference to " + toAddr + " isInMainMemorySpace: " + isInMainMemorySpace);
|
||||||
|
}
|
||||||
|
if (isInMainMemorySpace) {
|
||||||
|
String addrKey = toAddr.toString();
|
||||||
|
if (!foundAddresses.contains(addrKey)) {
|
||||||
|
// Check if the target address appears in the instruction bytes (absolute
|
||||||
|
// addressing)
|
||||||
|
int operandOffset = findAbsoluteAddressOffset(instruction, toAddr, trace);
|
||||||
|
if (operandOffset >= 0) {
|
||||||
|
recordRelocation(instruction.getAddress(), toAddr, instruction.getMnemonicString(),
|
||||||
|
"reference_" + ref.getReferenceType().getName(), operandOffset);
|
||||||
|
foundAddresses.add(addrKey);
|
||||||
|
} else {
|
||||||
|
if (trace) {
|
||||||
|
println("DEBUG: operandOffset was not found: " + operandOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int findAbsoluteAddressOffset(Instruction instruction, Address targetAddr, boolean trace) {
|
||||||
|
try {
|
||||||
|
byte[] instructionBytes = instruction.getBytes();
|
||||||
|
long targetValue = targetAddr.getOffset();
|
||||||
|
|
||||||
|
// Convert target address to little-endian byte array (x86 32-bit)
|
||||||
|
byte[] targetBytes = new byte[4];
|
||||||
|
targetBytes[0] = (byte) (targetValue & 0xFF);
|
||||||
|
targetBytes[1] = (byte) ((targetValue >> 8) & 0xFF);
|
||||||
|
targetBytes[2] = (byte) ((targetValue >> 16) & 0xFF);
|
||||||
|
targetBytes[3] = (byte) ((targetValue >> 24) & 0xFF);
|
||||||
|
|
||||||
|
// Search for the target address bytes in the instruction and return offset
|
||||||
|
int offset = findSequenceOffset(instructionBytes, targetBytes, trace);
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (trace) {
|
||||||
|
println("findAbsoluteAddressOffset exception: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String bytesToHex(byte[] bytes) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < bytes.length; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
sb.append(" ");
|
||||||
|
sb.append(String.format("%02x", bytes[i] & 0xFF));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int findSequenceOffset(byte[] haystack, byte[] needle, boolean trace) {
|
||||||
|
if (trace) {
|
||||||
|
println("findSequenceOffset inspected bytes: " + bytesToHex(haystack) + " (length: " + haystack.length + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needle.length > haystack.length) {
|
||||||
|
if (trace) {
|
||||||
|
println("findSequenceOffset needle.length > haystack.length");
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i <= haystack.length - needle.length; i++) {
|
||||||
|
boolean found = true;
|
||||||
|
for (int j = 0; j < needle.length; j++) {
|
||||||
|
if (haystack[i + j] != needle[j]) {
|
||||||
|
found = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found) {
|
||||||
|
return i; // Return the offset where the sequence starts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isRelocatableInstruction(String mnemonic) {
|
||||||
|
// Instructions that commonly use absolute addresses
|
||||||
|
return true;
|
||||||
|
// mnemonic.equals("mov") || mnemonic.equals("lea") ||
|
||||||
|
// mnemonic.equals("call") || mnemonic.equals("jmp") ||
|
||||||
|
// mnemonic.equals("push") || mnemonic.equals("cmp") ||
|
||||||
|
// mnemonic.equals("test") || mnemonic.equals("add") ||
|
||||||
|
// mnemonic.equals("sub") || mnemonic.equals("and") ||
|
||||||
|
// mnemonic.equals("or") || mnemonic.equals("xor") ||
|
||||||
|
// mnemonic.startsWith("j"); // All jumps, we'll filter by byte analysis
|
||||||
|
}
|
||||||
|
|
||||||
|
private void analyzeDataReferences(long instructionsProcessed, long totalWork) {
|
||||||
|
// Only scan actual data sections, not code sections
|
||||||
|
MemoryBlock[] blocks = currentProgram.getMemory().getBlocks();
|
||||||
|
long processedBytes = 0;
|
||||||
|
int pointerSize = currentProgram.getDefaultPointerSize();
|
||||||
|
|
||||||
|
for (MemoryBlock block : blocks) {
|
||||||
|
// Skip executable blocks (code sections)
|
||||||
|
if (block.isExecute()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only scan initialized data blocks
|
||||||
|
if (!block.isInitialized()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (monitor.isCancelled()) {
|
||||||
|
println("Operation cancelled by user");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block.getName().equals(".rsrc")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
println("Scanning data block: " + block.getName() + " (" + block.getStart() + " - " + block.getEnd() + ")");
|
||||||
|
|
||||||
|
Address addr = block.getStart();
|
||||||
|
while (addr != null && addr.compareTo(block.getEnd()) <= 0) {
|
||||||
|
try {
|
||||||
|
// Check if this location contains a pointer-sized value
|
||||||
|
byte[] bytes = new byte[pointerSize];
|
||||||
|
currentProgram.getMemory().getBytes(addr, bytes);
|
||||||
|
|
||||||
|
long value = 0;
|
||||||
|
for (int i = 0; i < bytes.length; i++) {
|
||||||
|
value |= ((long) (bytes[i] & 0xFF)) << (i * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (looksLikeAddress(value)) {
|
||||||
|
try {
|
||||||
|
Address targetAddr = currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(value);
|
||||||
|
if (isInMainMemorySpace(targetAddr)) {
|
||||||
|
recordRelocation(addr, targetAddr, "data", "pointer", 0);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Invalid address, ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = addr.add(pointerSize);
|
||||||
|
processedBytes += pointerSize;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
addr = addr.add(1);
|
||||||
|
processedBytes++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isInMainMemorySpace(Address addr) {
|
||||||
|
if (addr == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check if address is in a loaded memory block
|
||||||
|
return currentProgram.getMemory().contains(addr) &&
|
||||||
|
!addr.getAddressSpace().isOverlaySpace();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean looksLikeAddress(long value) {
|
||||||
|
// Heuristic: check if value is in reasonable address range
|
||||||
|
// Adjust these ranges based on your target architecture
|
||||||
|
return value >= addrMin
|
||||||
|
&& value <= addrMax; // Typical executable range
|
||||||
|
}
|
||||||
|
|
||||||
|
private void recordRelocation(Address fromAddr, Address toAddr, String instruction, String type, int operandOffset) {
|
||||||
|
String relocKey = fromAddr.toString() + " -> " + toAddr.toString();
|
||||||
|
|
||||||
|
if (foundRelocations.add(relocKey)) {
|
||||||
|
String instructionBytes = getInstructionBytesString(fromAddr);
|
||||||
|
Address operandPtr = fromAddr.add(operandOffset);
|
||||||
|
|
||||||
|
String line = String.format("REL(0x%s, 0x%s, 0x%s) // %s [%s] | %s",
|
||||||
|
fromAddr.toString(),
|
||||||
|
operandPtr.toString(),
|
||||||
|
toAddr.toString(),
|
||||||
|
instruction,
|
||||||
|
type,
|
||||||
|
instructionBytes);
|
||||||
|
|
||||||
|
outputFile.println(line);
|
||||||
|
outputFile.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getInstructionBytesString(Address addr) {
|
||||||
|
try {
|
||||||
|
Instruction instruction = currentProgram.getListing().getInstructionAt(addr);
|
||||||
|
if (instruction != null) {
|
||||||
|
byte[] bytes = instruction.getBytes();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < bytes.length; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
sb.append(" ");
|
||||||
|
sb.append(String.format("%02x", bytes[i] & 0xFF));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
} else {
|
||||||
|
// This is a data reference, show the pointer bytes
|
||||||
|
byte[] bytes = new byte[4]; // Show 4 bytes for data
|
||||||
|
int bytesRead = currentProgram.getMemory().getBytes(addr, bytes);
|
||||||
|
if (bytesRead > 0) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < bytesRead; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
sb.append(" ");
|
||||||
|
sb.append(String.format("%02x", bytes[i] & 0xFF));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Check if this is in an initialized memory block
|
||||||
|
if (currentProgram.getMemory().contains(addr)) {
|
||||||
|
return "unreadable";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "??";
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isPartOfFunction(Address addr) {
|
||||||
|
// Check if there's an instruction at this address
|
||||||
|
Instruction instruction = currentProgram.getListing().getInstructionAt(addr);
|
||||||
|
if (instruction != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this address is within any function's body
|
||||||
|
Function function = currentProgram.getFunctionManager().getFunctionContaining(addr);
|
||||||
|
if (function != null) {
|
||||||
|
// Additional check: make sure we're in the function body, not just data
|
||||||
|
// referenced by it
|
||||||
|
AddressSetView functionBody = function.getBody();
|
||||||
|
return functionBody.contains(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
1009
GhidraScripts/PdbGen.java
Normal file
1009
GhidraScripts/PdbGen.java
Normal file
File diff suppressed because it is too large
Load Diff
38
GhidraScripts/RedumpStubFunctions.java
Normal file
38
GhidraScripts/RedumpStubFunctions.java
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
// Script to regenerate all dumped stub functions
|
||||||
|
// @category _Reman3
|
||||||
|
// @menupath Reman3.Redump Stub Functions
|
||||||
|
// @importpackage org.sqlite
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import ghidra.app.script.GhidraScript;
|
||||||
|
import ghidra.program.model.listing.Function;
|
||||||
|
import re3lib.GlobalDumper;
|
||||||
|
import re3lib.RemanConfig;
|
||||||
|
import re3lib.TypeDumper;
|
||||||
|
import re3lib.FunctionDatabase;
|
||||||
|
import re3lib.FunctionDumper;
|
||||||
|
|
||||||
|
public class RedumpStubFunctions extends GhidraScript {
|
||||||
|
@Override
|
||||||
|
protected void run() throws Exception {
|
||||||
|
RemanConfig.INSTANCE = new RemanConfig(this);
|
||||||
|
RemanConfig.INSTANCE.createDirectories();
|
||||||
|
|
||||||
|
try (FunctionDatabase functionDatabase = new FunctionDatabase(this)) {
|
||||||
|
List<FunctionDatabase.FunctionEntry> entries = functionDatabase.loadAllEntries();
|
||||||
|
FunctionDumper dumper = new FunctionDumper(this, functionDatabase, null);
|
||||||
|
for (FunctionDatabase.FunctionEntry entry : entries) {
|
||||||
|
if (entry.type == FunctionDatabase.Type.Stub) {
|
||||||
|
Function function = getFunctionAt(entry.address);
|
||||||
|
if (function == null) {
|
||||||
|
printerr("Function not found at address: " + entry.address);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// println("Dumping stub function: " + function.getName());
|
||||||
|
dumper.dumpStubFunction(function, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
GhidraScripts/SanitizeGlobalSymbols.java
Normal file
25
GhidraScripts/SanitizeGlobalSymbols.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Script to sanitize global symbols in Ghidra
|
||||||
|
// @category _Reman3
|
||||||
|
// @menupath Reman3.Sanitize Global Symbols
|
||||||
|
// @importpackage org.sqlite
|
||||||
|
|
||||||
|
import ghidra.app.script.GhidraScript;
|
||||||
|
import re3lib.GlobalDumper;
|
||||||
|
import re3lib.RemanConfig;
|
||||||
|
import re3lib.FunctionDatabase;
|
||||||
|
|
||||||
|
public class SanitizeGlobalSymbols extends GhidraScript {
|
||||||
|
@Override
|
||||||
|
public void run() throws Exception {
|
||||||
|
RemanConfig.INSTANCE = new RemanConfig(this);
|
||||||
|
RemanConfig.INSTANCE.createDirectories();
|
||||||
|
|
||||||
|
try (FunctionDatabase functionDatabase = new FunctionDatabase(this)) {
|
||||||
|
GlobalDumper globalDumper = new GlobalDumper(this, functionDatabase);
|
||||||
|
|
||||||
|
globalDumper.sanitizeGlobalSymbols();
|
||||||
|
|
||||||
|
globalDumper.dumpGlobals();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
580
GhidraScripts/re3lib/DataTypeWriter.java
Normal file
580
GhidraScripts/re3lib/DataTypeWriter.java
Normal file
@@ -0,0 +1,580 @@
|
|||||||
|
// Source code is decompiled from a .class file using FernFlower decompiler.
|
||||||
|
package re3lib;
|
||||||
|
|
||||||
|
import ghidra.program.model.data.*;
|
||||||
|
import ghidra.program.model.data.Enum;
|
||||||
|
import ghidra.util.Msg;
|
||||||
|
import ghidra.util.exception.CancelledException;
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class DataTypeWriter {
|
||||||
|
public HashSet<String> requiredFunctionTypes;
|
||||||
|
public HashMap<String, FunctionDefinition> lazyFunctionTypeBlocks;
|
||||||
|
|
||||||
|
private static String[] INTEGRAL_TYPES = new String[] { "char", "short", "int", "long", "long long", "__int64",
|
||||||
|
"float", "double", "long double", "void" };
|
||||||
|
private static String[] INTEGRAL_MODIFIERS = new String[] { "signed", "unsigned", "const", "static", "volatile",
|
||||||
|
"mutable" };
|
||||||
|
private static String EOL = System.getProperty("line.separator");
|
||||||
|
|
||||||
|
private Writer writer;
|
||||||
|
private DataTypeManager dtm;
|
||||||
|
private DataOrganization dataOrganization;
|
||||||
|
private AnnotationHandler annotator;
|
||||||
|
private boolean cppStyleComments;
|
||||||
|
|
||||||
|
// Block represents a single data type declaration with its dependencies
|
||||||
|
private static class Block {
|
||||||
|
final DataType dataType;
|
||||||
|
final String code;
|
||||||
|
final Set<String> dependencies;
|
||||||
|
|
||||||
|
Block(DataType dataType, String code, Set<String> dependencies) {
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.code = code;
|
||||||
|
this.dependencies = new HashSet<>(dependencies);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataTypeWriter(DataTypeManager dtm, Writer writer) throws IOException {
|
||||||
|
this(dtm, writer, new DefaultAnnotationHandler());
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataTypeWriter(DataTypeManager dtm, Writer writer, boolean cppStyleComments) throws IOException {
|
||||||
|
this(dtm, writer, new DefaultAnnotationHandler(), cppStyleComments);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataTypeWriter(DataTypeManager dtm, Writer writer, AnnotationHandler annotator) throws IOException {
|
||||||
|
this(dtm, writer, annotator, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataTypeWriter(DataTypeManager dtm, Writer writer, AnnotationHandler annotator, boolean cppStyleComments)
|
||||||
|
throws IOException {
|
||||||
|
this.cppStyleComments = false;
|
||||||
|
this.dtm = dtm;
|
||||||
|
if (dtm != null) {
|
||||||
|
this.dataOrganization = dtm.getDataOrganization();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.dataOrganization == null) {
|
||||||
|
this.dataOrganization = DataOrganizationImpl.getDefaultOrganization();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.writer = writer;
|
||||||
|
this.annotator = annotator;
|
||||||
|
this.cppStyleComments = cppStyleComments;
|
||||||
|
this.requiredFunctionTypes = new HashSet<>();
|
||||||
|
this.lazyFunctionTypeBlocks = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String comment(String text) {
|
||||||
|
if (text == null) {
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
return this.cppStyleComments ? "// " + text : "/* " + text + " */";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(DataTypeManager dataTypeManager, TaskMonitor monitor) throws IOException, CancelledException {
|
||||||
|
this.write(dataTypeManager.getRootCategory(), monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(Category category, TaskMonitor monitor) throws IOException, CancelledException {
|
||||||
|
DataType[] dataTypes = category.getDataTypes();
|
||||||
|
this.write(dataTypes, monitor);
|
||||||
|
Category[] subCategories = category.getCategories();
|
||||||
|
Category[] var5 = subCategories;
|
||||||
|
int var6 = subCategories.length;
|
||||||
|
|
||||||
|
for (int var7 = 0; var7 < var6; ++var7) {
|
||||||
|
Category subCategory = var5[var7];
|
||||||
|
if (monitor.isCancelled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.write(subCategory, monitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(DataType[] dataTypes, TaskMonitor monitor) throws IOException, CancelledException {
|
||||||
|
write(Arrays.asList(dataTypes), monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(List<DataType> dataTypes, TaskMonitor monitor) throws IOException, CancelledException {
|
||||||
|
this.write(dataTypes, monitor, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(List<DataType> dataTypes, TaskMonitor monitor, boolean throwExceptionOnInvalidType)
|
||||||
|
throws IOException, CancelledException {
|
||||||
|
monitor.initialize((long) dataTypes.size());
|
||||||
|
|
||||||
|
// Step 1: Create blocks for each data type
|
||||||
|
Map<String, Block> blocks = new HashMap<>();
|
||||||
|
|
||||||
|
int cnt = 0;
|
||||||
|
for (DataType dataType : dataTypes) {
|
||||||
|
monitor.checkCancelled();
|
||||||
|
|
||||||
|
if (dataType == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Block block = createBlock(dataType);
|
||||||
|
if (block != null) {
|
||||||
|
blocks.put(dataType.getDisplayName(), block);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (throwExceptionOnInvalidType) {
|
||||||
|
throw new IOException("Failed to process data type: " + dataType.getDisplayName(), e);
|
||||||
|
}
|
||||||
|
Msg.error(this, "Failed to process data type: " + dataType.getDisplayName(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
++cnt;
|
||||||
|
monitor.setProgress((long) cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: Check if we're missing any function type typedefs
|
||||||
|
for (String funcName : requiredFunctionTypes) {
|
||||||
|
if (!blocks.containsKey(funcName)) {
|
||||||
|
FunctionDefinition funcType = lazyFunctionTypeBlocks.get(funcName);
|
||||||
|
|
||||||
|
Set<String> dependencies = new HashSet<>();
|
||||||
|
StringBuilder code = new StringBuilder();
|
||||||
|
this.writeFunctionDefinitionBlock(funcType, funcName, code, dependencies);
|
||||||
|
blocks.put(funcName, new Block(funcType, code.toString(), dependencies));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3: Topological sort and write
|
||||||
|
List<Block> sortedBlocks = topologicalSort(blocks);
|
||||||
|
for (Block block : sortedBlocks) {
|
||||||
|
writer.write(block.code);
|
||||||
|
writer.write(EOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Block createBlock(DataType dt) throws IOException {
|
||||||
|
if (dt instanceof FactoryDataType) {
|
||||||
|
return null; // Skip only factory types
|
||||||
|
}
|
||||||
|
|
||||||
|
dt = dt.clone(this.dtm);
|
||||||
|
Set<String> dependencies = new HashSet<>();
|
||||||
|
StringBuilder code = new StringBuilder();
|
||||||
|
|
||||||
|
// if (dt.getDisplayName().contains("HIE_tduLinkedObject")) {
|
||||||
|
// System.out.println("DEBUG " + dt.getDisplayName());
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (dt.equals(DataType.DEFAULT)) {
|
||||||
|
code.append("typedef unsigned char ").append(DataType.DEFAULT.getName()).append(";");
|
||||||
|
} else if (dt instanceof Dynamic) {
|
||||||
|
// Handle dynamic types
|
||||||
|
Dynamic dynamicType = (Dynamic) dt;
|
||||||
|
DataType baseDt = dynamicType.getReplacementBaseType();
|
||||||
|
if (baseDt != null) {
|
||||||
|
dependencies.add(baseDt.getDisplayName());
|
||||||
|
}
|
||||||
|
code.append(comment("Dynamic type: " + dt.getDisplayName()));
|
||||||
|
} else if (dt instanceof Structure) {
|
||||||
|
writeStructureBlock((Structure) dt, code, dependencies);
|
||||||
|
} else if (dt instanceof Union) {
|
||||||
|
writeUnionBlock((Union) dt, code, dependencies);
|
||||||
|
} else if (dt instanceof Enum) {
|
||||||
|
if (dt.getDisplayName().contains(".conflict"))
|
||||||
|
return null;
|
||||||
|
writeEnumBlock((Enum) dt, code, dependencies);
|
||||||
|
} else if (dt instanceof TypeDef) {
|
||||||
|
writeTypeDefBlock((TypeDef) dt, code, dependencies);
|
||||||
|
} else if (dt instanceof BuiltInDataType) {
|
||||||
|
writeBuiltInBlock((BuiltInDataType) dt, code, dependencies);
|
||||||
|
} else if (dt instanceof FunctionDefinition) {
|
||||||
|
// Store these for later, a lot of them are going to be unused
|
||||||
|
lazyFunctionTypeBlocks.put(dt.getDisplayName(), (FunctionDefinition) dt);
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
code.append(comment("Unable to write datatype. Type unrecognized: " + dt.getClass()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Block(dt, code.toString(), dependencies);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeStructureBlock(Structure struct, StringBuilder code, Set<String> dependencies) {
|
||||||
|
String structName = struct.getDisplayName();
|
||||||
|
|
||||||
|
// Struct definition
|
||||||
|
code.append("struct ").append(structName).append(" {");
|
||||||
|
String descrip = struct.getDescription();
|
||||||
|
if (descrip != null && descrip.length() > 0) {
|
||||||
|
code.append(" ").append(comment(descrip));
|
||||||
|
}
|
||||||
|
code.append(EOL);
|
||||||
|
|
||||||
|
// Process components
|
||||||
|
for (DataTypeComponent component : struct.getComponents()) {
|
||||||
|
writeComponentBlock(component, struct, code, dependencies);
|
||||||
|
}
|
||||||
|
|
||||||
|
code.append(annotator.getSuffix(struct, null));
|
||||||
|
code.append("};");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeUnionBlock(Union union, StringBuilder code, Set<String> dependencies) {
|
||||||
|
String unionName = union.getDisplayName();
|
||||||
|
|
||||||
|
// Union definition (no forward declaration needed - let dependency ordering
|
||||||
|
// handle it)
|
||||||
|
code.append("union ").append(unionName).append(" {");
|
||||||
|
String descrip = union.getDescription();
|
||||||
|
if (descrip != null && descrip.length() > 0) {
|
||||||
|
code.append(" ").append(comment(descrip));
|
||||||
|
}
|
||||||
|
code.append(EOL);
|
||||||
|
|
||||||
|
// Process components
|
||||||
|
for (DataTypeComponent component : union.getComponents()) {
|
||||||
|
writeComponentBlock(component, union, code, dependencies);
|
||||||
|
}
|
||||||
|
|
||||||
|
code.append(annotator.getSuffix(union, null));
|
||||||
|
code.append("};");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeComponentBlock(DataTypeComponent component, Composite composite, StringBuilder code,
|
||||||
|
Set<String> dependencies) {
|
||||||
|
code.append(" ");
|
||||||
|
code.append(annotator.getPrefix(composite, component));
|
||||||
|
|
||||||
|
String fieldName = component.getFieldName();
|
||||||
|
String originalName = fieldName;
|
||||||
|
boolean needsFixing = fieldName != null && fieldName.contains("?");
|
||||||
|
if (fieldName == null || fieldName.length() == 0 || needsFixing) {
|
||||||
|
fieldName = component.getDefaultFieldName();
|
||||||
|
}
|
||||||
|
|
||||||
|
DataType componentDataType = component.getDataType();
|
||||||
|
|
||||||
|
DataType depType = getImmediateDependencyType(componentDataType);
|
||||||
|
if (depType != null) {
|
||||||
|
dependencies.add(depType.getDisplayName());
|
||||||
|
if (depType instanceof FunctionDefinition) {
|
||||||
|
requiredFunctionTypes.add(depType.getDisplayName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
code.append(getTypeDeclaration(fieldName, componentDataType, component.getLength()));
|
||||||
|
code.append(";");
|
||||||
|
code.append(annotator.getSuffix(composite, component));
|
||||||
|
|
||||||
|
String comment = component.getComment();
|
||||||
|
String commentText = comment != null && comment.length() > 0 ? comment : "";
|
||||||
|
if (needsFixing) {
|
||||||
|
commentText += (commentText.length() > 0 ? " " : "") + "(fix name \"" + originalName + "\")";
|
||||||
|
}
|
||||||
|
if (commentText.length() > 0) {
|
||||||
|
code.append(" ").append(comment(commentText));
|
||||||
|
}
|
||||||
|
code.append(EOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeEnumBlock(Enum enumm, StringBuilder code, Set<String> dependencies) {
|
||||||
|
String enumName = enumm.getDisplayName();
|
||||||
|
|
||||||
|
if (enumName.startsWith("define_") && enumName.length() > 7 && enumm.getCount() == 1) {
|
||||||
|
long val = enumm.getValues()[0];
|
||||||
|
code.append("#define ").append(enumName.substring(7)).append(" ").append(Long.toString(val));
|
||||||
|
} else {
|
||||||
|
code.append("enum ").append(enumName).append(" {");
|
||||||
|
String description = enumm.getDescription();
|
||||||
|
if (description != null && description.length() != 0) {
|
||||||
|
code.append(" ").append(comment(description));
|
||||||
|
}
|
||||||
|
code.append(EOL);
|
||||||
|
|
||||||
|
String[] names = enumm.getNames();
|
||||||
|
for (int j = 0; j < names.length; ++j) {
|
||||||
|
code.append(" ");
|
||||||
|
code.append(annotator.getPrefix(enumm, names[j]));
|
||||||
|
code.append(names[j]);
|
||||||
|
code.append("=");
|
||||||
|
code.append(Long.toString(enumm.getValue(names[j])));
|
||||||
|
String comment = enumm.getComment(names[j]);
|
||||||
|
if (!comment.isBlank()) {
|
||||||
|
code.append(" ").append(comment(comment));
|
||||||
|
}
|
||||||
|
code.append(annotator.getSuffix(enumm, names[j]));
|
||||||
|
if (j < names.length - 1) {
|
||||||
|
code.append(",");
|
||||||
|
}
|
||||||
|
code.append(EOL);
|
||||||
|
}
|
||||||
|
code.append("};");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean writeFunctionDefinitionBlock(FunctionDefinition funcDef, String name, StringBuilder code,
|
||||||
|
Set<String> dependencies) {
|
||||||
|
DataType returnType = funcDef.getReturnType();
|
||||||
|
ParameterDefinition[] params = funcDef.getArguments();
|
||||||
|
|
||||||
|
// Add return type dependency if not built-in
|
||||||
|
if (returnType != null && !isBuiltInType(returnType)) {
|
||||||
|
DataType depType = getImmediateDependencyType(returnType);
|
||||||
|
if (depType != null) {
|
||||||
|
dependencies.add(depType.getDisplayName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build function typedef
|
||||||
|
code.append("typedef ");
|
||||||
|
if (returnType != null) {
|
||||||
|
code.append(getTypeDeclaration("", returnType, -1)).append(" ");
|
||||||
|
} else {
|
||||||
|
code.append("void ");
|
||||||
|
}
|
||||||
|
|
||||||
|
code.append("(*").append(name).append(")(");
|
||||||
|
|
||||||
|
if (params != null && params.length > 0) {
|
||||||
|
for (int i = 0; i < params.length; i++) {
|
||||||
|
ParameterDefinition param = params[i];
|
||||||
|
DataType paramType = param.getDataType();
|
||||||
|
|
||||||
|
// Add parameter type dependency if not built-in
|
||||||
|
if (!isBuiltInType(paramType) && !isPointerType(paramType)) {
|
||||||
|
DataType depType = getImmediateDependencyType(paramType);
|
||||||
|
if (depType != null) {
|
||||||
|
dependencies.add(depType.getDisplayName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String paramName = param.getName();
|
||||||
|
if (paramName == null || paramName.isEmpty()) {
|
||||||
|
paramName = "param" + (i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
code.append(getTypeDeclaration(paramName, paramType, -1));
|
||||||
|
if (i < params.length - 1) {
|
||||||
|
code.append(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
code.append("void");
|
||||||
|
}
|
||||||
|
|
||||||
|
code.append(");");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean writeTypeDefBlock(TypeDef typeDef, StringBuilder code, Set<String> dependencies) {
|
||||||
|
String typedefName = typeDef.getDisplayName();
|
||||||
|
DataType dataType = typeDef.getDataType();
|
||||||
|
|
||||||
|
// Handle function definition typedefs
|
||||||
|
if (dataType instanceof FunctionDefinition) {
|
||||||
|
return writeFunctionDefinitionBlock((FunctionDefinition) dataType, typedefName, code, dependencies);
|
||||||
|
} // Could be pointer to function
|
||||||
|
else if (dataType instanceof Pointer) {
|
||||||
|
Pointer ptr = (Pointer) dataType;
|
||||||
|
if (ptr.getDataType() instanceof FunctionDefinition) {
|
||||||
|
return writeFunctionDefinitionBlock((FunctionDefinition) ((Pointer) dataType).getDataType(), typedefName, code,
|
||||||
|
dependencies);
|
||||||
|
} else {
|
||||||
|
// Try to write the typedef as a forward declaration
|
||||||
|
code.append("typedef ");
|
||||||
|
code.append(getTypeDeclaration(typedefName, dataType, -1));
|
||||||
|
code.append(";");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DataType depType = getImmediateDependencyType(dataType);
|
||||||
|
if (depType != null && !isBuiltInType(depType)) {
|
||||||
|
dependencies.add(depType.getDisplayName());
|
||||||
|
}
|
||||||
|
|
||||||
|
String typedefString = getTypeDeclaration(typedefName, dataType, -1);
|
||||||
|
code.append("typedef ").append(typedefString).append(";");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeBuiltInBlock(BuiltInDataType dt, StringBuilder code, Set<String> dependencies) {
|
||||||
|
String declaration = dt.getCTypeDeclaration(this.dataOrganization);
|
||||||
|
if (declaration != null) {
|
||||||
|
code.append(declaration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isPointerType(DataType dt) {
|
||||||
|
return dt instanceof Pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isBuiltInType(DataType dt) {
|
||||||
|
return dt instanceof BuiltInDataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DataType getImmediateDependencyType(DataType dt) {
|
||||||
|
// Only unwrap arrays and bitfields, but preserve typedefs and other types
|
||||||
|
while (dt != null) {
|
||||||
|
if (dt instanceof Array) {
|
||||||
|
dt = ((Array) dt).getDataType();
|
||||||
|
} else if (dt instanceof BitFieldDataType) {
|
||||||
|
dt = ((BitFieldDataType) dt).getBaseDataType();
|
||||||
|
} else if (dt instanceof Pointer) {
|
||||||
|
dt = ((Pointer) dt).getDataType();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getTypeDeclaration(String name, DataType dataType, int instanceLength) {
|
||||||
|
if (name == null) {
|
||||||
|
name = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
if (dataType instanceof BitFieldDataType) {
|
||||||
|
BitFieldDataType bfDt = (BitFieldDataType) dataType;
|
||||||
|
name = name + ":" + bfDt.getDeclaredBitSize();
|
||||||
|
dataType = bfDt.getBaseDataType();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle arrays and pointers
|
||||||
|
while (dataType instanceof Array) {
|
||||||
|
Array array = (Array) dataType;
|
||||||
|
name = name + "[" + array.getNumElements() + "]";
|
||||||
|
dataType = array.getDataType();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (dataType instanceof Pointer) {
|
||||||
|
Pointer pointer = (Pointer) dataType;
|
||||||
|
DataType elem = pointer.getDataType();
|
||||||
|
if (elem == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
name = "*" + name;
|
||||||
|
dataType = elem;
|
||||||
|
if (elem instanceof Array) {
|
||||||
|
name = "(" + name + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String prefix = getDataTypePrefix(dataType);
|
||||||
|
|
||||||
|
String dataTypeString;
|
||||||
|
if (dataType instanceof AbstractIntegerDataType) {
|
||||||
|
dataTypeString = ((AbstractIntegerDataType) dataType).getCDeclaration();
|
||||||
|
} else {
|
||||||
|
dataTypeString = dataType.getDisplayName();
|
||||||
|
}
|
||||||
|
|
||||||
|
String componentString = prefix + dataTypeString;
|
||||||
|
if (name.length() != 0) {
|
||||||
|
componentString = componentString + " " + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return componentString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getDataTypePrefix(DataType dataType) {
|
||||||
|
// Don't add struct/union prefix for typedefs - they already have their own name
|
||||||
|
if (dataType instanceof TypeDef) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only add struct/union prefix for direct struct/union references (not
|
||||||
|
// typedefs)
|
||||||
|
if (dataType instanceof Structure) {
|
||||||
|
return "struct ";
|
||||||
|
} else if (dataType instanceof Union) {
|
||||||
|
return "union ";
|
||||||
|
} else if (dataType instanceof Enum) {
|
||||||
|
return "enum ";
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isIntegral(String typedefName, String basetypeName) {
|
||||||
|
for (String type : INTEGRAL_TYPES) {
|
||||||
|
if (typedefName.equals(type)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean endsWithIntegralType = false;
|
||||||
|
for (String type : INTEGRAL_TYPES) {
|
||||||
|
if (typedefName.endsWith(" " + type)) {
|
||||||
|
endsWithIntegralType = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String modifier : INTEGRAL_MODIFIERS) {
|
||||||
|
if (typedefName.indexOf(modifier + " ") >= 0 || typedefName.indexOf(" " + modifier) >= 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endsWithIntegralType) {
|
||||||
|
return true;
|
||||||
|
} else if (typedefName.endsWith(" " + basetypeName)) {
|
||||||
|
return false; // Let it through as a regular typedef
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Block> topologicalSort(Map<String, Block> blocks) {
|
||||||
|
List<Block> result = new ArrayList<>();
|
||||||
|
Set<String> visited = new HashSet<>();
|
||||||
|
Set<String> visiting = new HashSet<>();
|
||||||
|
|
||||||
|
for (Block block : blocks.values()) {
|
||||||
|
if (!visited.contains(block.dataType.getDisplayName())) {
|
||||||
|
topologicalSortVisit(block, blocks, visited, visiting, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void topologicalSortVisit(Block block, Map<String, Block> blocks,
|
||||||
|
Set<String> visited, Set<String> visiting, List<Block> result) {
|
||||||
|
String blockName = block.dataType.getDisplayName();
|
||||||
|
|
||||||
|
if (visiting.contains(blockName)) {
|
||||||
|
// Circular dependency detected, but we'll continue (forward declarations should
|
||||||
|
// handle this)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visited.contains(blockName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
visiting.add(blockName);
|
||||||
|
|
||||||
|
// Visit dependencies first
|
||||||
|
for (String dep : block.dependencies) {
|
||||||
|
Block depBlock = blocks.get(dep);
|
||||||
|
if (depBlock != null) {
|
||||||
|
topologicalSortVisit(depBlock, blocks, visited, visiting, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
visiting.remove(blockName);
|
||||||
|
visited.add(blockName);
|
||||||
|
result.add(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
820
GhidraScripts/re3lib/FunctionDatabase.java
Normal file
820
GhidraScripts/re3lib/FunctionDatabase.java
Normal file
@@ -0,0 +1,820 @@
|
|||||||
|
package re3lib;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.sqlite.JDBC;
|
||||||
|
|
||||||
|
import ghidra.app.script.GhidraScript;
|
||||||
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.listing.Function;
|
||||||
|
|
||||||
|
public class FunctionDatabase implements AutoCloseable {
|
||||||
|
public static enum Type {
|
||||||
|
Auto(0),
|
||||||
|
Fix(1),
|
||||||
|
Stub(2),
|
||||||
|
Ref(3);
|
||||||
|
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
Type(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Type fromValue(int value) {
|
||||||
|
for (Type type : Type.values()) {
|
||||||
|
if (type.value == value) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unknown type value: " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum CallingConvention {
|
||||||
|
Cdecl(0),
|
||||||
|
Stdcall(1),
|
||||||
|
Fastcall(2);
|
||||||
|
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
CallingConvention(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CallingConvention fromValue(int value) {
|
||||||
|
for (CallingConvention conv : CallingConvention.values()) {
|
||||||
|
if (conv.value == value) {
|
||||||
|
return conv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unknown calling convention value: " + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CallingConvention fromString(String convStr) {
|
||||||
|
if (convStr == null) {
|
||||||
|
return Cdecl; // Default
|
||||||
|
}
|
||||||
|
|
||||||
|
String lower = convStr.toLowerCase();
|
||||||
|
if (lower.contains("fastcall")) {
|
||||||
|
return Fastcall;
|
||||||
|
} else if (lower.contains("stdcall")) {
|
||||||
|
return Stdcall;
|
||||||
|
} else {
|
||||||
|
return Cdecl; // Default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
switch (this) {
|
||||||
|
case Fastcall:
|
||||||
|
return "fastcall";
|
||||||
|
case Stdcall:
|
||||||
|
return "stdcall";
|
||||||
|
case Cdecl:
|
||||||
|
default:
|
||||||
|
return "cdecl";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FunctionEntry {
|
||||||
|
public Address address;
|
||||||
|
public String name;
|
||||||
|
public File file;
|
||||||
|
public Type type;
|
||||||
|
public CallingConvention callingConvention;
|
||||||
|
public String parameterNames; // Semicolon-separated parameter names
|
||||||
|
public String parameterTypes; // Semicolon-separated parameter types
|
||||||
|
public String returnType; // Function return type
|
||||||
|
|
||||||
|
public FunctionEntry(Address address, String name, File file, Type type, CallingConvention callingConvention,
|
||||||
|
String parameterNames, String parameterTypes, String returnType) {
|
||||||
|
this.address = address;
|
||||||
|
this.name = name;
|
||||||
|
this.file = file;
|
||||||
|
this.type = type;
|
||||||
|
this.callingConvention = callingConvention;
|
||||||
|
this.parameterNames = parameterNames != null ? parameterNames : "";
|
||||||
|
this.parameterTypes = parameterTypes != null ? parameterTypes : "";
|
||||||
|
this.returnType = returnType != null ? returnType : "void";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper methods to work with semicolon-separated parameter lists
|
||||||
|
public String[] getParameterNamesArray() {
|
||||||
|
if (parameterNames == null || parameterNames.trim().isEmpty()) {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
return parameterNames.split(";");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getParameterTypesArray() {
|
||||||
|
if (parameterTypes == null || parameterTypes.trim().isEmpty()) {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
return parameterTypes.split(";");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParameterNamesArray(String[] names) {
|
||||||
|
if (names == null || names.length == 0) {
|
||||||
|
this.parameterNames = "";
|
||||||
|
} else {
|
||||||
|
this.parameterNames = String.join(";", names);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParameterTypesArray(String[] types) {
|
||||||
|
if (types == null || types.length == 0) {
|
||||||
|
this.parameterTypes = "";
|
||||||
|
} else {
|
||||||
|
this.parameterTypes = String.join(";", types);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GlobalEntry {
|
||||||
|
public Address address;
|
||||||
|
public String name;
|
||||||
|
public File file;
|
||||||
|
|
||||||
|
public GlobalEntry(Address address, String name, File file) {
|
||||||
|
this.address = address;
|
||||||
|
this.name = name;
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private File dbFile;
|
||||||
|
private transient GhidraScript script;
|
||||||
|
private Connection connection;
|
||||||
|
|
||||||
|
// Prepared statements for better performance
|
||||||
|
private PreparedStatement findByNameFunctions;
|
||||||
|
private PreparedStatement findByNameImports;
|
||||||
|
private PreparedStatement findByAddressFunctions;
|
||||||
|
private PreparedStatement findByAddressImports;
|
||||||
|
private PreparedStatement insertOrReplaceFunctions;
|
||||||
|
private PreparedStatement insertOrReplaceImports;
|
||||||
|
private PreparedStatement deleteByFilepathFunctions;
|
||||||
|
private PreparedStatement deleteByFilepathImports;
|
||||||
|
private PreparedStatement loadAllFunctions;
|
||||||
|
private PreparedStatement loadAllImports;
|
||||||
|
|
||||||
|
// Add these prepared statements after the existing ones
|
||||||
|
private PreparedStatement findByNameGlobals;
|
||||||
|
private PreparedStatement findByAddressGlobals;
|
||||||
|
private PreparedStatement insertOrReplaceGlobals;
|
||||||
|
private PreparedStatement deleteByFilepathGlobals;
|
||||||
|
private PreparedStatement loadAllGlobals;
|
||||||
|
|
||||||
|
public FunctionDatabase(GhidraScript script) {
|
||||||
|
this.script = script;
|
||||||
|
dbFile = RemanConfig.INSTANCE.databasePath;
|
||||||
|
try {
|
||||||
|
java.sql.DriverManager.registerDriver(new JDBC());
|
||||||
|
} catch (SQLException e) {
|
||||||
|
script.printerr("Error registering JDBC driver: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect() throws Exception {
|
||||||
|
if (connection != null && !connection.isClosed()) {
|
||||||
|
return; // Already connected
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dbFile.exists()) {
|
||||||
|
script.println("Database file not found: " + dbFile);
|
||||||
|
// Create parent directories if they don't exist
|
||||||
|
dbFile.getParentFile().mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
connection = DriverManager.getConnection("jdbc:sqlite:" + dbFile.getAbsolutePath());
|
||||||
|
createTablesIfNotExist();
|
||||||
|
prepareCachedStatements();
|
||||||
|
script.println("Connected to database: " + dbFile);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
script.println("Error connecting to database: " + e.getMessage());
|
||||||
|
// throw new Exception("Failed to connect to database", e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disconnect() throws Exception {
|
||||||
|
if (connection != null && !connection.isClosed()) {
|
||||||
|
try {
|
||||||
|
// Close prepared statements
|
||||||
|
closePreparedStatements();
|
||||||
|
connection.close();
|
||||||
|
script.println("Disconnected from database");
|
||||||
|
} catch (SQLException e) {
|
||||||
|
script.println("Error disconnecting from database: " + e.getMessage());
|
||||||
|
throw new Exception("Failed to disconnect from database", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureConnection() throws Exception {
|
||||||
|
if (connection == null || connection.isClosed()) {
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prepareCachedStatements() throws SQLException {
|
||||||
|
// Find by name
|
||||||
|
findByNameFunctions = connection.prepareStatement(
|
||||||
|
"SELECT filepath, name, address, type, calling_convention, parameter_names, parameter_types, return_type FROM Functions WHERE name = ?");
|
||||||
|
findByNameImports = connection.prepareStatement(
|
||||||
|
"SELECT filepath, name, address, type, calling_convention, parameter_names, parameter_types, return_type FROM Imports WHERE name = ?");
|
||||||
|
|
||||||
|
// Find by address
|
||||||
|
findByAddressFunctions = connection.prepareStatement(
|
||||||
|
"SELECT filepath, name, address, type, calling_convention, parameter_names, parameter_types, return_type FROM Functions WHERE address = ?");
|
||||||
|
findByAddressImports = connection.prepareStatement(
|
||||||
|
"SELECT filepath, name, address, type, calling_convention, parameter_names, parameter_types, return_type FROM Imports WHERE address = ?");
|
||||||
|
|
||||||
|
// Insert or replace
|
||||||
|
insertOrReplaceFunctions = connection.prepareStatement(
|
||||||
|
"INSERT OR REPLACE INTO Functions (filepath, name, address, type, calling_convention, parameter_names, parameter_types, return_type) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
||||||
|
insertOrReplaceImports = connection.prepareStatement(
|
||||||
|
"INSERT OR REPLACE INTO Imports (filepath, name, address, type, calling_convention, parameter_names, parameter_types, return_type) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
||||||
|
|
||||||
|
// Delete by filepath
|
||||||
|
deleteByFilepathFunctions = connection.prepareStatement(
|
||||||
|
"DELETE FROM Functions WHERE filepath = ?");
|
||||||
|
deleteByFilepathImports = connection.prepareStatement(
|
||||||
|
"DELETE FROM Imports WHERE filepath = ?");
|
||||||
|
|
||||||
|
// Load all entries
|
||||||
|
loadAllFunctions = connection.prepareStatement(
|
||||||
|
"SELECT filepath, name, address, type, calling_convention, parameter_names, parameter_types, return_type FROM Functions");
|
||||||
|
loadAllImports = connection.prepareStatement(
|
||||||
|
"SELECT filepath, name, address, type, calling_convention, parameter_names, parameter_types, return_type FROM Imports");
|
||||||
|
|
||||||
|
// Global statements
|
||||||
|
findByNameGlobals = connection.prepareStatement(
|
||||||
|
"SELECT filepath, name, address FROM Globals WHERE name = ?");
|
||||||
|
findByAddressGlobals = connection.prepareStatement(
|
||||||
|
"SELECT filepath, name, address FROM Globals WHERE address = ?");
|
||||||
|
insertOrReplaceGlobals = connection.prepareStatement(
|
||||||
|
"INSERT OR REPLACE INTO Globals (filepath, name, address) VALUES (?, ?, ?)");
|
||||||
|
deleteByFilepathGlobals = connection.prepareStatement(
|
||||||
|
"DELETE FROM Globals WHERE filepath = ?");
|
||||||
|
loadAllGlobals = connection.prepareStatement(
|
||||||
|
"SELECT filepath, name, address FROM Globals");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void closePreparedStatements() throws SQLException {
|
||||||
|
if (findByNameFunctions != null)
|
||||||
|
findByNameFunctions.close();
|
||||||
|
if (findByNameImports != null)
|
||||||
|
findByNameImports.close();
|
||||||
|
if (findByAddressFunctions != null)
|
||||||
|
findByAddressFunctions.close();
|
||||||
|
if (findByAddressImports != null)
|
||||||
|
findByAddressImports.close();
|
||||||
|
if (insertOrReplaceFunctions != null)
|
||||||
|
insertOrReplaceFunctions.close();
|
||||||
|
if (insertOrReplaceImports != null)
|
||||||
|
insertOrReplaceImports.close();
|
||||||
|
if (deleteByFilepathFunctions != null)
|
||||||
|
deleteByFilepathFunctions.close();
|
||||||
|
if (deleteByFilepathImports != null)
|
||||||
|
deleteByFilepathImports.close();
|
||||||
|
if (loadAllFunctions != null)
|
||||||
|
loadAllFunctions.close();
|
||||||
|
if (loadAllImports != null)
|
||||||
|
loadAllImports.close();
|
||||||
|
|
||||||
|
if (findByNameGlobals != null)
|
||||||
|
findByNameGlobals.close();
|
||||||
|
if (findByAddressGlobals != null)
|
||||||
|
findByAddressGlobals.close();
|
||||||
|
if (insertOrReplaceGlobals != null)
|
||||||
|
insertOrReplaceGlobals.close();
|
||||||
|
if (deleteByFilepathGlobals != null)
|
||||||
|
deleteByFilepathGlobals.close();
|
||||||
|
if (loadAllGlobals != null)
|
||||||
|
loadAllGlobals.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<FunctionEntry> loadAllEntries() throws Exception {
|
||||||
|
ensureConnection();
|
||||||
|
List<FunctionEntry> entries = new ArrayList<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Load from Functions table
|
||||||
|
try (ResultSet rs = loadAllFunctions.executeQuery()) {
|
||||||
|
while (rs.next()) {
|
||||||
|
FunctionEntry entry = createEntryFromResultSet(rs);
|
||||||
|
if (entry != null) {
|
||||||
|
entries.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
script.println("Loaded " + entries.size() + " function entries from database");
|
||||||
|
return entries;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
script.println("Error loading entries: " + e.getMessage());
|
||||||
|
throw new Exception("Failed to load entries", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private FunctionEntry createEntryFromResultSet(ResultSet rs) throws SQLException {
|
||||||
|
String filepath = rs.getString("filepath");
|
||||||
|
String name = rs.getString("name");
|
||||||
|
String addressStr = rs.getString("address");
|
||||||
|
int typeValue = rs.getInt("type");
|
||||||
|
int callingConventionValue = rs.getInt("calling_convention");
|
||||||
|
String parameterNames = rs.getString("parameter_names");
|
||||||
|
String parameterTypes = rs.getString("parameter_types");
|
||||||
|
String returnType = rs.getString("return_type");
|
||||||
|
|
||||||
|
if (addressStr != null && !addressStr.isEmpty()) {
|
||||||
|
Address address = script.getCurrentProgram().getAddressFactory().getAddress(addressStr);
|
||||||
|
File file = new File(RemanConfig.INSTANCE.outputDir, filepath);
|
||||||
|
Type type = Type.fromValue(typeValue);
|
||||||
|
CallingConvention callingConvention = CallingConvention.fromValue(callingConventionValue);
|
||||||
|
|
||||||
|
return new FunctionEntry(address, name, file, type, callingConvention,
|
||||||
|
parameterNames, parameterTypes, returnType);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createTablesIfNotExist() throws SQLException {
|
||||||
|
String createFunctions = """
|
||||||
|
CREATE TABLE IF NOT EXISTS Functions (
|
||||||
|
filepath TEXT,
|
||||||
|
name TEXT,
|
||||||
|
address TEXT,
|
||||||
|
type INTEGER DEFAULT 0,
|
||||||
|
calling_convention INTEGER DEFAULT 0,
|
||||||
|
parameter_names TEXT DEFAULT '',
|
||||||
|
parameter_types TEXT DEFAULT '',
|
||||||
|
return_type TEXT DEFAULT '',
|
||||||
|
PRIMARY KEY (name, filepath)
|
||||||
|
)""";
|
||||||
|
|
||||||
|
String createImports = """
|
||||||
|
CREATE TABLE IF NOT EXISTS Imports (
|
||||||
|
filepath TEXT,
|
||||||
|
name TEXT,
|
||||||
|
address TEXT,
|
||||||
|
type INTEGER DEFAULT 0,
|
||||||
|
calling_convention INTEGER DEFAULT 0,
|
||||||
|
parameter_names TEXT DEFAULT '',
|
||||||
|
parameter_types TEXT DEFAULT '',
|
||||||
|
return_type TEXT DEFAULT '',
|
||||||
|
PRIMARY KEY (name, filepath)
|
||||||
|
)""";
|
||||||
|
|
||||||
|
String createGlobals = """
|
||||||
|
CREATE TABLE IF NOT EXISTS Globals (
|
||||||
|
filepath TEXT,
|
||||||
|
name TEXT,
|
||||||
|
address TEXT,
|
||||||
|
PRIMARY KEY (name, filepath)
|
||||||
|
)""";
|
||||||
|
|
||||||
|
connection.prepareStatement(createFunctions).executeUpdate();
|
||||||
|
connection.prepareStatement(createImports).executeUpdate();
|
||||||
|
connection.prepareStatement(createGlobals).executeUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method to find entries by name
|
||||||
|
public List<FunctionEntry> findEntriesByName(String name) throws Exception {
|
||||||
|
ensureConnection();
|
||||||
|
List<FunctionEntry> results = new ArrayList<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Search Functions table
|
||||||
|
findByNameFunctions.setString(1, name);
|
||||||
|
try (ResultSet rs = findByNameFunctions.executeQuery()) {
|
||||||
|
while (rs.next()) {
|
||||||
|
FunctionEntry entry = createEntryFromResultSet(rs);
|
||||||
|
if (entry != null) {
|
||||||
|
results.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search Imports table
|
||||||
|
findByNameImports.setString(1, name);
|
||||||
|
try (ResultSet rs = findByNameImports.executeQuery()) {
|
||||||
|
while (rs.next()) {
|
||||||
|
FunctionEntry entry = createEntryFromResultSet(rs);
|
||||||
|
if (entry != null) {
|
||||||
|
results.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
script.println("Error finding entries by name: " + e.getMessage());
|
||||||
|
throw new Exception("Failed to find entries by name", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method to find entries by address
|
||||||
|
public List<FunctionEntry> findEntriesByAddress(Address address) throws Exception {
|
||||||
|
ensureConnection();
|
||||||
|
List<FunctionEntry> results = new ArrayList<>();
|
||||||
|
String addressStr = address.toString();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Search Functions table
|
||||||
|
findByAddressFunctions.setString(1, addressStr);
|
||||||
|
try (ResultSet rs = findByAddressFunctions.executeQuery()) {
|
||||||
|
while (rs.next()) {
|
||||||
|
FunctionEntry entry = createEntryFromResultSet(rs);
|
||||||
|
if (entry != null) {
|
||||||
|
results.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search Imports table
|
||||||
|
findByAddressImports.setString(1, addressStr);
|
||||||
|
try (ResultSet rs = findByAddressImports.executeQuery()) {
|
||||||
|
while (rs.next()) {
|
||||||
|
FunctionEntry entry = createEntryFromResultSet(rs);
|
||||||
|
if (entry != null) {
|
||||||
|
results.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
script.println("Error finding entries by address: " + e.getMessage());
|
||||||
|
throw new Exception("Failed to find entries by address", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method to add/update entry (insert or replace based on filename)
|
||||||
|
public void addEntryAt(FunctionEntry entry) throws Exception {
|
||||||
|
ensureConnection();
|
||||||
|
|
||||||
|
String relativePath = new File(RemanConfig.INSTANCE.outputDir).toPath()
|
||||||
|
.relativize(entry.file.toPath()).toString().replace('\\', '/');
|
||||||
|
|
||||||
|
try {
|
||||||
|
insertOrReplaceFunctions.setString(1, relativePath);
|
||||||
|
insertOrReplaceFunctions.setString(2, entry.name);
|
||||||
|
insertOrReplaceFunctions.setString(3, entry.address.toString());
|
||||||
|
insertOrReplaceFunctions.setInt(4, entry.type.getValue());
|
||||||
|
insertOrReplaceFunctions.setInt(5, entry.callingConvention.getValue());
|
||||||
|
insertOrReplaceFunctions.setString(6, entry.parameterNames);
|
||||||
|
insertOrReplaceFunctions.setString(7, entry.parameterTypes);
|
||||||
|
insertOrReplaceFunctions.setString(8, entry.returnType);
|
||||||
|
insertOrReplaceFunctions.executeUpdate();
|
||||||
|
|
||||||
|
script.println("Added/updated entry: " + entry.name + " at " + entry.address + " in " + relativePath
|
||||||
|
+ " (calling convention: " + entry.callingConvention + ", return type: " + entry.returnType + ")");
|
||||||
|
} catch (SQLException e) {
|
||||||
|
script.println("Error adding entry: " + e.getMessage());
|
||||||
|
throw new Exception("Failed to add entry", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method to add import entry
|
||||||
|
public void addImportEntry(FunctionEntry entry) throws Exception {
|
||||||
|
ensureConnection();
|
||||||
|
|
||||||
|
String relativePath = new File(RemanConfig.INSTANCE.outputDir).toPath()
|
||||||
|
.relativize(entry.file.toPath()).toString().replace('\\', '/');
|
||||||
|
|
||||||
|
try {
|
||||||
|
insertOrReplaceImports.setString(1, relativePath);
|
||||||
|
insertOrReplaceImports.setString(2, entry.name);
|
||||||
|
insertOrReplaceImports.setString(3, entry.address.toString());
|
||||||
|
insertOrReplaceImports.setInt(4, entry.type.getValue());
|
||||||
|
insertOrReplaceImports.setInt(5, entry.callingConvention.getValue());
|
||||||
|
insertOrReplaceImports.setString(6, entry.parameterNames);
|
||||||
|
insertOrReplaceImports.setString(7, entry.parameterTypes);
|
||||||
|
insertOrReplaceImports.setString(8, entry.returnType);
|
||||||
|
insertOrReplaceImports.executeUpdate();
|
||||||
|
|
||||||
|
script.println("Added/updated import entry: " + entry.name + " at " + entry.address + " in " + relativePath
|
||||||
|
+ " (calling convention: " + entry.callingConvention + ", return type: " + entry.returnType + ")");
|
||||||
|
} catch (SQLException e) {
|
||||||
|
script.println("Error adding import entry: " + e.getMessage());
|
||||||
|
throw new Exception("Failed to add import entry", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method to remove entry by file path
|
||||||
|
public void removeEntryAt(String filePath) throws Exception {
|
||||||
|
ensureConnection();
|
||||||
|
|
||||||
|
String relativePath = new File(RemanConfig.INSTANCE.outputDir).toPath()
|
||||||
|
.relativize(new File(filePath).toPath()).toString().replace('\\', '/');
|
||||||
|
|
||||||
|
try {
|
||||||
|
deleteByFilepathFunctions.setString(1, relativePath);
|
||||||
|
int deletedCount = deleteByFilepathFunctions.executeUpdate();
|
||||||
|
|
||||||
|
deleteByFilepathImports.setString(1, relativePath);
|
||||||
|
deletedCount += deleteByFilepathImports.executeUpdate();
|
||||||
|
|
||||||
|
script.println("Removed " + deletedCount + " entries for file: " + relativePath);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
script.println("Error removing entries: " + e.getMessage());
|
||||||
|
throw new Exception("Failed to remove entries", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(FunctionEntry entry) throws Exception {
|
||||||
|
// Add entry directly to database
|
||||||
|
addEntryAt(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyDefaultFilters(boolean rebuildAllGlobals) throws Exception {
|
||||||
|
GlobalDumper globalDumper = new GlobalDumper(script, this);
|
||||||
|
FunctionDumper dumper = new FunctionDumper(script, this, globalDumper);
|
||||||
|
|
||||||
|
if (rebuildAllGlobals) {
|
||||||
|
globalDumper.removeGlobalManifest();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean madeAnyChanges = false;
|
||||||
|
|
||||||
|
// Load all entries from database
|
||||||
|
List<FunctionEntry> entries = loadAllEntries();
|
||||||
|
|
||||||
|
// Create a hash map to store symbol names
|
||||||
|
Map<Address, String> symbolNames = new HashMap<>();
|
||||||
|
Map<String, File> exportedFunctionNames = new HashMap<>();
|
||||||
|
for (FunctionEntry entry : entries) {
|
||||||
|
Function function = script.getFunctionAt(entry.address);
|
||||||
|
if (function != null) {
|
||||||
|
boolean isAuto = entry.type == Type.Auto;
|
||||||
|
boolean isFix = entry.type == Type.Fix;
|
||||||
|
// Get the actual symbol name and store it in the hash map
|
||||||
|
String symbolName = function.getName();
|
||||||
|
symbolNames.put(entry.address, symbolName);
|
||||||
|
|
||||||
|
if (isAuto && !exportedFunctionNames.containsKey(entry.name)) {
|
||||||
|
exportedFunctionNames.put(entry.name, entry.file);
|
||||||
|
} else if (isFix) {
|
||||||
|
exportedFunctionNames.replace(entry.name, entry.file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the number of symbol names collected
|
||||||
|
script.println("Collected " + symbolNames.size() + " symbol names");
|
||||||
|
|
||||||
|
boolean dryMode = false;
|
||||||
|
|
||||||
|
HashSet<Function> functionsToRegenerate = new HashSet<>();
|
||||||
|
|
||||||
|
Iterator<FunctionEntry> iterator = entries.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
FunctionEntry entry = iterator.next();
|
||||||
|
Function function = script.getFunctionAt(entry.address);
|
||||||
|
|
||||||
|
boolean pendingDelete = false;
|
||||||
|
boolean pendingRegenerate = false;
|
||||||
|
|
||||||
|
if (rebuildAllGlobals) {
|
||||||
|
pendingRegenerate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove CRT and other blacklisted functions
|
||||||
|
if (function == null || !dumper.isValidFunction(function)) {
|
||||||
|
// Remove the file
|
||||||
|
if (entry.file != null && entry.file.exists()) {
|
||||||
|
script.println("Removed file: " + entry.file.getAbsolutePath());
|
||||||
|
pendingDelete = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove entry from the list
|
||||||
|
script.println("Removed invalid function entry: " + entry.name + " at " + entry.address);
|
||||||
|
function = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if symbol name matches the symbol name parsed from the file
|
||||||
|
if (function != null) {
|
||||||
|
String actualSymbolName = symbolNames.get(entry.address);
|
||||||
|
if (actualSymbolName == null) {
|
||||||
|
throw new Exception(
|
||||||
|
"Symbol name not found for function at " + entry.address + " in file " + entry.file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actualSymbolName != null && !actualSymbolName.equals(entry.name)) {
|
||||||
|
File fnExportedFile = exportedFunctionNames.get(entry.name);
|
||||||
|
if (fnExportedFile != null && fnExportedFile != entry.file) {
|
||||||
|
// Already exists elsewhere, so remove this file
|
||||||
|
script.println("Removing duplicate function: " + entry.name + " at " + entry.address + " overridden by "
|
||||||
|
+ fnExportedFile);
|
||||||
|
pendingDelete = true;
|
||||||
|
} else {
|
||||||
|
// Regeneral this function
|
||||||
|
script.println("Symbol name mismatch for function at " + entry.address + ": " +
|
||||||
|
"File name: " + entry.name + ", Actual symbol: " + actualSymbolName);
|
||||||
|
entry.name = actualSymbolName; // Update the entry name to match the actual symbol
|
||||||
|
pendingRegenerate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.name = actualSymbolName; // Update the entry name to match the actual symbol
|
||||||
|
madeAnyChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pendingDelete) {
|
||||||
|
iterator.remove();
|
||||||
|
if (!dryMode) {
|
||||||
|
entry.file.delete();
|
||||||
|
// Remove from database
|
||||||
|
removeEntryAt(entry.file.getAbsolutePath());
|
||||||
|
madeAnyChanges = true;
|
||||||
|
}
|
||||||
|
} else if (pendingRegenerate && entry.type != Type.Stub) {
|
||||||
|
if (!dryMode) {
|
||||||
|
functionsToRegenerate.add(function);
|
||||||
|
// Update entry in database with corrected name
|
||||||
|
addEntryAt(entry);
|
||||||
|
madeAnyChanges = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Function function : functionsToRegenerate) {
|
||||||
|
script.println("Regenerating function: " + function.getName() + " at " + function.getEntryPoint());
|
||||||
|
dumper.dump(function);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (madeAnyChanges) {
|
||||||
|
// Update CMake timestamp
|
||||||
|
RemanConfig.INSTANCE.touchCMakeTimestamp();
|
||||||
|
globalDumper.dumpGlobals();
|
||||||
|
|
||||||
|
TypeDumper typeDumper = new TypeDumper(script);
|
||||||
|
typeDumper.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Global-specific methods
|
||||||
|
public List<GlobalEntry> loadAllGlobals() throws Exception {
|
||||||
|
ensureConnection();
|
||||||
|
List<GlobalEntry> globals = new ArrayList<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
try (ResultSet rs = loadAllGlobals.executeQuery()) {
|
||||||
|
while (rs.next()) {
|
||||||
|
GlobalEntry entry = createGlobalEntryFromResultSet(rs);
|
||||||
|
if (entry != null) {
|
||||||
|
globals.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
script.println("Loaded " + globals.size() + " global entries from database");
|
||||||
|
return globals;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
script.println("Error loading globals: " + e.getMessage());
|
||||||
|
throw new Exception("Failed to load globals", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private GlobalEntry createGlobalEntryFromResultSet(ResultSet rs) throws SQLException {
|
||||||
|
String filepath = rs.getString("filepath");
|
||||||
|
String name = rs.getString("name");
|
||||||
|
String addressStr = rs.getString("address");
|
||||||
|
|
||||||
|
if (addressStr != null && !addressStr.isEmpty()) {
|
||||||
|
Address address = script.getCurrentProgram().getAddressFactory().getAddress(addressStr);
|
||||||
|
File file = new File(RemanConfig.INSTANCE.outputDir, filepath);
|
||||||
|
|
||||||
|
return new GlobalEntry(address, name, file);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GlobalEntry> findGlobalsByName(String name) throws Exception {
|
||||||
|
ensureConnection();
|
||||||
|
List<GlobalEntry> results = new ArrayList<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
findByNameGlobals.setString(1, name);
|
||||||
|
try (ResultSet rs = findByNameGlobals.executeQuery()) {
|
||||||
|
while (rs.next()) {
|
||||||
|
GlobalEntry entry = createGlobalEntryFromResultSet(rs);
|
||||||
|
if (entry != null) {
|
||||||
|
results.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
script.println("Error finding globals by name: " + e.getMessage());
|
||||||
|
throw new Exception("Failed to find globals by name", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GlobalEntry> findGlobalsByAddress(Address address) throws Exception {
|
||||||
|
ensureConnection();
|
||||||
|
List<GlobalEntry> results = new ArrayList<>();
|
||||||
|
String addressStr = address.toString();
|
||||||
|
|
||||||
|
try {
|
||||||
|
findByAddressGlobals.setString(1, addressStr);
|
||||||
|
try (ResultSet rs = findByAddressGlobals.executeQuery()) {
|
||||||
|
while (rs.next()) {
|
||||||
|
GlobalEntry entry = createGlobalEntryFromResultSet(rs);
|
||||||
|
if (entry != null) {
|
||||||
|
results.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
script.println("Error finding globals by address: " + e.getMessage());
|
||||||
|
throw new Exception("Failed to find globals by address", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addGlobal(Address address, String name) throws Exception {
|
||||||
|
ensureConnection();
|
||||||
|
|
||||||
|
String filepath = RemanConfig.GLOBAL_H_FILE; // Default filepath for globals
|
||||||
|
String addressStr = address.toString();
|
||||||
|
|
||||||
|
try {
|
||||||
|
insertOrReplaceGlobals.setString(1, filepath);
|
||||||
|
insertOrReplaceGlobals.setString(2, name);
|
||||||
|
insertOrReplaceGlobals.setString(3, addressStr);
|
||||||
|
insertOrReplaceGlobals.executeUpdate();
|
||||||
|
|
||||||
|
script.println("Added/updated global: " + name + " at " + address);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
script.println("Error adding global: " + e.getMessage());
|
||||||
|
throw new Exception("Failed to add global", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeGlobalsByFilepath(String filePath) throws Exception {
|
||||||
|
ensureConnection();
|
||||||
|
|
||||||
|
String relativePath;
|
||||||
|
|
||||||
|
// Check if filePath is already a relative path or just a filename
|
||||||
|
File inputFile = new File(filePath);
|
||||||
|
if (inputFile.isAbsolute()) {
|
||||||
|
// Convert absolute path to relative
|
||||||
|
try {
|
||||||
|
relativePath = new File(RemanConfig.INSTANCE.outputDir).toPath()
|
||||||
|
.relativize(inputFile.toPath()).toString().replace('\\', '/');
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// Fallback if paths can't be relativized (different drives, etc.)
|
||||||
|
script.println("Warning: Could not relativize path: " + filePath + ", using as-is");
|
||||||
|
relativePath = filePath.replace('\\', '/');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Already relative or just a filename, use as-is
|
||||||
|
relativePath = filePath.replace('\\', '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
deleteByFilepathGlobals.setString(1, relativePath);
|
||||||
|
int deletedCount = deleteByFilepathGlobals.executeUpdate();
|
||||||
|
|
||||||
|
script.println("Removed " + deletedCount + " global entries for file: " + relativePath);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
script.println("Error removing global entries: " + e.getMessage());
|
||||||
|
throw new Exception("Failed to remove global entries", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws Exception {
|
||||||
|
this.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
513
GhidraScripts/re3lib/FunctionDumper.java
Normal file
513
GhidraScripts/re3lib/FunctionDumper.java
Normal file
@@ -0,0 +1,513 @@
|
|||||||
|
package re3lib;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import ghidra.app.decompiler.ClangLine;
|
||||||
|
import ghidra.app.decompiler.ClangSyntaxToken;
|
||||||
|
import ghidra.app.decompiler.ClangToken;
|
||||||
|
import ghidra.app.decompiler.DecompileResults;
|
||||||
|
import ghidra.app.decompiler.PrettyPrinter;
|
||||||
|
import ghidra.app.script.GhidraScript;
|
||||||
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.listing.Function;
|
||||||
|
import ghidra.program.model.pcode.HighFunction;
|
||||||
|
import ghidra.program.model.pcode.HighSymbol;
|
||||||
|
import ghidra.program.model.pcode.PcodeOp;
|
||||||
|
import ghidra.program.model.pcode.Varnode;
|
||||||
|
|
||||||
|
public class FunctionDumper {
|
||||||
|
GhidraScript script;
|
||||||
|
GlobalDumper globalDumper;
|
||||||
|
FunctionDatabase functionDatabase;
|
||||||
|
|
||||||
|
public HashSet<Address> functionAddrBlackList = new HashSet<>();
|
||||||
|
|
||||||
|
public boolean createdFile = false;
|
||||||
|
// Collects functions called by the current function
|
||||||
|
public HashSet<Function> functionReferences = new HashSet<>();
|
||||||
|
|
||||||
|
// Add flag to force Fix type
|
||||||
|
public boolean forceFixType = false;
|
||||||
|
|
||||||
|
static final Pattern fieldAccessRegex = Pattern.compile("^_([0-9]+)_([0-9]+)_$");
|
||||||
|
|
||||||
|
public FunctionDumper(GhidraScript script, FunctionDatabase functionDatabase, GlobalDumper globalDumper) {
|
||||||
|
this.script = script;
|
||||||
|
this.functionDatabase = functionDatabase;
|
||||||
|
this.globalDumper = globalDumper;
|
||||||
|
initFunctionBlacklist();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method to extract parameter names from Ghidra function
|
||||||
|
private String extractParameterNames(Function function) {
|
||||||
|
var parameters = function.getParameters();
|
||||||
|
if (parameters.length == 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder names = new StringBuilder();
|
||||||
|
for (int i = 0; i < parameters.length; i++) {
|
||||||
|
if (i > 0) names.append(";");
|
||||||
|
String paramName = parameters[i].getName();
|
||||||
|
names.append(paramName != null ? paramName : "param" + i);
|
||||||
|
}
|
||||||
|
return names.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method to extract parameter types from Ghidra function
|
||||||
|
private String extractParameterTypes(Function function) {
|
||||||
|
var parameters = function.getParameters();
|
||||||
|
if (parameters.length == 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder types = new StringBuilder();
|
||||||
|
for (int i = 0; i < parameters.length; i++) {
|
||||||
|
if (i > 0) types.append(";");
|
||||||
|
String paramType = parameters[i].getDataType().toString();
|
||||||
|
types.append(paramType != null ? paramType : "void*");
|
||||||
|
}
|
||||||
|
return types.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method to extract return type from Ghidra function
|
||||||
|
private String extractReturnType(Function function) {
|
||||||
|
var returnType = function.getReturnType();
|
||||||
|
return returnType != null ? returnType.getDisplayName() : "void";
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isValidFunction(Function function) {
|
||||||
|
if (functionAddrBlackList.contains(function.getEntryPoint()))
|
||||||
|
return false;
|
||||||
|
if (function.getComment() != null) {
|
||||||
|
if (function.getComment().startsWith("/i"))
|
||||||
|
return false;
|
||||||
|
if (function.getComment().startsWith("library function"))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (function.getName().startsWith("crt_"))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initFunctionBlacklist() {
|
||||||
|
functionAddrBlackList = Utils.loadFunctionBlacklist(RemanConfig.INSTANCE.functionBlacklistPath);
|
||||||
|
|
||||||
|
// Build blacklist if not loaded
|
||||||
|
if (functionAddrBlackList == null) {
|
||||||
|
boolean modified = false;
|
||||||
|
Iterator<Function> functionsIt = script.getCurrentProgram().getFunctionManager().getFunctions(true).iterator();
|
||||||
|
while (functionsIt.hasNext()) {
|
||||||
|
Function function = functionsIt.next();
|
||||||
|
if (functionAddrBlackList.contains(function.getEntryPoint())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String comment = function.getComment();
|
||||||
|
boolean isIgnoredFunction = false;
|
||||||
|
if (comment != null && comment.contains("Library Function")) {
|
||||||
|
script.println("Adding library function " + function.getName() + " to blacklist");
|
||||||
|
script.println("ac:" + functionAddrBlackList.size() + " jj:"
|
||||||
|
+ functionAddrBlackList.contains(function.getEntryPoint()) + " "
|
||||||
|
+ function.getEntryPoint());
|
||||||
|
isIgnoredFunction = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (function.getName().startsWith("crt_")) {
|
||||||
|
script.println("Adding crt function " + function.getName() + " to blacklist");
|
||||||
|
isIgnoredFunction = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isIgnoredFunction) {
|
||||||
|
// Decompile and trace
|
||||||
|
PCallTracer tracer = new PCallTracer();
|
||||||
|
tracer.setBlacklist(functionAddrBlackList);
|
||||||
|
tracer.traceCalls(function);
|
||||||
|
for (Function f : tracer.out) {
|
||||||
|
script.println(" Adding " + f.getName() + " to blacklist");
|
||||||
|
functionAddrBlackList.add(f.getEntryPoint());
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modified) {
|
||||||
|
Utils.saveFunctionBlacklist(functionAddrBlackList, RemanConfig.INSTANCE.functionBlacklistPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dumpStubFunction(Function externalFunction, boolean force) throws Exception {
|
||||||
|
String sanitizedExtFunctionName = Utils.sanitizeIdentifier(externalFunction.getName());
|
||||||
|
|
||||||
|
List<FunctionDatabase.FunctionEntry> entries1 = functionDatabase
|
||||||
|
.findEntriesByAddress(externalFunction.getEntryPoint());
|
||||||
|
boolean needStub = true;
|
||||||
|
if (!force) {
|
||||||
|
for (FunctionDatabase.FunctionEntry entry : entries1) {
|
||||||
|
if (entry.type == FunctionDatabase.Type.Auto || entry.type == FunctionDatabase.Type.Fix) {
|
||||||
|
needStub = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!needStub) {
|
||||||
|
script.println("Function exists for " + externalFunction.getName() + " - skipping generating stub");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String fileName = sanitizedExtFunctionName + ".cxx";
|
||||||
|
File f4 = new File(RemanConfig.INSTANCE.dirDecompStub, fileName);
|
||||||
|
script.println("Generating function stub for " + externalFunction.getName() + " => " + f4.toString());
|
||||||
|
|
||||||
|
// Extract calling convention from Ghidra function
|
||||||
|
String callingConventionName = externalFunction.getCallingConventionName();
|
||||||
|
FunctionDatabase.CallingConvention callingConvention = FunctionDatabase.CallingConvention
|
||||||
|
.fromString(callingConventionName);
|
||||||
|
script.println("Detected calling convention: " + callingConventionName + " -> " + callingConvention);
|
||||||
|
|
||||||
|
// Extract parameter information and return type
|
||||||
|
String parameterNames = extractParameterNames(externalFunction);
|
||||||
|
String parameterTypes = extractParameterTypes(externalFunction);
|
||||||
|
String returnType = extractReturnType(externalFunction);
|
||||||
|
|
||||||
|
try (PrintWriter writer2 = new PrintWriter(f4, "UTF-8")) {
|
||||||
|
writer2.println("// AUTO-GENERATED FILE!!!!");
|
||||||
|
writer2.println("// This function has yet to be decompiled using 'Dump Current Function' in ghidra");
|
||||||
|
writer2.println("// with possible manualy fixes");
|
||||||
|
writer2.println();
|
||||||
|
writer2.println("#include <r3/binders/auto.h>");
|
||||||
|
writer2.println("#include <r3/binders/stub.h>");
|
||||||
|
writer2.println("#include <gh_global.h>");
|
||||||
|
writer2.println();
|
||||||
|
writer2.println("// " + externalFunction.getEntryPoint());
|
||||||
|
writer2.println("// " + externalFunction.getName());
|
||||||
|
|
||||||
|
// Parse function signature to extract calling convention, return type, and
|
||||||
|
// parameters
|
||||||
|
String signature = externalFunction.getSignature().getPrototypeString(false);
|
||||||
|
signature = signature.replace(externalFunction.getName(), sanitizedExtFunctionName);
|
||||||
|
script.println("Santized Signature: " + signature);
|
||||||
|
|
||||||
|
// Generate function stub using appropriate forwarding function
|
||||||
|
writer2.println("extern \"C\" " + signature + " {");
|
||||||
|
|
||||||
|
// Determine which stub function to use based on calling convention
|
||||||
|
String stubFunction;
|
||||||
|
if (callingConvention == FunctionDatabase.CallingConvention.Stdcall) {
|
||||||
|
stubFunction = "gh_stub_impl_stdcall";
|
||||||
|
} else if (callingConvention == FunctionDatabase.CallingConvention.Fastcall) {
|
||||||
|
stubFunction = "gh_stub_impl_fastcall";
|
||||||
|
} else {
|
||||||
|
// Default to cdecl for most cases
|
||||||
|
stubFunction = "gh_stub_impl_cdecl";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate parameter list for the call
|
||||||
|
StringBuilder paramList = new StringBuilder();
|
||||||
|
var params = externalFunction.getParameters();
|
||||||
|
for (int i = 0; i < params.length; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
paramList.append(", ");
|
||||||
|
paramList.append(params[i].getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate the stub call
|
||||||
|
String addrString = "0x" +
|
||||||
|
externalFunction.getEntryPoint().toString().replace("0x", "");
|
||||||
|
if (returnType.equals("void")) {
|
||||||
|
writer2.println(" " + stubFunction + "<(stub_t)" + addrString + ", void>(" + paramList.toString() + ");");
|
||||||
|
} else {
|
||||||
|
writer2.println(" return " + stubFunction + "<(stub_t)" + addrString + ", " + returnType + ">(" +
|
||||||
|
paramList.toString() + ");");
|
||||||
|
}
|
||||||
|
|
||||||
|
writer2.println("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!f4.exists()) {
|
||||||
|
createdFile = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add stub function to database with calling convention and parameter information
|
||||||
|
FunctionDatabase.FunctionEntry newEntry = new FunctionDatabase.FunctionEntry(externalFunction.getEntryPoint(),
|
||||||
|
externalFunction.getName(), f4, FunctionDatabase.Type.Stub, callingConvention,
|
||||||
|
parameterNames, parameterTypes, returnType);
|
||||||
|
functionDatabase.addEntryAt(newEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dump(Function function)
|
||||||
|
throws Exception {
|
||||||
|
String sanitizedFunctionName = Utils.sanitizeIdentifier(function.getName());
|
||||||
|
String fileName = sanitizedFunctionName + ".cxx";
|
||||||
|
|
||||||
|
Address entrypoint = function.getEntryPoint();
|
||||||
|
List<FunctionDatabase.FunctionEntry> entries = functionDatabase.findEntriesByAddress(entrypoint);
|
||||||
|
FunctionDatabase.Type targetType = FunctionDatabase.Type.Auto;
|
||||||
|
|
||||||
|
// Extract calling convention from Ghidra function
|
||||||
|
String callingConventionName = function.getCallingConventionName();
|
||||||
|
FunctionDatabase.CallingConvention callingConvention = FunctionDatabase.CallingConvention
|
||||||
|
.fromString(callingConventionName);
|
||||||
|
script.println("Detected calling convention: " + callingConventionName + " -> " + callingConvention);
|
||||||
|
|
||||||
|
// Extract parameter information and return type
|
||||||
|
String parameterNames = extractParameterNames(function);
|
||||||
|
String parameterTypes = extractParameterTypes(function);
|
||||||
|
String returnType = extractReturnType(function);
|
||||||
|
|
||||||
|
script.println("Parameters: " + parameterNames + " | Types: " + parameterTypes + " | Return: " + returnType);
|
||||||
|
|
||||||
|
// Handle forceFixType flag
|
||||||
|
if (forceFixType) {
|
||||||
|
targetType = FunctionDatabase.Type.Fix;
|
||||||
|
|
||||||
|
// Remove any existing Auto entries for this function
|
||||||
|
for (FunctionDatabase.FunctionEntry entry : entries) {
|
||||||
|
if (entry.type == FunctionDatabase.Type.Auto) {
|
||||||
|
script.println("Removing existing Auto entry: " + entry.file);
|
||||||
|
if (entry.file.exists()) {
|
||||||
|
entry.file.delete();
|
||||||
|
}
|
||||||
|
functionDatabase.removeEntryAt(entry.file.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Original logic for determining target type
|
||||||
|
for (FunctionDatabase.FunctionEntry entry : entries) {
|
||||||
|
script.println("Found existing decompiled entry at " + entry.file + " - " + entry.name);
|
||||||
|
if (entry.type == FunctionDatabase.Type.Fix) {
|
||||||
|
targetType = FunctionDatabase.Type.Ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always remove stub entries regardless of mode
|
||||||
|
for (FunctionDatabase.FunctionEntry entry : entries) {
|
||||||
|
if (entry.type == FunctionDatabase.Type.Stub) {
|
||||||
|
// Remove the stub file, since we now use the decompiled file
|
||||||
|
File stubFile = entry.file;
|
||||||
|
if (stubFile.exists()) {
|
||||||
|
script.println("Removing function stub " + stubFile);
|
||||||
|
stubFile.delete();
|
||||||
|
createdFile = true;
|
||||||
|
functionDatabase.removeEntryAt(entry.file.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
File targetFilename = null;
|
||||||
|
if (targetType == FunctionDatabase.Type.Ref) {
|
||||||
|
targetFilename = new File(RemanConfig.INSTANCE.dirDecompRef, fileName);
|
||||||
|
} else if (targetType == FunctionDatabase.Type.Fix) {
|
||||||
|
targetFilename = new File(RemanConfig.INSTANCE.dirDecompFix, fileName);
|
||||||
|
} else {
|
||||||
|
targetFilename = new File(RemanConfig.INSTANCE.dirDecompAuto, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle overwrite prompting for Fix type
|
||||||
|
if (targetFilename.exists()) {
|
||||||
|
if (targetType == FunctionDatabase.Type.Fix) {
|
||||||
|
script.println("Fix file already exists: " + targetFilename);
|
||||||
|
boolean overwrite = script.askYesNo("Overwrite existing Fix file?",
|
||||||
|
"The Fix file " + targetFilename.getName() + " already exists. Do you want to overwrite it?");
|
||||||
|
if (!overwrite) {
|
||||||
|
script.println("Aborted: User chose not to overwrite existing Fix file.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
targetFilename.delete();
|
||||||
|
script.println("Overwriting existing file " + targetFilename);
|
||||||
|
} else {
|
||||||
|
createdFile = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
File f0 = targetFilename;
|
||||||
|
script.println("Processing " + function.getName() + " => " + f0.toString());
|
||||||
|
|
||||||
|
// Update database with calling convention and parameter information
|
||||||
|
FunctionDatabase.FunctionEntry newEntry = new FunctionDatabase.FunctionEntry(entrypoint, function.getName(), f0,
|
||||||
|
targetType, callingConvention, parameterNames, parameterTypes, returnType);
|
||||||
|
functionDatabase.addEntryAt(newEntry);
|
||||||
|
|
||||||
|
List<Function> externalFunctionCalls = new ArrayList<>();
|
||||||
|
HashMap<String, String> replacementMap = new HashMap<>();
|
||||||
|
|
||||||
|
String newFunctionName = sanitizedFunctionName;
|
||||||
|
if (callingConvention == FunctionDatabase.CallingConvention.Stdcall ||
|
||||||
|
callingConvention == FunctionDatabase.CallingConvention.Fastcall) {
|
||||||
|
newFunctionName = "__" + callingConvention.toString() + " " + newFunctionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
String originalFunctionName = function.getName();
|
||||||
|
if (newFunctionName != originalFunctionName) {
|
||||||
|
replacementMap.put(originalFunctionName, newFunctionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
DecompileResults decompRes = RemanConfig.INSTANCE.decompCache.getOrInsert(function);
|
||||||
|
try (PrintWriter writer2 = new PrintWriter(f0, "UTF-8")) {
|
||||||
|
writer2.println("// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!! ");
|
||||||
|
writer2.println();
|
||||||
|
writer2.println("#include <r3/binders/auto.h>");
|
||||||
|
writer2.println("#include <gh_global.h>");
|
||||||
|
writer2.println();
|
||||||
|
writer2.println("extern \"C\" {");
|
||||||
|
|
||||||
|
HighFunction highFunction = decompRes.getHighFunction();
|
||||||
|
|
||||||
|
HashSet<String> headers = new HashSet<>();
|
||||||
|
StringWriter codeWriter = new StringWriter();
|
||||||
|
|
||||||
|
PrettyPrinter pp = new PrettyPrinter(decompRes.getFunction(), decompRes.getCCodeMarkup(), null);
|
||||||
|
Iterator<ClangLine> lines = pp.getLines().iterator();
|
||||||
|
while (lines.hasNext()) {
|
||||||
|
ClangLine line = lines.next();
|
||||||
|
for (int i = 0; i < line.getIndent(); i++) {
|
||||||
|
codeWriter.write(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ClangToken> tokens = new ArrayList<>();
|
||||||
|
// Parse preliminary line tokens
|
||||||
|
for (int i = 0; i < line.getNumTokens(); i++) {
|
||||||
|
ClangToken token = line.getToken(i);
|
||||||
|
if (!token.getText().isEmpty())
|
||||||
|
tokens.add(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preprocess tokens
|
||||||
|
boolean prevDot = false;
|
||||||
|
for (int t = 0; t < tokens.size(); t++) {
|
||||||
|
ClangToken token = tokens.get(t);
|
||||||
|
|
||||||
|
boolean thisDot = false;
|
||||||
|
// script.println("Token: " + token.toString());
|
||||||
|
if (token.toString().equals(".")) {
|
||||||
|
// println("Found dot: " + token.toString() + " - " + token.getClass());
|
||||||
|
thisDot = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevDot) {
|
||||||
|
// println("Possible field access: " + token.getText());
|
||||||
|
if (token instanceof ClangSyntaxToken) {
|
||||||
|
// Parse _4_4_ sub-access using regex
|
||||||
|
String text = token.getText();
|
||||||
|
Matcher matcher = fieldAccessRegex.matcher(text);
|
||||||
|
if (matcher.matches()) {
|
||||||
|
int offset = Integer.parseInt(matcher.group(1));
|
||||||
|
int size = Integer.parseInt(matcher.group(2));
|
||||||
|
// println("MATCHED: " + token.getText() + " - " + token.getSyntaxType() + " - "
|
||||||
|
// + token.getVarnode() + " - "
|
||||||
|
// + token.getPcodeOp());
|
||||||
|
|
||||||
|
// Replace tokens with + Field<offset, size>
|
||||||
|
ClangToken replacement = new ClangToken(token.Parent(), " + Field<" + offset + ", " + size + ">()");
|
||||||
|
tokens.remove(t);
|
||||||
|
tokens.remove(t - 1);
|
||||||
|
tokens.add(t - 1, replacement);
|
||||||
|
t--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract memory references
|
||||||
|
HighSymbol gsym = token.getHighSymbol(highFunction);
|
||||||
|
if (gsym != null) {
|
||||||
|
var symStorage = gsym.getStorage();
|
||||||
|
var sym = gsym.getSymbol();
|
||||||
|
|
||||||
|
Address address;
|
||||||
|
if (symStorage.isUnassignedStorage()) {
|
||||||
|
address = sym.getAddress();
|
||||||
|
} else {
|
||||||
|
address = gsym.getStorage().getMinAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if it's a function pointer, otherwise add to globals
|
||||||
|
if (address.isMemoryAddress()) {
|
||||||
|
// script.println("Address: " + address + " - " + sym.getName());
|
||||||
|
Function maybeFunction = script.getFunctionAt(address);
|
||||||
|
if (maybeFunction != null) {
|
||||||
|
externalFunctionCalls.add(maybeFunction);
|
||||||
|
} else {
|
||||||
|
script.println("Add globals " + address + " - " + gsym.getName() + " - " + token.getText());
|
||||||
|
globalDumper.addGlobal(address, gsym);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract external function calls
|
||||||
|
PcodeOp op = token.getPcodeOp();
|
||||||
|
if (op != null && op.getOpcode() == PcodeOp.CALL) {
|
||||||
|
// println("PcodeOp: " + op.toString() + " - " + op.getInput(0).toString());
|
||||||
|
Varnode target = op.getInput(0);
|
||||||
|
if (target.isAddress()) {
|
||||||
|
Address callAddr = target.getAddress();
|
||||||
|
Function calledFunction = script.getFunctionAt(callAddr);
|
||||||
|
if (calledFunction != null) {
|
||||||
|
if (isValidFunction(calledFunction)) {
|
||||||
|
externalFunctionCalls.add(calledFunction);
|
||||||
|
String fname = calledFunction.getName();
|
||||||
|
String fsname = Utils.sanitizeIdentifier(fname);
|
||||||
|
if (fsname != fname) {
|
||||||
|
replacementMap.put(fname, fsname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prevDot = thisDot;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print tokens
|
||||||
|
for (int t = 0; t < tokens.size(); t++) {
|
||||||
|
ClangToken token = tokens.get(t);
|
||||||
|
codeWriter.write(token.toString());
|
||||||
|
}
|
||||||
|
codeWriter.write('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Function externalFunction : externalFunctionCalls) {
|
||||||
|
String proto = externalFunction.getSignature().getPrototypeString(false);
|
||||||
|
String name = externalFunction.getName();
|
||||||
|
proto = proto.replace(name, Utils.sanitizeIdentifier(name));
|
||||||
|
|
||||||
|
// Add calling convention information to the comment
|
||||||
|
String callingConv = externalFunction.getCallingConventionName();
|
||||||
|
FunctionDatabase.CallingConvention conv = FunctionDatabase.CallingConvention.fromString(callingConv);
|
||||||
|
|
||||||
|
headers.add("" + proto
|
||||||
|
+ "; // " + externalFunction.getEntryPoint() + " // "
|
||||||
|
+ name + " // " + conv);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String header : headers) {
|
||||||
|
writer2.println(header);
|
||||||
|
}
|
||||||
|
writer2.println();
|
||||||
|
writer2.print("// " + function.getEntryPoint());
|
||||||
|
String codeString = codeWriter.toString();
|
||||||
|
for (HashMap.Entry<String, String> entry : replacementMap.entrySet()) {
|
||||||
|
String oldName = entry.getKey();
|
||||||
|
String newName = entry.getValue();
|
||||||
|
codeString = codeString.replace(oldName, newName);
|
||||||
|
}
|
||||||
|
writer2.print(codeString);
|
||||||
|
writer2.println("}");
|
||||||
|
writer2.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Possibly generate stubs for external functions
|
||||||
|
for (Function externalFunction : externalFunctionCalls) {
|
||||||
|
dumpStubFunction(externalFunction, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,10 +22,9 @@ import ghidra.program.model.address.Address;
|
|||||||
import ghidra.program.model.data.AbstractStringDataType;
|
import ghidra.program.model.data.AbstractStringDataType;
|
||||||
import ghidra.program.model.data.Array;
|
import ghidra.program.model.data.Array;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.DataTypeManager;
|
import ghidra.program.model.data.FunctionDefinition;
|
||||||
import ghidra.program.model.data.DataTypePath;
|
import ghidra.program.model.data.Pointer;
|
||||||
import ghidra.program.model.data.PointerDataType;
|
import ghidra.program.model.data.PointerDataType;
|
||||||
import ghidra.program.model.data.Undefined;
|
|
||||||
import ghidra.program.model.listing.Data;
|
import ghidra.program.model.listing.Data;
|
||||||
import ghidra.program.model.pcode.HighSymbol;
|
import ghidra.program.model.pcode.HighSymbol;
|
||||||
import ghidra.program.model.symbol.SourceType;
|
import ghidra.program.model.symbol.SourceType;
|
||||||
@@ -48,91 +47,22 @@ public class GlobalDumper {
|
|||||||
};
|
};
|
||||||
|
|
||||||
GhidraScript script;
|
GhidraScript script;
|
||||||
File manifestFile;
|
FunctionDatabase functionDatabase;
|
||||||
HashMap<Address, GlobalRec> globalAddrs = new HashMap<>();
|
|
||||||
|
|
||||||
public GlobalDumper(GhidraScript script) {
|
public GlobalDumper(GhidraScript script, FunctionDatabase functionDatabase) {
|
||||||
this.script = script;
|
this.script = script;
|
||||||
manifestFile = new File(RecompileConfig.INSTANCE.outputDir, "globals.txt");
|
this.functionDatabase = functionDatabase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeGlobalManifest() {
|
public void removeGlobalManifest() {
|
||||||
if (manifestFile.exists()) {
|
// Remove globals from database
|
||||||
manifestFile.delete();
|
try {
|
||||||
|
functionDatabase.removeGlobalsByFilepath(RemanConfig.INSTANCE.GLOBAL_H_FILE);
|
||||||
|
} catch (Exception e) {
|
||||||
|
script.println("Error removing global manifest: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean loadGlobalManifest() throws Exception {
|
|
||||||
// Globals are stored in the format of
|
|
||||||
// <address> || <name> || <type>
|
|
||||||
|
|
||||||
if (!manifestFile.exists()) {
|
|
||||||
script.println("Global manifest file not found: " + manifestFile);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the dataTypeManagerService
|
|
||||||
DataTypeManagerService dataTypeManagerService = (DataTypeManagerService) script.getState().getTool()
|
|
||||||
.getService(DataTypeManagerService.class);
|
|
||||||
DataTypeManager dtm = script.getCurrentProgram().getDataTypeManager();
|
|
||||||
DataTypeParser dtp = new DataTypeParser(dataTypeManagerService, AllowedDataTypes.ALL);
|
|
||||||
try (BufferedReader reader = new BufferedReader(new FileReader(manifestFile))) {
|
|
||||||
String line;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
String[] parts = line.split("\\|\\|");
|
|
||||||
if (parts.length == 4) {
|
|
||||||
Address address = script.parseAddress(parts[0].trim());
|
|
||||||
String name = parts[1].trim();
|
|
||||||
String categoryPath = parts[2].trim();
|
|
||||||
String dataTypePath = parts[3].trim();
|
|
||||||
DataTypePath typePath = new DataTypePath(categoryPath, dataTypePath);
|
|
||||||
DataType type = null;
|
|
||||||
type = dtm.getDataType(typePath);
|
|
||||||
if (type == null) {
|
|
||||||
// script.println("Parsing type: " + dataTypePath);
|
|
||||||
type = dtp.parse(dataTypePath);
|
|
||||||
}
|
|
||||||
if (type == null) {
|
|
||||||
script.println("WARNING: Failed to find type: " + dataTypePath + " for global: " + name + " at " + address);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
globalAddrs.put(address, new GlobalRec(address, name, type));
|
|
||||||
} else {
|
|
||||||
script.println("Invalid global manifest line: " + line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
script.println("Loaded " + globalAddrs.size() + " globals from " + manifestFile);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addGlobal(Address addr, HighSymbol sym) throws Exception {
|
|
||||||
if (addr.compareTo(RecompileConfig.INSTANCE.staticMemoryBlockStart) < 0
|
|
||||||
|| addr.compareTo(RecompileConfig.INSTANCE.staticMemoryBlockEnd) > 0) {
|
|
||||||
throw new Exception("Global address out of range: " + addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
DataType dt = sym.getDataType();
|
|
||||||
// if(symb.get
|
|
||||||
if (sym.getDataType().getName() == "undefined") {
|
|
||||||
// script.println("UNDEFINED: " + addr + " - " + dt.getDisplayName() + " - " +
|
|
||||||
// dt.getClass().getName());
|
|
||||||
Data data = script.getDataAt(addr);
|
|
||||||
if (data != null) {
|
|
||||||
dt = data.getDataType();
|
|
||||||
// script.println("DATA: " + addr + " - " + dt.getDisplayName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dt == null) {
|
|
||||||
script.println("WARNING: Missing type for global: " + sym.getName() + " at " + addr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// script.println("Global: " + addr + " - " + sym.getName() + " - " +
|
|
||||||
// dt.getDisplayName());
|
|
||||||
globalAddrs.put(addr, new GlobalRec(addr, sym.getName(), dt));
|
|
||||||
}
|
|
||||||
|
|
||||||
String escapeCString(String str) {
|
String escapeCString(String str) {
|
||||||
str = str.replace("\\", "\\\\");
|
str = str.replace("\\", "\\\\");
|
||||||
str = str.replace("\"", "\\\"");
|
str = str.replace("\"", "\\\"");
|
||||||
@@ -162,20 +92,52 @@ public class GlobalDumper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void dumpGlobals() throws Exception {
|
public void dumpGlobals() throws Exception {
|
||||||
File globalSymbolsListH = new File(RecompileConfig.INSTANCE.outputDir, "gh_global.h");
|
File globalSymbolsListH = new File(RemanConfig.INSTANCE.outputDir, RemanConfig.GLOBAL_H_FILE);
|
||||||
PrintWriter hwriter = new PrintWriter(globalSymbolsListH, "UTF-8");
|
PrintWriter hwriter = new PrintWriter(globalSymbolsListH, "UTF-8");
|
||||||
hwriter.println("// AUTO-GENERATED FILE ");
|
hwriter.println("// AUTO-GENERATED FILE ");
|
||||||
Utils.headerGuardPre(hwriter, "GLOBALS");
|
Utils.headerGuardPre(hwriter, "GLOBALS");
|
||||||
hwriter.println("#include <r3/binders/global.h>");
|
hwriter.println("#include <r3/binders/global.h>");
|
||||||
hwriter.println();
|
hwriter.println();
|
||||||
|
|
||||||
File globalSymbolsListC = new File(RecompileConfig.INSTANCE.outputDir, "gh_global.cxx");
|
File globalSymbolsListC = new File(RemanConfig.INSTANCE.outputDir, RemanConfig.GLOBAL_CXX_FILE);
|
||||||
PrintWriter cwriter = new PrintWriter(globalSymbolsListC, "UTF-8");
|
PrintWriter cwriter = new PrintWriter(globalSymbolsListC, "UTF-8");
|
||||||
cwriter.println("// AUTO-GENERATED FILE ");
|
cwriter.println("// AUTO-GENERATED FILE ");
|
||||||
cwriter.println("#include <r3/binders/global.h>");
|
cwriter.println("#include <r3/binders/global.h>");
|
||||||
hwriter.println();
|
hwriter.println();
|
||||||
|
|
||||||
List<GlobalRec> globals = new ArrayList<>(globalAddrs.values());
|
// Load globals directly from database
|
||||||
|
List<FunctionDatabase.GlobalEntry> dbGlobals = functionDatabase.loadAllGlobals();
|
||||||
|
List<GlobalRec> globals = new ArrayList<>();
|
||||||
|
|
||||||
|
// Convert database entries to GlobalRec objects
|
||||||
|
for (FunctionDatabase.GlobalEntry entry : dbGlobals) {
|
||||||
|
DataType type = null;
|
||||||
|
|
||||||
|
// Try to get from existing data at address
|
||||||
|
Data data = script.getDataAt(entry.address);
|
||||||
|
if (data != null) {
|
||||||
|
type = data.getDataType();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == null) {
|
||||||
|
script.println("WARNING: Could not determine type for global: " + entry.name + " at " + entry.address);
|
||||||
|
// Get the dataTypeManagerService for parsing types
|
||||||
|
DataTypeManagerService dataTypeManagerService = (DataTypeManagerService) script.getState().getTool()
|
||||||
|
.getService(DataTypeManagerService.class);
|
||||||
|
DataTypeParser dtp = new DataTypeParser(dataTypeManagerService, AllowedDataTypes.ALL);
|
||||||
|
type = dtp.parse("undefined4");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve the current symbol name (may have changed since stored)
|
||||||
|
Symbol sym = script.getSymbolAt(entry.address);
|
||||||
|
String currentName = entry.name;
|
||||||
|
if (sym != null) {
|
||||||
|
currentName = sym.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
globals.add(new GlobalRec(entry.address, currentName, type));
|
||||||
|
}
|
||||||
|
|
||||||
globals.sort((o1, o2) -> o1.address.compareTo(o2.address));
|
globals.sort((o1, o2) -> o1.address.compareTo(o2.address));
|
||||||
|
|
||||||
for (GlobalRec global : globals) {
|
for (GlobalRec global : globals) {
|
||||||
@@ -203,11 +165,18 @@ public class GlobalDumper {
|
|||||||
// String type
|
// String type
|
||||||
initBlk += "\"" + escapeCString(readCString(addr, 2048)) + "\"";
|
initBlk += "\"" + escapeCString(readCString(addr, 2048)) + "\"";
|
||||||
fullyDefinedType = true;
|
fullyDefinedType = true;
|
||||||
} else if (dt instanceof PointerDataType) {
|
} else if (dt instanceof Pointer) {
|
||||||
PointerDataType pdt = (PointerDataType) dt;
|
DataType baseType = ((Pointer) dt).getDataType();
|
||||||
DataType baseType = pdt.getDataType();
|
if (baseType == null) {
|
||||||
dataType = baseType.getDisplayName() + "*";
|
script.println("WARNING: Missing base type for pointer: " + name + " at " + addr);
|
||||||
initBlk += "(" + dataType + ")&GH_MEM(0x" + addr + ")";
|
dataType = "pointer&";
|
||||||
|
} else if (baseType instanceof FunctionDefinition) {
|
||||||
|
script.println("Value is a function type " + name + " at " + addr);
|
||||||
|
dataType = ((FunctionDefinition) baseType).getDisplayName();
|
||||||
|
} else {
|
||||||
|
dataType = baseType.getDisplayName() + "*&";
|
||||||
|
}
|
||||||
|
initBlk += "(" + dataType + ")GH_MEM(0x" + addr + ")";
|
||||||
fullyDefinedType = true;
|
fullyDefinedType = true;
|
||||||
}
|
}
|
||||||
String linkagePrefix = "extern ";
|
String linkagePrefix = "extern ";
|
||||||
@@ -243,45 +212,58 @@ public class GlobalDumper {
|
|||||||
cwriter.close();
|
cwriter.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveGlobalManifest() throws Exception {
|
public void addGlobal(Address addr, HighSymbol sym) throws Exception {
|
||||||
File backupFile = new File(manifestFile.getParentFile(), manifestFile.getName() + ".bak");
|
if (sym.getName().equals("ExceptionList")) {
|
||||||
if (backupFile.exists()) {
|
return;
|
||||||
if (!backupFile.delete()) {
|
|
||||||
throw new Exception("Failed to delete backup file: " + backupFile + ", globals will not be saved!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (manifestFile.exists()) {
|
if (addr.compareTo(RemanConfig.INSTANCE.staticMemoryBlockStart) < 0
|
||||||
if (!manifestFile.renameTo(backupFile))
|
|| addr.compareTo(RemanConfig.INSTANCE.staticMemoryBlockEnd) > 0) {
|
||||||
throw new Exception("Failed to rename manifest file: " + manifestFile + ", globals will not be saved!");
|
throw new Exception("Global address out of range: " + addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
try (PrintWriter writer = new PrintWriter(manifestFile)) {
|
DataType dt = sym.getDataType();
|
||||||
script.println("Saving global manifest to " + manifestFile);
|
// if(symb.get
|
||||||
GlobalRec[] globals = globalAddrs.values().toArray(new GlobalRec[0]);
|
if (sym.getDataType().getName() == "undefined") {
|
||||||
Arrays.sort(globals, (a, b) -> a.address.compareTo(b.address));
|
// script.println("UNDEFINED: " + addr + " - " + dt.getDisplayName() + " - " +
|
||||||
for (GlobalRec global : globals) {
|
// dt.getClass().getName());
|
||||||
DataTypePath path = global.type.getDataTypePath();
|
Data data = script.getDataAt(addr);
|
||||||
writer.println(global.address.toString() + " || " + global.name + " || " + path.getCategoryPath() + " || "
|
if (data != null) {
|
||||||
+ path.getDataTypeName());
|
dt = data.getDataType();
|
||||||
|
// script.println("DATA: " + addr + " - " + dt.getDisplayName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (dt == null) {
|
||||||
|
script.println("WARNING: Missing type for global: " + sym.getName() + " at " + addr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// script.println("Global: " + addr + " - " + sym.getName() + " - " +
|
||||||
|
// dt.getDisplayName());
|
||||||
|
|
||||||
|
// Add directly to database instead of storing in memory
|
||||||
|
functionDatabase.addGlobal(addr, sym.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sanitizeGlobalSymbols() {
|
public void sanitizeGlobalSymbols() throws Exception {
|
||||||
for (GlobalRec global : globalAddrs.values()) {
|
// Load globals from database, sanitize symbol names, and update both Ghidra
|
||||||
String sanitizedName = Utils.sanitizeIdentifier(global.name);
|
// symbols and database
|
||||||
if (!sanitizedName.equals(global.name)) {
|
List<FunctionDatabase.GlobalEntry> dbGlobals = functionDatabase.loadAllGlobals();
|
||||||
Symbol symbol = script.getSymbolAt(global.address);
|
|
||||||
|
for (FunctionDatabase.GlobalEntry entry : dbGlobals) {
|
||||||
|
String sanitizedName = Utils.sanitizeIdentifier(entry.name);
|
||||||
|
if (!sanitizedName.equals(entry.name)) {
|
||||||
|
Symbol symbol = script.getSymbolAt(entry.address);
|
||||||
if (symbol != null) {
|
if (symbol != null) {
|
||||||
script.println("Renaming global symbol: " + global.name + " -> " + sanitizedName);
|
script.println("Renaming global symbol: " + entry.name + " -> " + sanitizedName);
|
||||||
AddLabelCmd cmd = new AddLabelCmd(global.address, sanitizedName,
|
AddLabelCmd cmd = new AddLabelCmd(entry.address, sanitizedName,
|
||||||
symbol.getParentNamespace(),
|
symbol.getParentNamespace(),
|
||||||
SourceType.USER_DEFINED);
|
SourceType.USER_DEFINED);
|
||||||
if (!cmd.applyTo(script.getCurrentProgram())) {
|
if (!cmd.applyTo(script.getCurrentProgram())) {
|
||||||
script.println("Error renaming symbol: " + cmd.getStatusMsg());
|
script.println("Error renaming symbol: " + cmd.getStatusMsg());
|
||||||
|
} else {
|
||||||
|
// Update the database with the new name
|
||||||
|
functionDatabase.addGlobal(entry.address, sanitizedName);
|
||||||
}
|
}
|
||||||
global.name = sanitizedName;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,7 +42,7 @@ public class PCallTracer {
|
|||||||
Program program;
|
Program program;
|
||||||
|
|
||||||
public PCallTracer() {
|
public PCallTracer() {
|
||||||
this.script = RecompileConfig.INSTANCE.script;
|
this.script = RemanConfig.INSTANCE.script;
|
||||||
this.program = this.script.getCurrentProgram();
|
this.program = this.script.getCurrentProgram();
|
||||||
// this.decomp = RecompileConfig.INSTANCE.decompCache;
|
// this.decomp = RecompileConfig.INSTANCE.decompCache;
|
||||||
}
|
}
|
||||||
@@ -10,13 +10,17 @@ import ghidra.program.flatapi.FlatProgramAPI;
|
|||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
|
||||||
public class RecompileConfig {
|
// A general configuration for the reman project
|
||||||
|
// including all paths, specific addresses and stuff
|
||||||
|
public class RemanConfig {
|
||||||
private static final String RECOMPILE_PREFIX = "game_re";
|
private static final String RECOMPILE_PREFIX = "game_re";
|
||||||
|
|
||||||
// Version control project root
|
// Version control project root
|
||||||
public final String rootDir;
|
public final String rootDir;
|
||||||
// The output directory for the recompiled game
|
// The output directory for the recompiled game
|
||||||
public final String outputDir;
|
public final String outputDir;
|
||||||
|
// The output directory for the original game
|
||||||
|
public final String originalDir;
|
||||||
public final String typeBlacklistPath;
|
public final String typeBlacklistPath;
|
||||||
public final String categoryPathBlacklistPath;
|
public final String categoryPathBlacklistPath;
|
||||||
public final String functionBlacklistPath;
|
public final String functionBlacklistPath;
|
||||||
@@ -24,6 +28,9 @@ public class RecompileConfig {
|
|||||||
public final Address staticMemoryBlockStart;
|
public final Address staticMemoryBlockStart;
|
||||||
public final Address staticMemoryBlockEnd;
|
public final Address staticMemoryBlockEnd;
|
||||||
|
|
||||||
|
// The path to the database file
|
||||||
|
public final File databasePath;
|
||||||
|
|
||||||
// The automatically decompiled files
|
// The automatically decompiled files
|
||||||
public final File dirDecompAuto;
|
public final File dirDecompAuto;
|
||||||
// The manually decompiled files (will not be overwritten by the auto
|
// The manually decompiled files (will not be overwritten by the auto
|
||||||
@@ -48,10 +55,13 @@ public class RecompileConfig {
|
|||||||
|
|
||||||
public final GhidraScript script;
|
public final GhidraScript script;
|
||||||
|
|
||||||
public static RecompileConfig INSTANCE;
|
public static RemanConfig INSTANCE;
|
||||||
|
|
||||||
public RecompileConfig(GhidraScript script) {
|
public static final String GLOBAL_H_FILE = "gh_global.h"; // Default filepath for globals
|
||||||
staticMemoryBlockStart = script.getCurrentProgram().getAddressFactory().getAddress("00597000");
|
public static final String GLOBAL_CXX_FILE = "gh_global.cxx"; // Default filepath for globals
|
||||||
|
|
||||||
|
public RemanConfig(GhidraScript script) {
|
||||||
|
staticMemoryBlockStart = script.getCurrentProgram().getAddressFactory().getAddress("00400000");
|
||||||
staticMemoryBlockEnd = script.getCurrentProgram().getAddressFactory().getAddress("00843fff");
|
staticMemoryBlockEnd = script.getCurrentProgram().getAddressFactory().getAddress("00843fff");
|
||||||
|
|
||||||
this.script = script;
|
this.script = script;
|
||||||
@@ -60,10 +70,14 @@ public class RecompileConfig {
|
|||||||
outputDir = new File(rootDir, RECOMPILE_PREFIX).toString();
|
outputDir = new File(rootDir, RECOMPILE_PREFIX).toString();
|
||||||
script.println("Output path: " + outputDir);
|
script.println("Output path: " + outputDir);
|
||||||
|
|
||||||
|
originalDir = new File(rootDir, "game").toString();
|
||||||
|
|
||||||
typeBlacklistPath = new File(outputDir, "type_blacklist.txt").toString();
|
typeBlacklistPath = new File(outputDir, "type_blacklist.txt").toString();
|
||||||
categoryPathBlacklistPath = new File(outputDir, "type_path_blacklist.txt").toString();
|
categoryPathBlacklistPath = new File(outputDir, "type_path_blacklist.txt").toString();
|
||||||
functionBlacklistPath = new File(outputDir, "function_blacklist.txt").toString();
|
functionBlacklistPath = new File(outputDir, "function_blacklist.txt").toString();
|
||||||
|
|
||||||
|
databasePath = new File(outputDir, "gh.db");
|
||||||
|
|
||||||
dirDecompAuto = new File(outputDir, "gh_auto");
|
dirDecompAuto = new File(outputDir, "gh_auto");
|
||||||
dirDecompFix = new File(outputDir, "gh_fix");
|
dirDecompFix = new File(outputDir, "gh_fix");
|
||||||
dirDecompRef = new File(outputDir, "gh_ref");
|
dirDecompRef = new File(outputDir, "gh_ref");
|
||||||
@@ -8,15 +8,23 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.app.script.GhidraScript;
|
import ghidra.app.script.GhidraScript;
|
||||||
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.CategoryPath;
|
import ghidra.program.model.data.CategoryPath;
|
||||||
import ghidra.program.model.data.Composite;
|
import ghidra.program.model.data.Composite;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
|
import ghidra.program.model.data.Enum;
|
||||||
import ghidra.program.model.data.EnumDataType;
|
import ghidra.program.model.data.EnumDataType;
|
||||||
|
import ghidra.program.model.data.FunctionDefinition;
|
||||||
|
import ghidra.program.model.data.Pointer;
|
||||||
import ghidra.program.model.data.ProgramBasedDataTypeManager;
|
import ghidra.program.model.data.ProgramBasedDataTypeManager;
|
||||||
import ghidra.program.model.data.Structure;
|
import ghidra.program.model.data.Structure;
|
||||||
import ghidra.program.model.data.TypeDef;
|
import ghidra.program.model.data.TypeDef;
|
||||||
import ghidra.program.model.data.TypedefDataType;
|
import ghidra.program.model.data.TypedefDataType;
|
||||||
|
import ghidra.program.model.data.Union;
|
||||||
|
import ghidra.program.model.data.UnionDataType;
|
||||||
|
import ghidra.program.model.listing.Data;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
import re3lib.FunctionDatabase.GlobalEntry;
|
||||||
|
|
||||||
public class TypeDumper {
|
public class TypeDumper {
|
||||||
Program currentProgram;
|
Program currentProgram;
|
||||||
@@ -25,15 +33,38 @@ public class TypeDumper {
|
|||||||
public TypeDumper(GhidraScript script) {
|
public TypeDumper(GhidraScript script) {
|
||||||
this.script = script;
|
this.script = script;
|
||||||
currentProgram = script.getCurrentProgram();
|
currentProgram = script.getCurrentProgram();
|
||||||
RecompileConfig.INSTANCE = new RecompileConfig(script);
|
RemanConfig.INSTANCE = new RemanConfig(script);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
ProgramBasedDataTypeManager dtm = currentProgram.getDataTypeManager();
|
ProgramBasedDataTypeManager dtm = currentProgram.getDataTypeManager();
|
||||||
|
|
||||||
HashSet<String> typeBlacklist = Utils.loadSimpleBlacklist(RecompileConfig.INSTANCE.typeBlacklistPath);
|
HashSet<String> requiredFunctionTypes = new HashSet<>();
|
||||||
|
FunctionDatabase fd = new FunctionDatabase(script);
|
||||||
|
List<GlobalEntry> globals = fd.loadAllGlobals();
|
||||||
|
for (GlobalEntry globalEntry : globals) {
|
||||||
|
// Fetch type of global from ghidra
|
||||||
|
Address addr = globalEntry.address;
|
||||||
|
if (globalEntry.name.equals("p_fn_vDisplayAll"))
|
||||||
|
script.println("EE" + globalEntry.name + "EE");
|
||||||
|
// script.print("Global: " + globalEntry.name);
|
||||||
|
|
||||||
|
Data data = script.getDataAt(addr);
|
||||||
|
if (data != null) {
|
||||||
|
DataType type = data.getDataType();
|
||||||
|
if (type instanceof Pointer) {
|
||||||
|
DataType inner = ((Pointer) type).getDataType();
|
||||||
|
if (inner instanceof FunctionDefinition) {
|
||||||
|
requiredFunctionTypes.add(inner.getDisplayName());
|
||||||
|
script.println("Adding required global function type: " + type.getDisplayName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HashSet<String> typeBlacklist = Utils.loadSimpleBlacklist(RemanConfig.INSTANCE.typeBlacklistPath);
|
||||||
HashSet<String> categoryPathBlacklist = Utils
|
HashSet<String> categoryPathBlacklist = Utils
|
||||||
.loadSimpleBlacklist(RecompileConfig.INSTANCE.categoryPathBlacklistPath);
|
.loadSimpleBlacklist(RemanConfig.INSTANCE.categoryPathBlacklistPath);
|
||||||
|
|
||||||
if (typeBlacklist == null) {
|
if (typeBlacklist == null) {
|
||||||
script.println("Building struct blacklist from existing data types");
|
script.println("Building struct blacklist from existing data types");
|
||||||
@@ -45,7 +76,7 @@ public class TypeDumper {
|
|||||||
typeBlacklist.add(dt.getDisplayName());
|
typeBlacklist.add(dt.getDisplayName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Utils.saveStructBlacklist(typeBlacklist, RecompileConfig.INSTANCE.typeBlacklistPath);
|
Utils.saveStructBlacklist(typeBlacklist, RemanConfig.INSTANCE.typeBlacklistPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<DataType> filteredTypes = new ArrayList<>();
|
List<DataType> filteredTypes = new ArrayList<>();
|
||||||
@@ -74,32 +105,42 @@ public class TypeDumper {
|
|||||||
Iterator<DataType> it = dtm.getAllDataTypes();
|
Iterator<DataType> it = dtm.getAllDataTypes();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
DataType dt = it.next();
|
DataType dt = it.next();
|
||||||
|
|
||||||
if (typeBlacklist.contains(dt.getDisplayName()))
|
if (typeBlacklist.contains(dt.getDisplayName()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CategoryPath catPath = dt.getCategoryPath();
|
CategoryPath catPath = dt.getCategoryPath();
|
||||||
if (catPath.getPathElements().length > 0 && categoryPathBlacklist.contains(catPath.getPathElements()[0]))
|
if (catPath.getPathElements().length > 0 && categoryPathBlacklist.contains(catPath.getPathElements()[0]))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// script.println("Type: " + dt.getDisplayName() + " - CatPath: " + dt.getCategoryPath());
|
if (dt instanceof Structure || dt instanceof TypeDef || dt instanceof EnumDataType
|
||||||
|
|| dt instanceof Union || dt instanceof Enum || dt instanceof FunctionDefinition) {
|
||||||
|
|
||||||
// if (dt.getName().equals("ImageBaseOffset32"))
|
if (dt.getDisplayName().contains("level_displayFn") || dt.getDisplayName().contains("_M_IX86"))
|
||||||
// throw new Exception("Found: " + dt.getDisplayName() + " - " + catPath.getPathElements()[0] + " - " + dt.getClass().getSimpleName());
|
script.println("DEBUG " + dt.getDisplayName() + " - " + dt.getClass().getSimpleName());
|
||||||
|
|
||||||
|
// if (dt.getDisplayName().contains("tdstObjectTypeElement_") ||
|
||||||
|
// dt.getDisplayName().contains("ObjectTypeElementHandle"))
|
||||||
|
|
||||||
if (dt instanceof Structure || dt instanceof TypeDef || dt instanceof EnumDataType) {
|
|
||||||
// script.println("Adding: " + dt.getDisplayName() + " - " +
|
|
||||||
// dt.getClass().getSimpleName());
|
|
||||||
filteredTypes.add(dt);
|
filteredTypes.add(dt);
|
||||||
}
|
}
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
try (PrintWriter writer = new PrintWriter(new File(RecompileConfig.INSTANCE.outputDir, "gh_types.h"),
|
// String s = "";
|
||||||
|
// for (DataType dataType : filteredTypes) {
|
||||||
|
// s += dataType.getDisplayName() + ", ";
|
||||||
|
// }
|
||||||
|
// script.println(s);
|
||||||
|
|
||||||
|
try (PrintWriter writer = new PrintWriter(new File(RemanConfig.INSTANCE.outputDir, "gh_types.h"),
|
||||||
"UTF-8")) {
|
"UTF-8")) {
|
||||||
Utils.headerGuardPre(writer, "STRUCTS");
|
Utils.headerGuardPre(writer, "STRUCTS");
|
||||||
writer.println("// AUTO-GENERATED FILE ");
|
writer.println("// AUTO-GENERATED FILE ");
|
||||||
writer.println("#include <r3/binders/type.h>");
|
writer.println("#include <r3/binders/type.h>");
|
||||||
|
|
||||||
DataTypeWriter dtw = new DataTypeWriter(dtm, writer);
|
DataTypeWriter dtw = new DataTypeWriter(dtm, writer);
|
||||||
dtw.blacklistedTypes = typeBlacklist;
|
dtw.requiredFunctionTypes = requiredFunctionTypes;
|
||||||
dtw.write(filteredTypes, script.getMonitor());
|
dtw.write(filteredTypes, script.getMonitor());
|
||||||
|
|
||||||
Utils.headerGuardPost(writer, "STRUCTS");
|
Utils.headerGuardPost(writer, "STRUCTS");
|
||||||
@@ -22,7 +22,10 @@ public class Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String sanitizeIdentifier(String name) {
|
public static String sanitizeIdentifier(String name) {
|
||||||
return name.replaceAll("[^a-zA-Z0-9_]", "_");
|
String r = name;
|
||||||
|
r = r.replaceAll("\\?", "UNK");
|
||||||
|
r = r.replaceAll("[^a-zA-Z0-9_]", "_");
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static HashSet<String> loadSimpleBlacklist(String path) {
|
public static HashSet<String> loadSimpleBlacklist(String path) {
|
||||||
@@ -51,7 +54,7 @@ public class Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static HashSet<Address> loadFunctionBlacklist(String path) {
|
public static HashSet<Address> loadFunctionBlacklist(String path) {
|
||||||
GhidraScript script = RecompileConfig.INSTANCE.script;
|
GhidraScript script = RemanConfig.INSTANCE.script;
|
||||||
HashSet<Address> fnBlacklist = new HashSet<>();
|
HashSet<Address> fnBlacklist = new HashSet<>();
|
||||||
File blacklistFile = new File(path);
|
File blacklistFile = new File(path);
|
||||||
try (Scanner scanner = new Scanner(blacklistFile)) {
|
try (Scanner scanner = new Scanner(blacklistFile)) {
|
||||||
@@ -60,7 +63,7 @@ public class Utils {
|
|||||||
// Strip comment
|
// Strip comment
|
||||||
String line1 = line.split("//")[0].trim();
|
String line1 = line.split("//")[0].trim();
|
||||||
// Deserialize address
|
// Deserialize address
|
||||||
Address addr = RecompileConfig.INSTANCE.currentProgram.getAddressFactory().getAddress(line1);
|
Address addr = RemanConfig.INSTANCE.currentProgram.getAddressFactory().getAddress(line1);
|
||||||
fnBlacklist.add(addr);
|
fnBlacklist.add(addr);
|
||||||
}
|
}
|
||||||
script.println("Loaded blacklist with " + fnBlacklist.size() + " entries");
|
script.println("Loaded blacklist with " + fnBlacklist.size() + " entries");
|
||||||
@@ -71,7 +74,7 @@ public class Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void saveFunctionBlacklist(HashSet<Address> fnBlacklist, String path) {
|
public static void saveFunctionBlacklist(HashSet<Address> fnBlacklist, String path) {
|
||||||
GhidraScript script = RecompileConfig.INSTANCE.script;
|
GhidraScript script = RemanConfig.INSTANCE.script;
|
||||||
File blacklistFile = new File(path);
|
File blacklistFile = new File(path);
|
||||||
try (PrintWriter writer = new PrintWriter(blacklistFile)) {
|
try (PrintWriter writer = new PrintWriter(blacklistFile)) {
|
||||||
for (Address addr : fnBlacklist) {
|
for (Address addr : fnBlacklist) {
|
||||||
73
GhidraScripts/readme.md
Normal file
73
GhidraScripts/readme.md
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# Ghidra Scripts
|
||||||
|
|
||||||
|
Add this to your ghidra scripts folder to add the reman decompile scripts to ghidra
|
||||||
|
|
||||||
|
NOTE: Make sure to also add the include `sqlite-jdbc-3.49.1.0.jar` to the ghidra scripts folders, as this is required for the ghidra scripts to read the decompile database.
|
||||||
|
|
||||||
|
## Decompile database
|
||||||
|
|
||||||
|
The decompile database is a sqlite database that contains a list of all files that implement decompiled functions and their source address. It is used to regenerate files, check for duplicates, and more.
|
||||||
|
|
||||||
|
To generate the database from the current set of files, run the scan_sources script in the /game_re folder.
|
||||||
|
|
||||||
|
Make sure you have set up the tooling by running the /tooling/setup script.
|
||||||
|
|
||||||
|
|
||||||
|
## IDE Notes
|
||||||
|
|
||||||
|
This should work with the redhat java plugin for vscode, you however need to manually add the referenced libraries to the settings, like so:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"java.project.referencedLibraries": [
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\Base\\lib\\Base.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\Decompiler\\lib\\Decompiler.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\BSim\\lib\\BSim.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\BSimFeatureVisualizer\\lib\\BSimFeatureVisualizer.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\Base\\lib\\Base.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\BytePatterns\\lib\\BytePatterns.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\ByteViewer\\lib\\ByteViewer.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\CodeCompare\\lib\\CodeCompare.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\DebugUtils\\lib\\DebugUtils.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\Decompiler\\lib\\Decompiler.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\DecompilerDependent\\lib\\DecompilerDependent.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\FileFormats\\lib\\FileFormats.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\FunctionGraph\\lib\\FunctionGraph.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\FunctionGraphDecompilerExtension\\lib\\FunctionGraphDecompilerExtension.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\FunctionID\\lib\\FunctionID.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\GhidraGo\\lib\\GhidraGo.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\GhidraServer\\lib\\GhidraServer.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\GnuDemangler\\lib\\GnuDemangler.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\GraphFunctionCalls\\lib\\GraphFunctionCalls.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\GraphServices\\lib\\GraphServices.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\MicrosoftCodeAnalyzer\\lib\\MicrosoftCodeAnalyzer.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\MicrosoftDemangler\\lib\\MicrosoftDemangler.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\MicrosoftDmang\\lib\\MicrosoftDmang.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\PDB\\lib\\PDB.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\ProgramDiff\\lib\\ProgramDiff.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\ProgramGraph\\lib\\ProgramGraph.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\Python\\lib\\Python.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\Recognizers\\lib\\Recognizers.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\Sarif\\lib\\Sarif.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\SourceCodeLookup\\lib\\SourceCodeLookup.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\SwiftDemangler\\lib\\SwiftDemangler.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\SystemEmulation\\lib\\SystemEmulation.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\VersionTracking\\lib\\VersionTracking.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\VersionTrackingBSim\\lib\\VersionTrackingBSim.jar",
|
||||||
|
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\WildcardAssembler\\lib\\WildcardAssembler.jar",
|
||||||
|
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\DB\\lib\\DB.jar",
|
||||||
|
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\Docking\\lib\\Docking.jar",
|
||||||
|
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\Emulation\\lib\\Emulation.jar",
|
||||||
|
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\FileSystem\\lib\\FileSystem.jar",
|
||||||
|
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\Generic\\lib\\Generic.jar",
|
||||||
|
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\Graph\\lib\\Graph.jar",
|
||||||
|
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\Gui\\lib\\Gui.jar",
|
||||||
|
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\Help\\lib\\Help.jar",
|
||||||
|
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\Project\\lib\\Project.jar",
|
||||||
|
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\Pty\\lib\\Pty.jar",
|
||||||
|
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\SoftwareModeling\\lib\\SoftwareModeling.jar",
|
||||||
|
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\Utility\\lib\\Utility.jar",
|
||||||
|
"c:\\Projects\\R3\\java\\ghidra\\sqlite-jdbc-3.49.1.0.jar"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
BIN
GhidraScripts/sqlite-jdbc-3.49.1.0.jar
Normal file
BIN
GhidraScripts/sqlite-jdbc-3.49.1.0.jar
Normal file
Binary file not shown.
7
game_re/.gitignore
vendored
7
game_re/.gitignore
vendored
@@ -1,5 +1,10 @@
|
|||||||
gh_auto/*
|
|
||||||
gh_ref/*
|
gh_ref/*
|
||||||
|
old/
|
||||||
*.bak
|
*.bak
|
||||||
gh_cmake_timestamp
|
gh_cmake_timestamp
|
||||||
functions.dat
|
functions.dat
|
||||||
|
*.zip
|
||||||
|
.tmp
|
||||||
|
.txt
|
||||||
|
*.db
|
||||||
|
logs/
|
||||||
@@ -1,84 +1,125 @@
|
|||||||
# Build for 32-bit compatibility
|
function(setup_target TARGET DBG_MODE)
|
||||||
add_compile_options(-m32)
|
set(SOURCES
|
||||||
add_link_options(-m32)
|
r3/main.cxx
|
||||||
|
r3/binders/stub.cxx
|
||||||
|
gh_global.cxx)
|
||||||
|
|
||||||
add_subdirectory(third_party/spdlog)
|
if(DBG_MODE)
|
||||||
|
add_library(${TARGET} SHARED ${SOURCES})
|
||||||
|
else()
|
||||||
|
add_executable(${TARGET} ${SOURCES})
|
||||||
|
set_target_properties(
|
||||||
|
${TARGET} PROPERTIES
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_executable(game_re
|
target_compile_features(${TARGET} PUBLIC cxx_std_20)
|
||||||
r3/main.cpp
|
target_include_directories(${TARGET} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
r3/binders/static_mem.cxx
|
|
||||||
gh_global.cxx
|
|
||||||
)
|
|
||||||
|
|
||||||
target_compile_features(game_re PUBLIC cxx_std_20)
|
if(WIN32 AND R3_32BIT)
|
||||||
|
target_link_libraries(${TARGET} PRIVATE
|
||||||
|
binkw32
|
||||||
|
dinput8
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
target_include_directories(game_re PUBLIC
|
target_compile_definitions(${TARGET} PRIVATE
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
R3_GAME_DATA_DIR=\"${GAME_DATA_DIR}\"
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/third_party/bink
|
|
||||||
)
|
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
target_link_directories(game_re PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/bink)
|
|
||||||
target_include_directories(game_re PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/bink)
|
|
||||||
target_link_libraries(game_re PRIVATE binkw32)
|
|
||||||
|
|
||||||
# Copy to output dir
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/binkw32.dll
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/third_party/bink/binkw32.dll ${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
)
|
)
|
||||||
add_custom_target(copy_binkw32 ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/binkw32.dll)
|
|
||||||
add_dependencies(game_re copy_binkw32)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_compile_definitions(game_re PRIVATE
|
if(NOT DBG_MODE)
|
||||||
R3_GAME_DATA_DIR=\"${GAME_DATA_DIR}\"
|
get_filename_component(R3_DATA_SEGMENT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/gh_datasegment.bin" ABSOLUTE)
|
||||||
)
|
target_compile_definitions(${TARGET} PRIVATE
|
||||||
|
R3_DATA_SEGMENT_FILE=\"${R3_DATA_SEGMENT_FILE}\"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
get_filename_component(R3_DATA_SEGMENT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/gh_datasegment.bin" ABSOLUTE)
|
target_compile_definitions(${TARGET} PRIVATE
|
||||||
target_compile_definitions(game_re PRIVATE
|
_CRT_SECURE_NO_WARNINGS=1
|
||||||
R3_DATA_SEGMENT_FILE=\"${R3_DATA_SEGMENT_FILE}\"
|
_CRT_NONSTDC_NO_WARNINGS=1
|
||||||
)
|
SPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_TRACE
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
target_link_directories(game_re PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/mssdk/lib)
|
|
||||||
target_include_directories(game_re SYSTEM AFTER PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/mssdk/include)
|
|
||||||
target_link_libraries(game_re PRIVATE
|
|
||||||
d3d8
|
|
||||||
dinput8
|
|
||||||
)
|
)
|
||||||
endif()
|
|
||||||
|
|
||||||
target_compile_definitions(game_re PRIVATE
|
target_link_libraries(${TARGET} PRIVATE spdlog CLI11 magic_enum)
|
||||||
_CRT_SECURE_NO_WARNINGS=1
|
|
||||||
_CRT_NONSTDC_NO_WARNINGS=1)
|
|
||||||
|
|
||||||
target_link_libraries(game_re PRIVATE spdlog)
|
file(GLOB GH_AUTO_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/gh_auto/*.cxx)
|
||||||
|
file(GLOB GH_FIX_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/gh_fix/*.cxx)
|
||||||
|
file(GLOB GH_STUB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/gh_stub/*.cxx)
|
||||||
|
|
||||||
file(GLOB GH_AUTO_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/gh_auto/*.cxx)
|
target_sources(${TARGET} PRIVATE
|
||||||
file(GLOB GH_FIX_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/gh_fix/*.cxx)
|
${GH_AUTO_SOURCES}
|
||||||
file(GLOB GH_STUB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/gh_stub/*.cxx)
|
${GH_FIX_SOURCES}
|
||||||
|
${GH_STUB_SOURCES}
|
||||||
|
)
|
||||||
|
|
||||||
target_sources(game_re PRIVATE
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||||
${GH_AUTO_SOURCES}
|
target_compile_definitions(${TARGET} PRIVATE MSVC=1)
|
||||||
${GH_FIX_SOURCES}
|
|
||||||
${GH_STUB_SOURCES}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Ignore -Wformat-security
|
# Disable SAFESEH on Windows
|
||||||
target_compile_options(game_re PRIVATE -Wno-format-security)
|
if(WIN32)
|
||||||
|
target_link_options(${TARGET} PRIVATE /SAFESEH:NO)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
target_compile_definitions(${TARGET} PRIVATE MSVC=0)
|
||||||
|
|
||||||
# Ignore -Wmicrosoft-cast
|
# Ignore -Wformat-security
|
||||||
target_compile_options(game_re PRIVATE -Wno-microsoft-cast)
|
target_compile_options(${TARGET} PRIVATE -Wno-format-security)
|
||||||
|
|
||||||
# Automatically re-run CMake if any gh_*.cxx files change
|
# Ignore -Wmicrosoft-cast
|
||||||
# due to ghidra script runs
|
target_compile_options(${TARGET} PRIVATE -Wno-microsoft-cast)
|
||||||
set_property(
|
|
||||||
DIRECTORY
|
|
||||||
APPEND
|
|
||||||
PROPERTY CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/gh_cmake_timestamp
|
|
||||||
)
|
|
||||||
|
|
||||||
target_precompile_headers(game_re PRIVATE
|
# Disable safeseh
|
||||||
"$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_CURRENT_SOURCE_DIR}/r3/binders/auto_pch.cxx>"
|
# target_link_options(${TARGET} PRIVATE -Wl,/SAFESEH:NO)
|
||||||
)
|
endif()
|
||||||
|
|
||||||
|
# Automatically re-run CMake if any gh_*.cxx files change
|
||||||
|
# due to ghidra script runs
|
||||||
|
set_property(
|
||||||
|
DIRECTORY
|
||||||
|
APPEND
|
||||||
|
PROPERTY CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/gh_cmake_timestamp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_precompile_headers(${TARGET} PRIVATE
|
||||||
|
"$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_CURRENT_SOURCE_DIR}/r3/binders/auto_pch.cxx>"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Potentially might want 1/1 translation for code
|
||||||
|
# For now it has the following values:
|
||||||
|
# 0 = 100% original (as possible)
|
||||||
|
# 1 = Runtime QOL (no cd checks, windowed mode, etc.)
|
||||||
|
target_compile_definitions(${TARGET} PRIVATE
|
||||||
|
RE_AUTHENTIC=1
|
||||||
|
)
|
||||||
|
|
||||||
|
if(DBG_MODE)
|
||||||
|
target_sources(${TARGET} PRIVATE
|
||||||
|
r3/binders/dbg_mem.cxx
|
||||||
|
)
|
||||||
|
target_compile_definitions(game_dbg PRIVATE RE_DBG_INJECTED=1)
|
||||||
|
target_link_libraries(${TARGET} PRIVATE
|
||||||
|
DbgHelp
|
||||||
|
hooker
|
||||||
|
)
|
||||||
|
|
||||||
|
find_program(gh_tool
|
||||||
|
NAMES gh_tool gh_tool.exe
|
||||||
|
HINTS ${CMAKE_CURRENT_LIST_DIR}/../tooling/bin
|
||||||
|
REQUIRED
|
||||||
|
)
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${gh_tool} -d${CMAKE_CURRENT_SOURCE_DIR}/gh.db
|
||||||
|
hooks -o ${CMAKE_CURRENT_BINARY_DIR}/hooks.def
|
||||||
|
)
|
||||||
|
target_include_directories(${TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
|
else()
|
||||||
|
target_sources(${TARGET} PRIVATE
|
||||||
|
r3/binders/static_mem.cxx
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
setup_target(game_re OFF)
|
||||||
|
setup_target(game_dbg ON)
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
gh_fix
|
|
||||||
@@ -203,3 +203,4 @@
|
|||||||
0054c925 // _chdir
|
0054c925 // _chdir
|
||||||
0054bce5 // strlwr
|
0054bce5 // strlwr
|
||||||
00402960 // sprintf
|
00402960 // sprintf
|
||||||
|
0059736c // Direct3DCreate8
|
||||||
@@ -3,13 +3,14 @@
|
|||||||
#include <r3/binders/auto.h>
|
#include <r3/binders/auto.h>
|
||||||
#include <gh_global.h>
|
#include <gh_global.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
// 00401410
|
// 004013f0
|
||||||
|
HANDLE __cdecl r3_getDrawSemaphore(void)
|
||||||
HWND getHWND(void)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
return g_gameHWND;
|
return g_drawSemaphore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
BIN
game_re/gh_datasegment.bin
(Stored with Git LFS)
BIN
game_re/gh_datasegment.bin
(Stored with Git LFS)
Binary file not shown.
@@ -3,9 +3,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
#define GH_DATA_START 0x00597000
|
#define GH_DATA_START 0x00400000
|
||||||
#define GH_DATA_END 0x00843fff
|
#define GH_DATA_END 0x00843fff
|
||||||
#define GH_DATA_SIZE (GH_DATA_END - GH_DATA_START)
|
#define GH_DATA_SIZE (GH_DATA_END - GH_DATA_START)
|
||||||
constexpr size_t gh_data_start = 0x00597000;
|
constexpr size_t gh_data_start = 0x00400000;
|
||||||
constexpr size_t gh_data_end = 0x00843fff;
|
constexpr size_t gh_data_end = 0x00843fff;
|
||||||
constexpr size_t gh_data_size = gh_data_end - gh_data_start;
|
constexpr size_t gh_data_size = gh_data_end - gh_data_start;
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
|
||||||
|
|
||||||
#include <r3/binders/auto.h>
|
|
||||||
#include <gh_global.h>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
// 0043e1d0
|
|
||||||
/* Allocate error manager system numbers */
|
|
||||||
|
|
||||||
byte Erm_fn_ucInitErrMsg(void)
|
|
||||||
|
|
||||||
{
|
|
||||||
byte RVar1;
|
|
||||||
tdstLastErrorInfo *pdVar2;
|
|
||||||
int iVar2;
|
|
||||||
|
|
||||||
RVar1 = g_ucErmNbOfModule;
|
|
||||||
if (g_ucErmNbOfModule == 0) {
|
|
||||||
for (size_t i = 0; i < std::size(g_stErmTheLastErrorInfo); i++) {
|
|
||||||
g_stErmTheLastErrorInfo[i].lastErr = 0;
|
|
||||||
g_stErmTheLastErrorInfo[i].ulChannelId = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_ucErmNbOfModule = g_ucErmNbOfModule + 1;
|
|
||||||
return RVar1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
|
||||||
|
|
||||||
#include <r3/binders/auto.h>
|
|
||||||
#include <gh_global.h>
|
|
||||||
#include <spdlog/spdlog.h>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
void r3_noop(void *p_cTxt1, void *p_cTxt2); // 00401100 // r3_noop
|
|
||||||
tdstLastErrorInfo *Erm_fn_p_stFindstMyLastErrorInfo(
|
|
||||||
ulong ulChannelId); // 0043e2b0 // Erm_fn_p_stFindstMyLastErrorInfo
|
|
||||||
|
|
||||||
// 0043e410
|
|
||||||
/* Check CpaError.h */
|
|
||||||
|
|
||||||
void Erm_fn_v_UpdateLastError(ushort uwStartOfWarningsId, byte ucModuleId,
|
|
||||||
ulong ulChannelId, ushort uwErrNum,
|
|
||||||
long lDebugData, uchar ucOpenInfoWindow,
|
|
||||||
uchar ucStopForDebug, char *szPersonalMsg)
|
|
||||||
|
|
||||||
{
|
|
||||||
tdstLastErrorInfo *ptVar2;
|
|
||||||
|
|
||||||
ptVar2 = Erm_fn_p_stFindstMyLastErrorInfo(ulChannelId);
|
|
||||||
if (ptVar2 == (tdstLastErrorInfo *)0x0) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
fmt::format("{} {}", s_Error_in_the_Erm__005bd374,
|
|
||||||
s_There_is_no_more_Channel_error_t_005bd388));
|
|
||||||
}
|
|
||||||
if (ptVar2->lastErr != 0) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
fmt::format("{}", s_Strange__The_last_error_was_neve_005bd348));
|
|
||||||
}
|
|
||||||
ptVar2->lastErr = uwErrNum;
|
|
||||||
ptVar2->ucLastFailedModuleId = ucModuleId;
|
|
||||||
ptVar2->ulChannelId = ulChannelId;
|
|
||||||
if (uwErrNum < uwStartOfWarningsId) {
|
|
||||||
if (szPersonalMsg == (char *)0x0) {
|
|
||||||
throw std::runtime_error(fmt::format(
|
|
||||||
"Unkown fatal error ({}, module: {})", uwErrNum, ucModuleId));
|
|
||||||
} else {
|
|
||||||
throw std::runtime_error(
|
|
||||||
fmt::format("Unkown fatal error ({}, module: {}, {})", uwErrNum,
|
|
||||||
ucModuleId, szPersonalMsg));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (szPersonalMsg == (char *)0x0) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
SPDLOG_WARN("Erm_Warn: {}, module: {}, {}", uwErrNum, ucModuleId,
|
|
||||||
szPersonalMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
|
||||||
|
|
||||||
#include <r3/binders/auto.h>
|
|
||||||
#include <gh_global.h>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
// 0043ff60
|
|
||||||
/* WARNING: Globals starting with '_' overlap smaller symbols at the same address */
|
|
||||||
|
|
||||||
void FUN_0043ff60(float param_1,float param_2,float param_3)
|
|
||||||
|
|
||||||
{
|
|
||||||
longlong lVar1;
|
|
||||||
longlong lVar2;
|
|
||||||
longlong lVar3;
|
|
||||||
|
|
||||||
lVar1 = r3_ftol(param_1 * 255.0);
|
|
||||||
lVar2 = r3_ftol(param_2 * 255.0);
|
|
||||||
lVar3 = r3_ftol(param_3 * 255.0);
|
|
||||||
DAT_007a2c14 = ((int)lVar1 << 8 | (uint)lVar2) << 8 | (uint)lVar3;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
|
||||||
|
|
||||||
#include <r3/binders/auto.h>
|
|
||||||
#include <gh_global.h>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
undefined4* FUN_0046ecc0(undefined2 param_1, undefined2 param_2); // 0046ecc0 // FUN_0046ecc0
|
|
||||||
|
|
||||||
// 0046f240
|
|
||||||
/* WARNING: Globals starting with '_' overlap smaller symbols at the same address */
|
|
||||||
|
|
||||||
undefined4 FUN_0046f240(short param_1,short param_2,undefined4 *param_3)
|
|
||||||
|
|
||||||
{
|
|
||||||
uint uVar1;
|
|
||||||
undefined4 *puVar2;
|
|
||||||
uint uVar3;
|
|
||||||
int iVar4;
|
|
||||||
|
|
||||||
DAT_005e6b04 = 1;
|
|
||||||
do {
|
|
||||||
} while (DAT_005e6b00 != 0);
|
|
||||||
uVar1 = (uint)param_2;
|
|
||||||
uVar3 = uVar1 & 0x8000000f;
|
|
||||||
if ((int)uVar3 < 0) {
|
|
||||||
uVar3 = (uVar3 - 1 | 0xfffffff0) + 1;
|
|
||||||
}
|
|
||||||
puVar2 = (undefined4 *)FUN_0046ecc0((int)(uVar1 + ((int)uVar1 >> 0x1f & 0xfU)) >> 4,uVar3);
|
|
||||||
puVar2[0x19] = 0xffffffff;
|
|
||||||
puVar2[0x18] = 0;
|
|
||||||
for (iVar4 = 0x1c; iVar4 != 0; iVar4 = iVar4 + -1) {
|
|
||||||
*param_3 = *puVar2;
|
|
||||||
puVar2 = puVar2 + 1;
|
|
||||||
param_3 = param_3 + 1;
|
|
||||||
}
|
|
||||||
DAT_005e6b04 = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
|
||||||
|
|
||||||
#include <r3/binders/auto.h>
|
|
||||||
#include <gh_global.h>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
undefined FUN_0047c340(dword* param_1, dword* param_2, undefined4 param_3); // 0047c340 // FUN_0047c340
|
|
||||||
undefined FUN_0046f240(short param_1, short param_2, undefined4 * param_3); // 0046f240 // FUN_0046f240
|
|
||||||
undefined FUN_0046f060(short param_1, undefined4 * param_2); // 0046f060 // FUN_0046f060
|
|
||||||
|
|
||||||
// 0047c150
|
|
||||||
void FUN_0047c150(short param_1,short param_2,int param_3)
|
|
||||||
|
|
||||||
{
|
|
||||||
int iVar1;
|
|
||||||
dword local_d0 [24];
|
|
||||||
dword local_70 [28];
|
|
||||||
|
|
||||||
iVar1 = FUN_0046f060(param_1,local_d0);
|
|
||||||
if ((iVar1 != 0) && (iVar1 = FUN_0046f240(param_1,param_2,local_70), iVar1 != 0)) {
|
|
||||||
if (param_3 != 0) {
|
|
||||||
DAT_005f5e24 = param_3;
|
|
||||||
}
|
|
||||||
FUN_0047c340(local_d0,local_70,DAT_005f5e24);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
26
game_re/gh_fix/FUN_004995f0.cxx
Normal file
26
game_re/gh_fix/FUN_004995f0.cxx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||||
|
|
||||||
|
#include <r3/binders/auto.h>
|
||||||
|
#include <gh_global.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
undefined FUN_004993a0(undefined4 param_1); // 004993a0 // FUN_004993a0 // cdecl
|
||||||
|
undefined FUN_00498e90(undefined4 param_1); // 00498e90 // FUN_00498e90 // cdecl
|
||||||
|
undefined FUN_00499540(undefined4 param_1); // 00499540 // FUN_00499540 // cdecl
|
||||||
|
|
||||||
|
// 004995f0
|
||||||
|
void FUN_004995f0(undefined4 param_1,undefined4 param_2)
|
||||||
|
|
||||||
|
{
|
||||||
|
int iVar1;
|
||||||
|
|
||||||
|
iVar1 = FUN_00499540(param_1);
|
||||||
|
if (iVar1 != 0) {
|
||||||
|
FUN_00498e90(param_2);
|
||||||
|
FUN_004993a0(param_2);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
37
game_re/gh_fix/IPT_fn_hGetEntryActionHandle.cxx
Normal file
37
game_re/gh_fix/IPT_fn_hGetEntryActionHandle.cxx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||||
|
|
||||||
|
#include <r3/binders/auto.h>
|
||||||
|
#include <gh_global.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
// 00506510
|
||||||
|
int __cdecl IPT_fn_hGetEntryActionHandle(char *param_1)
|
||||||
|
|
||||||
|
{
|
||||||
|
char *pcVar1;
|
||||||
|
int iVar2;
|
||||||
|
uint uVar3;
|
||||||
|
int iVar4;
|
||||||
|
int iVar5;
|
||||||
|
|
||||||
|
/* 0x106510 47 IPT_fn_hGetEntryActionHandle */
|
||||||
|
iVar5 = 0;
|
||||||
|
uVar3 = 0;
|
||||||
|
iVar4 = 0;
|
||||||
|
do {
|
||||||
|
if (DAT_00840e9c <= uVar3) {
|
||||||
|
return iVar5;
|
||||||
|
}
|
||||||
|
pcVar1 = *(char **)(iVar4 + 8 + DAT_00840ea0);
|
||||||
|
if ((pcVar1 != (char *)0x0) && (iVar2 = strcmpi(pcVar1,param_1), iVar2 == 0)) {
|
||||||
|
iVar5 = iVar4 + DAT_00840ea0;
|
||||||
|
}
|
||||||
|
uVar3 = uVar3 + 1;
|
||||||
|
iVar4 = iVar4 + 0x1c;
|
||||||
|
} while (iVar5 == 0);
|
||||||
|
return iVar5;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
|
||||||
|
|
||||||
#include <r3/binders/auto.h>
|
|
||||||
#include <gh_global.h>
|
|
||||||
#include <bink.h>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
// 00441e40
|
|
||||||
void binkInit(void) {
|
|
||||||
BinkSetSoundSystem(&BinkOpenDirectSound, 0);
|
|
||||||
BinkSetSoundOnOff(0, 0);
|
|
||||||
BinkSetIOSize(0x80000000);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
90
game_re/gh_fix/entry.cxx
Normal file
90
game_re/gh_fix/entry.cxx
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||||
|
|
||||||
|
#include <r3/binders/auto.h>
|
||||||
|
#include <r3/binders/stub.h>
|
||||||
|
#include <gh_global.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
undefined4 crt_createProgramHeap(undefined4 param_1) {
|
||||||
|
return gh_stub_impl_cdecl<(stub_t)0x00404902, undefined4>(param_1);
|
||||||
|
}
|
||||||
|
undefined4 ioinit(void) {
|
||||||
|
return gh_stub_impl_cdecl<(stub_t)0x004046bf, undefined4>();
|
||||||
|
}
|
||||||
|
void crt_initConsole(void) {
|
||||||
|
return gh_stub_impl_cdecl<(stub_t)0x00404503, void>();
|
||||||
|
}
|
||||||
|
LPSTR crt_setupEnv(void) {
|
||||||
|
return gh_stub_impl_cdecl<(stub_t)0x004043d1, LPSTR>();
|
||||||
|
}
|
||||||
|
undefined4 crt_main2(void) {
|
||||||
|
return gh_stub_impl_cdecl<(stub_t)0x00404184, undefined4>();
|
||||||
|
}
|
||||||
|
undefined4 crt_main1(void) {
|
||||||
|
return gh_stub_impl_cdecl<(stub_t)0x004040cb, undefined4>();
|
||||||
|
}
|
||||||
|
void crt_static_init(void) {
|
||||||
|
return gh_stub_impl_cdecl<(stub_t)0x004027be, void>();
|
||||||
|
}
|
||||||
|
|
||||||
|
char *crt_0(void) { return gh_stub_impl_cdecl<(stub_t)0x00404073, char *>(); }
|
||||||
|
|
||||||
|
void gh_pre_main(void) {
|
||||||
|
DWORD DVar1;
|
||||||
|
int iVar2;
|
||||||
|
LPSTR *cmdline;
|
||||||
|
uint showCmd;
|
||||||
|
HMODULE hInstance;
|
||||||
|
HINSTANCE hPrevInstance;
|
||||||
|
_STARTUPINFOA local_60;
|
||||||
|
undefined1 *local_1c;
|
||||||
|
void *pvStack_14;
|
||||||
|
undefined1 *puStack_10;
|
||||||
|
undefined *puStack_c;
|
||||||
|
undefined4 local_8;
|
||||||
|
|
||||||
|
local_8 = 0xffffffff;
|
||||||
|
// This sets up the unhandled exception handler i think?
|
||||||
|
// puStack_c = &DAT_00597ca0;
|
||||||
|
// puStack_10 = &LAB_00404a58;
|
||||||
|
// pvStack_14 = ExceptionList;
|
||||||
|
// local_1c = &stack0xffffff88;
|
||||||
|
// ExceptionList = &pvStack_14;
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
DVar1 = GetVersion();
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
DWORD_005cf980 = DVar1 >> 8 & 0xff;
|
||||||
|
DWORD_005cf97c = DVar1 & 0xff;
|
||||||
|
DWORD_005cf978 = DWORD_005cf97c * 0x100 + DWORD_005cf980;
|
||||||
|
DWORD_005cf974 = DVar1 >> 0x10;
|
||||||
|
iVar2 = crt_createProgramHeap(1);
|
||||||
|
if (iVar2 == 0) {
|
||||||
|
SPDLOG_ERROR("crt_createProgramHeap failed");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
iVar2 = ioinit();
|
||||||
|
if (iVar2 == 0) {
|
||||||
|
SPDLOG_ERROR("_ioinit failed");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
local_8 = 0;
|
||||||
|
crt_initConsole();
|
||||||
|
g_crt_cmdLine = GetCommandLineA();
|
||||||
|
PTR_005cf9b4 = crt_setupEnv();
|
||||||
|
crt_main2();
|
||||||
|
crt_main1();
|
||||||
|
crt_static_init();
|
||||||
|
local_60.dwFlags = 0;
|
||||||
|
GetStartupInfoA(&local_60);
|
||||||
|
cmdline = (LPSTR *)crt_0();
|
||||||
|
if ((local_60.dwFlags & 1) == 0) {
|
||||||
|
showCmd = 10;
|
||||||
|
} else {
|
||||||
|
showCmd = (uint)local_60.wShowWindow;
|
||||||
|
}
|
||||||
|
hPrevInstance = (HINSTANCE)0x0;
|
||||||
|
hInstance = GetModuleHandleA((LPCSTR)0x0);
|
||||||
|
}
|
||||||
|
}
|
||||||
196
game_re/gh_fix/gfx_init.cxx
Normal file
196
game_re/gh_fix/gfx_init.cxx
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||||
|
|
||||||
|
#include <r3/binders/auto.h>
|
||||||
|
#include <gh_global.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
undefined FUN_00496ac0(void); // 00496ac0 // FUN_00496ac0 // cdecl
|
||||||
|
undefined FUN_00470b00(void); // 00470b00 // FUN_00470b00 // cdecl
|
||||||
|
undefined FUN_00484ea0(undefined4 param_1); // 00484ea0 // FUN_00484ea0 // cdecl
|
||||||
|
//
|
||||||
|
// 0046f870
|
||||||
|
undefined4 gfx_init(HWND hwnd, int param_2, UINT param_3, UINT param_4,
|
||||||
|
int param_5)
|
||||||
|
|
||||||
|
{
|
||||||
|
undefined4 *puVar1;
|
||||||
|
HRESULT HVar2;
|
||||||
|
int iVar3;
|
||||||
|
D3DFORMAT AdapterFormat;
|
||||||
|
D3DPRESENT_PARAMETERS *pDVar4;
|
||||||
|
D3DDISPLAYMODE DStack_54;
|
||||||
|
D3DDISPLAYMODE displayMode;
|
||||||
|
D3DPRESENT_PARAMETERS DStack_34;
|
||||||
|
|
||||||
|
puVar1 = &DAT_007eaf60;
|
||||||
|
for (iVar3 = 0x13; iVar3 != 0; iVar3 = iVar3 + -1) {
|
||||||
|
*puVar1 = 0;
|
||||||
|
puVar1 = puVar1 + 1;
|
||||||
|
}
|
||||||
|
puVar1 = &g_gfx_lastColorOp;
|
||||||
|
for (iVar3 = 0x58; iVar3 != 0; iVar3 = iVar3 + -1) {
|
||||||
|
*puVar1 = 0;
|
||||||
|
puVar1 = puVar1 + 1;
|
||||||
|
}
|
||||||
|
puVar1 = &DAT_007eb044;
|
||||||
|
do {
|
||||||
|
*puVar1 = 0xbf800000;
|
||||||
|
puVar1 = puVar1 + 0xb;
|
||||||
|
} while ((int)puVar1 < 0x7eb1a4);
|
||||||
|
DAT_005bf684 = param_2;
|
||||||
|
if (param_2 == 0) {
|
||||||
|
DWORD_005e6c20 = g_GLI_width0;
|
||||||
|
DWORD_005e6c24 = g_GLI_height0;
|
||||||
|
DAT_005e6c28 = g_GLI_bitdepth0;
|
||||||
|
if (param_3 == 0) {
|
||||||
|
param_3 = g_GLI_width0;
|
||||||
|
}
|
||||||
|
if (param_4 == 0) {
|
||||||
|
param_4 = g_GLI_height0;
|
||||||
|
}
|
||||||
|
if (param_5 == 0) {
|
||||||
|
param_5 = g_GLI_bitdepth0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DWORD_005e6c20 = param_3;
|
||||||
|
DWORD_005e6c24 = param_4;
|
||||||
|
DAT_005e6c28 = param_5;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FnD3Create8 fn_Direct3DCreate8 = getDirect3DCreate8();
|
||||||
|
gfx_d3d = fn_Direct3DCreate8(0xdc);
|
||||||
|
if (gfx_d3d == (IDirect3D8 *)0x0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
HVar2 = (*gfx_d3d->lpVtbl->GetAdapterDisplayMode)(gfx_d3d, 0, &displayMode);
|
||||||
|
if (HVar2 < 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
pDVar4 = &DStack_34;
|
||||||
|
for (iVar3 = 0xd; iVar3 != 0; iVar3 = iVar3 + -1) {
|
||||||
|
pDVar4->BackBufferWidth = 0;
|
||||||
|
pDVar4 = (D3DPRESENT_PARAMETERS *)&pDVar4->BackBufferHeight;
|
||||||
|
}
|
||||||
|
DStack_34.Windowed = (BOOL)(DAT_005bf684 == 0);
|
||||||
|
if (DAT_005bf684 == 0) {
|
||||||
|
DStack_34.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC;
|
||||||
|
DStack_34.BackBufferFormat = displayMode.Format;
|
||||||
|
param_5 = FUN_00484ea0(displayMode.Format);
|
||||||
|
AdapterFormat = displayMode.Format;
|
||||||
|
DAT_005e6c28 = param_5;
|
||||||
|
} else {
|
||||||
|
DStack_34.SwapEffect = D3DSWAPEFFECT_FLIP;
|
||||||
|
if (param_5 == 0x10) {
|
||||||
|
DStack_34.BackBufferFormat = D3DFMT_R5G6B5;
|
||||||
|
AdapterFormat = D3DFMT_R5G6B5;
|
||||||
|
} else {
|
||||||
|
DStack_34.BackBufferFormat = D3DFMT_A8R8G8B8;
|
||||||
|
AdapterFormat = D3DFMT_X8R8G8B8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DStack_34.FullScreen_PresentationInterval = (UINT)(DAT_005bf684 != 0);
|
||||||
|
DStack_34.BackBufferHeight = param_4;
|
||||||
|
DStack_34.BackBufferCount = 1;
|
||||||
|
DStack_34.EnableAutoDepthStencil = 1;
|
||||||
|
DStack_34.FullScreen_RefreshRateInHz = 0;
|
||||||
|
DStack_34.BackBufferWidth = param_3;
|
||||||
|
if (0x10 < param_5) {
|
||||||
|
HVar2 = (*gfx_d3d->lpVtbl->CheckDeviceFormat)(
|
||||||
|
gfx_d3d, g_GLI_adapter, D3DDEVTYPE_HAL, AdapterFormat, 2,
|
||||||
|
D3DRTYPE_SURFACE, D3DFMT_D24S8);
|
||||||
|
if (HVar2 == 0) {
|
||||||
|
DStack_34.AutoDepthStencilFormat = D3DFMT_D24S8;
|
||||||
|
DAT_0063be50 = 1;
|
||||||
|
goto LAB_0046fa6f;
|
||||||
|
}
|
||||||
|
HVar2 = (*gfx_d3d->lpVtbl->CheckDeviceFormat)(
|
||||||
|
gfx_d3d, g_GLI_adapter, D3DDEVTYPE_HAL, AdapterFormat, 2,
|
||||||
|
D3DRTYPE_SURFACE, D3DFMT_D32);
|
||||||
|
DAT_0063be50 = 0;
|
||||||
|
if (HVar2 == 0) {
|
||||||
|
DStack_34.AutoDepthStencilFormat = D3DFMT_D32;
|
||||||
|
goto LAB_0046fa6f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DAT_0063be50 = 0;
|
||||||
|
DStack_34.AutoDepthStencilFormat = D3DFMT_D16;
|
||||||
|
(*gfx_d3d->lpVtbl->CheckDeviceFormat)(gfx_d3d, g_GLI_adapter, D3DDEVTYPE_HAL,
|
||||||
|
AdapterFormat, 2, D3DRTYPE_SURFACE,
|
||||||
|
D3DFMT_D16);
|
||||||
|
LAB_0046fa6f:
|
||||||
|
DStack_34.Flags = 1;
|
||||||
|
if (g_GLI_tnl == '\0') {
|
||||||
|
HVar2 =
|
||||||
|
(*gfx_d3d->lpVtbl->CreateDevice)(gfx_d3d, g_GLI_adapter, D3DDEVTYPE_HAL,
|
||||||
|
hwnd, 0x24, &DStack_34, &gfx_device);
|
||||||
|
if (HVar2 < 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
HVar2 =
|
||||||
|
(*gfx_d3d->lpVtbl->CreateDevice)(gfx_d3d, g_GLI_adapter, D3DDEVTYPE_HAL,
|
||||||
|
hwnd, 0x44, &DStack_34, &gfx_device);
|
||||||
|
if ((HVar2 < 0) && (HVar2 = (*gfx_d3d->lpVtbl->CreateDevice)(
|
||||||
|
gfx_d3d, g_GLI_adapter, D3DDEVTYPE_HAL, hwnd, 0x24,
|
||||||
|
&DStack_34, &gfx_device),
|
||||||
|
HVar2 < 0)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(*gfx_device->lpVtbl->SetRenderState)(gfx_device, D3DRS_NORMALIZENORMALS, 0);
|
||||||
|
DAT_007eafa4 = 0;
|
||||||
|
(*gfx_device->lpVtbl->SetRenderState)(gfx_device, D3DRS_ZENABLE, 1);
|
||||||
|
DAT_007eafa0 = 1;
|
||||||
|
(*gfx_device->lpVtbl->SetRenderState)(gfx_device, D3DRS_ZFUNC, 4);
|
||||||
|
DAT_007eaf7c = 4;
|
||||||
|
(*gfx_device->lpVtbl->SetRenderState)(gfx_device, D3DRS_DITHERENABLE, 1);
|
||||||
|
(*gfx_device->lpVtbl->SetRenderState)(gfx_device, D3DRS_SPECULARENABLE, 0);
|
||||||
|
(*gfx_device->lpVtbl->SetRenderState)(gfx_device, D3DRS_CULLMODE, 1);
|
||||||
|
(*gfx_device->lpVtbl->SetTextureStageState)(gfx_device, 0, D3DTSS_COLORARG1,
|
||||||
|
2);
|
||||||
|
(*gfx_device->lpVtbl->SetTextureStageState)(gfx_device, 0, D3DTSS_COLORARG2,
|
||||||
|
0);
|
||||||
|
(*gfx_device->lpVtbl->SetTextureStageState)(gfx_device, 0, D3DTSS_COLOROP, 4);
|
||||||
|
(*gfx_device->lpVtbl->SetTextureStageState)(gfx_device, 0, D3DTSS_MINFILTER,
|
||||||
|
2);
|
||||||
|
(*gfx_device->lpVtbl->SetTextureStageState)(gfx_device, 0, D3DTSS_MAGFILTER,
|
||||||
|
2);
|
||||||
|
(*gfx_device->lpVtbl->SetTextureStageState)(gfx_device, 1, D3DTSS_MINFILTER,
|
||||||
|
2);
|
||||||
|
(*gfx_device->lpVtbl->SetTextureStageState)(gfx_device, 1, D3DTSS_MAGFILTER,
|
||||||
|
2);
|
||||||
|
FUN_00470b00();
|
||||||
|
(*gfx_device->lpVtbl->SetRenderState)(gfx_device, D3DRS_ALPHATESTENABLE, 0);
|
||||||
|
(*gfx_device->lpVtbl->SetRenderState)(gfx_device, D3DRS_ALPHAFUNC, 7);
|
||||||
|
(*gfx_device->lpVtbl->SetRenderState)(gfx_device, D3DRS_ALPHAREF, 0xc0);
|
||||||
|
(*gfx_device->lpVtbl->SetRenderState)(gfx_device, D3DRS_CLIPPING, 1);
|
||||||
|
(*gfx_device->lpVtbl->SetRenderState)(gfx_device, D3DRS_LIGHTING, 0);
|
||||||
|
DAT_007eafcc = 0x3f800000;
|
||||||
|
DAT_007eafc8 = 0x3f800000;
|
||||||
|
DAT_007eafc4 = 0x3f800000;
|
||||||
|
DAT_007eafc0 = 0x3f800000;
|
||||||
|
DAT_007eafdc = 0x3f800000;
|
||||||
|
DAT_007eafd8 = 0x3f800000;
|
||||||
|
DAT_007eafd4 = 0x3f800000;
|
||||||
|
DAT_007eafd0 = 0x3f800000;
|
||||||
|
DAT_007eaff8 = 0;
|
||||||
|
DAT_007eaff4 = 0;
|
||||||
|
DAT_007eaff0 = 0;
|
||||||
|
DAT_007eaffc = 0x3f800000;
|
||||||
|
DAT_007eb000 = 0;
|
||||||
|
(*gfx_device->lpVtbl->SetMaterial)(gfx_device, (D3DMATERIAL8 *)&DAT_007eafc0);
|
||||||
|
(*gfx_device->lpVtbl->SetRenderState)(gfx_device, D3DRS_FOGVERTEXMODE, 3);
|
||||||
|
if ((g_startOfGfxStruct.d3dSurface != (IDirect3DSurface8 *)0x0) ||
|
||||||
|
(HVar2 = (*gfx_device->lpVtbl->GetBackBuffer)(
|
||||||
|
gfx_device, 0, D3DBACKBUFFER_TYPE_MONO,
|
||||||
|
&g_startOfGfxStruct.d3dSurface),
|
||||||
|
HVar2 == 0)) {
|
||||||
|
(*gfx_device->lpVtbl->GetDisplayMode)(gfx_device, &DStack_54);
|
||||||
|
DStack_54.Height = 0;
|
||||||
|
DStack_54.Width = DStack_54.RefreshRate;
|
||||||
|
g_perfCounterRate = (float)DStack_54.RefreshRate;
|
||||||
|
FUN_00496ac0();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
209
game_re/gh_fix/r3_BNK_playMovie.cxx
Normal file
209
game_re/gh_fix/r3_BNK_playMovie.cxx
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||||
|
|
||||||
|
#include <r3/binders/auto.h>
|
||||||
|
#include <gh_global.h>
|
||||||
|
#include <bink.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
undefined FUN_00401270(void); // 00401270 // FUN_00401270 // cdecl
|
||||||
|
undefined FUN_0047bb20(undefined4 param_1); // 0047bb20 // FUN_0047bb20 // cdecl
|
||||||
|
HANDLE r3_getDrawSemaphore(void); // 004013f0 // r3_getDrawSemaphore // cdecl
|
||||||
|
undefined FUN_0047bb10(void); // 0047bb10 // FUN_0047bb10 // cdecl
|
||||||
|
void r3_validateBinkVideoQuality(
|
||||||
|
byte videoBpp,
|
||||||
|
byte wantedVideoQuality); // 00442090 // r3_validateBinkVideoQuality //
|
||||||
|
// stdcall
|
||||||
|
BOOL GLD_bGetViewportAttributes(
|
||||||
|
short param_1, short combinedWindowHandle,
|
||||||
|
GLD_ViewportAttributes
|
||||||
|
*out); // 0046f240 // GLD_bGetViewportAttributes // cdecl
|
||||||
|
int IPT_fn_hGetEntryActionHandle(
|
||||||
|
const char *param_1); // 00506510 // IPT_fn_hGetEntryActionHandle // cdecl
|
||||||
|
undefined FUN_0046f680(undefined param_1,
|
||||||
|
undefined4 param_2); // 0046f680 // FUN_0046f680 // cdecl
|
||||||
|
undefined FUN_00441f30(void); // 00441f30 // FUN_00441f30 // cdecl
|
||||||
|
undefined FUN_00470f20(void); // 00470f20 // FUN_00470f20 // cdecl
|
||||||
|
undefined FUN_0047bfe0(undefined4 param_1); // 0047bfe0 // FUN_0047bfe0 // cdecl
|
||||||
|
undefined FUN_00485320(undefined4* outPtr, undefined4 param_2,
|
||||||
|
undefined4 param_3, undefined4 unused); // 00485320 // FUN_00485320 // cdecl
|
||||||
|
undefined SND_fn_vKillAllObjectSound(
|
||||||
|
void); // 0040a220 // SND_fn_vKillAllObjectSound // cdecl
|
||||||
|
undefined *getMoviePath(void); // 0055aa00 // getMoviePath // cdecl
|
||||||
|
undefined FUN_004420f0(undefined4 param_1); // 004420f0 // FUN_004420f0 // cdecl
|
||||||
|
undefined r3_binkLoop(void); // 004427a0 // r3_binkLoop // cdecl
|
||||||
|
undefined FUN_00485400(undefined4 param_1); // 00485400 // FUN_00485400 // cdecl
|
||||||
|
undefined FUN_004422c0(undefined4 param_1); // 004422c0 // FUN_004422c0 // cdecl
|
||||||
|
undefined FUN_00444810(void); // 00444810 // FUN_00444810 // cdecl
|
||||||
|
HBINK r3_binkOpen(char *movieFilename,
|
||||||
|
ulong flags); // 00442240 // r3_binkOpen // cdecl
|
||||||
|
void Erm_fn_v_UpdateLastError(
|
||||||
|
ushort uwStartOfWarningsId, byte ucModuleId, ulong ulChannelId,
|
||||||
|
ushort uwErrNum, long lDebugData, uchar ucOpenInfoWindow,
|
||||||
|
uchar ucStopForDebug,
|
||||||
|
char *szPersonalMsg); // 0043e410 // Erm_fn_v_UpdateLastError // stdcall
|
||||||
|
undefined FUN_0046f410(uint unused0,
|
||||||
|
uint unused1); // 0046f410 // FUN_0046f410 // cdecl
|
||||||
|
void r3_checkMovieDisc(
|
||||||
|
char *movieName); // 00445a10 // r3_checkMovieDisc // stdcall
|
||||||
|
undefined FUN_0046ed40(undefined param_1, undefined param_2,
|
||||||
|
undefined2 param_3); // 0046ed40 // FUN_0046ed40 // cdecl
|
||||||
|
uint32_t r3_doesMovieHaveSoundtrack(
|
||||||
|
char *param_1); // 00442130 // r3_doesMovieHaveSoundtrack // cdecl
|
||||||
|
|
||||||
|
// 00442330
|
||||||
|
/* WARNING: Inlined function: FUN_00485390 */
|
||||||
|
|
||||||
|
void r3_BNK_playMovie(char *param_1, char param_2, int param_3)
|
||||||
|
|
||||||
|
{
|
||||||
|
uint uVar1;
|
||||||
|
byte bVar2;
|
||||||
|
undefined *puVar3;
|
||||||
|
char *puVar4;
|
||||||
|
int haveSoundtrack;
|
||||||
|
longlong lVar5;
|
||||||
|
longlong lVar6;
|
||||||
|
float fVar5;
|
||||||
|
float extraout_ST0;
|
||||||
|
undefined4 uVar7;
|
||||||
|
char auStack_1b4[65];
|
||||||
|
undefined1 auStack_b0[64];
|
||||||
|
GLD_ViewportAttributes GStack_70;
|
||||||
|
|
||||||
|
bVar2 = BYTE_007a2c54;
|
||||||
|
g_currentBinkMovie.drawSemaphore = (HANDLE)r3_getDrawSemaphore();
|
||||||
|
DAT_007a2e01 = FUN_0047bb10();
|
||||||
|
g_StopVideoActionHandle = IPT_fn_hGetEntryActionHandle(s_StopVideo_005bd740);
|
||||||
|
uVar1 = (uint)bVar2;
|
||||||
|
DWORD_005bd62c = uVar1;
|
||||||
|
if (param_2 != '\0') {
|
||||||
|
SND_fn_vKillAllObjectSound();
|
||||||
|
}
|
||||||
|
r3_validateBinkVideoQuality(g_bink_videoBpp, g_bink_realVideoQuality);
|
||||||
|
haveSoundtrack = FUN_00444810();
|
||||||
|
BinkSetSoundTrack(haveSoundtrack + 1);
|
||||||
|
if (param_1 == 0) {
|
||||||
|
r3_checkMovieDisc(*(char **)(DAT_007a2c4c + 4 + uVar1 * 8));
|
||||||
|
uVar7 = *(undefined4 *)(DAT_007a2c4c + 4 + uVar1 * 8);
|
||||||
|
/* maybe, not initialized yet */
|
||||||
|
puVar3 = getMoviePath();
|
||||||
|
sprintf((char *)auStack_1b4, s_percent_s_path_2, puVar3, uVar7);
|
||||||
|
puVar4 = strlwr(auStack_1b4);
|
||||||
|
haveSoundtrack = r3_doesMovieHaveSoundtrack(puVar4);
|
||||||
|
if (haveSoundtrack == 0) {
|
||||||
|
/* BINKIOSIZE | BINKNOSKIP | BINKSNDTRACK */
|
||||||
|
uVar7 = 0x1084000;
|
||||||
|
} else {
|
||||||
|
/* BINKIOSIZE | BINKNOSKIP */
|
||||||
|
uVar7 = 0x1080000;
|
||||||
|
}
|
||||||
|
g_binkHandle = (HBINK)r3_binkOpen(auStack_1b4, uVar7);
|
||||||
|
if (g_binkHandle != (HBINK)0x0)
|
||||||
|
goto LAB_00442549;
|
||||||
|
uVar7 = *(undefined4 *)(DAT_007a2c4c + 4 + uVar1 * 8);
|
||||||
|
puVar3 = getMoviePath();
|
||||||
|
sprintf((char *)auStack_1b4, s_percent_s_path_3, 0x5d26a8, puVar3, uVar7);
|
||||||
|
puVar4 = strlwr((char *)*(uint **)(DAT_007a2c4c + 4 + uVar1 * 8));
|
||||||
|
haveSoundtrack = r3_doesMovieHaveSoundtrack(puVar4);
|
||||||
|
if (haveSoundtrack == 0) {
|
||||||
|
/* BINKNOSKIP | BINKSNDTRACK | BINKPRELOADALL */
|
||||||
|
uVar7 = 0x86000;
|
||||||
|
} else {
|
||||||
|
/* BINKNOSKIP | BINKPRELOADALL */
|
||||||
|
uVar7 = 0x82000;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Similar logic to above */
|
||||||
|
r3_checkMovieDisc((char *)param_1);
|
||||||
|
sprintf((char *)auStack_1b4, s_percent_s_path_2, s_Videos_005bd72c,
|
||||||
|
param_1);
|
||||||
|
puVar4 = strlwr(auStack_1b4);
|
||||||
|
haveSoundtrack = r3_doesMovieHaveSoundtrack(puVar4);
|
||||||
|
if (haveSoundtrack == 0) {
|
||||||
|
/* BINKIOSIZE | BINKNOSKIP | BINKSNDTRACK */
|
||||||
|
uVar7 = 0x1084000;
|
||||||
|
} else {
|
||||||
|
/* BINKIOSIZE | BINKNOSKIP */
|
||||||
|
uVar7 = 0x1080000;
|
||||||
|
}
|
||||||
|
g_binkHandle = (HBINK)r3_binkOpen(auStack_1b4, uVar7);
|
||||||
|
if ((g_binkHandle != (HBINK)0x0) ||
|
||||||
|
(g_currentBinkMovie.movieName[0] == '\0'))
|
||||||
|
goto LAB_00442549;
|
||||||
|
/* g_currentBinkMovie.movieName */
|
||||||
|
sprintf((char *)auStack_1b4, s_percent_s_path_3,
|
||||||
|
g_currentBinkMovie.movieName, s_Videos_005bd72c, param_1);
|
||||||
|
puVar4 = strlwr(param_1);
|
||||||
|
haveSoundtrack = r3_doesMovieHaveSoundtrack(puVar4);
|
||||||
|
if (haveSoundtrack == 0) {
|
||||||
|
uVar7 = 0x86000;
|
||||||
|
} else {
|
||||||
|
uVar7 = 0x82000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_binkHandle = (HBINK)r3_binkOpen(auStack_1b4, uVar7);
|
||||||
|
if (g_binkHandle == (HBINK)0x0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LAB_00442549:
|
||||||
|
g_binkMovieEnded = 0;
|
||||||
|
DAT_007a2dbc = 0;
|
||||||
|
DAT_007a2dc0 = 0;
|
||||||
|
DAT_007a2da8 = 0;
|
||||||
|
DAT_007a2dac = 0;
|
||||||
|
DAT_007a2db0 = 0;
|
||||||
|
DAT_007a2db8 = 0;
|
||||||
|
DAT_007a2e14 = 1;
|
||||||
|
if (g_binkHandle == (HBINK)0x0) {
|
||||||
|
Erm_fn_v_UpdateLastError(6, g_BNK_moduleId, 0, 7, -1, 0xff, 0xff,
|
||||||
|
(char *)auStack_1b4);
|
||||||
|
} else {
|
||||||
|
DAT_007a2dd4 = g_binkHandle->Width;
|
||||||
|
FLOAT_007a2dd8 = (float)g_binkHandle->Height;
|
||||||
|
g_bink_videoBpp = FUN_00485320(&g_binkDestStorage, g_binkHandle->Width,
|
||||||
|
g_binkHandle->Height, 0);
|
||||||
|
haveSoundtrack = g_binkDestStorage;
|
||||||
|
if (g_binkDestStorage != 0) {
|
||||||
|
r3_validateBinkVideoQuality(g_bink_videoBpp, g_bink_realVideoQuality);
|
||||||
|
FUN_00485400(haveSoundtrack, 0);
|
||||||
|
FUN_004420f0(0);
|
||||||
|
uVar7 = FUN_00401270(0, 0);
|
||||||
|
FUN_0046f680(uVar7, 0);
|
||||||
|
FUN_0046ed40(0, 0, 1);
|
||||||
|
FUN_0046f410(0, 0xff);
|
||||||
|
FUN_0046ed40(0, 0, 1);
|
||||||
|
GLD_bGetViewportAttributes(0, 0, &GStack_70);
|
||||||
|
fVar5 = (float)DAT_007a2dd4 *
|
||||||
|
((float)GStack_70.dwWidth / (float)(DAT_007a2dd4 * 2));
|
||||||
|
extraout_ST0 = (float)(fVar5 + fVar5);
|
||||||
|
lVar5 = r3_ftol(extraout_ST0);
|
||||||
|
lVar6 = r3_ftol((float)((float)(uint)FLOAT_007a2dd8 * extraout_ST0));
|
||||||
|
DAT_007a2ddc = (GStack_70.dwHeight - (int)lVar6) >> 1;
|
||||||
|
DAT_007a2de0 = DAT_007a2ddc + (int)lVar6;
|
||||||
|
DAT_007a2de4 = (GStack_70.dwWidth - (int)lVar5) >> 1;
|
||||||
|
DAT_007a2de8 = DAT_007a2de4 + (int)lVar5;
|
||||||
|
BinkSetSoundOnOff(g_binkHandle, 1);
|
||||||
|
if (param_3 == -1) {
|
||||||
|
param_3 = DAT_007a2dd0;
|
||||||
|
}
|
||||||
|
BinkSetVolume(g_binkHandle, param_3);
|
||||||
|
FUN_0047bfe0(4);
|
||||||
|
FUN_00470f20();
|
||||||
|
r3_binkLoop();
|
||||||
|
g_binkDestStorage = 0;
|
||||||
|
BinkSetSoundOnOff(g_binkHandle, 0);
|
||||||
|
FUN_004422c0(g_binkHandle);
|
||||||
|
g_binkHandle = (HBINK)0x0;
|
||||||
|
FUN_00441f30();
|
||||||
|
FUN_0047bb20(4);
|
||||||
|
uVar7 = FUN_00401270(0, 0);
|
||||||
|
FUN_0046f680(uVar7);
|
||||||
|
FUN_0046ed40(0, 0, 3);
|
||||||
|
FUN_0046f410(0, 0xff);
|
||||||
|
FUN_0046ed40(0, 0, 3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
118
game_re/gh_fix/r3_checkDisc.cxx
Normal file
118
game_re/gh_fix/r3_checkDisc.cxx
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||||
|
|
||||||
|
#include <r3/binders/auto.h>
|
||||||
|
#include <gh_global.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
undefined r3_wait_for_dvd(char *param_1, char *param_2,
|
||||||
|
undefined4 param_3); // 0043e540 // r3_wait_for_dvd
|
||||||
|
|
||||||
|
// 004464f0
|
||||||
|
void r3_checkDisc(void)
|
||||||
|
|
||||||
|
{
|
||||||
|
char cVar1;
|
||||||
|
DWORD logicalDriveBits;
|
||||||
|
UINT UVar2;
|
||||||
|
int iVar3;
|
||||||
|
char *pcVar4;
|
||||||
|
char *pcVar5;
|
||||||
|
CHAR local_41c[256];
|
||||||
|
CHAR local_31c[264];
|
||||||
|
char local_214[260];
|
||||||
|
int local_110;
|
||||||
|
char local_10c[260];
|
||||||
|
int local_8;
|
||||||
|
|
||||||
|
logicalDriveBits = GetLogicalDrives();
|
||||||
|
g_driveLetter[0] = s_driveLetterTemplate[0];
|
||||||
|
g_driveLetter[1] = s_driveLetterTemplate[1];
|
||||||
|
g_driveLetter[2] = s_driveLetterTemplate[2];
|
||||||
|
g_driveLetter[3] = s_driveLetterTemplate[3];
|
||||||
|
local_110 = 0;
|
||||||
|
g_currentBinkMovie.movieName[0] = '\0';
|
||||||
|
|
||||||
|
#if RE_AUTHENTIC == 0
|
||||||
|
do {
|
||||||
|
do {
|
||||||
|
if (local_110 != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (local_8 = 0; local_8 < 0x20; local_8 = local_8 + 1) {
|
||||||
|
if ((logicalDriveBits & 1 << ((byte)local_8 & 0x1f)) != 0) {
|
||||||
|
g_driveLetter[0] = (byte)local_8 + 0x41;
|
||||||
|
UVar2 = GetDriveTypeA(g_driveLetter);
|
||||||
|
if (UVar2 == 5) {
|
||||||
|
GetVolumeInformationA(g_driveLetter, s_volumeNameBuffer, 0x80,
|
||||||
|
(LPDWORD)0x0, (LPDWORD)0x0, (LPDWORD)0x0,
|
||||||
|
(LPSTR)0x0, 0);
|
||||||
|
iVar3 = strcmpi(s_volumeNameBuffer, s_R3_DVD_005bdfd8);
|
||||||
|
if ((iVar3 == 0) ||
|
||||||
|
(iVar3 = strcmpi(s_volumeNameBuffer, s_R3_DVD_005be0ec),
|
||||||
|
iVar3 == 0)) {
|
||||||
|
sprintf(g_currentBinkMovie.movieName, s_fmt_c_colon_s,
|
||||||
|
local_8 + 0x41, s_r3_program_files);
|
||||||
|
local_110 = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (local_110 != 0);
|
||||||
|
GetWindowsDirectoryA(local_31c, 0x104);
|
||||||
|
iVar3 = -1;
|
||||||
|
pcVar4 = local_31c;
|
||||||
|
do {
|
||||||
|
pcVar5 = pcVar4;
|
||||||
|
if (iVar3 == 0)
|
||||||
|
break;
|
||||||
|
iVar3 = iVar3 + -1;
|
||||||
|
pcVar5 = pcVar4 + 1;
|
||||||
|
cVar1 = *pcVar4;
|
||||||
|
pcVar4 = pcVar5;
|
||||||
|
} while (cVar1 != '\0');
|
||||||
|
*(undefined4 *)(pcVar5 + -1) = s_UbiSoft_Ubi_ini + Field<0, 4>();
|
||||||
|
*(undefined4 *)(pcVar5 + 3) = s_UbiSoft_Ubi_ini + Field<4, 4>();
|
||||||
|
*(undefined4 *)(pcVar5 + 7) = s_UbiSoft_Ubi_ini + Field<8, 4>();
|
||||||
|
*(undefined4 *)(pcVar5 + 0xb) = s_UbiSoft_Ubi_ini + Field<12, 4>();
|
||||||
|
pcVar5[0xf] = s_UbiSoft_Ubi_ini[0x10];
|
||||||
|
GetPrivateProfileStringA(lpAppName_005b68f0, s_Language_005b6840,
|
||||||
|
s_English_005b684c, local_41c, 0xff, local_31c);
|
||||||
|
iVar3 = strcmpi(local_41c, s_French_005b6828);
|
||||||
|
if (iVar3 == 0) {
|
||||||
|
sprintf(local_10c, s_Veuillez_ins_rer_le_DVD_dans_vot_005be500);
|
||||||
|
sprintf(local_214, s_Impossible_de_trouver_le_DVD_____005be238,
|
||||||
|
s_windowTitle);
|
||||||
|
} else {
|
||||||
|
iVar3 = strcmpi(local_41c, s_Spanish_005b67a0);
|
||||||
|
if (iVar3 == 0) {
|
||||||
|
sprintf(local_10c, s_Introduce_el_DVD_de_Rayman_3_en_l_005be4c0);
|
||||||
|
sprintf(local_214, s_DVD_s_no_v_lido_005be1ec, s_windowTitle);
|
||||||
|
} else {
|
||||||
|
iVar3 = strcmpi(local_41c, s_Italian_005b6730);
|
||||||
|
if (iVar3 == 0) {
|
||||||
|
sprintf(local_10c, s_Inserisci_il_DVD_di_Rayman_3_nel_005be484);
|
||||||
|
sprintf(local_214, s_Impossibile_trovare_il_DVD____s_005be198,
|
||||||
|
s_windowTitle);
|
||||||
|
} else {
|
||||||
|
iVar3 = strcmpi(local_41c, s_German_005b66c4);
|
||||||
|
if (iVar3 == 0) {
|
||||||
|
sprintf(local_10c, s_Bitte_legen_Sie_DVD_von_Rayman_3_005be438);
|
||||||
|
sprintf(local_214, s_Die__s_DVDROM_kann_nicht_gelesen_005be130,
|
||||||
|
s_windowTitle);
|
||||||
|
} else {
|
||||||
|
sprintf(local_10c, s_Please_insert_the_DVD_in_the_DVD_005be400);
|
||||||
|
sprintf(local_214, s__s_DVD_missing_005be0f4, s_windowTitle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iVar3 = r3_wait_for_dvd(local_10c, local_214, 5);
|
||||||
|
if (iVar3 == 2) {
|
||||||
|
/* WARNING: Subroutine does not return */
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
} while (true);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
28
game_re/gh_fix/r3_getVignettePath.cxx
Normal file
28
game_re/gh_fix/r3_getVignettePath.cxx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||||
|
|
||||||
|
#include <r3/binders/auto.h>
|
||||||
|
#include <r3/config/static.hpp>
|
||||||
|
#include <gh_global.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
// 00445f20
|
||||||
|
char *r3_getVignettePath(void)
|
||||||
|
|
||||||
|
{
|
||||||
|
char cVar1;
|
||||||
|
int iVar2;
|
||||||
|
char *pcVar3;
|
||||||
|
char *pcVar4;
|
||||||
|
|
||||||
|
char filename[256];
|
||||||
|
auto &config = getDefaultConfig();
|
||||||
|
strcpy(filename, config.gameRootDir.c_str());
|
||||||
|
strcat(filename, "/ubi.ini");
|
||||||
|
|
||||||
|
GetPrivateProfileStringA(lpAppName_005b68f0, s_VignettesFile_005be2dc,
|
||||||
|
(LPCSTR)&lpDefault_005cf96c,
|
||||||
|
(char *)&lpReturnedString_007d9aa0, 0xff, filename);
|
||||||
|
return (char *)&lpReturnedString_007d9aa0;
|
||||||
|
}
|
||||||
|
}
|
||||||
20
game_re/gh_fix/r3_getVolumeInformation.cxx
Normal file
20
game_re/gh_fix/r3_getVolumeInformation.cxx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||||
|
|
||||||
|
#include <r3/binders/auto.h>
|
||||||
|
#include <gh_global.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
// 004464b0
|
||||||
|
char * r3_getVolumeInformation(void)
|
||||||
|
|
||||||
|
{
|
||||||
|
s_volumeNameBuffer[0] = (char)lpDefault_005cf96c;
|
||||||
|
GetVolumeInformationA
|
||||||
|
(g_driveLetter,s_volumeNameBuffer,0x80,(LPDWORD)0x0,(LPDWORD)0x0,(LPDWORD)0x0,(LPSTR)0x0
|
||||||
|
,0);
|
||||||
|
return s_volumeNameBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
57
game_re/gh_fix/r3_initAllModules.cxx
Normal file
57
game_re/gh_fix/r3_initAllModules.cxx
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||||
|
|
||||||
|
#include <r3/binders/auto.h>
|
||||||
|
#include <gh_global.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
undefined r3_module1_init(void); // 0043e630 // r3_module1_init // cdecl
|
||||||
|
byte Erm_fn_ucInitErrMsg(void); // 0043e1d0 // Erm_fn_ucInitErrMsg // cdecl
|
||||||
|
undefined r3_module_big_init(void); // 00443f10 // r3_module_big_init // cdecl
|
||||||
|
void Mmg_fn_vFirstInitMmgModule(byte ucMaxNbChannel); // 0043f830 // Mmg_fn_vFirstInitMmgModule // cdecl
|
||||||
|
|
||||||
|
// 00401000
|
||||||
|
void __cdecl r3_initAllModules(void)
|
||||||
|
|
||||||
|
{
|
||||||
|
char cVar1;
|
||||||
|
size_t sVar2;
|
||||||
|
size_t sVar3;
|
||||||
|
uint uVar4;
|
||||||
|
char *pcVar5;
|
||||||
|
CHAR exePath [255];
|
||||||
|
char acStack_101 [257];
|
||||||
|
|
||||||
|
if (g_errModDInput == 0xff) {
|
||||||
|
g_errModDInput = Erm_fn_ucInitErrMsg();
|
||||||
|
}
|
||||||
|
if (g_errModMmg == 0xff) {
|
||||||
|
g_errModMmg = Erm_fn_ucInitErrMsg();
|
||||||
|
}
|
||||||
|
/* Init the memory manager */
|
||||||
|
Mmg_fn_vFirstInitMmgModule(10);
|
||||||
|
/* Set to exe path */
|
||||||
|
GetModuleFileNameA((HMODULE)0x0,exePath,0xff);
|
||||||
|
uVar4 = 0xffffffff;
|
||||||
|
pcVar5 = exePath;
|
||||||
|
do {
|
||||||
|
if (uVar4 == 0) break;
|
||||||
|
uVar4 = uVar4 - 1;
|
||||||
|
cVar1 = *pcVar5;
|
||||||
|
pcVar5 = pcVar5 + 1;
|
||||||
|
} while (cVar1 != '\0');
|
||||||
|
sVar2 = ~uVar4;
|
||||||
|
do {
|
||||||
|
sVar3 = sVar2;
|
||||||
|
sVar2 = sVar3 - 1;
|
||||||
|
if ((int)sVar2 < 0) break;
|
||||||
|
} while (exePath[sVar2] != '\\');
|
||||||
|
strncpy(acStack_101 + 1,exePath,sVar2);
|
||||||
|
acStack_101[sVar3] = '\0';
|
||||||
|
SetCurrentDirectoryA(acStack_101 + 1);
|
||||||
|
r3_module1_init();
|
||||||
|
r3_module_big_init();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
|
||||||
|
|
||||||
#include <r3/binders/auto.h>
|
|
||||||
#include <gh_global.h>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
// 0045d2e0
|
|
||||||
void r3_initUnusedSM(void)
|
|
||||||
|
|
||||||
{
|
|
||||||
WORD_007d9e68 = 1;
|
|
||||||
/* 0x53 */
|
|
||||||
sz_S[0] = s_S_005bf008[0];
|
|
||||||
sz_S[1] = s_S_005bf008[1];
|
|
||||||
WORD_007d9e6c = 2;
|
|
||||||
/* 0x4d */
|
|
||||||
sz_M[0] = s_M_005bf004[0];
|
|
||||||
sz_M[1] = s_M_005bf004[1];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
66
game_re/gh_fix/r3_levelDisplayFn.cxx
Normal file
66
game_re/gh_fix/r3_levelDisplayFn.cxx
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||||
|
|
||||||
|
#include <r3/binders/auto.h>
|
||||||
|
#include <gh_global.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
undefined FUN_00447130(void); // 00447130 // FUN_00447130 // cdecl
|
||||||
|
void doGraphics(byte param_1); // 00447460 // doGraphics // cdecl
|
||||||
|
bool UNKr3_renderViewport(byte viewportIdx); // 00447200 // ?r3_renderViewport // cdecl
|
||||||
|
int get_one(void); // 0046f2c0 // get_one // cdecl
|
||||||
|
undefined FUN_00451530(undefined4 param_1); // 00451530 // FUN_00451530 // cdecl
|
||||||
|
undefined FUN_0048a920(undefined4 param_1); // 0048a920 // FUN_0048a920 // cdecl
|
||||||
|
void r3_setRendererState(void); // 0046fec0 // r3_setRendererState // cdecl
|
||||||
|
undefined FUN_0045fc70(undefined4 param_1); // 0045fc70 // FUN_0045fc70 // cdecl
|
||||||
|
|
||||||
|
// 00446fc0
|
||||||
|
/* WARNING: Inlined function: get_one */
|
||||||
|
|
||||||
|
void __cdecl r3_levelDisplayFn(byte param)
|
||||||
|
|
||||||
|
{
|
||||||
|
int iVar1;
|
||||||
|
int *piVar2;
|
||||||
|
char cVar3;
|
||||||
|
|
||||||
|
FUN_00447130();
|
||||||
|
WaitForSingleObject(g_stEngineStructure.drawSemaphore,0xffffffff);
|
||||||
|
if (((g_stEngineStructure + Field<1556, 4>() == 0) || (DAT_005d2b18 != 0)) || (param == 0)) {
|
||||||
|
if (DAT_005e693c != 0) {
|
||||||
|
ReleaseSemaphore(g_stEngineStructure.drawSemaphore,1,(LPLONG)0x0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FUN_0048a920(~-(uint)(DAT_007d98fc != '\0') &
|
||||||
|
g_stEngineStructure.stEngineTimer.ulUsefulDeltaTime);
|
||||||
|
FUN_00451530(param);
|
||||||
|
DAT_0063be24 = 1;
|
||||||
|
UNKr3_renderViewport(param);
|
||||||
|
doGraphics(param);
|
||||||
|
if (DAT_005d2b18 != 0) {
|
||||||
|
if (param == 0) {
|
||||||
|
param = 0;
|
||||||
|
for (piVar2 = (int *)(g_stEngineStructure + Field<1500, 4>()); piVar2 != (int *)0x0;
|
||||||
|
piVar2 = (int *)piVar2[1]) {
|
||||||
|
iVar1 = *(int *)(*(int *)(*piVar2 + 4) + 0x10);
|
||||||
|
cVar3 = FUN_0045fc70(*(undefined4 *)(iVar1 + 4));
|
||||||
|
if (cVar3 != '\0') {
|
||||||
|
param = param + 1;
|
||||||
|
}
|
||||||
|
if (param == DAT_005d2b18) {
|
||||||
|
FUN_0045fc70(*(undefined4 *)(iVar1 + 4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (DAT_005d2b18 != 0) {
|
||||||
|
r3_setRendererState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* WARNING: Could not inline here */
|
||||||
|
get_one();
|
||||||
|
ReleaseSemaphore(g_stEngineStructure.drawSemaphore,1,(LPLONG)0x0);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
60
game_re/gh_fix/r3_loadVignette.cxx
Normal file
60
game_re/gh_fix/r3_loadVignette.cxx
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||||
|
|
||||||
|
#include <r3/binders/auto.h>
|
||||||
|
#include <gh_global.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void r3_beginLoadLevel(void); // 00447860 // r3_beginLoadLevel // cdecl
|
||||||
|
FIL_ConcatFile * FIL_fn_vOpenConcatFile(char * fileName); // 0055d890 // FIL_fn_vOpenConcatFile // cdecl
|
||||||
|
undefined r3_waitForDvd(const char * param_1, const char * param_2, undefined4 param_3); // 0043e540 // r3_waitForDvd // cdecl
|
||||||
|
void r3_unlockLoadLevelMutex(void); // 00447890 // r3_unlockLoadLevelMutex // cdecl
|
||||||
|
|
||||||
|
// 004fa4a0
|
||||||
|
void r3_loadVignette(char *param_1)
|
||||||
|
|
||||||
|
{
|
||||||
|
char cVar1;
|
||||||
|
int iVar2;
|
||||||
|
char *local_11c;
|
||||||
|
char *local_118;
|
||||||
|
char *local_10c;
|
||||||
|
char *local_108;
|
||||||
|
char local_104 [256];
|
||||||
|
|
||||||
|
r3_beginLoadLevel();
|
||||||
|
g_fileWrapper1 = FIL_fn_vOpenConcatFile(param_1);
|
||||||
|
if (g_fileWrapper1 == (FIL_ConcatFile *)0x0) {
|
||||||
|
local_108 = param_1;
|
||||||
|
local_10c = local_104;
|
||||||
|
do {
|
||||||
|
cVar1 = *local_108;
|
||||||
|
*local_10c = cVar1;
|
||||||
|
local_108 = local_108 + 1;
|
||||||
|
local_10c = local_10c + 1;
|
||||||
|
} while (cVar1 != '\0');
|
||||||
|
sprintf(param_1,s_percent_s_path_2,0x5d26a8,local_104);
|
||||||
|
g_fileWrapper1 = FIL_fn_vOpenConcatFile(param_1);
|
||||||
|
while (g_fileWrapper1 == (FIL_ConcatFile *)0x0) {
|
||||||
|
iVar2 = r3_waitForDvd(s_Please_insert_the_CD_005be980,s_Please_insert_the_CD_005be980,0x40035)
|
||||||
|
;
|
||||||
|
if (iVar2 == 2) {
|
||||||
|
/* WARNING: Subroutine does not return */
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
g_fileWrapper1 = FIL_fn_vOpenConcatFile(param_1);
|
||||||
|
}
|
||||||
|
local_118 = local_104;
|
||||||
|
local_11c = param_1;
|
||||||
|
do {
|
||||||
|
cVar1 = *local_118;
|
||||||
|
*local_11c = cVar1;
|
||||||
|
local_118 = local_118 + 1;
|
||||||
|
local_11c = local_11c + 1;
|
||||||
|
} while (cVar1 != '\0');
|
||||||
|
}
|
||||||
|
r3_unlockLoadLevelMutex();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -5,28 +5,27 @@
|
|||||||
#include <r3/config/static.hpp>
|
#include <r3/config/static.hpp>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
undefined FUN_00470db0(void); // 00470db0 // FUN_00470db0
|
int setupWindow(HINSTANCE instance, undefined4 param_2,
|
||||||
undefined r3_checkDisc(void); // 004464f0 // r3_checkDisc
|
int windowedParam); // 00402140 // setupWindow
|
||||||
undefined FUN_00503710(void); // 00503710 // FUN_00503710
|
undefined FUN_00470db0(void); // 00470db0 // FUN_00470db0
|
||||||
undefined r3_initAllModules(void); // 00401000 // r3_initAllModules
|
undefined r3_checkDisc(void); // 004464f0 // r3_checkDisc
|
||||||
undefined FUN_00472150(void); // 00472150 // FUN_00472150
|
undefined FUN_00503710(void); // 00503710 // FUN_00503710
|
||||||
undefined r3_wait_for_dvd(char *param_1, char *param_2,
|
undefined r3_initAllModules(void); // 00401000 // r3_initAllModules
|
||||||
undefined4 param_3); // 0043e540 // r3_wait_for_dvd
|
undefined FUN_00472150(void); // 00472150 // FUN_00472150
|
||||||
|
undefined r3_waitForDvd(char *param_1, char *param_2,
|
||||||
|
undefined4 param_3); // 0043e540 // r3_waitForDvd
|
||||||
undefined FUN_004725a0(void); // 004725a0 // FUN_004725a0
|
undefined FUN_004725a0(void); // 004725a0 // FUN_004725a0
|
||||||
int r3_get_gli_width1(void); // 0047baf0 // r3_get_gli_width1
|
int r3_get_gli_width1(void); // 0047baf0 // r3_get_gli_width1
|
||||||
undefined gfx_init2(void); // 00470be0 // gfx_init2
|
undefined gfx_init2(void); // 00470be0 // gfx_init2
|
||||||
void g_setInitVar0(void); // 00401310 // g_setInitVar0
|
void g_setInitVar0(void); // 00401310 // g_setInitVar0
|
||||||
int r3_get_gli_height1(void); // 0047bb00 // r3_get_gli_height1
|
int r3_get_gli_height1(void); // 0047bb00 // r3_get_gli_height1
|
||||||
undefined FUN_004010b0(void); // 004010b0 // FUN_004010b0
|
undefined FUN_004010b0(void); // 004010b0 // FUN_004010b0
|
||||||
undefined FUN_00401320(void); // 00401320 // FUN_00401320
|
undefined r3_windowLockCursor(void); // 00401320 // r3_windowLockCursor
|
||||||
void r3_noop(void *p_cTxt1, void *p_cTxt2); // 00401100 // r3_noop
|
void r3_noop(void *p_cTxt1, void *p_cTxt2); // 00401100 // r3_noop
|
||||||
undefined r3_initEngine(void); // 00401220 // r3_initEngine
|
|
||||||
undefined FUN_005038e0(void); // 005038e0 // FUN_005038e0
|
undefined FUN_005038e0(void); // 005038e0 // FUN_005038e0
|
||||||
undefined FUN_004fb300(void); // 004fb300 // FUN_004fb300
|
undefined FUN_004fb300(void); // 004fb300 // FUN_004fb300
|
||||||
undefined spawnThread(void); // 004477d0 // spawnThread
|
undefined spawnThread(void); // 004477d0 // spawnThread
|
||||||
undefined
|
undefined r3_engineLoop(void); // 00401220 // r3_engineLoop
|
||||||
r3_setupWindow(HINSTANCE hInstance, undefined4 param_2,
|
|
||||||
undefined4 maximizeWindow); // 00402140 // r3_setupWindow
|
|
||||||
|
|
||||||
// 00401630
|
// 00401630
|
||||||
int r3_main(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR *cmdline,
|
int r3_main(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR *cmdline,
|
||||||
@@ -34,6 +33,7 @@ int r3_main(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR *cmdline,
|
|||||||
|
|
||||||
{
|
{
|
||||||
undefined4 uVar1;
|
undefined4 uVar1;
|
||||||
|
undefined2 uVar2;
|
||||||
undefined2 uVar3;
|
undefined2 uVar3;
|
||||||
LPSTR pCVar3;
|
LPSTR pCVar3;
|
||||||
char *pcVar4;
|
char *pcVar4;
|
||||||
@@ -44,68 +44,228 @@ int r3_main(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR *cmdline,
|
|||||||
HANDLE hTargetProcessHandle;
|
HANDLE hTargetProcessHandle;
|
||||||
HANDLE hSourceHandle;
|
HANDLE hSourceHandle;
|
||||||
HANDLE hSourceProcessHandle;
|
HANDLE hSourceProcessHandle;
|
||||||
LPSTR *ppCVar8;
|
uint *ppCVar8;
|
||||||
uint32_t uVar9;
|
|
||||||
HWND hWnd;
|
HWND hWnd;
|
||||||
int iVar10;
|
int iVar10;
|
||||||
int iVar11;
|
int iVar11;
|
||||||
int iVar12;
|
int iVar12;
|
||||||
int iVar13;
|
int iVar13;
|
||||||
uint uVar14;
|
uint uVar14;
|
||||||
void *unaff_ESI;
|
HKEY unaff_ESI;
|
||||||
undefined4 *puVar15;
|
|
||||||
void *unaff_EDI;
|
|
||||||
undefined4 *puVar16;
|
|
||||||
char *pcVar17;
|
char *pcVar17;
|
||||||
undefined4 uStack_83c;
|
void *p_cTxt1;
|
||||||
HKEY pHStack_838;
|
void *p_cTxt2;
|
||||||
HANDLE pvStack_834;
|
undefined4 uStack_85c;
|
||||||
UINT UStack_830;
|
undefined4 uStack_858;
|
||||||
BYTE aBStack_82c[4];
|
LPSTR lpBuffer;
|
||||||
DWORD DStack_828;
|
UINT uiParam;
|
||||||
DWORD DStack_824;
|
BYTE uStack_83c[4];
|
||||||
tagRECT tStack_820;
|
DWORD pHStack_838;
|
||||||
char acStack_810[260];
|
DWORD pvStack_834;
|
||||||
CHAR languageStr[256];
|
char UStack_830[16];
|
||||||
CHAR pathToUbi_ini[260];
|
char tStack_820[260];
|
||||||
char acStack_508[260];
|
CHAR aCStack_71c[256];
|
||||||
CHAR windowsDir[260];
|
char acStack_61c[16];
|
||||||
char acStack_300[256];
|
CHAR pathToUbi_ini[228];
|
||||||
char acStack_200[256];
|
char acStack_528[16];
|
||||||
char acStack_100[256];
|
char acStack_518[244];
|
||||||
|
char acStack_424[0x104];
|
||||||
|
char acStack_320[16];
|
||||||
|
char acStack_310[240];
|
||||||
|
char acStack_220[256];
|
||||||
|
char acStack_120[260];
|
||||||
|
HINSTANCE instance;
|
||||||
|
uint *puStack_14;
|
||||||
|
undefined4 uStack_10;
|
||||||
|
int iStack_8;
|
||||||
BOOL BVar18;
|
BOOL BVar18;
|
||||||
char cVar1;
|
char cVar1;
|
||||||
undefined4 chars;
|
undefined4 chars;
|
||||||
DWORD dwOptions;
|
DWORD dwOptions;
|
||||||
tagRECT *lpRect;
|
LPRECT lpRect;
|
||||||
HANDLE *lpTargetHandle;
|
LPHANDLE lpTargetHandle;
|
||||||
undefined2 uVar2;
|
|
||||||
undefined4 uVar22;
|
undefined4 uVar22;
|
||||||
|
|
||||||
|
#if RE_AUTHENTIC == 0
|
||||||
|
lpBuffer = pathToUbi_ini;
|
||||||
|
uiParam = 0x104;
|
||||||
|
/* Append windows dir / ubi.ini */
|
||||||
|
uStack_858 = 0x40164d;
|
||||||
|
GetWindowsDirectoryA(lpBuffer, 0x104);
|
||||||
|
iVar13 = -1;
|
||||||
|
pcVar4 = acStack_61c;
|
||||||
|
do {
|
||||||
|
pcVar17 = pcVar4;
|
||||||
|
if (iVar13 == 0)
|
||||||
|
break;
|
||||||
|
iVar13 = iVar13 + -1;
|
||||||
|
pcVar17 = pcVar4 + 1;
|
||||||
|
cVar1 = *pcVar4;
|
||||||
|
pcVar4 = pcVar17;
|
||||||
|
} while (cVar1 != '\0');
|
||||||
|
*(undefined4 *)(pcVar17 + -1) = s_UbiSoft_Ubi_ini + Field<0, 4>();
|
||||||
|
*(undefined4 *)(pcVar17 + 3) = s_UbiSoft_Ubi_ini + Field<4, 4>();
|
||||||
|
*(undefined4 *)(pcVar17 + 7) = s_UbiSoft_Ubi_ini + Field<8, 4>();
|
||||||
|
*(undefined4 *)(pcVar17 + 0xb) = s_UbiSoft_Ubi_ini + Field<12, 4>();
|
||||||
|
pcVar17[0xf] = s_UbiSoft_Ubi_ini[0x10];
|
||||||
pCVar3 = GetCommandLineA();
|
pCVar3 = GetCommandLineA();
|
||||||
|
pcVar4 = pCVar3 + 1;
|
||||||
R3Config &gameConfig = getDefaultConfig();
|
iVar13 = -(int)pcVar4;
|
||||||
|
do {
|
||||||
// Store and change to game directory
|
cVar1 = *pcVar4;
|
||||||
chdir(gameConfig.gameRootDir.c_str());
|
pcVar4[(int)(tStack_820 + iVar13)] = cVar1;
|
||||||
strcpy(r3_main_data_005d28b6.gameDataDir, gameConfig.gameRootDir.c_str());
|
pcVar4 = pcVar4 + 1;
|
||||||
|
} while (cVar1 != '\0');
|
||||||
strcpy(languageStr, gameConfig.language.c_str());
|
pcVar4 = strrchr(tStack_820, 0x5c); // Get the exe path
|
||||||
|
if (pcVar4 == (char *)0x0) {
|
||||||
|
/* Read from ubi.ini */
|
||||||
|
GetPrivateProfileStringA(lpAppName_005b68f0, s_Directory_005b68f8, s_None,
|
||||||
|
tStack_820, 0xff, acStack_61c);
|
||||||
|
iVar13 = strcmpi(tStack_820, s_None);
|
||||||
|
} else { // We have the .exe path
|
||||||
|
pcVar4 = strrchr(tStack_820, 0x5c);
|
||||||
|
*pcVar4 = '\0'; // Split into the binary path (strip .exe)
|
||||||
|
iVar13 = chdir(tStack_820); // Change into the binary path
|
||||||
|
if (iVar13 != -1)
|
||||||
|
goto LAB_00401765;
|
||||||
|
/* Read from ubi.ini */
|
||||||
|
GetPrivateProfileStringA(lpAppName_005b68f0, s_Directory_005b68f8, s_None,
|
||||||
|
tStack_820, 0xff, acStack_61c);
|
||||||
|
iVar13 = strcmpi(tStack_820, s_None);
|
||||||
|
}
|
||||||
|
if (iVar13 != 0) {
|
||||||
|
chdir(tStack_820);
|
||||||
|
}
|
||||||
|
LAB_00401765:
|
||||||
|
/* strcpy */
|
||||||
|
iVar13 = 0;
|
||||||
|
do {
|
||||||
|
cVar1 = tStack_820[iVar13];
|
||||||
|
r3_main_data_005d28b6.gameDataDir[iVar13] = cVar1;
|
||||||
|
iVar13 = iVar13 + 1;
|
||||||
|
} while (cVar1 != '\0');
|
||||||
|
strlwr(r3_main_data_005d28b6.gameDataDir);
|
||||||
|
iVar13 = -1;
|
||||||
|
pcVar4 = r3_main_data_005d28b6.gameDataDir;
|
||||||
|
do {
|
||||||
|
if (iVar13 == 0)
|
||||||
|
break;
|
||||||
|
iVar13 = iVar13 + -1;
|
||||||
|
cVar1 = *pcVar4;
|
||||||
|
pcVar4 = pcVar4 + 1;
|
||||||
|
} while (cVar1 != '\0');
|
||||||
|
joined_r0x00401792:
|
||||||
|
if (iVar13 != -2) {
|
||||||
|
uVar14 = 0xffffffff;
|
||||||
|
pcVar4 = r3_main_data_005d28b6.gameDataDir;
|
||||||
|
do {
|
||||||
|
if (uVar14 == 0)
|
||||||
|
break;
|
||||||
|
uVar14 = uVar14 - 1;
|
||||||
|
cVar1 = *pcVar4;
|
||||||
|
pcVar4 = pcVar4 + 1;
|
||||||
|
} while (cVar1 != '\0');
|
||||||
|
if (r3_main_data_005d28b6.gameDataDir[~uVar14 - 2] != '\\')
|
||||||
|
goto LAB_004017ce;
|
||||||
|
uVar14 = 0xffffffff;
|
||||||
|
pcVar4 = r3_main_data_005d28b6.gameDataDir;
|
||||||
|
do {
|
||||||
|
if (uVar14 == 0)
|
||||||
|
break;
|
||||||
|
uVar14 = uVar14 - 1;
|
||||||
|
cVar1 = *pcVar4;
|
||||||
|
pcVar4 = pcVar4 + 1;
|
||||||
|
} while (cVar1 != '\0');
|
||||||
|
r3_main_data_005d28b6.gameDataDir[~uVar14 - 2] = '\0';
|
||||||
|
iVar13 = -1;
|
||||||
|
pcVar4 = r3_main_data_005d28b6.gameDataDir;
|
||||||
|
do {
|
||||||
|
if (iVar13 == 0)
|
||||||
|
break;
|
||||||
|
iVar13 = iVar13 + -1;
|
||||||
|
cVar1 = *pcVar4;
|
||||||
|
pcVar4 = pcVar4 + 1;
|
||||||
|
} while (cVar1 != '\0');
|
||||||
|
goto joined_r0x00401792;
|
||||||
|
}
|
||||||
|
LAB_004017ce:
|
||||||
|
pFVar5 = fopen(acStack_61c, fopen_mode_r_text);
|
||||||
|
GetPrivateProfileStringA(lpAppName_005b68f0, s_Adapter_005b68e4,
|
||||||
|
(LPCSTR)&lpDefault_005cf96c, acStack_310, 0xff,
|
||||||
|
acStack_61c);
|
||||||
|
if ((pFVar5 == (FILE *)0x0) || (acStack_310[0] == '\0')) {
|
||||||
|
/* Concat game data dir with r3 setup exe */
|
||||||
|
iVar13 = 0;
|
||||||
|
do {
|
||||||
|
cVar1 = r3_main_data_005d28b6.gameDataDir[iVar13];
|
||||||
|
acStack_518[iVar13] = cVar1;
|
||||||
|
iVar13 = iVar13 + 1;
|
||||||
|
} while (cVar1 != '\0');
|
||||||
|
iVar13 = -1;
|
||||||
|
pcVar4 = acStack_518;
|
||||||
|
do {
|
||||||
|
pcVar17 = pcVar4;
|
||||||
|
if (iVar13 == 0)
|
||||||
|
break;
|
||||||
|
iVar13 = iVar13 + -1;
|
||||||
|
pcVar17 = pcVar4 + 1;
|
||||||
|
cVar1 = *pcVar4;
|
||||||
|
pcVar4 = pcVar17;
|
||||||
|
} while (cVar1 != '\0');
|
||||||
|
*(undefined4 *)(pcVar17 + -1) =
|
||||||
|
s__R3_Setup_DX8_exe_005b68d0 + Field<0, 4>();
|
||||||
|
*(undefined4 *)(pcVar17 + 3) = s__R3_Setup_DX8_exe_005b68d0 + Field<4, 4>();
|
||||||
|
*(undefined4 *)(pcVar17 + 7) = s__R3_Setup_DX8_exe_005b68d0 + Field<8, 4>();
|
||||||
|
*(undefined4 *)(pcVar17 + 0xb) =
|
||||||
|
s__R3_Setup_DX8_exe_005b68d0 + Field<12, 4>();
|
||||||
|
*(undefined2 *)(pcVar17 + 0xf) =
|
||||||
|
s__R3_Setup_DX8_exe_005b68d0 + Field<16, 2>();
|
||||||
|
pFVar5 = fopen(acStack_518, fopen_mode_r_binary);
|
||||||
|
if (pFVar5 == (FILE *)0x0) {
|
||||||
|
MessageBoxA((HWND)0x0, s_Unable_to_find_R3_Setup_DX8_exe__005b6880,
|
||||||
|
s_Rayman_3_Error_005b68bc, 0x10);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fclose(pFVar5);
|
||||||
|
spawnl(0, acStack_518, acStack_518, 0);
|
||||||
|
pFVar5 = fopen(acStack_61c, fopen_mode_r_text);
|
||||||
|
if (pFVar5 == (FILE *)0x0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(pFVar5);
|
||||||
|
/* Open reg key
|
||||||
|
HKEY_LOCAL_MACHINE\\SOFTWARE\\UBI SOFT\\RAYMAN 3 */
|
||||||
|
HKEY key;
|
||||||
|
LVar6 =
|
||||||
|
RegOpenKeyExA(HKEY_LOCAL_MACHINE, s_SOFTWARE_UBI_SOFT_RAYMAN_3_005b6864,
|
||||||
|
0, 0x20019, &key);
|
||||||
|
if (LVar6 == 0) {
|
||||||
|
LVar6 = RegQueryValueExA(key, s_CompleteInstall_005b6854, (LPDWORD)0x0,
|
||||||
|
&pvStack_834, uStack_83c, &pHStack_838);
|
||||||
|
DAT_007d9cc4 = (uint)(LVar6 == 0);
|
||||||
|
if (key != (HKEY)0x0) {
|
||||||
|
RegCloseKey(key);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DAT_007d9cc4 = 0;
|
||||||
|
}
|
||||||
|
GetPrivateProfileStringA(lpAppName_005b68f0, s_Language_005b6840,
|
||||||
|
s_English_005b684c, aCStack_71c, 0xff, acStack_61c);
|
||||||
sprintf(g_mutexName_Rayman3, s_percents, lpAppName_005b68f0);
|
sprintf(g_mutexName_Rayman3, s_percents, lpAppName_005b68f0);
|
||||||
sprintf(g_windowTitle, s_percents, s_windowTitle);
|
sprintf(g_windowTitle, s_percents, s_windowTitle);
|
||||||
|
|
||||||
/* Setup localized quiting/restoring strings */
|
/* Setup localized quiting/restoring strings */
|
||||||
iVar13 = strcmpi(languageStr, s_French_005b6828);
|
iVar13 = strcmpi(aCStack_71c, s_French_005b6828);
|
||||||
if (iVar13 == 0) {
|
if (iVar13 == 0) {
|
||||||
sprintf(s_windowTitleRestoring, s_Restauration_fmt, s_windowTitle);
|
sprintf(g_windowTitleRestoring, s_Restauration_fmt, s_windowTitle);
|
||||||
chars = s_QUITTER + Field<4, 4>();
|
chars = s_QUITTER + Field<4, 4>();
|
||||||
puVar15 = (undefined4 *)s_ou_appuyez_sur_Echap_pour_quitte_005b67d0;
|
pcVar4 = s_ou_appuyez_sur_Echap_pour_quitte_005b67d0;
|
||||||
puVar16 = (undefined4 *)s_quitting1;
|
pcVar17 = s_quitting1;
|
||||||
for (iVar13 = 0xb; uVar22 = s_QUITTER + Field<4, 4>(), iVar13 != 0;
|
for (iVar13 = 0xb; uVar22 = s_QUITTER + Field<4, 4>(), iVar13 != 0;
|
||||||
iVar13 = iVar13 + -1) {
|
iVar13 = iVar13 + -1) {
|
||||||
*puVar16 = *puVar15;
|
*(undefined4 *)pcVar17 = *(undefined4 *)pcVar4;
|
||||||
puVar15 = puVar15 + 1;
|
pcVar4 = pcVar4 + 4;
|
||||||
puVar16 = puVar16 + 1;
|
pcVar17 = pcVar17 + 4;
|
||||||
}
|
}
|
||||||
s_wndStrQuiting[0] = s_QUITTER[0];
|
s_wndStrQuiting[0] = s_QUITTER[0];
|
||||||
s_wndStrQuiting[1] = s_QUITTER[1];
|
s_wndStrQuiting[1] = s_QUITTER[1];
|
||||||
@@ -121,30 +281,30 @@ int r3_main(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR *cmdline,
|
|||||||
s_wndStrQuiting[6] = s_QUITTER[6];
|
s_wndStrQuiting[6] = s_QUITTER[6];
|
||||||
s_wndStrQuiting[7] = s_QUITTER[7];
|
s_wndStrQuiting[7] = s_QUITTER[7];
|
||||||
s_QUITTER + Field<4, 4>() = uVar22;
|
s_QUITTER + Field<4, 4>() = uVar22;
|
||||||
sprintf(lpString_0077d2c0, s__s___Pause_005b67c4, s_windowTitle);
|
sprintf(g_windowTitle1, s__s___Pause_005b67c4, s_windowTitle);
|
||||||
puVar15 = (undefined4 *)s_Restauration;
|
pcVar4 = s_Restauration;
|
||||||
puVar16 = (undefined4 *)s_wndStrRestoring;
|
pcVar17 = s_wndStrRestoring;
|
||||||
for (iVar13 = 7; iVar13 != 0; iVar13 = iVar13 + -1) {
|
for (iVar13 = 7; iVar13 != 0; iVar13 = iVar13 + -1) {
|
||||||
*puVar16 = *puVar15;
|
*(undefined4 *)pcVar17 = *(undefined4 *)pcVar4;
|
||||||
puVar15 = puVar15 + 1;
|
pcVar4 = pcVar4 + 4;
|
||||||
puVar16 = puVar16 + 1;
|
pcVar17 = pcVar17 + 4;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
iVar13 = strcmpi(languageStr, s_Spanish_005b67a0);
|
iVar13 = strcmpi(aCStack_71c, s_Spanish_005b67a0);
|
||||||
if (iVar13 == 0) {
|
if (iVar13 == 0) {
|
||||||
sprintf(s_windowTitleRestoring, s__s___Restablecer_datos____005b6784,
|
sprintf(g_windowTitleRestoring, s__s___Restablecer_datos____005b6784,
|
||||||
s_windowTitle);
|
s_windowTitle);
|
||||||
uVar2 = s_SALIR_005b675c + Field<4, 2>();
|
uVar2 = s_SALIR_005b675c + Field<4, 2>();
|
||||||
puVar15 = (undefined4 *)s_Pulsa_ESC_para_salir_Rayman_3__005b6764;
|
pcVar4 = s_Pulsa_ESC_para_salir_Rayman_3__005b6764;
|
||||||
puVar16 = (undefined4 *)s_quitting1;
|
pcVar17 = s_quitting1;
|
||||||
for (iVar13 = 7; chars = s_SALIR_005b675c + Field<0, 4>(), iVar13 != 0;
|
for (iVar13 = 7; chars = s_SALIR_005b675c + Field<0, 4>(), iVar13 != 0;
|
||||||
iVar13 = iVar13 + -1) {
|
iVar13 = iVar13 + -1) {
|
||||||
*puVar16 = *puVar15;
|
*(undefined4 *)pcVar17 = *(undefined4 *)pcVar4;
|
||||||
puVar15 = puVar15 + 1;
|
pcVar4 = pcVar4 + 4;
|
||||||
puVar16 = puVar16 + 1;
|
pcVar17 = pcVar17 + 4;
|
||||||
}
|
}
|
||||||
*(undefined2 *)puVar16 = *(undefined2 *)puVar15;
|
*(undefined2 *)pcVar17 = *(undefined2 *)pcVar4;
|
||||||
*(undefined *)((int)puVar16 + 2) = *(undefined *)((int)puVar15 + 2);
|
pcVar17[2] = pcVar4[2];
|
||||||
uVar3 = s_SALIR_005b675c + Field<4, 2>();
|
uVar3 = s_SALIR_005b675c + Field<4, 2>();
|
||||||
uVar22 = s_SALIR_005b675c + Field<0, 4>();
|
uVar22 = s_SALIR_005b675c + Field<0, 4>();
|
||||||
s_SALIR_005b675c[0] = (char)chars;
|
s_SALIR_005b675c[0] = (char)chars;
|
||||||
@@ -161,36 +321,42 @@ int r3_main(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR *cmdline,
|
|||||||
s_wndStrQuiting[5] = s_SALIR_005b675c[5];
|
s_wndStrQuiting[5] = s_SALIR_005b675c[5];
|
||||||
s_SALIR_005b675c + Field<0, 4>() = uVar22;
|
s_SALIR_005b675c + Field<0, 4>() = uVar22;
|
||||||
s_SALIR_005b675c + Field<4, 2>() = uVar3;
|
s_SALIR_005b675c + Field<4, 2>() = uVar3;
|
||||||
sprintf(lpString_0077d2c0, s__s___Rotura_005b6750, s_windowTitle);
|
sprintf(g_windowTitle1, s__s___Rotura_005b6750, s_windowTitle);
|
||||||
puVar15 = (undefined4 *)s_Restablecer_datos____005b6738;
|
pcVar4 = s_Restablecer_datos____005b6738;
|
||||||
puVar16 = (undefined4 *)s_wndStrRestoring;
|
pcVar17 = s_wndStrRestoring;
|
||||||
for (iVar13 = 5; iVar13 != 0; iVar13 = iVar13 + -1) {
|
for (iVar13 = 5; iVar13 != 0; iVar13 = iVar13 + -1) {
|
||||||
*puVar16 = *puVar15;
|
*(undefined4 *)pcVar17 = *(undefined4 *)pcVar4;
|
||||||
puVar15 = puVar15 + 1;
|
pcVar4 = pcVar4 + 4;
|
||||||
puVar16 = puVar16 + 1;
|
pcVar17 = pcVar17 + 4;
|
||||||
}
|
}
|
||||||
*(undefined *)puVar16 = *(undefined *)puVar15;
|
*pcVar17 = *pcVar4;
|
||||||
} else {
|
} else {
|
||||||
iVar13 = strcmpi(languageStr, s_Italian_005b6730);
|
iVar13 = strcmpi(aCStack_71c, s_Italian_005b6730);
|
||||||
if (iVar13 == 0) {
|
if (iVar13 == 0) {
|
||||||
sprintf(s_windowTitleRestoring, s__s___Ripristino_dati____005b6718,
|
sprintf(g_windowTitleRestoring, s__s___Ripristino_dati____005b6718,
|
||||||
s_windowTitle);
|
s_windowTitle);
|
||||||
uVar2 = s_USCIRE_005b66ec + Field<4, 2>();
|
uVar2 = s_USCIRE_005b66ec + Field<4, 2>();
|
||||||
puVar15 = (undefined4 *)s_Premi_ESC_per_uscire_da_Rayman_3_005b66f4;
|
pcVar4 = s_Premi_ESC_per_uscire_da_Rayman_3_005b66f4;
|
||||||
puVar16 = (undefined4 *)s_quitting1;
|
pcVar17 = s_quitting1;
|
||||||
for (iVar13 = 8; cVar1 = s_USCIRE_005b66ec[6], iVar13 != 0;
|
for (iVar13 = 8; cVar1 = s_USCIRE_005b66ec[6], iVar13 != 0;
|
||||||
iVar13 = iVar13 + -1) {
|
iVar13 = iVar13 + -1) {
|
||||||
*puVar16 = *puVar15;
|
*(undefined4 *)pcVar17 = *(undefined4 *)pcVar4;
|
||||||
puVar15 = puVar15 + 1;
|
pcVar4 = pcVar4 + 4;
|
||||||
puVar16 = puVar16 + 1;
|
pcVar17 = pcVar17 + 4;
|
||||||
}
|
}
|
||||||
s_wndStrQuiting[0] = s_USCIRE_005b66ec[0];
|
s_wndStrQuiting[0] = s_USCIRE_005b66ec[0];
|
||||||
s_wndStrQuiting[1] = s_USCIRE_005b66ec[1];
|
s_wndStrQuiting[1] = s_USCIRE_005b66ec[1];
|
||||||
s_wndStrQuiting[2] = s_USCIRE_005b66ec[2];
|
s_wndStrQuiting[2] = s_USCIRE_005b66ec[2];
|
||||||
s_wndStrQuiting[3] = s_USCIRE_005b66ec[3];
|
s_wndStrQuiting[3] = s_USCIRE_005b66ec[3];
|
||||||
*(undefined2 *)puVar16 = *(undefined2 *)puVar15;
|
*(undefined2 *)pcVar17 = *(undefined2 *)pcVar4;
|
||||||
s_wndStrQuiting + Field<4, 3>() = CONCAT12(cVar1, uVar2);
|
uVar3 = s_USCIRE_005b66ec + Field<4, 2>();
|
||||||
sprintf(lpString_0077d2c0, s__s___Pausa_005b66e0, s_windowTitle);
|
s_wndStrQuiting[6] = cVar1;
|
||||||
|
s_USCIRE_005b66ec[4] = (char)uVar2;
|
||||||
|
s_USCIRE_005b66ec[5] = SUB21(uVar2, 1);
|
||||||
|
s_wndStrQuiting[4] = s_USCIRE_005b66ec[4];
|
||||||
|
s_wndStrQuiting[5] = s_USCIRE_005b66ec[5];
|
||||||
|
s_USCIRE_005b66ec + Field<4, 2>() = uVar3;
|
||||||
|
sprintf(g_windowTitle1, s__s___Pausa_005b66e0, s_windowTitle);
|
||||||
s_wndStrRestoring[0] = s_Ripristino_dati____005b66cc[0];
|
s_wndStrRestoring[0] = s_Ripristino_dati____005b66cc[0];
|
||||||
s_wndStrRestoring[1] = s_Ripristino_dati____005b66cc[1];
|
s_wndStrRestoring[1] = s_Ripristino_dati____005b66cc[1];
|
||||||
s_wndStrRestoring[2] = s_Ripristino_dati____005b66cc[2];
|
s_wndStrRestoring[2] = s_Ripristino_dati____005b66cc[2];
|
||||||
@@ -209,21 +375,21 @@ int r3_main(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR *cmdline,
|
|||||||
s_Ripristino_dati____005b66cc + Field<16, 2>();
|
s_Ripristino_dati____005b66cc + Field<16, 2>();
|
||||||
s_wndStrRestoring[0x12] = s_Ripristino_dati____005b66cc[0x12];
|
s_wndStrRestoring[0x12] = s_Ripristino_dati____005b66cc[0x12];
|
||||||
} else {
|
} else {
|
||||||
iVar13 = strcmpi(languageStr, s_German_005b66c4);
|
iVar13 = strcmpi(aCStack_71c, s_German_005b66c4);
|
||||||
if (iVar13 == 0) {
|
if (iVar13 == 0) {
|
||||||
sprintf(s_windowTitleRestoring, s__s___Daten_Reparatur____005b66ac,
|
sprintf(g_windowTitleRestoring, s__s___Daten_Reparatur____005b66ac,
|
||||||
s_windowTitle);
|
s_windowTitle);
|
||||||
chars = s_BEENDIGEN_005b6678 + Field<0, 4>();
|
chars = s_BEENDIGEN_005b6678 + Field<0, 4>();
|
||||||
puVar15 = (undefined4 *)&CHAR_E_005b6684;
|
pcVar4 = &CHAR_E_005b6684;
|
||||||
puVar16 = (undefined4 *)s_quitting1;
|
pcVar17 = s_quitting1;
|
||||||
for (iVar13 = 9; uVar2 = s_BEENDIGEN_005b6678 + Field<8, 2>(),
|
for (iVar13 = 9; uVar2 = s_BEENDIGEN_005b6678 + Field<8, 2>(),
|
||||||
uVar22 = s_BEENDIGEN_005b6678 + Field<4, 4>(), iVar13 != 0;
|
uVar22 = s_BEENDIGEN_005b6678 + Field<4, 4>(), iVar13 != 0;
|
||||||
iVar13 = iVar13 + -1) {
|
iVar13 = iVar13 + -1) {
|
||||||
*puVar16 = *puVar15;
|
*(undefined4 *)pcVar17 = *(undefined4 *)pcVar4;
|
||||||
puVar15 = puVar15 + 1;
|
pcVar4 = pcVar4 + 4;
|
||||||
puVar16 = puVar16 + 1;
|
pcVar17 = pcVar17 + 4;
|
||||||
}
|
}
|
||||||
*(undefined2 *)puVar16 = *(undefined2 *)puVar15;
|
*(undefined2 *)pcVar17 = *(undefined2 *)pcVar4;
|
||||||
uVar1 = s_BEENDIGEN_005b6678 + Field<0, 4>();
|
uVar1 = s_BEENDIGEN_005b6678 + Field<0, 4>();
|
||||||
s_BEENDIGEN_005b6678[0] = (char)chars;
|
s_BEENDIGEN_005b6678[0] = (char)chars;
|
||||||
s_BEENDIGEN_005b6678[1] = SUB41(chars, 1);
|
s_BEENDIGEN_005b6678[1] = SUB41(chars, 1);
|
||||||
@@ -234,7 +400,7 @@ int r3_main(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR *cmdline,
|
|||||||
s_wndStrQuiting[2] = s_BEENDIGEN_005b6678[2];
|
s_wndStrQuiting[2] = s_BEENDIGEN_005b6678[2];
|
||||||
s_wndStrQuiting[3] = s_BEENDIGEN_005b6678[3];
|
s_wndStrQuiting[3] = s_BEENDIGEN_005b6678[3];
|
||||||
s_BEENDIGEN_005b6678 + Field<0, 4>() = uVar1;
|
s_BEENDIGEN_005b6678 + Field<0, 4>() = uVar1;
|
||||||
*(undefined *)((int)puVar16 + 2) = *(undefined *)((int)puVar15 + 2);
|
pcVar17[2] = pcVar4[2];
|
||||||
uVar3 = s_BEENDIGEN_005b6678 + Field<8, 2>();
|
uVar3 = s_BEENDIGEN_005b6678 + Field<8, 2>();
|
||||||
chars = s_BEENDIGEN_005b6678 + Field<4, 4>();
|
chars = s_BEENDIGEN_005b6678 + Field<4, 4>();
|
||||||
s_BEENDIGEN_005b6678[4] = (char)uVar22;
|
s_BEENDIGEN_005b6678[4] = (char)uVar22;
|
||||||
@@ -251,7 +417,7 @@ int r3_main(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR *cmdline,
|
|||||||
s_wndStrQuiting[9] = s_BEENDIGEN_005b6678[9];
|
s_wndStrQuiting[9] = s_BEENDIGEN_005b6678[9];
|
||||||
s_BEENDIGEN_005b6678 + Field<4, 4>() = chars;
|
s_BEENDIGEN_005b6678 + Field<4, 4>() = chars;
|
||||||
s_BEENDIGEN_005b6678 + Field<8, 2>() = uVar3;
|
s_BEENDIGEN_005b6678 + Field<8, 2>() = uVar3;
|
||||||
sprintf(lpString_0077d2c0, s__s___Pause_005b67c4, s_windowTitle);
|
sprintf(g_windowTitle1, s__s___Pause_005b67c4, s_windowTitle);
|
||||||
s_wndStrRestoring[0] = s_Daten_Reparatur____005b6664[0];
|
s_wndStrRestoring[0] = s_Daten_Reparatur____005b6664[0];
|
||||||
s_wndStrRestoring[1] = s_Daten_Reparatur____005b6664[1];
|
s_wndStrRestoring[1] = s_Daten_Reparatur____005b6664[1];
|
||||||
s_wndStrRestoring[2] = s_Daten_Reparatur____005b6664[2];
|
s_wndStrRestoring[2] = s_Daten_Reparatur____005b6664[2];
|
||||||
@@ -272,19 +438,19 @@ int r3_main(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR *cmdline,
|
|||||||
s_wndStrRestoring[0x11] = s_Daten_Reparatur____005b6664[0x11];
|
s_wndStrRestoring[0x11] = s_Daten_Reparatur____005b6664[0x11];
|
||||||
s_wndStrRestoring[0x12] = s_Daten_Reparatur____005b6664[0x12];
|
s_wndStrRestoring[0x12] = s_Daten_Reparatur____005b6664[0x12];
|
||||||
} else {
|
} else {
|
||||||
sprintf(s_windowTitleRestoring, s__s___Restoring_data____005b664c,
|
sprintf(g_windowTitleRestoring, s__s___Restoring_data____005b664c,
|
||||||
s_windowTitle);
|
s_windowTitle);
|
||||||
chars = s_QUIT + Field<0, 4>();
|
chars = s_QUIT + Field<0, 4>();
|
||||||
puVar15 = (undefined4 *)s_or_press_ESC_to_quit_Rayman_3__005b662c;
|
pcVar4 = s_or_press_ESC_to_quit_Rayman_3__005b662c;
|
||||||
puVar16 = (undefined4 *)s_quitting1;
|
pcVar17 = s_quitting1;
|
||||||
for (iVar13 = 7; cVar1 = s_QUIT[4], iVar13 != 0;
|
for (iVar13 = 7; cVar1 = s_QUIT[4], iVar13 != 0;
|
||||||
iVar13 = iVar13 + -1) {
|
iVar13 = iVar13 + -1) {
|
||||||
*puVar16 = *puVar15;
|
*(undefined4 *)pcVar17 = *(undefined4 *)pcVar4;
|
||||||
puVar15 = puVar15 + 1;
|
pcVar4 = pcVar4 + 4;
|
||||||
puVar16 = puVar16 + 1;
|
pcVar17 = pcVar17 + 4;
|
||||||
}
|
}
|
||||||
*(undefined2 *)puVar16 = *(undefined2 *)puVar15;
|
*(undefined2 *)pcVar17 = *(undefined2 *)pcVar4;
|
||||||
*(undefined *)((int)puVar16 + 2) = *(undefined *)((int)puVar15 + 2);
|
pcVar17[2] = pcVar4[2];
|
||||||
uVar22 = s_QUIT + Field<0, 4>();
|
uVar22 = s_QUIT + Field<0, 4>();
|
||||||
s_QUIT[0] = (char)chars;
|
s_QUIT[0] = (char)chars;
|
||||||
s_QUIT[1] = SUB41(chars, 1);
|
s_QUIT[1] = SUB41(chars, 1);
|
||||||
@@ -296,7 +462,7 @@ int r3_main(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR *cmdline,
|
|||||||
s_wndStrQuiting[3] = s_QUIT[3];
|
s_wndStrQuiting[3] = s_QUIT[3];
|
||||||
s_wndStrQuiting[4] = cVar1;
|
s_wndStrQuiting[4] = cVar1;
|
||||||
s_QUIT + Field<0, 4>() = uVar22;
|
s_QUIT + Field<0, 4>() = uVar22;
|
||||||
sprintf(lpString_0077d2c0, s__s___Pause_005b67c4, s_windowTitle);
|
sprintf(g_windowTitle1, s__s___Pause_005b67c4, s_windowTitle);
|
||||||
s_wndStrRestoring[0] = s_Restoring_data_____005b6610[0];
|
s_wndStrRestoring[0] = s_Restoring_data_____005b6610[0];
|
||||||
s_wndStrRestoring[1] = s_Restoring_data_____005b6610[1];
|
s_wndStrRestoring[1] = s_Restoring_data_____005b6610[1];
|
||||||
s_wndStrRestoring[2] = s_Restoring_data_____005b6610[2];
|
s_wndStrRestoring[2] = s_Restoring_data_____005b6610[2];
|
||||||
@@ -318,108 +484,179 @@ int r3_main(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR *cmdline,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
auto &config = getDefaultConfig();
|
||||||
|
strcpy(g_windowTitle, "Reman3");
|
||||||
|
strcpy(g_windowTitle1, "Reman3 - Paused");
|
||||||
|
strcpy(g_windowTitleRestoring, "Restoring data");
|
||||||
|
strcpy(r3_main_data_005d28b6.gameDataDir, config.gameRootDir.c_str());
|
||||||
|
strlwr(r3_main_data_005d28b6.gameDataDir);
|
||||||
|
strcpy(g_mutexName_Rayman3, "Rayman3");
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Create draw semaphore
|
/* Create draw semaphore
|
||||||
Initial count = 1
|
Initial count = 1
|
||||||
Maximum count = 1 */
|
Maximum count = 1 */
|
||||||
g_drawSemaphore =
|
g_drawSemaphore =
|
||||||
CreateSemaphoreA((LPSECURITY_ATTRIBUTES)0x0, 1, 1, s_DRAWSEM_005b6608);
|
CreateSemaphoreA((LPSECURITY_ATTRIBUTES)0x0, 1, 1, s_DRAWSEM_005b6608);
|
||||||
if (hPrevInstance != (HINSTANCE)0x0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// FIXME: Not sure where this is set
|
||||||
|
/*if (iStack_8 != 0) {
|
||||||
|
return -1;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
#if RE_AUTHENTIC == 0
|
||||||
/* Load DirectPlay probably unused */
|
/* Load DirectPlay probably unused */
|
||||||
// hLibModule = LoadLibraryA(s_dpnhpast_dll_005b65f8);
|
hLibModule = LoadLibraryA(s_dpnhpast_dll_005b65f8);
|
||||||
// if (hLibModule == (HMODULE)0x0) {
|
if (hLibModule == (HMODULE)0x0) {
|
||||||
// iVar13 = strcmpi(languageStr, s_French_005b6828);
|
iVar13 = strcmpi(aCStack_71c, s_French_005b6828);
|
||||||
// if (iVar13 == 0) {
|
if (iVar13 == 0) {
|
||||||
// MessageBoxA((HWND)0x0, lpText_005b6598, s_Erreur_Rayman_3_005b65e4,
|
MessageBoxA((HWND)0x0, lpText_005b6598, s_Erreur_Rayman_3_005b65e4, 0x10);
|
||||||
// 0x10); return -1;
|
return -1;
|
||||||
// }
|
}
|
||||||
// iVar13 = strcmpi(languageStr, s_Spanish_005b67a0);
|
iVar13 = strcmpi(aCStack_71c, s_Spanish_005b67a0);
|
||||||
// if (iVar13 == 0) {
|
if (iVar13 == 0) {
|
||||||
// MessageBoxA((HWND)0x0, lpText_005b6540, s_Rayman_3_005b6588, 0x10);
|
MessageBoxA((HWND)0x0, lpText_005b6540, s_Rayman_3_005b6588, 0x10);
|
||||||
// return -1;
|
return -1;
|
||||||
// }
|
}
|
||||||
// iVar13 = strcmpi(languageStr, s_Italian_005b6730);
|
iVar13 = strcmpi(aCStack_71c, s_Italian_005b6730);
|
||||||
// if (iVar13 == 0) {
|
if (iVar13 == 0) {
|
||||||
// MessageBoxA((HWND)0x0, lpText_005b64f0, s_Rayman_3_005b6588, 0x10);
|
MessageBoxA((HWND)0x0, lpText_005b64f0, s_Rayman_3_005b6588, 0x10);
|
||||||
// return -1;
|
return -1;
|
||||||
// }
|
}
|
||||||
// iVar13 = strcmpi(languageStr, s_German_005b66c4);
|
iVar13 = strcmpi(aCStack_71c, s_German_005b66c4);
|
||||||
// if (iVar13 != 0) {
|
if (iVar13 != 0) {
|
||||||
// MessageBoxA((HWND)0x0, s_Check_your_version_of_DirectX__V_005b6430,
|
MessageBoxA((HWND)0x0, s_Check_your_version_of_DirectX__V_005b6430,
|
||||||
// s_Rayman_3_Error_005b68bc, 0x10);
|
s_Rayman_3_Error_005b68bc, 0x10);
|
||||||
// return -1;
|
return -1;
|
||||||
// }
|
}
|
||||||
// MessageBoxA((HWND)0x0, lpText_005b6478, s_Rayman_3_005b6588, 0x10);
|
MessageBoxA((HWND)0x0, lpText_005b6478, s_Rayman_3_005b6588, 0x10);
|
||||||
// return -1;
|
|
||||||
// }
|
|
||||||
// FreeLibrary(hLibModule);
|
|
||||||
|
|
||||||
/* For GLIMode
|
|
||||||
1 = maximize
|
|
||||||
0 = windowed */
|
|
||||||
g_runMaximized = (int)(acStack_200[0] != '0');
|
|
||||||
// r3_checkDisc();
|
|
||||||
dwOptions = 0;
|
|
||||||
BVar18 = 0;
|
|
||||||
lpTargetHandle = &pvStack_834;
|
|
||||||
DVar7 = 0x1f03ff;
|
|
||||||
g_hinstance = hInstance;
|
|
||||||
hTargetProcessHandle = GetCurrentProcess();
|
|
||||||
hSourceHandle = GetCurrentThread();
|
|
||||||
hSourceProcessHandle = GetCurrentProcess();
|
|
||||||
DuplicateHandle(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle,
|
|
||||||
lpTargetHandle, DVar7, BVar18, dwOptions);
|
|
||||||
g_mainThreadHandle = pvStack_834;
|
|
||||||
/* Copy cmdline */
|
|
||||||
strcpy(g_appCmdLine, GetCommandLineA());
|
|
||||||
|
|
||||||
// SetErrorMode(1);
|
|
||||||
|
|
||||||
r3_initAllModules();
|
|
||||||
iVar13 = r3_setupWindow(hInstance, showCmd, g_runMaximized);
|
|
||||||
if (iVar13 == 0) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
g_setInitVar0();
|
FreeLibrary(hLibModule);
|
||||||
FUN_00401320();
|
#endif
|
||||||
spawnThread();
|
p_cTxt1 = (void *)0x401e2a;
|
||||||
gfx_init2();
|
CreateMutexA((LPSECURITY_ATTRIBUTES)0x0, 1, g_mutexName_Rayman3);
|
||||||
lpRect = &tStack_820;
|
DVar7 = GetLastError();
|
||||||
hWnd = GetDesktopWindow();
|
if (DVar7 == 0xb7) {
|
||||||
GetWindowRect(hWnd, lpRect);
|
/* Mutex already exists */
|
||||||
BVar18 = 1;
|
return -1;
|
||||||
iVar13 = r3_get_gli_height1();
|
}
|
||||||
iVar13 = iVar13 + 0x20;
|
p_cTxt2 = (void *)0x401e5a;
|
||||||
iVar10 = r3_get_gli_width1();
|
#if RE_AUTHENTIC == 0
|
||||||
iVar10 = iVar10 + 0xc;
|
GetWindowsDirectoryA(acStack_424, 0x104);
|
||||||
iVar11 = r3_get_gli_height1();
|
iVar13 = -1;
|
||||||
iVar11 = (tStack_820.bottom - iVar11) / 2;
|
/* Append ubi.ini */
|
||||||
iVar12 = r3_get_gli_width1();
|
pcVar4 = acStack_424;
|
||||||
MoveWindow(g_gameHWND, (tStack_820.right - iVar12) / 2, iVar11, iVar10,
|
do {
|
||||||
iVar13, BVar18);
|
pcVar17 = pcVar4;
|
||||||
FUN_004010b0();
|
if (iVar13 == 0)
|
||||||
SystemParametersInfoA(0x10, 0, &UStack_830, 0);
|
break;
|
||||||
SystemParametersInfoA(0x11, 0, (PVOID)0x0, 0);
|
iVar13 = iVar13 + -1;
|
||||||
ShowCursor(0);
|
pcVar17 = pcVar4 + 1;
|
||||||
uStack_83c = 0;
|
cVar1 = *pcVar4;
|
||||||
SystemParametersInfoA(0x61, 1, &uStack_83c, 0);
|
pcVar4 = pcVar17;
|
||||||
g_engineRunning = 1;
|
} while (cVar1 != '\0');
|
||||||
r3_initEngine();
|
*(undefined4 *)(pcVar17 + -1) = s_UbiSoft_Ubi_ini + Field<0, 4>();
|
||||||
FUN_004725a0();
|
*(undefined4 *)(pcVar17 + 3) = s_UbiSoft_Ubi_ini + Field<4, 4>();
|
||||||
FUN_005038e0();
|
*(undefined4 *)(pcVar17 + 7) = s_UbiSoft_Ubi_ini + Field<8, 4>();
|
||||||
FUN_00503710();
|
*(undefined4 *)(pcVar17 + 0xb) = s_UbiSoft_Ubi_ini + Field<12, 4>();
|
||||||
FUN_004fb300();
|
pcVar17[0xf] = s_UbiSoft_Ubi_ini[0x10];
|
||||||
FUN_00472150();
|
#else
|
||||||
FUN_00470db0();
|
strcpy(acStack_424, config.gameRootDir.c_str());
|
||||||
uStack_83c = 0;
|
strcat(acStack_424, "/ubi.ini");
|
||||||
SystemParametersInfoA(0x61, 0, &uStack_83c, 0);
|
instance = hInstance;
|
||||||
ShowCursor(1);
|
#endif
|
||||||
SystemParametersInfoA(0x11, UStack_830, (PVOID)0x0, 0);
|
/* Read graphics settings */
|
||||||
CloseHandle(pvStack_834);
|
GetPrivateProfileStringA(lpAppName_005b68f0, s_Adapter_005b68e4,
|
||||||
|
(LPCSTR)&lpDefault_005cf96c, acStack_320, 0xff,
|
||||||
return 0;
|
acStack_424);
|
||||||
|
GetPrivateProfileStringA(lpAppName_005b68f0, s_Identifier_005b6420,
|
||||||
|
(LPCSTR)&lpDefault_005cf96c, acStack_120, 0xff,
|
||||||
|
acStack_424);
|
||||||
|
GetPrivateProfileStringA(lpAppName_005b68f0, s_Gli_Mode_005b6414,
|
||||||
|
(LPCSTR)&lpDefault_005cf96c, acStack_220, 0xff,
|
||||||
|
acStack_424);
|
||||||
|
/* If they're all set */
|
||||||
|
if (((acStack_320[0] != '\0') && (acStack_120[0] != '\0')) &&
|
||||||
|
(acStack_220[0] != '\0')) {
|
||||||
|
/* For GLIMode
|
||||||
|
1 = maximize
|
||||||
|
0 = windowed */
|
||||||
|
g_runMaximized = (int)(acStack_220[0] != '0');
|
||||||
|
r3_checkDisc();
|
||||||
|
dwOptions = 0;
|
||||||
|
BVar18 = 0;
|
||||||
|
HANDLE duplicatedHandle;
|
||||||
|
DVar7 = 0x1f03ff;
|
||||||
|
g_hinstance = instance;
|
||||||
|
hTargetProcessHandle = GetCurrentProcess();
|
||||||
|
hSourceHandle = GetCurrentThread();
|
||||||
|
hSourceProcessHandle = GetCurrentProcess();
|
||||||
|
DuplicateHandle(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle,
|
||||||
|
&duplicatedHandle, DVar7, BVar18, dwOptions);
|
||||||
|
/* Copy cmdline */
|
||||||
|
LPSTR cmdline = GetCommandLineA();
|
||||||
|
strncpy(g_appCmdLine, cmdline, std::size(g_appCmdLine));
|
||||||
|
/* SEM_FAILCRITICALERRORS */
|
||||||
|
SetErrorMode(1);
|
||||||
|
pcVar4 = strstr(cmdline, s_dashCC);
|
||||||
|
if (pcVar4 == (char *)0x0) {
|
||||||
|
r3_initAllModules();
|
||||||
|
iVar13 = setupWindow(instance, 0, g_runMaximized);
|
||||||
|
if (iVar13 == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
g_setInitVar0();
|
||||||
|
r3_windowLockCursor();
|
||||||
|
spawnThread();
|
||||||
|
r3_noop(p_cTxt1, p_cTxt2);
|
||||||
|
gfx_init2();
|
||||||
|
RECT rect;
|
||||||
|
hWnd = GetDesktopWindow();
|
||||||
|
GetWindowRect(hWnd, &rect);
|
||||||
|
BVar18 = 1;
|
||||||
|
iVar13 = r3_get_gli_height1();
|
||||||
|
iVar13 = iVar13 + 0x20;
|
||||||
|
iVar10 = r3_get_gli_width1();
|
||||||
|
iVar10 = iVar10 + 0xc;
|
||||||
|
iVar11 = r3_get_gli_height1();
|
||||||
|
iVar11 = (int)(rect.bottom - iVar11) / 2;
|
||||||
|
iVar12 = r3_get_gli_width1();
|
||||||
|
MoveWindow(g_gameHWND, 0, 0, iVar10,
|
||||||
|
iVar13, BVar18);
|
||||||
|
FUN_004010b0();
|
||||||
|
#if RE_AUTHENTIC == 0
|
||||||
|
DWORD screensaveActive;
|
||||||
|
SystemParametersInfoA(SPI_GETSCREENSAVEACTIVE, 0, &screensaveActive, 0);
|
||||||
|
SystemParametersInfoA(SPI_SETSCREENSAVEACTIVE, 0, (PVOID)0x0, 0);
|
||||||
|
ShowCursor(0);
|
||||||
|
uStack_85c = 0;
|
||||||
|
SystemParametersInfoA(0x61, 1, &uStack_85c, 0);
|
||||||
|
#endif
|
||||||
|
g_engineRunning = 1;
|
||||||
|
r3_engineLoop();
|
||||||
|
/* cleanup starts here */
|
||||||
|
FUN_004725a0();
|
||||||
|
FUN_005038e0();
|
||||||
|
FUN_00503710();
|
||||||
|
FUN_004fb300();
|
||||||
|
FUN_00472150();
|
||||||
|
FUN_00470db0();
|
||||||
|
#if RE_AUTHENTIC == 0
|
||||||
|
uStack_85c = 0;
|
||||||
|
SystemParametersInfoA(0x61, 0, &uStack_85c, 0);
|
||||||
|
ShowCursor(1);
|
||||||
|
SystemParametersInfoA(0x11, uiParam, (PVOID)0x0, 0);
|
||||||
|
#endif
|
||||||
|
CloseHandle(duplicatedHandle);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
sprintf(UStack_830, s_Please_run_the__s_setup__005b63f4, s_windowTitle);
|
||||||
|
sprintf(acStack_528, s__s_not_initialized__005b63e0, s_windowTitle);
|
||||||
|
r3_waitForDvd(UStack_830, acStack_528, 0);
|
||||||
|
/* WARNING: Subroutine does not return */
|
||||||
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
|
||||||
|
|
||||||
#include <r3/binders/auto.h>
|
|
||||||
#include <gh_global.h>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
void Erm_fn_v_UpdateLastError(ushort uwStartOfWarningsId, byte ucModuleId, ulong ulChannelId, ushort uwErrNum, long lDebugData, uchar ucOpenInfoWindow, uchar ucStopForDebug, char * szPersonalMsg); // 0043e410 // Erm_fn_v_UpdateLastError
|
|
||||||
byte Erm_fn_ucInitErrMsg(void); // 0043e1d0 // Erm_fn_ucInitErrMsg
|
|
||||||
|
|
||||||
// 00504ef0
|
|
||||||
void r3_module10_init(void)
|
|
||||||
|
|
||||||
{
|
|
||||||
/* 0x104ef0 95 IPT_fn_vFirstInitInput */
|
|
||||||
if (g_errMod10 == 0xff) {
|
|
||||||
g_errMod10 = Erm_fn_ucInitErrMsg();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Erm_fn_v_UpdateLastError(3,g_errMod0,0,4,-1,0xff,0xff,(char *)0x0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
|
||||||
|
|
||||||
#include <r3/binders/auto.h>
|
|
||||||
#include <gh_global.h>
|
|
||||||
|
|
||||||
|
|
||||||
// 00401100
|
|
||||||
|
|
||||||
/* Sometimes: Erm_fn_v_PrintErrMsg
|
|
||||||
Also used as noop function */
|
|
||||||
|
|
||||||
void r3_noop(void *p_cTxt1,void *p_cTxt2)
|
|
||||||
|
|
||||||
{
|
|
||||||
/* 0x1100 145 SND_PrintUsedStaticMemory
|
|
||||||
0x1100 205 SND_fn_vChangeVolumeSound
|
|
||||||
0x1100 210 SND_fn_vFadeOut
|
|
||||||
0x1100 215 SND_fn_vInitStereoSound
|
|
||||||
0x1100 230 SND_fn_vSetDopplerFactorSound
|
|
||||||
0x1100 231 SND_fn_vSetFadeOutTicks
|
|
||||||
0x1100 233 SND_fn_vSetMusicFadeOut
|
|
||||||
0x1100 237 SND_fn_vSetReverseStereoSound
|
|
||||||
0x1100 239 SND_fn_vSetStereoSound */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -5,61 +5,102 @@
|
|||||||
#include <r3/config/static.hpp>
|
#include <r3/config/static.hpp>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
undefined r3_config_setIdentifier(
|
undefined
|
||||||
const char *param_1); // 00470570 // r3_config_setIdentifier
|
r3_config_setIdentifier(char *param_1); // 00470570 // r3_config_setIdentifier
|
||||||
|
void r3_set_GameDataPath(char *param_1); // 0055a8d0 // r3_set_GameDataPath
|
||||||
void r3_config_setTexturesMem(
|
void r3_config_setTexturesMem(
|
||||||
const char *param_1); // 00470f30 // r3_config_setTexturesMem
|
char *param_1); // 00470f30 // r3_config_setTexturesMem
|
||||||
void r3_noop(void *p_cTxt1, void *p_cTxt2); // 00401100 // r3_noop
|
void r3_noop(void *p_cTxt1, void *p_cTxt2); // 00401100 // r3_noop
|
||||||
undefined
|
undefined
|
||||||
r3_read_game_config_udp_port(void); // 00446040 // r3_read_game_config_udp_port
|
r3_read_game_config_udp_port(void); // 00446040 // r3_read_game_config_udp_port
|
||||||
undefined
|
undefined
|
||||||
r3_config_setGLIMode(const char *param_1); // 004704e0 // r3_config_setGLIMode
|
r3_config_setGLIMode(char *param_1); // 004704e0 // r3_config_setGLIMode
|
||||||
undefined r3_set_GameDataBinPath(
|
|
||||||
const char *param_1); // 0055a8d0 // r3_set_GameDataBinPath
|
|
||||||
undefined r3_read_game_config_modem_quality(
|
undefined r3_read_game_config_modem_quality(
|
||||||
void); // 00445fc0 // r3_read_game_config_modem_quality
|
void); // 00445fc0 // r3_read_game_config_modem_quality
|
||||||
|
|
||||||
// 004460c0
|
// 004460c0
|
||||||
void r3_read_gli_config(void) {
|
/* WARNING: Inlined function: r3_config_set_adapter */
|
||||||
R3Config &config = getDefaultConfig();
|
/* WARNING: Inlined function: r3_config_setTexturesCompressed */
|
||||||
r3_config_setGLIMode(config.gfxGliMode.c_str());
|
/* WARNING: Inlined function: r3_config_setTnl */
|
||||||
r3_config_setIdentifier(config.gfxIdentifier.c_str());
|
/* WARNING: Inlined function: r3_config_setTrilinearFiltering */
|
||||||
r3_config_setTexturesMem(config.gfxTexturesMem.c_str());
|
|
||||||
g_GLI_adapter = config.gfxAdapter;
|
|
||||||
r3_config_setIdentifier(config.gfxIdentifier.c_str());
|
|
||||||
g_config_tex_compressed = config.gfxTexturesCompressed;
|
|
||||||
g_GLI_tnl = config.gfxTnl;
|
|
||||||
g_GLI_trilinear = config.gfxTrilinear;
|
|
||||||
r3_config_setTexturesMem(config.gfxTexturesMem.c_str());
|
|
||||||
g_config_unused0 = 0;
|
|
||||||
g_config_camera_hor_axis = config.cameraHorizontalAxis;
|
|
||||||
g_config_camera_ver_axis = config.cameraVerticalAxis;
|
|
||||||
r3_set_GameDataBinPath(config.gameDataBinPath.c_str());
|
|
||||||
|
|
||||||
// GetPrivateProfileStringA
|
void r3_read_gli_config(void)
|
||||||
// (sectionName,s_SingleProcessor_005be308,&lpDefault_005be318,stringBuffer,0x104,local_204
|
|
||||||
// );
|
{
|
||||||
// /* Set single processor mode */
|
UINT tempOutVal;
|
||||||
// iVar4 = strcmpi(stringBuffer,(char *)&s_Yes);
|
void *pcVar2;
|
||||||
// if (iVar4 == 0) {
|
void *pcVar3;
|
||||||
// sectionName[4] = '\x01';
|
HANDLE hProcess;
|
||||||
// sectionName[5] = '\0';
|
int iVar4;
|
||||||
// sectionName[6] = '\0';
|
char *pcVar1;
|
||||||
// sectionName[7] = '\0';
|
char *pcVar4;
|
||||||
// sectionName[0] = -0x1a;
|
void *in_stack_fffffce0;
|
||||||
// sectionName[1] = 'c';
|
char *ptr0;
|
||||||
// sectionName[2] = 'D';
|
char *ptr1;
|
||||||
// sectionName[3] = '\0';
|
char local_218[20];
|
||||||
// sectionName + Field<0, 4>() = GetCurrentProcess();
|
char local_204[168];
|
||||||
// SetProcessAffinityMask((HANDLE)sectionName + Field<0, 4>(),sectionName +
|
char local_15c[32];
|
||||||
// Field<4, 4>());
|
char stringBuffer[256];
|
||||||
// }
|
char cVar1;
|
||||||
// sectionName[4] = -0xe;
|
DWORD_PTR dwProcessAffinityMask;
|
||||||
// sectionName[5] = 'c';
|
|
||||||
// sectionName[6] = 'D';
|
const char *iniPath = getIniPath();
|
||||||
// sectionName[7] = '\0';
|
|
||||||
// r3_read_game_config_modem_quality();
|
GetPrivateProfileStringA(lpAppName_005b68f0, s_GLI_Mode_005be3e0,
|
||||||
// r3_read_game_config_udp_port();
|
g_default_display_mode, stringBuffer, 0xff, iniPath);
|
||||||
|
r3_config_setGLIMode(stringBuffer);
|
||||||
|
g_GLI_adapter =
|
||||||
|
GetPrivateProfileIntA(lpAppName_005b68f0, s_Adapter_005b68e4, 0, iniPath);
|
||||||
|
/* set adapter */
|
||||||
|
GetPrivateProfileStringA(lpAppName_005b68f0, s_Identifier_005b6420,
|
||||||
|
(LPCSTR)&lpDefault_005cf96c, stringBuffer, 0xff,
|
||||||
|
iniPath);
|
||||||
|
r3_config_setIdentifier(stringBuffer);
|
||||||
|
tempOutVal = GetPrivateProfileIntA(lpAppName_005b68f0,
|
||||||
|
s_TexturesCompressed_005be3cc, 0, iniPath);
|
||||||
|
g_config_tex_compressed = (undefined1)tempOutVal;
|
||||||
|
tempOutVal =
|
||||||
|
GetPrivateProfileIntA(lpAppName_005b68f0, (LPCSTR)&s_Tnl, 0, iniPath);
|
||||||
|
g_GLI_tnl = (undefined1)tempOutVal;
|
||||||
|
tempOutVal = GetPrivateProfileIntA(lpAppName_005b68f0, s_TriLinear_005be3bc,
|
||||||
|
0, iniPath);
|
||||||
|
g_GLI_trilinear = (undefined1)tempOutVal;
|
||||||
|
pcVar2 = (void *)GetPrivateProfileIntA(lpAppName_005b68f0,
|
||||||
|
s_DynamicShadows_005be3ac, 0, iniPath);
|
||||||
|
pcVar3 = (void *)GetPrivateProfileIntA(lpAppName_005b68f0,
|
||||||
|
s_StaticShadows_005be39c, 0, iniPath);
|
||||||
|
//r3_noop(pcVar2, pcVar3);
|
||||||
|
pcVar2 = (void *)GetPrivateProfileIntA(lpAppName_005b68f0, s_Outline_005be394,
|
||||||
|
0, iniPath);
|
||||||
|
//r3_noop(pcVar2, in_stack_fffffce0);
|
||||||
|
GetPrivateProfileStringA(lpAppName_005b68f0, s_TexturesMem_005be384,
|
||||||
|
(LPCSTR)&s_Agp, stringBuffer, 0xff, iniPath);
|
||||||
|
r3_config_setTexturesMem(stringBuffer);
|
||||||
|
GetPrivateProfileStringA(lpAppName_005b68f0, s_SoundOnHD_005be374, "0",
|
||||||
|
stringBuffer, 0x104, iniPath);
|
||||||
|
sscanf(stringBuffer, s_percent_d, &g_soundOnHD);
|
||||||
|
GetPrivateProfileStringA(lpAppName_005b68f0, s_Complete_005be364, "1",
|
||||||
|
stringBuffer, 0x104, iniPath);
|
||||||
|
sscanf(stringBuffer, s_percent_d, &g_complete);
|
||||||
|
g_config_unused0 = 0;
|
||||||
|
g_config_camera_hor_axis = GetPrivateProfileIntA(
|
||||||
|
lpAppName_005b68f0, s_Camera_HorizontalAxis_005be34c, 2, iniPath);
|
||||||
|
g_config_camera_ver_axis = GetPrivateProfileIntA(
|
||||||
|
lpAppName_005b68f0, s_Camera_VerticalAxis_005be338, 5, iniPath);
|
||||||
|
GetPrivateProfileStringA(lpAppName_005b68f0, s_StartDirectory_005be31c,
|
||||||
|
s_Gamedata_005be32c, stringBuffer, 0x104, iniPath);
|
||||||
|
r3_set_GameDataPath(stringBuffer);
|
||||||
|
GetPrivateProfileStringA(lpAppName_005b68f0, s_SingleProcessor_005be308, "No",
|
||||||
|
stringBuffer, 0x104, iniPath);
|
||||||
|
/* Set single processor mode */
|
||||||
|
iVar4 = strcmpi(stringBuffer, (char *)&s_Yes);
|
||||||
|
if (iVar4 == 0) {
|
||||||
|
dwProcessAffinityMask = 1;
|
||||||
|
hProcess = GetCurrentProcess();
|
||||||
|
SetProcessAffinityMask(hProcess, dwProcessAffinityMask);
|
||||||
|
}
|
||||||
|
r3_read_game_config_modem_quality();
|
||||||
|
r3_read_game_config_udp_port();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
118
game_re/gh_fix/r3_restore.cxx
Normal file
118
game_re/gh_fix/r3_restore.cxx
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||||
|
|
||||||
|
#include <r3/binders/auto.h>
|
||||||
|
#include <gh_global.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
undefined FUN_00470350(void); // 00470350 // FUN_00470350 // cdecl
|
||||||
|
undefined r3_load_textures_2(void); // 00471760 // r3_load_textures_2 // cdecl
|
||||||
|
void r3_levelDisplayFn(byte param); // 00446fc0 // r3_levelDisplayFn // cdecl
|
||||||
|
void r3_noop(void * p_cTxt1, void * p_cTxt2); // 00401100 // r3_noop // cdecl
|
||||||
|
undefined r3_closeConcatTextureFile(void); // 004711d0 // r3_closeConcatTextureFile // cdecl
|
||||||
|
undefined FUN_00470db0(void); // 00470db0 // FUN_00470db0 // cdecl
|
||||||
|
undefined FUN_00503710(void); // 00503710 // FUN_00503710 // cdecl
|
||||||
|
undefined FUN_00443120(undefined4 param_1); // 00443120 // FUN_00443120 // cdecl
|
||||||
|
undefined FUN_00442c50(void); // 00442c50 // FUN_00442c50 // cdecl
|
||||||
|
undefined FUN_00470410(void); // 00470410 // FUN_00470410 // cdecl
|
||||||
|
undefined FUN_00472150(void); // 00472150 // FUN_00472150 // cdecl
|
||||||
|
undefined FUN_00445460(void); // 00445460 // FUN_00445460 // cdecl
|
||||||
|
undefined FUN_00442f70(undefined4 param_1); // 00442f70 // FUN_00442f70 // cdecl
|
||||||
|
undefined FUN_00445440(void); // 00445440 // FUN_00445440 // cdecl
|
||||||
|
undefined SND_fn_vResumeSound(void); // 0040a1e0 // SND_fn_vResumeSound // cdecl
|
||||||
|
undefined IPT_fn_vActivateAllEntryElements(void); // 00505490 // IPT_fn_vActivateAllEntryElements // cdecl
|
||||||
|
undefined r3_windowLockCursor(void); // 00401320 // r3_windowLockCursor // cdecl
|
||||||
|
undefined FUN_00402470(HWND param_1); // 00402470 // FUN_00402470 // cdecl
|
||||||
|
undefined gfx_init2(void); // 00470be0 // gfx_init2 // cdecl
|
||||||
|
undefined FUN_004725a0(void); // 004725a0 // FUN_004725a0 // cdecl
|
||||||
|
undefined FUN_0051a900(short hGLDDevice); // 0051a900 // FUN_0051a900 // cdecl
|
||||||
|
undefined FUN_005038e0(void); // 005038e0 // FUN_005038e0 // cdecl
|
||||||
|
undefined FUN_004fb300(void); // 004fb300 // FUN_004fb300 // cdecl
|
||||||
|
undefined FUN_004fa650(void); // 004fa650 // FUN_004fa650 // cdecl
|
||||||
|
undefined r3_processInput1(void); // 00446f10 // r3_processInput1 // cdecl
|
||||||
|
undefined FUN_0047bae0(void); // 0047bae0 // FUN_0047bae0 // cdecl
|
||||||
|
undefined FUN_0051a7a0(short hGLDDevice, undefined4 param_2); // 0051a7a0 // FUN_0051a7a0 // cdecl
|
||||||
|
|
||||||
|
// 00401490
|
||||||
|
/* WARNING: Inlined function: r3_get_engine_mode */
|
||||||
|
|
||||||
|
undefined4 r3_restore(undefined4 param_1)
|
||||||
|
|
||||||
|
{
|
||||||
|
HWND hWnd;
|
||||||
|
int iVar1;
|
||||||
|
DWORD DVar2;
|
||||||
|
|
||||||
|
hWnd = g_gameHWND;
|
||||||
|
if (g_engineRunning != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (g_gameHWND == (HWND)0x0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
SetWindowTextA(g_gameHWND,g_windowTitleRestoring);
|
||||||
|
UpdateWindow(hWnd);
|
||||||
|
SetForegroundWindow(hWnd);
|
||||||
|
if (p_fn_vDisplayAll == (void*)&r3_noop) {
|
||||||
|
/* Set window callback? */
|
||||||
|
p_fn_vDisplayAll = &r3_levelDisplayFn;
|
||||||
|
}
|
||||||
|
if (PTR_r3_processInput1_005bdb1c == (void*)&r3_noop) {
|
||||||
|
PTR_r3_processInput1_005bdb1c = r3_processInput1;
|
||||||
|
IPT_fn_vActivateAllEntryElements();
|
||||||
|
}
|
||||||
|
iVar1 = FUN_0047bae0();
|
||||||
|
if (iVar1 == 0) goto LAB_004015f7;
|
||||||
|
DVar2 = WaitForSingleObject(g_drawSemaphore,500);
|
||||||
|
if (DVar2 == 0x102) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
FUN_004725a0();
|
||||||
|
if (g_currentBinkMovie + Field<32, 4>() == 0) {
|
||||||
|
FUN_00470410();
|
||||||
|
}
|
||||||
|
FUN_0051a900(g_stEngineStructure.hGLDDevice);
|
||||||
|
FUN_005038e0();
|
||||||
|
FUN_00503710();
|
||||||
|
FUN_004fb300();
|
||||||
|
FUN_00472150();
|
||||||
|
FUN_00470db0();
|
||||||
|
FUN_00445440();
|
||||||
|
gfx_init2();
|
||||||
|
FUN_00445460();
|
||||||
|
FUN_00402470(hWnd);
|
||||||
|
FUN_0051a7a0(g_stEngineStructure.hGLDDevice,0);
|
||||||
|
if (g_currentBinkMovie + Field<32, 4>() == 0) {
|
||||||
|
FUN_00442f70(0);
|
||||||
|
FUN_00443120(0);
|
||||||
|
FUN_00442f70(1);
|
||||||
|
FUN_00443120(1);
|
||||||
|
FUN_00470350();
|
||||||
|
if (g_currentBinkMovie + Field<32, 4>() != 0) goto LAB_004015bc;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LAB_004015bc:
|
||||||
|
FUN_00445440();
|
||||||
|
}
|
||||||
|
r3_load_textures_2();
|
||||||
|
if (((g_stEngineStructure.eEngineMode == E_EM_ModeStartingProgram) ||
|
||||||
|
(g_stEngineStructure.eEngineMode == E_EM_ModeEnterGame)) ||
|
||||||
|
(g_stEngineStructure.eEngineMode == E_EM_ModeEnterLevel)) {
|
||||||
|
FUN_004fa650();
|
||||||
|
}
|
||||||
|
r3_closeConcatTextureFile();
|
||||||
|
ReleaseSemaphore(g_drawSemaphore,1,(LPLONG)0x0);
|
||||||
|
LAB_004015f7:
|
||||||
|
g_stEngineStructure + Field<91, 1>() = 0;
|
||||||
|
SetWindowTextA(hWnd,g_windowTitle);
|
||||||
|
UpdateWindow(hWnd);
|
||||||
|
SetForegroundWindow(hWnd);
|
||||||
|
FUN_00442c50();
|
||||||
|
SND_fn_vResumeSound();
|
||||||
|
r3_windowLockCursor();
|
||||||
|
/* Keep suspended
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
|
||||||
|
|
||||||
#include <r3/binders/auto.h>
|
|
||||||
#include <gh_global.h>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
undefined4 get_one(void); // 00485bd0 // get_one
|
|
||||||
void set_unk(HWND wnd); // 0043e620 // set_unk
|
|
||||||
int r3_get_gli_width0(void); // 004012c0 // r3_get_gli_width0
|
|
||||||
int r3_get_gli_height0(void); // 004012d0 // r3_get_gli_height0
|
|
||||||
undefined4 FUN_0046ed70(char * param_1, short * param_2); // 0046ed70 // FUN_0046ed70
|
|
||||||
undefined FUN_0046f640(undefined param_1, short param_2, undefined4 * param_3); // 0046f640 // FUN_0046f640
|
|
||||||
void FUN_0047c150(short param_1, short param_2, int param_3); // 0047c150 // FUN_0047c150
|
|
||||||
long r3_windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); // 004025e0 // r3_windowProc
|
|
||||||
int r3_get_gli_width1(void); // 0047baf0 // r3_get_gli_width1
|
|
||||||
void r3_load_splash_bitmap(HWND unused); // 00402450 // r3_load_splash_bitmap
|
|
||||||
int r3_get_gli_height1(void); // 0047bb00 // r3_get_gli_height1
|
|
||||||
undefined4 FUN_0046f0b0(short param_1, undefined4 * param_2, short * param_3); // 0046f0b0 // FUN_0046f0b0
|
|
||||||
void r3_set_window_wh(undefined4 param_1, undefined4 param_2); // 004012a0 // r3_set_window_wh
|
|
||||||
|
|
||||||
// 00402140
|
|
||||||
undefined4 r3_setupWindow(HINSTANCE hInstance,undefined4 param_2,int maximizeWindow)
|
|
||||||
|
|
||||||
{
|
|
||||||
ATOM AVar1;
|
|
||||||
int iVar2;
|
|
||||||
HWND hWnd;
|
|
||||||
HWND pHVar3;
|
|
||||||
bool bVar4;
|
|
||||||
char acStack_e0 [28];
|
|
||||||
int iStack_c4;
|
|
||||||
int iStack_c0;
|
|
||||||
undefined4 uStack_bc;
|
|
||||||
HWND pHStack_b8;
|
|
||||||
HWND pHStack_b4;
|
|
||||||
undefined4 uStack_b0;
|
|
||||||
undefined4 uStack_ac;
|
|
||||||
undefined4 auStack_80 [5];
|
|
||||||
undefined4 uStack_6c;
|
|
||||||
DWORD dwStyle;
|
|
||||||
int iVar5;
|
|
||||||
int iVar6;
|
|
||||||
undefined local_28 [28];
|
|
||||||
HBRUSH pHStack_c;
|
|
||||||
LPCSTR pCStack_8;
|
|
||||||
char *pcStack_4;
|
|
||||||
|
|
||||||
INT_0077d0a4 = 1;
|
|
||||||
/* WindowClassA (overlaps usage below) */
|
|
||||||
local_28 + Field<0, 4>() = 0x3003;
|
|
||||||
local_28 + Field<4, 4>() = r3_windowProc;
|
|
||||||
local_28 + Field<8, 4>() = 0;
|
|
||||||
local_28 + Field<12, 4>() = 0;
|
|
||||||
local_28 + Field<16, 4>() = hInstance;
|
|
||||||
local_28 + Field<20, 4>() = LoadIconA(hInstance,(LPCSTR)0x65);
|
|
||||||
local_28 + Field<24, 4>() = LoadCursorA((HINSTANCE)0x0,(LPCSTR)0x7f00);
|
|
||||||
pHStack_c = (HBRUSH)0x6;
|
|
||||||
pCStack_8 = (LPCSTR)0x0;
|
|
||||||
pcStack_4 = g_windowTitle;
|
|
||||||
AVar1 = RegisterClassA((WNDCLASSA *)local_28);
|
|
||||||
if (AVar1 != 0) {
|
|
||||||
bVar4 = maximizeWindow == 0;
|
|
||||||
if (bVar4) {
|
|
||||||
iVar5 = GetSystemMetrics(0x20);
|
|
||||||
iVar5 = iVar5 * 2 + 0x140;
|
|
||||||
iVar6 = GetSystemMetrics(0x21);
|
|
||||||
iVar2 = GetSystemMetrics(4);
|
|
||||||
iVar6 = iVar2 + 0xf0 + iVar6 * 2;
|
|
||||||
dwStyle = 0x90cf0000;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
iVar6 = 0xf0;
|
|
||||||
iVar5 = 0x140;
|
|
||||||
dwStyle = 0x91000000;
|
|
||||||
}
|
|
||||||
uStack_6c = 0x40221d;
|
|
||||||
hWnd = CreateWindowExA(0,g_windowTitle,g_windowTitle,dwStyle,(uint)bVar4,(uint)bVar4,iVar5,iVar6
|
|
||||||
,(HWND)0x0,(HMENU)0x0,hInstance,(LPVOID)0x0);
|
|
||||||
g_gameHWND1 = hWnd;
|
|
||||||
if (hWnd != (HWND)0x0) {
|
|
||||||
g_gameHWND = hWnd;
|
|
||||||
SetWindowTextA(hWnd,s_windowTitle);
|
|
||||||
if (maximizeWindow == 0) {
|
|
||||||
/* SW_NORMAL */
|
|
||||||
iVar5 = 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* SW_MAXIMIZE */
|
|
||||||
iVar5 = 3;
|
|
||||||
}
|
|
||||||
ShowWindow(hWnd,iVar5);
|
|
||||||
SetWindowPos(hWnd,(HWND)0x0,0,0,0,0,0x43);
|
|
||||||
EnableWindow(hWnd,1);
|
|
||||||
SetFocus(hWnd);
|
|
||||||
UpdateWindow(hWnd);
|
|
||||||
SetForegroundWindow(hWnd);
|
|
||||||
pHVar3 = GetFocus();
|
|
||||||
while (pHVar3 != hWnd) {
|
|
||||||
SetWindowPos(hWnd,(HWND)0x0,0,0,0,0,0x43);
|
|
||||||
EnableWindow(hWnd,1);
|
|
||||||
SetFocus(hWnd);
|
|
||||||
UpdateWindow(hWnd);
|
|
||||||
SetForegroundWindow(hWnd);
|
|
||||||
pHVar3 = GetFocus();
|
|
||||||
}
|
|
||||||
set_unk(hWnd);
|
|
||||||
r3_load_splash_bitmap(hWnd);
|
|
||||||
INT_0077d0a4 = 1;
|
|
||||||
iVar5 = get_one();
|
|
||||||
/* always taken */
|
|
||||||
if (iVar5 != 0) {
|
|
||||||
iVar5 = get_one();
|
|
||||||
/* never taken */
|
|
||||||
if (iVar5 == 0) {
|
|
||||||
/* WARNING: Subroutine does not return */
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
iVar5 = r3_get_gli_height1();
|
|
||||||
iVar6 = r3_get_gli_width1();
|
|
||||||
r3_set_window_wh(iVar6,iVar5);
|
|
||||||
GetClientRect(g_gameHWND,(LPRECT)(local_28 + 0x18));
|
|
||||||
uStack_b0 = 1;
|
|
||||||
iStack_c4 = r3_get_gli_width0();
|
|
||||||
iStack_c0 = r3_get_gli_height0();
|
|
||||||
uStack_bc = 0x10;
|
|
||||||
pHStack_b8 = g_gameHWND;
|
|
||||||
pHStack_b4 = g_gameHWND;
|
|
||||||
uStack_ac = 10;
|
|
||||||
iVar5 = FUN_0046ed70(acStack_e0,(short *)&WORD_0077d4d4);
|
|
||||||
if (iVar5 != 0) {
|
|
||||||
local_28 + Field<0, 4>() = 0;
|
|
||||||
local_28 + Field<4, 4>() = (WNDPROC)0x0;
|
|
||||||
iVar5 = FUN_0046f0b0(WORD_0077d4d4,auStack_80,(short *)&WORD_0077d4d6);
|
|
||||||
if ((iVar5 != 0) &&
|
|
||||||
(iVar5 = FUN_0046f640((char)WORD_0077d4d4,WORD_0077d4d6,&DWORD_0077d4d8), iVar5 != 0))
|
|
||||||
{
|
|
||||||
if (DWORD_0077d4d8 != 0) {
|
|
||||||
FUN_0047c150(WORD_0077d4d4,WORD_0077d4d6,DWORD_0077d4d8);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Failed */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* WARNING: Subroutine does not return */
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Failed */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
|
||||||
|
|
||||||
#include <r3/binders/auto.h>
|
|
||||||
#include <gh_global.h>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
// 00442090
|
|
||||||
void r3_validateBinkVideoQuality(byte videoBpp, byte wantedVideoQuality)
|
|
||||||
|
|
||||||
{
|
|
||||||
byte bVar1;
|
|
||||||
|
|
||||||
bVar1 = wantedVideoQuality;
|
|
||||||
if (4 < wantedVideoQuality) {
|
|
||||||
bVar1 = 4;
|
|
||||||
}
|
|
||||||
g_bink_realVideoQuality = g_bink_wantedVideoQuality;
|
|
||||||
if ((g_bink_wantedVideoQuality <= bVar1) &&
|
|
||||||
(g_bink_realVideoQuality = 4, wantedVideoQuality < 5)) {
|
|
||||||
g_bink_realVideoQuality = wantedVideoQuality;
|
|
||||||
}
|
|
||||||
wantedVideoQuality = (uint)g_bink_realVideoQuality;
|
|
||||||
g_bink_videoBpp = videoBpp;
|
|
||||||
g_bink_wantedVideoQualityPlus1 = wantedVideoQuality + 1;
|
|
||||||
DAT_007a2e0c = -(uint)(wantedVideoQuality != 0) & 0x80000000;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
41
game_re/gh_fix/r3_waitForDvd.cxx
Normal file
41
game_re/gh_fix/r3_waitForDvd.cxx
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||||
|
|
||||||
|
#include <r3/binders/auto.h>
|
||||||
|
#include <gh_global.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
undefined r3_setRendererState1(undefined4 param_1, undefined4 param_2, undefined4 param_3); // 0046fe20 // r3_setRendererState1 // cdecl
|
||||||
|
undefined FUN_0043e4f0(void); // 0043e4f0 // FUN_0043e4f0 // cdecl
|
||||||
|
undefined r3_gfxFrameUNK(void); // 0046fed0 // r3_gfxFrame? // cdecl
|
||||||
|
undefined FUN_00441d70(undefined4 param_1, undefined4 param_2, undefined4 param_3, undefined4 param_4, undefined4 param_5); // 00441d70 // FUN_00441d70 // cdecl
|
||||||
|
void IPT_fn_vReadInput(void); // 00505fe0 // IPT_fn_vReadInput // cdecl
|
||||||
|
|
||||||
|
// 0043e540
|
||||||
|
int __cdecl r3_waitForDvd(const char *param_1,const char *param_2,uint param_3)
|
||||||
|
|
||||||
|
{
|
||||||
|
ushort uVar1;
|
||||||
|
int iVar2;
|
||||||
|
char local_64 [100];
|
||||||
|
|
||||||
|
r3_setRendererState1(1,1,0);
|
||||||
|
iVar2 = FUN_00441d70((undefined4)param_1,0x42c80000,0x43480000,0,0xffffffff);
|
||||||
|
if (iVar2 == 0) {
|
||||||
|
iVar2 = MessageBoxA(g_gameHWND1,param_1,param_2,param_3 | 0x10000);
|
||||||
|
return iVar2;
|
||||||
|
}
|
||||||
|
if ((param_3 & 5) != 0) {
|
||||||
|
FUN_00441d70((undefined4)s_quitting1,0x42c80000,0x438c0000,0,0xffffffff);
|
||||||
|
FUN_0043e4f0();
|
||||||
|
sprintf(local_64,s__jc_z_d__s_005bd460,DAT_005bd454,s_wndStrQuiting);
|
||||||
|
FUN_00441d70((undefined4)local_64,0x43340000,0x43b40000,0,0xffffffff);
|
||||||
|
r3_gfxFrameUNK();
|
||||||
|
IPT_fn_vReadInput();
|
||||||
|
uVar1 = GetAsyncKeyState(0x1b);
|
||||||
|
return ((uVar1 & 0x8000) != 0) + 1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
37
game_re/gh_fix/r3_windowLockCursor.cxx
Normal file
37
game_re/gh_fix/r3_windowLockCursor.cxx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||||
|
|
||||||
|
#include <r3/binders/auto.h>
|
||||||
|
#include <gh_global.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
HWND getHWND(void); // 00401300 // getHWND // cdecl
|
||||||
|
|
||||||
|
// 00401320
|
||||||
|
void __cdecl r3_windowLockCursor(void)
|
||||||
|
|
||||||
|
{
|
||||||
|
HWND pHVar1;
|
||||||
|
tagRECT *ptVar2;
|
||||||
|
RECT RStack_30;
|
||||||
|
tagRECT local_20;
|
||||||
|
tagRECT tStack_10;
|
||||||
|
|
||||||
|
if (g_initVar0 != '\0') {
|
||||||
|
ptVar2 = &local_20;
|
||||||
|
pHVar1 = getHWND();
|
||||||
|
GetWindowRect(pHVar1,ptVar2);
|
||||||
|
ptVar2 = &tStack_10;
|
||||||
|
pHVar1 = getHWND();
|
||||||
|
GetClientRect(pHVar1,ptVar2);
|
||||||
|
RStack_30.left = local_20.left + 5;
|
||||||
|
RStack_30.top = local_20.bottom - tStack_10.bottom;
|
||||||
|
RStack_30.right = tStack_10.right + -5 + RStack_30.left;
|
||||||
|
RStack_30.bottom = RStack_30.top + -5 + tStack_10.bottom;
|
||||||
|
// ClipCursor(&RStack_30);
|
||||||
|
// ShowCursor(0);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -4,11 +4,11 @@
|
|||||||
#include <gh_global.h>
|
#include <gh_global.h>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
undefined FUN_004013a0(void); // 004013a0 // FUN_004013a0
|
undefined r3_windowLockCursor(void); // 00401320 // r3_windowLockCursor // cdecl
|
||||||
undefined FUN_00401320(void); // 00401320 // FUN_00401320
|
undefined r3_windowUnlockCursor(void); // 004013a0 // r3_windowUnlockCursor // cdecl
|
||||||
|
|
||||||
// 004025e0
|
// 004025e0
|
||||||
long r3_windowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
long __stdcall r3_windowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
||||||
|
|
||||||
{
|
{
|
||||||
long lVar1;
|
long lVar1;
|
||||||
@@ -16,14 +16,14 @@ long r3_windowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
|||||||
if (uMsg < WM_SETCURSOR + 1) {
|
if (uMsg < WM_SETCURSOR + 1) {
|
||||||
if (uMsg == WM_SETCURSOR) {
|
if (uMsg == WM_SETCURSOR) {
|
||||||
if (((g_engineShouldRun != 0) && (g_engineRunning != 0)) && (g_runMaximized != 0)) {
|
if (((g_engineShouldRun != 0) && (g_engineRunning != 0)) && (g_runMaximized != 0)) {
|
||||||
FUN_00401320();
|
r3_windowLockCursor();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (uMsg == WM_CLOSE) {
|
if (uMsg == WM_CLOSE) {
|
||||||
FUN_004013a0();
|
r3_windowUnlockCursor();
|
||||||
DAT_0077d0b8 = 1;
|
g_windowCloseRequested = 1;
|
||||||
if (g_drawSemaphore != (HANDLE)0x0) {
|
if (g_drawSemaphore != (HANDLE)0x0) {
|
||||||
CloseHandle(g_drawSemaphore);
|
CloseHandle(g_drawSemaphore);
|
||||||
}
|
}
|
||||||
|
|||||||
23
game_re/gh_fix/r3_windowUnlockCursor.cxx
Normal file
23
game_re/gh_fix/r3_windowUnlockCursor.cxx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||||
|
|
||||||
|
#include <r3/binders/auto.h>
|
||||||
|
#include <gh_global.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
// 004013a0
|
||||||
|
void r3_windowUnlockCursor(void)
|
||||||
|
|
||||||
|
{
|
||||||
|
HCURSOR hCursor;
|
||||||
|
|
||||||
|
/* IDC_ARROW */
|
||||||
|
hCursor = LoadCursorA((HINSTANCE)0x0,(LPCSTR)0x7f00);
|
||||||
|
SetCursor(hCursor);
|
||||||
|
ClipCursor((RECT *)0x0);
|
||||||
|
ShowCursor(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
105
game_re/gh_fix/setupWindow.cxx
Normal file
105
game_re/gh_fix/setupWindow.cxx
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||||
|
|
||||||
|
#include <r3/binders/auto.h>
|
||||||
|
#include <gh_global.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
long CALLBACK r3_windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); // 004025e0 // r3_windowProc
|
||||||
|
undefined fn_bCreateMainDisplayScreen(void); // 004022f0 // fn_bCreateMainDisplayScreen
|
||||||
|
void loadSplashBitmap(HWND unused); // 00402450 // loadSplashBitmap
|
||||||
|
void setGameHWND3(HWND wnd); // 0043e620 // setGameHWND3
|
||||||
|
|
||||||
|
// 00402140
|
||||||
|
int setupWindow(HINSTANCE instance,undefined4 param_2,int windowedParam)
|
||||||
|
|
||||||
|
{
|
||||||
|
ATOM AVar1;
|
||||||
|
int windowHeight;
|
||||||
|
int yCaption;
|
||||||
|
HWND hWnd;
|
||||||
|
HWND pHVar2;
|
||||||
|
int r0;
|
||||||
|
BOOL success;
|
||||||
|
bool windowed;
|
||||||
|
GLD_DeviceAttributes *windowParams;
|
||||||
|
DWORD dwStyle;
|
||||||
|
WNDCLASSA wndClass;
|
||||||
|
int showWindow;
|
||||||
|
int windowWidth;
|
||||||
|
|
||||||
|
g_windowInitialized = 1;
|
||||||
|
/* WindowClassA (overlaps usage below) */
|
||||||
|
wndClass.style = 0x3003;
|
||||||
|
wndClass.lpfnWndProc = r3_windowProc;
|
||||||
|
wndClass.cbClsExtra = 0;
|
||||||
|
wndClass.cbWndExtra = 0;
|
||||||
|
wndClass.hInstance = instance;
|
||||||
|
wndClass.hIcon = LoadIconA(instance,(LPCSTR)0x65);
|
||||||
|
wndClass.hCursor = LoadCursorA((HINSTANCE)0x0,(LPCSTR)0x7f00);
|
||||||
|
wndClass.hbrBackground = (HBRUSH)COLOR_WINDOWFRAME;
|
||||||
|
wndClass.lpszMenuName = (LPCSTR)0x0;
|
||||||
|
wndClass.lpszClassName = g_windowTitle;
|
||||||
|
AVar1 = RegisterClassA(&wndClass);
|
||||||
|
if (AVar1 != 0) {
|
||||||
|
windowed = windowedParam == 0;
|
||||||
|
if (windowed) {
|
||||||
|
/* SM_CXSIZEFRAME */
|
||||||
|
windowWidth = GetSystemMetrics(32);
|
||||||
|
/* x*2 + 320 */
|
||||||
|
windowWidth = windowWidth * 2 + 320;
|
||||||
|
/* SM_CYSIZEFRAME, retrieves the size of the vertical resizing border */
|
||||||
|
windowHeight = GetSystemMetrics(33);
|
||||||
|
/* SM_CYCAPTION, The height of a caption area, in pixels */
|
||||||
|
yCaption = GetSystemMetrics(4);
|
||||||
|
/* ebp still 0 at this point */
|
||||||
|
windowHeight = yCaption + 240 + windowHeight * 2;
|
||||||
|
dwStyle = 0x90cf0000;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
windowHeight = 0xf0;
|
||||||
|
windowWidth = 0x140;
|
||||||
|
dwStyle = 0x91000000;
|
||||||
|
}
|
||||||
|
hWnd = CreateWindowExA(0,g_windowTitle,g_windowTitle,dwStyle,(uint)windowed,(uint)windowed,
|
||||||
|
windowWidth,windowHeight,(HWND)0x0,(HMENU)0x0,instance,(LPVOID)0x0);
|
||||||
|
g_gameHWND1 = hWnd;
|
||||||
|
if (hWnd != (HWND)0x0) {
|
||||||
|
g_gameHWND = hWnd;
|
||||||
|
SetWindowTextA(hWnd,s_windowTitle);
|
||||||
|
if (windowedParam == 0) {
|
||||||
|
/* SW_NORMAL */
|
||||||
|
showWindow = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* SW_MAXIMIZE */
|
||||||
|
showWindow = 3;
|
||||||
|
}
|
||||||
|
ShowWindow(hWnd,showWindow);
|
||||||
|
SetWindowPos(hWnd,(HWND)0x0,0,0,0,0,0x43);
|
||||||
|
EnableWindow(hWnd,1);
|
||||||
|
SetFocus(hWnd);
|
||||||
|
UpdateWindow(hWnd);
|
||||||
|
SetForegroundWindow(hWnd);
|
||||||
|
pHVar2 = GetFocus();
|
||||||
|
while (pHVar2 != hWnd) {
|
||||||
|
SetWindowPos(hWnd,(HWND)0x0,0,0,0,0,0x43);
|
||||||
|
EnableWindow(hWnd,1);
|
||||||
|
SetFocus(hWnd);
|
||||||
|
UpdateWindow(hWnd);
|
||||||
|
SetForegroundWindow(hWnd);
|
||||||
|
pHVar2 = GetFocus();
|
||||||
|
}
|
||||||
|
setGameHWND3(hWnd);
|
||||||
|
loadSplashBitmap(hWnd);
|
||||||
|
/* unused? */
|
||||||
|
g_windowInitialized = 1;
|
||||||
|
r0 = fn_bCreateMainDisplayScreen();
|
||||||
|
return r0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Failed */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
1734
game_re/gh_global.h
1734
game_re/gh_global.h
File diff suppressed because it is too large
Load Diff
@@ -3,12 +3,11 @@
|
|||||||
// with possible manualy fixes
|
// with possible manualy fixes
|
||||||
|
|
||||||
#include <r3/binders/auto.h>
|
#include <r3/binders/auto.h>
|
||||||
|
#include <r3/binders/stub.h>
|
||||||
#include <gh_global.h>
|
#include <gh_global.h>
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
// 00401320
|
// 0043e1d0
|
||||||
// FUN_00401320
|
// Erm_fn_ucInitErrMsg
|
||||||
extern "C" undefined FUN_00401320(void) {
|
extern "C" byte Erm_fn_ucInitErrMsg(void) {
|
||||||
// TODO: Implement this function
|
return gh_stub_impl_cdecl<(stub_t)0x0043e1d0, byte>();
|
||||||
throw GHStubException("Function not implemented: FUN_00401320");
|
|
||||||
}
|
}
|
||||||
13
game_re/gh_stub/Erm_fn_v_UpdateLastError.cxx
Normal file
13
game_re/gh_stub/Erm_fn_v_UpdateLastError.cxx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// AUTO-GENERATED FILE!!!!
|
||||||
|
// This function has yet to be decompiled using 'Dump Current Function' in ghidra
|
||||||
|
// with possible manualy fixes
|
||||||
|
|
||||||
|
#include <r3/binders/auto.h>
|
||||||
|
#include <r3/binders/stub.h>
|
||||||
|
#include <gh_global.h>
|
||||||
|
|
||||||
|
// 0043e410
|
||||||
|
// Erm_fn_v_UpdateLastError
|
||||||
|
extern "C" void Erm_fn_v_UpdateLastError(ushort uwStartOfWarningsId, byte ucModuleId, ulong ulChannelId, ushort uwErrNum, long lDebugData, uchar ucOpenInfoWindow, uchar ucStopForDebug, char * szPersonalMsg) {
|
||||||
|
gh_stub_impl_stdcall<(stub_t)0x0043e410, void>(uwStartOfWarningsId, ucModuleId, ulChannelId, uwErrNum, lDebugData, ucOpenInfoWindow, ucStopForDebug, szPersonalMsg);
|
||||||
|
}
|
||||||
13
game_re/gh_stub/FIL_fn_vOpenConcatFile.cxx
Normal file
13
game_re/gh_stub/FIL_fn_vOpenConcatFile.cxx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// AUTO-GENERATED FILE!!!!
|
||||||
|
// This function has yet to be decompiled using 'Dump Current Function' in ghidra
|
||||||
|
// with possible manualy fixes
|
||||||
|
|
||||||
|
#include <r3/binders/auto.h>
|
||||||
|
#include <r3/binders/stub.h>
|
||||||
|
#include <gh_global.h>
|
||||||
|
|
||||||
|
// 0055d890
|
||||||
|
// FIL_fn_vOpenConcatFile
|
||||||
|
extern "C" FIL_ConcatFile * FIL_fn_vOpenConcatFile(char * fileName) {
|
||||||
|
return gh_stub_impl_cdecl<(stub_t)0x0055d890, FIL_ConcatFile *>(fileName);
|
||||||
|
}
|
||||||
@@ -3,12 +3,11 @@
|
|||||||
// with possible manualy fixes
|
// with possible manualy fixes
|
||||||
|
|
||||||
#include <r3/binders/auto.h>
|
#include <r3/binders/auto.h>
|
||||||
|
#include <r3/binders/stub.h>
|
||||||
#include <gh_global.h>
|
#include <gh_global.h>
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
// 004010b0
|
// 004010b0
|
||||||
// FUN_004010b0
|
// FUN_004010b0
|
||||||
extern "C" undefined FUN_004010b0(void) {
|
extern "C" undefined FUN_004010b0(void) {
|
||||||
// TODO: Implement this function
|
return gh_stub_impl_cdecl<(stub_t)0x004010b0, undefined>();
|
||||||
throw GHStubException("Function not implemented: FUN_004010b0");
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,11 @@
|
|||||||
// with possible manualy fixes
|
// with possible manualy fixes
|
||||||
|
|
||||||
#include <r3/binders/auto.h>
|
#include <r3/binders/auto.h>
|
||||||
|
#include <r3/binders/stub.h>
|
||||||
#include <gh_global.h>
|
#include <gh_global.h>
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
// 004464f0
|
// 00401270
|
||||||
// r3_checkDisc
|
// FUN_00401270
|
||||||
extern "C" undefined r3_checkDisc(void) {
|
extern "C" undefined FUN_00401270(void) {
|
||||||
// TODO: Implement this function
|
return gh_stub_impl_cdecl<(stub_t)0x00401270, undefined>();
|
||||||
throw GHStubException("Function not implemented: r3_checkDisc");
|
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user