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/
|
||||
build/
|
||||
build_msvc/
|
||||
# game_re/
|
||||
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"]
|
||||
path = game_re/third_party/spdlog
|
||||
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)
|
||||
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)
|
||||
|
||||
add_subdirectory(third_party)
|
||||
add_subdirectory(game_re)
|
||||
add_subdirectory(patcher)
|
||||
|
||||
# Use highest possible C standard
|
||||
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
|
||||
// @category _Reman3
|
||||
// @menupath Reman3.Dump Types
|
||||
// @importpackage org.sqlite
|
||||
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.program.model.data.DataType;
|
||||
@@ -1,13 +1,14 @@
|
||||
// Exports binary read only and data segments to a binary + header file
|
||||
// @category _Reman3
|
||||
// @menupath Tools.Reman3.Export Data
|
||||
// @menupath Reman3.Export Data Segment
|
||||
// @importpackage org.sqlite
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.program.model.address.Address;
|
||||
import re3lib.RecompileConfig;
|
||||
import re3lib.RemanConfig;
|
||||
|
||||
public class ExportData extends GhidraScript {
|
||||
|
||||
@@ -16,16 +17,16 @@ public class ExportData extends GhidraScript {
|
||||
if (currentProgram == null) {
|
||||
return;
|
||||
}
|
||||
RecompileConfig.INSTANCE = new RecompileConfig(this);
|
||||
RemanConfig.INSTANCE = new RemanConfig(this);
|
||||
|
||||
String dataFile = new File(RecompileConfig.INSTANCE.outputDir, "gh_datasegment.bin").toString();
|
||||
String headerFile = new File(RecompileConfig.INSTANCE.outputDir, "gh_datasegment.h").toString();
|
||||
String dataFile = new File(RemanConfig.INSTANCE.outputDir, "gh_datasegment.bin").toString();
|
||||
String headerFile = new File(RemanConfig.INSTANCE.outputDir, "gh_datasegment.h").toString();
|
||||
|
||||
FileOutputStream dataOutputStream = new FileOutputStream(dataFile);
|
||||
PrintWriter headerWriter = new PrintWriter(headerFile, "UTF-8");
|
||||
|
||||
Address startAddr = RecompileConfig.INSTANCE.staticMemoryBlockStart;
|
||||
Address endAddr = RecompileConfig.INSTANCE.staticMemoryBlockEnd;
|
||||
Address startAddr = RemanConfig.INSTANCE.staticMemoryBlockStart;
|
||||
Address endAddr = RemanConfig.INSTANCE.staticMemoryBlockEnd;
|
||||
|
||||
// Dump all the memory to the bin file
|
||||
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.Array;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.DataTypeManager;
|
||||
import ghidra.program.model.data.DataTypePath;
|
||||
import ghidra.program.model.data.FunctionDefinition;
|
||||
import ghidra.program.model.data.Pointer;
|
||||
import ghidra.program.model.data.PointerDataType;
|
||||
import ghidra.program.model.data.Undefined;
|
||||
import ghidra.program.model.listing.Data;
|
||||
import ghidra.program.model.pcode.HighSymbol;
|
||||
import ghidra.program.model.symbol.SourceType;
|
||||
@@ -48,91 +47,22 @@ public class GlobalDumper {
|
||||
};
|
||||
|
||||
GhidraScript script;
|
||||
File manifestFile;
|
||||
HashMap<Address, GlobalRec> globalAddrs = new HashMap<>();
|
||||
FunctionDatabase functionDatabase;
|
||||
|
||||
public GlobalDumper(GhidraScript script) {
|
||||
public GlobalDumper(GhidraScript script, FunctionDatabase functionDatabase) {
|
||||
this.script = script;
|
||||
manifestFile = new File(RecompileConfig.INSTANCE.outputDir, "globals.txt");
|
||||
this.functionDatabase = functionDatabase;
|
||||
}
|
||||
|
||||
public void removeGlobalManifest() {
|
||||
if (manifestFile.exists()) {
|
||||
manifestFile.delete();
|
||||
// Remove globals from database
|
||||
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) {
|
||||
str = str.replace("\\", "\\\\");
|
||||
str = str.replace("\"", "\\\"");
|
||||
@@ -162,20 +92,52 @@ public class GlobalDumper {
|
||||
}
|
||||
|
||||
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");
|
||||
hwriter.println("// AUTO-GENERATED FILE ");
|
||||
Utils.headerGuardPre(hwriter, "GLOBALS");
|
||||
hwriter.println("#include <r3/binders/global.h>");
|
||||
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");
|
||||
cwriter.println("// AUTO-GENERATED FILE ");
|
||||
cwriter.println("#include <r3/binders/global.h>");
|
||||
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));
|
||||
|
||||
for (GlobalRec global : globals) {
|
||||
@@ -203,11 +165,18 @@ public class GlobalDumper {
|
||||
// String type
|
||||
initBlk += "\"" + escapeCString(readCString(addr, 2048)) + "\"";
|
||||
fullyDefinedType = true;
|
||||
} else if (dt instanceof PointerDataType) {
|
||||
PointerDataType pdt = (PointerDataType) dt;
|
||||
DataType baseType = pdt.getDataType();
|
||||
dataType = baseType.getDisplayName() + "*";
|
||||
initBlk += "(" + dataType + ")&GH_MEM(0x" + addr + ")";
|
||||
} else if (dt instanceof Pointer) {
|
||||
DataType baseType = ((Pointer) dt).getDataType();
|
||||
if (baseType == null) {
|
||||
script.println("WARNING: Missing base type for pointer: " + name + " at " + 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;
|
||||
}
|
||||
String linkagePrefix = "extern ";
|
||||
@@ -243,45 +212,58 @@ public class GlobalDumper {
|
||||
cwriter.close();
|
||||
}
|
||||
|
||||
public void saveGlobalManifest() throws Exception {
|
||||
File backupFile = new File(manifestFile.getParentFile(), manifestFile.getName() + ".bak");
|
||||
if (backupFile.exists()) {
|
||||
if (!backupFile.delete()) {
|
||||
throw new Exception("Failed to delete backup file: " + backupFile + ", globals will not be saved!");
|
||||
}
|
||||
}
|
||||
|
||||
if (manifestFile.exists()) {
|
||||
if (!manifestFile.renameTo(backupFile))
|
||||
throw new Exception("Failed to rename manifest file: " + manifestFile + ", globals will not be saved!");
|
||||
public void addGlobal(Address addr, HighSymbol sym) throws Exception {
|
||||
if (sym.getName().equals("ExceptionList")) {
|
||||
return;
|
||||
}
|
||||
|
||||
try (PrintWriter writer = new PrintWriter(manifestFile)) {
|
||||
script.println("Saving global manifest to " + manifestFile);
|
||||
GlobalRec[] globals = globalAddrs.values().toArray(new GlobalRec[0]);
|
||||
Arrays.sort(globals, (a, b) -> a.address.compareTo(b.address));
|
||||
for (GlobalRec global : globals) {
|
||||
DataTypePath path = global.type.getDataTypePath();
|
||||
writer.println(global.address.toString() + " || " + global.name + " || " + path.getCategoryPath() + " || "
|
||||
+ path.getDataTypeName());
|
||||
if (addr.compareTo(RemanConfig.INSTANCE.staticMemoryBlockStart) < 0
|
||||
|| addr.compareTo(RemanConfig.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());
|
||||
|
||||
// Add directly to database instead of storing in memory
|
||||
functionDatabase.addGlobal(addr, sym.getName());
|
||||
}
|
||||
|
||||
public void sanitizeGlobalSymbols() {
|
||||
for (GlobalRec global : globalAddrs.values()) {
|
||||
String sanitizedName = Utils.sanitizeIdentifier(global.name);
|
||||
if (!sanitizedName.equals(global.name)) {
|
||||
Symbol symbol = script.getSymbolAt(global.address);
|
||||
public void sanitizeGlobalSymbols() throws Exception {
|
||||
// Load globals from database, sanitize symbol names, and update both Ghidra
|
||||
// symbols and database
|
||||
List<FunctionDatabase.GlobalEntry> dbGlobals = functionDatabase.loadAllGlobals();
|
||||
|
||||
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) {
|
||||
script.println("Renaming global symbol: " + global.name + " -> " + sanitizedName);
|
||||
AddLabelCmd cmd = new AddLabelCmd(global.address, sanitizedName,
|
||||
script.println("Renaming global symbol: " + entry.name + " -> " + sanitizedName);
|
||||
AddLabelCmd cmd = new AddLabelCmd(entry.address, sanitizedName,
|
||||
symbol.getParentNamespace(),
|
||||
SourceType.USER_DEFINED);
|
||||
if (!cmd.applyTo(script.getCurrentProgram())) {
|
||||
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;
|
||||
|
||||
public PCallTracer() {
|
||||
this.script = RecompileConfig.INSTANCE.script;
|
||||
this.script = RemanConfig.INSTANCE.script;
|
||||
this.program = this.script.getCurrentProgram();
|
||||
// this.decomp = RecompileConfig.INSTANCE.decompCache;
|
||||
}
|
||||
@@ -10,13 +10,17 @@ import ghidra.program.flatapi.FlatProgramAPI;
|
||||
import ghidra.program.model.address.Address;
|
||||
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";
|
||||
|
||||
// Version control project root
|
||||
public final String rootDir;
|
||||
// The output directory for the recompiled game
|
||||
public final String outputDir;
|
||||
// The output directory for the original game
|
||||
public final String originalDir;
|
||||
public final String typeBlacklistPath;
|
||||
public final String categoryPathBlacklistPath;
|
||||
public final String functionBlacklistPath;
|
||||
@@ -24,6 +28,9 @@ public class RecompileConfig {
|
||||
public final Address staticMemoryBlockStart;
|
||||
public final Address staticMemoryBlockEnd;
|
||||
|
||||
// The path to the database file
|
||||
public final File databasePath;
|
||||
|
||||
// The automatically decompiled files
|
||||
public final File dirDecompAuto;
|
||||
// The manually decompiled files (will not be overwritten by the auto
|
||||
@@ -48,10 +55,13 @@ public class RecompileConfig {
|
||||
|
||||
public final GhidraScript script;
|
||||
|
||||
public static RecompileConfig INSTANCE;
|
||||
public static RemanConfig INSTANCE;
|
||||
|
||||
public RecompileConfig(GhidraScript script) {
|
||||
staticMemoryBlockStart = script.getCurrentProgram().getAddressFactory().getAddress("00597000");
|
||||
public static final String GLOBAL_H_FILE = "gh_global.h"; // Default filepath for globals
|
||||
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");
|
||||
|
||||
this.script = script;
|
||||
@@ -59,11 +69,15 @@ public class RecompileConfig {
|
||||
rootDir = new File(script.getSourceFile().getAbsolutePath()).getParentFile().getParentFile().toString();
|
||||
outputDir = new File(rootDir, RECOMPILE_PREFIX).toString();
|
||||
script.println("Output path: " + outputDir);
|
||||
|
||||
originalDir = new File(rootDir, "game").toString();
|
||||
|
||||
typeBlacklistPath = new File(outputDir, "type_blacklist.txt").toString();
|
||||
categoryPathBlacklistPath = new File(outputDir, "type_path_blacklist.txt").toString();
|
||||
functionBlacklistPath = new File(outputDir, "function_blacklist.txt").toString();
|
||||
|
||||
databasePath = new File(outputDir, "gh.db");
|
||||
|
||||
dirDecompAuto = new File(outputDir, "gh_auto");
|
||||
dirDecompFix = new File(outputDir, "gh_fix");
|
||||
dirDecompRef = new File(outputDir, "gh_ref");
|
||||
@@ -8,15 +8,23 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.CategoryPath;
|
||||
import ghidra.program.model.data.Composite;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.Enum;
|
||||
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.Structure;
|
||||
import ghidra.program.model.data.TypeDef;
|
||||
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 re3lib.FunctionDatabase.GlobalEntry;
|
||||
|
||||
public class TypeDumper {
|
||||
Program currentProgram;
|
||||
@@ -25,15 +33,38 @@ public class TypeDumper {
|
||||
public TypeDumper(GhidraScript script) {
|
||||
this.script = script;
|
||||
currentProgram = script.getCurrentProgram();
|
||||
RecompileConfig.INSTANCE = new RecompileConfig(script);
|
||||
RemanConfig.INSTANCE = new RemanConfig(script);
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
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
|
||||
.loadSimpleBlacklist(RecompileConfig.INSTANCE.categoryPathBlacklistPath);
|
||||
.loadSimpleBlacklist(RemanConfig.INSTANCE.categoryPathBlacklistPath);
|
||||
|
||||
if (typeBlacklist == null) {
|
||||
script.println("Building struct blacklist from existing data types");
|
||||
@@ -45,7 +76,7 @@ public class TypeDumper {
|
||||
typeBlacklist.add(dt.getDisplayName());
|
||||
}
|
||||
}
|
||||
Utils.saveStructBlacklist(typeBlacklist, RecompileConfig.INSTANCE.typeBlacklistPath);
|
||||
Utils.saveStructBlacklist(typeBlacklist, RemanConfig.INSTANCE.typeBlacklistPath);
|
||||
}
|
||||
|
||||
List<DataType> filteredTypes = new ArrayList<>();
|
||||
@@ -74,32 +105,42 @@ public class TypeDumper {
|
||||
Iterator<DataType> it = dtm.getAllDataTypes();
|
||||
while (it.hasNext()) {
|
||||
DataType dt = it.next();
|
||||
|
||||
if (typeBlacklist.contains(dt.getDisplayName()))
|
||||
continue;
|
||||
|
||||
CategoryPath catPath = dt.getCategoryPath();
|
||||
if (catPath.getPathElements().length > 0 && categoryPathBlacklist.contains(catPath.getPathElements()[0]))
|
||||
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"))
|
||||
// throw new Exception("Found: " + dt.getDisplayName() + " - " + catPath.getPathElements()[0] + " - " + dt.getClass().getSimpleName());
|
||||
if (dt.getDisplayName().contains("level_displayFn") || dt.getDisplayName().contains("_M_IX86"))
|
||||
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);
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
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")) {
|
||||
Utils.headerGuardPre(writer, "STRUCTS");
|
||||
writer.println("// AUTO-GENERATED FILE ");
|
||||
writer.println("#include <r3/binders/type.h>");
|
||||
|
||||
DataTypeWriter dtw = new DataTypeWriter(dtm, writer);
|
||||
dtw.blacklistedTypes = typeBlacklist;
|
||||
dtw.requiredFunctionTypes = requiredFunctionTypes;
|
||||
dtw.write(filteredTypes, script.getMonitor());
|
||||
|
||||
Utils.headerGuardPost(writer, "STRUCTS");
|
||||
@@ -22,7 +22,10 @@ public class Utils {
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -51,7 +54,7 @@ public class Utils {
|
||||
}
|
||||
|
||||
public static HashSet<Address> loadFunctionBlacklist(String path) {
|
||||
GhidraScript script = RecompileConfig.INSTANCE.script;
|
||||
GhidraScript script = RemanConfig.INSTANCE.script;
|
||||
HashSet<Address> fnBlacklist = new HashSet<>();
|
||||
File blacklistFile = new File(path);
|
||||
try (Scanner scanner = new Scanner(blacklistFile)) {
|
||||
@@ -60,7 +63,7 @@ public class Utils {
|
||||
// Strip comment
|
||||
String line1 = line.split("//")[0].trim();
|
||||
// Deserialize address
|
||||
Address addr = RecompileConfig.INSTANCE.currentProgram.getAddressFactory().getAddress(line1);
|
||||
Address addr = RemanConfig.INSTANCE.currentProgram.getAddressFactory().getAddress(line1);
|
||||
fnBlacklist.add(addr);
|
||||
}
|
||||
script.println("Loaded blacklist with " + fnBlacklist.size() + " entries");
|
||||
@@ -71,7 +74,7 @@ public class Utils {
|
||||
}
|
||||
|
||||
public static void saveFunctionBlacklist(HashSet<Address> fnBlacklist, String path) {
|
||||
GhidraScript script = RecompileConfig.INSTANCE.script;
|
||||
GhidraScript script = RemanConfig.INSTANCE.script;
|
||||
File blacklistFile = new File(path);
|
||||
try (PrintWriter writer = new PrintWriter(blacklistFile)) {
|
||||
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.
9
game_re/.gitignore
vendored
9
game_re/.gitignore
vendored
@@ -1,5 +1,10 @@
|
||||
gh_auto/*
|
||||
gh_ref/*
|
||||
old/
|
||||
*.bak
|
||||
gh_cmake_timestamp
|
||||
functions.dat
|
||||
functions.dat
|
||||
*.zip
|
||||
.tmp
|
||||
.txt
|
||||
*.db
|
||||
logs/
|
||||
@@ -1,84 +1,125 @@
|
||||
# Build for 32-bit compatibility
|
||||
add_compile_options(-m32)
|
||||
add_link_options(-m32)
|
||||
function(setup_target TARGET DBG_MODE)
|
||||
set(SOURCES
|
||||
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
|
||||
r3/main.cpp
|
||||
r3/binders/static_mem.cxx
|
||||
gh_global.cxx
|
||||
)
|
||||
target_compile_features(${TARGET} PUBLIC cxx_std_20)
|
||||
target_include_directories(${TARGET} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
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
|
||||
${CMAKE_CURRENT_SOURCE_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}
|
||||
target_compile_definitions(${TARGET} PRIVATE
|
||||
R3_GAME_DATA_DIR=\"${GAME_DATA_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
|
||||
R3_GAME_DATA_DIR=\"${GAME_DATA_DIR}\"
|
||||
)
|
||||
if(NOT DBG_MODE)
|
||||
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(game_re PRIVATE
|
||||
R3_DATA_SEGMENT_FILE=\"${R3_DATA_SEGMENT_FILE}\"
|
||||
)
|
||||
|
||||
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
|
||||
target_compile_definitions(${TARGET} PRIVATE
|
||||
_CRT_SECURE_NO_WARNINGS=1
|
||||
_CRT_NONSTDC_NO_WARNINGS=1
|
||||
SPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_TRACE
|
||||
)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(game_re PRIVATE
|
||||
_CRT_SECURE_NO_WARNINGS=1
|
||||
_CRT_NONSTDC_NO_WARNINGS=1)
|
||||
target_link_libraries(${TARGET} PRIVATE spdlog CLI11 magic_enum)
|
||||
|
||||
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)
|
||||
file(GLOB GH_FIX_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/gh_fix/*.cxx)
|
||||
file(GLOB GH_STUB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/gh_stub/*.cxx)
|
||||
target_sources(${TARGET} PRIVATE
|
||||
${GH_AUTO_SOURCES}
|
||||
${GH_FIX_SOURCES}
|
||||
${GH_STUB_SOURCES}
|
||||
)
|
||||
|
||||
target_sources(game_re PRIVATE
|
||||
${GH_AUTO_SOURCES}
|
||||
${GH_FIX_SOURCES}
|
||||
${GH_STUB_SOURCES}
|
||||
)
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
target_compile_definitions(${TARGET} PRIVATE MSVC=1)
|
||||
|
||||
# Ignore -Wformat-security
|
||||
target_compile_options(game_re PRIVATE -Wno-format-security)
|
||||
# Disable SAFESEH on Windows
|
||||
if(WIN32)
|
||||
target_link_options(${TARGET} PRIVATE /SAFESEH:NO)
|
||||
endif()
|
||||
else()
|
||||
target_compile_definitions(${TARGET} PRIVATE MSVC=0)
|
||||
|
||||
# Ignore -Wmicrosoft-cast
|
||||
target_compile_options(game_re PRIVATE -Wno-microsoft-cast)
|
||||
# Ignore -Wformat-security
|
||||
target_compile_options(${TARGET} PRIVATE -Wno-format-security)
|
||||
|
||||
# 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
|
||||
)
|
||||
# Ignore -Wmicrosoft-cast
|
||||
target_compile_options(${TARGET} PRIVATE -Wno-microsoft-cast)
|
||||
|
||||
target_precompile_headers(game_re PRIVATE
|
||||
"$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_CURRENT_SOURCE_DIR}/r3/binders/auto_pch.cxx>"
|
||||
)
|
||||
# Disable safeseh
|
||||
# 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
|
||||
@@ -202,4 +202,5 @@
|
||||
00408d30 // strcmp
|
||||
0054c925 // _chdir
|
||||
0054bce5 // strlwr
|
||||
00402960 // sprintf
|
||||
00402960 // sprintf
|
||||
0059736c // Direct3DCreate8
|
||||
@@ -3,13 +3,14 @@
|
||||
#include <r3/binders/auto.h>
|
||||
#include <gh_global.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
// 00401410
|
||||
|
||||
HWND getHWND(void)
|
||||
// 004013f0
|
||||
HANDLE __cdecl r3_getDrawSemaphore(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
|
||||
#include <cstddef>
|
||||
|
||||
#define GH_DATA_START 0x00597000
|
||||
#define GH_DATA_START 0x00400000
|
||||
#define GH_DATA_END 0x00843fff
|
||||
#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_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>
|
||||
|
||||
extern "C" {
|
||||
undefined FUN_00470db0(void); // 00470db0 // FUN_00470db0
|
||||
undefined r3_checkDisc(void); // 004464f0 // r3_checkDisc
|
||||
undefined FUN_00503710(void); // 00503710 // FUN_00503710
|
||||
undefined r3_initAllModules(void); // 00401000 // r3_initAllModules
|
||||
undefined FUN_00472150(void); // 00472150 // FUN_00472150
|
||||
undefined r3_wait_for_dvd(char *param_1, char *param_2,
|
||||
undefined4 param_3); // 0043e540 // r3_wait_for_dvd
|
||||
int setupWindow(HINSTANCE instance, undefined4 param_2,
|
||||
int windowedParam); // 00402140 // setupWindow
|
||||
undefined FUN_00470db0(void); // 00470db0 // FUN_00470db0
|
||||
undefined r3_checkDisc(void); // 004464f0 // r3_checkDisc
|
||||
undefined FUN_00503710(void); // 00503710 // FUN_00503710
|
||||
undefined r3_initAllModules(void); // 00401000 // r3_initAllModules
|
||||
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
|
||||
int r3_get_gli_width1(void); // 0047baf0 // r3_get_gli_width1
|
||||
undefined gfx_init2(void); // 00470be0 // gfx_init2
|
||||
void g_setInitVar0(void); // 00401310 // g_setInitVar0
|
||||
int r3_get_gli_height1(void); // 0047bb00 // r3_get_gli_height1
|
||||
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
|
||||
undefined r3_initEngine(void); // 00401220 // r3_initEngine
|
||||
undefined FUN_005038e0(void); // 005038e0 // FUN_005038e0
|
||||
undefined FUN_004fb300(void); // 004fb300 // FUN_004fb300
|
||||
undefined spawnThread(void); // 004477d0 // spawnThread
|
||||
undefined
|
||||
r3_setupWindow(HINSTANCE hInstance, undefined4 param_2,
|
||||
undefined4 maximizeWindow); // 00402140 // r3_setupWindow
|
||||
undefined r3_engineLoop(void); // 00401220 // r3_engineLoop
|
||||
|
||||
// 00401630
|
||||
int r3_main(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR *cmdline,
|
||||
@@ -34,6 +33,7 @@ int r3_main(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR *cmdline,
|
||||
|
||||
{
|
||||
undefined4 uVar1;
|
||||
undefined2 uVar2;
|
||||
undefined2 uVar3;
|
||||
LPSTR pCVar3;
|
||||
char *pcVar4;
|
||||
@@ -44,68 +44,228 @@ int r3_main(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR *cmdline,
|
||||
HANDLE hTargetProcessHandle;
|
||||
HANDLE hSourceHandle;
|
||||
HANDLE hSourceProcessHandle;
|
||||
LPSTR *ppCVar8;
|
||||
uint32_t uVar9;
|
||||
uint *ppCVar8;
|
||||
HWND hWnd;
|
||||
int iVar10;
|
||||
int iVar11;
|
||||
int iVar12;
|
||||
int iVar13;
|
||||
uint uVar14;
|
||||
void *unaff_ESI;
|
||||
undefined4 *puVar15;
|
||||
void *unaff_EDI;
|
||||
undefined4 *puVar16;
|
||||
HKEY unaff_ESI;
|
||||
char *pcVar17;
|
||||
undefined4 uStack_83c;
|
||||
HKEY pHStack_838;
|
||||
HANDLE pvStack_834;
|
||||
UINT UStack_830;
|
||||
BYTE aBStack_82c[4];
|
||||
DWORD DStack_828;
|
||||
DWORD DStack_824;
|
||||
tagRECT tStack_820;
|
||||
char acStack_810[260];
|
||||
CHAR languageStr[256];
|
||||
CHAR pathToUbi_ini[260];
|
||||
char acStack_508[260];
|
||||
CHAR windowsDir[260];
|
||||
char acStack_300[256];
|
||||
char acStack_200[256];
|
||||
char acStack_100[256];
|
||||
void *p_cTxt1;
|
||||
void *p_cTxt2;
|
||||
undefined4 uStack_85c;
|
||||
undefined4 uStack_858;
|
||||
LPSTR lpBuffer;
|
||||
UINT uiParam;
|
||||
BYTE uStack_83c[4];
|
||||
DWORD pHStack_838;
|
||||
DWORD pvStack_834;
|
||||
char UStack_830[16];
|
||||
char tStack_820[260];
|
||||
CHAR aCStack_71c[256];
|
||||
char acStack_61c[16];
|
||||
CHAR pathToUbi_ini[228];
|
||||
char acStack_528[16];
|
||||
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;
|
||||
char cVar1;
|
||||
undefined4 chars;
|
||||
DWORD dwOptions;
|
||||
tagRECT *lpRect;
|
||||
HANDLE *lpTargetHandle;
|
||||
undefined2 uVar2;
|
||||
LPRECT lpRect;
|
||||
LPHANDLE lpTargetHandle;
|
||||
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();
|
||||
|
||||
R3Config &gameConfig = getDefaultConfig();
|
||||
|
||||
// Store and change to game directory
|
||||
chdir(gameConfig.gameRootDir.c_str());
|
||||
strcpy(r3_main_data_005d28b6.gameDataDir, gameConfig.gameRootDir.c_str());
|
||||
|
||||
strcpy(languageStr, gameConfig.language.c_str());
|
||||
pcVar4 = pCVar3 + 1;
|
||||
iVar13 = -(int)pcVar4;
|
||||
do {
|
||||
cVar1 = *pcVar4;
|
||||
pcVar4[(int)(tStack_820 + iVar13)] = cVar1;
|
||||
pcVar4 = pcVar4 + 1;
|
||||
} while (cVar1 != '\0');
|
||||
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_windowTitle, s_percents, s_windowTitle);
|
||||
|
||||
/* Setup localized quiting/restoring strings */
|
||||
iVar13 = strcmpi(languageStr, s_French_005b6828);
|
||||
iVar13 = strcmpi(aCStack_71c, s_French_005b6828);
|
||||
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>();
|
||||
puVar15 = (undefined4 *)s_ou_appuyez_sur_Echap_pour_quitte_005b67d0;
|
||||
puVar16 = (undefined4 *)s_quitting1;
|
||||
pcVar4 = s_ou_appuyez_sur_Echap_pour_quitte_005b67d0;
|
||||
pcVar17 = s_quitting1;
|
||||
for (iVar13 = 0xb; uVar22 = s_QUITTER + Field<4, 4>(), iVar13 != 0;
|
||||
iVar13 = iVar13 + -1) {
|
||||
*puVar16 = *puVar15;
|
||||
puVar15 = puVar15 + 1;
|
||||
puVar16 = puVar16 + 1;
|
||||
*(undefined4 *)pcVar17 = *(undefined4 *)pcVar4;
|
||||
pcVar4 = pcVar4 + 4;
|
||||
pcVar17 = pcVar17 + 4;
|
||||
}
|
||||
s_wndStrQuiting[0] = s_QUITTER[0];
|
||||
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[7] = s_QUITTER[7];
|
||||
s_QUITTER + Field<4, 4>() = uVar22;
|
||||
sprintf(lpString_0077d2c0, s__s___Pause_005b67c4, s_windowTitle);
|
||||
puVar15 = (undefined4 *)s_Restauration;
|
||||
puVar16 = (undefined4 *)s_wndStrRestoring;
|
||||
sprintf(g_windowTitle1, s__s___Pause_005b67c4, s_windowTitle);
|
||||
pcVar4 = s_Restauration;
|
||||
pcVar17 = s_wndStrRestoring;
|
||||
for (iVar13 = 7; iVar13 != 0; iVar13 = iVar13 + -1) {
|
||||
*puVar16 = *puVar15;
|
||||
puVar15 = puVar15 + 1;
|
||||
puVar16 = puVar16 + 1;
|
||||
*(undefined4 *)pcVar17 = *(undefined4 *)pcVar4;
|
||||
pcVar4 = pcVar4 + 4;
|
||||
pcVar17 = pcVar17 + 4;
|
||||
}
|
||||
} else {
|
||||
iVar13 = strcmpi(languageStr, s_Spanish_005b67a0);
|
||||
iVar13 = strcmpi(aCStack_71c, s_Spanish_005b67a0);
|
||||
if (iVar13 == 0) {
|
||||
sprintf(s_windowTitleRestoring, s__s___Restablecer_datos____005b6784,
|
||||
sprintf(g_windowTitleRestoring, s__s___Restablecer_datos____005b6784,
|
||||
s_windowTitle);
|
||||
uVar2 = s_SALIR_005b675c + Field<4, 2>();
|
||||
puVar15 = (undefined4 *)s_Pulsa_ESC_para_salir_Rayman_3__005b6764;
|
||||
puVar16 = (undefined4 *)s_quitting1;
|
||||
pcVar4 = s_Pulsa_ESC_para_salir_Rayman_3__005b6764;
|
||||
pcVar17 = s_quitting1;
|
||||
for (iVar13 = 7; chars = s_SALIR_005b675c + Field<0, 4>(), iVar13 != 0;
|
||||
iVar13 = iVar13 + -1) {
|
||||
*puVar16 = *puVar15;
|
||||
puVar15 = puVar15 + 1;
|
||||
puVar16 = puVar16 + 1;
|
||||
*(undefined4 *)pcVar17 = *(undefined4 *)pcVar4;
|
||||
pcVar4 = pcVar4 + 4;
|
||||
pcVar17 = pcVar17 + 4;
|
||||
}
|
||||
*(undefined2 *)puVar16 = *(undefined2 *)puVar15;
|
||||
*(undefined *)((int)puVar16 + 2) = *(undefined *)((int)puVar15 + 2);
|
||||
*(undefined2 *)pcVar17 = *(undefined2 *)pcVar4;
|
||||
pcVar17[2] = pcVar4[2];
|
||||
uVar3 = s_SALIR_005b675c + Field<4, 2>();
|
||||
uVar22 = s_SALIR_005b675c + Field<0, 4>();
|
||||
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_SALIR_005b675c + Field<0, 4>() = uVar22;
|
||||
s_SALIR_005b675c + Field<4, 2>() = uVar3;
|
||||
sprintf(lpString_0077d2c0, s__s___Rotura_005b6750, s_windowTitle);
|
||||
puVar15 = (undefined4 *)s_Restablecer_datos____005b6738;
|
||||
puVar16 = (undefined4 *)s_wndStrRestoring;
|
||||
sprintf(g_windowTitle1, s__s___Rotura_005b6750, s_windowTitle);
|
||||
pcVar4 = s_Restablecer_datos____005b6738;
|
||||
pcVar17 = s_wndStrRestoring;
|
||||
for (iVar13 = 5; iVar13 != 0; iVar13 = iVar13 + -1) {
|
||||
*puVar16 = *puVar15;
|
||||
puVar15 = puVar15 + 1;
|
||||
puVar16 = puVar16 + 1;
|
||||
*(undefined4 *)pcVar17 = *(undefined4 *)pcVar4;
|
||||
pcVar4 = pcVar4 + 4;
|
||||
pcVar17 = pcVar17 + 4;
|
||||
}
|
||||
*(undefined *)puVar16 = *(undefined *)puVar15;
|
||||
*pcVar17 = *pcVar4;
|
||||
} else {
|
||||
iVar13 = strcmpi(languageStr, s_Italian_005b6730);
|
||||
iVar13 = strcmpi(aCStack_71c, s_Italian_005b6730);
|
||||
if (iVar13 == 0) {
|
||||
sprintf(s_windowTitleRestoring, s__s___Ripristino_dati____005b6718,
|
||||
sprintf(g_windowTitleRestoring, s__s___Ripristino_dati____005b6718,
|
||||
s_windowTitle);
|
||||
uVar2 = s_USCIRE_005b66ec + Field<4, 2>();
|
||||
puVar15 = (undefined4 *)s_Premi_ESC_per_uscire_da_Rayman_3_005b66f4;
|
||||
puVar16 = (undefined4 *)s_quitting1;
|
||||
pcVar4 = s_Premi_ESC_per_uscire_da_Rayman_3_005b66f4;
|
||||
pcVar17 = s_quitting1;
|
||||
for (iVar13 = 8; cVar1 = s_USCIRE_005b66ec[6], iVar13 != 0;
|
||||
iVar13 = iVar13 + -1) {
|
||||
*puVar16 = *puVar15;
|
||||
puVar15 = puVar15 + 1;
|
||||
puVar16 = puVar16 + 1;
|
||||
*(undefined4 *)pcVar17 = *(undefined4 *)pcVar4;
|
||||
pcVar4 = pcVar4 + 4;
|
||||
pcVar17 = pcVar17 + 4;
|
||||
}
|
||||
s_wndStrQuiting[0] = s_USCIRE_005b66ec[0];
|
||||
s_wndStrQuiting[1] = s_USCIRE_005b66ec[1];
|
||||
s_wndStrQuiting[2] = s_USCIRE_005b66ec[2];
|
||||
s_wndStrQuiting[3] = s_USCIRE_005b66ec[3];
|
||||
*(undefined2 *)puVar16 = *(undefined2 *)puVar15;
|
||||
s_wndStrQuiting + Field<4, 3>() = CONCAT12(cVar1, uVar2);
|
||||
sprintf(lpString_0077d2c0, s__s___Pausa_005b66e0, s_windowTitle);
|
||||
*(undefined2 *)pcVar17 = *(undefined2 *)pcVar4;
|
||||
uVar3 = s_USCIRE_005b66ec + Field<4, 2>();
|
||||
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[1] = s_Ripristino_dati____005b66cc[1];
|
||||
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_wndStrRestoring[0x12] = s_Ripristino_dati____005b66cc[0x12];
|
||||
} else {
|
||||
iVar13 = strcmpi(languageStr, s_German_005b66c4);
|
||||
iVar13 = strcmpi(aCStack_71c, s_German_005b66c4);
|
||||
if (iVar13 == 0) {
|
||||
sprintf(s_windowTitleRestoring, s__s___Daten_Reparatur____005b66ac,
|
||||
sprintf(g_windowTitleRestoring, s__s___Daten_Reparatur____005b66ac,
|
||||
s_windowTitle);
|
||||
chars = s_BEENDIGEN_005b6678 + Field<0, 4>();
|
||||
puVar15 = (undefined4 *)&CHAR_E_005b6684;
|
||||
puVar16 = (undefined4 *)s_quitting1;
|
||||
pcVar4 = &CHAR_E_005b6684;
|
||||
pcVar17 = s_quitting1;
|
||||
for (iVar13 = 9; uVar2 = s_BEENDIGEN_005b6678 + Field<8, 2>(),
|
||||
uVar22 = s_BEENDIGEN_005b6678 + Field<4, 4>(), iVar13 != 0;
|
||||
iVar13 = iVar13 + -1) {
|
||||
*puVar16 = *puVar15;
|
||||
puVar15 = puVar15 + 1;
|
||||
puVar16 = puVar16 + 1;
|
||||
*(undefined4 *)pcVar17 = *(undefined4 *)pcVar4;
|
||||
pcVar4 = pcVar4 + 4;
|
||||
pcVar17 = pcVar17 + 4;
|
||||
}
|
||||
*(undefined2 *)puVar16 = *(undefined2 *)puVar15;
|
||||
*(undefined2 *)pcVar17 = *(undefined2 *)pcVar4;
|
||||
uVar1 = s_BEENDIGEN_005b6678 + Field<0, 4>();
|
||||
s_BEENDIGEN_005b6678[0] = (char)chars;
|
||||
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[3] = s_BEENDIGEN_005b6678[3];
|
||||
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>();
|
||||
chars = s_BEENDIGEN_005b6678 + Field<4, 4>();
|
||||
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_BEENDIGEN_005b6678 + Field<4, 4>() = chars;
|
||||
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[1] = s_Daten_Reparatur____005b6664[1];
|
||||
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[0x12] = s_Daten_Reparatur____005b6664[0x12];
|
||||
} else {
|
||||
sprintf(s_windowTitleRestoring, s__s___Restoring_data____005b664c,
|
||||
sprintf(g_windowTitleRestoring, s__s___Restoring_data____005b664c,
|
||||
s_windowTitle);
|
||||
chars = s_QUIT + Field<0, 4>();
|
||||
puVar15 = (undefined4 *)s_or_press_ESC_to_quit_Rayman_3__005b662c;
|
||||
puVar16 = (undefined4 *)s_quitting1;
|
||||
pcVar4 = s_or_press_ESC_to_quit_Rayman_3__005b662c;
|
||||
pcVar17 = s_quitting1;
|
||||
for (iVar13 = 7; cVar1 = s_QUIT[4], iVar13 != 0;
|
||||
iVar13 = iVar13 + -1) {
|
||||
*puVar16 = *puVar15;
|
||||
puVar15 = puVar15 + 1;
|
||||
puVar16 = puVar16 + 1;
|
||||
*(undefined4 *)pcVar17 = *(undefined4 *)pcVar4;
|
||||
pcVar4 = pcVar4 + 4;
|
||||
pcVar17 = pcVar17 + 4;
|
||||
}
|
||||
*(undefined2 *)puVar16 = *(undefined2 *)puVar15;
|
||||
*(undefined *)((int)puVar16 + 2) = *(undefined *)((int)puVar15 + 2);
|
||||
*(undefined2 *)pcVar17 = *(undefined2 *)pcVar4;
|
||||
pcVar17[2] = pcVar4[2];
|
||||
uVar22 = s_QUIT + Field<0, 4>();
|
||||
s_QUIT[0] = (char)chars;
|
||||
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[4] = cVar1;
|
||||
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[1] = s_Restoring_data_____005b6610[1];
|
||||
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
|
||||
Initial count = 1
|
||||
Maximum count = 1 */
|
||||
g_drawSemaphore =
|
||||
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 */
|
||||
// hLibModule = LoadLibraryA(s_dpnhpast_dll_005b65f8);
|
||||
// if (hLibModule == (HMODULE)0x0) {
|
||||
// iVar13 = strcmpi(languageStr, s_French_005b6828);
|
||||
// if (iVar13 == 0) {
|
||||
// MessageBoxA((HWND)0x0, lpText_005b6598, s_Erreur_Rayman_3_005b65e4,
|
||||
// 0x10); return -1;
|
||||
// }
|
||||
// iVar13 = strcmpi(languageStr, s_Spanish_005b67a0);
|
||||
// if (iVar13 == 0) {
|
||||
// MessageBoxA((HWND)0x0, lpText_005b6540, s_Rayman_3_005b6588, 0x10);
|
||||
// return -1;
|
||||
// }
|
||||
// iVar13 = strcmpi(languageStr, s_Italian_005b6730);
|
||||
// if (iVar13 == 0) {
|
||||
// MessageBoxA((HWND)0x0, lpText_005b64f0, s_Rayman_3_005b6588, 0x10);
|
||||
// return -1;
|
||||
// }
|
||||
// iVar13 = strcmpi(languageStr, s_German_005b66c4);
|
||||
// if (iVar13 != 0) {
|
||||
// MessageBoxA((HWND)0x0, s_Check_your_version_of_DirectX__V_005b6430,
|
||||
// s_Rayman_3_Error_005b68bc, 0x10);
|
||||
// return -1;
|
||||
// }
|
||||
// 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) {
|
||||
hLibModule = LoadLibraryA(s_dpnhpast_dll_005b65f8);
|
||||
if (hLibModule == (HMODULE)0x0) {
|
||||
iVar13 = strcmpi(aCStack_71c, s_French_005b6828);
|
||||
if (iVar13 == 0) {
|
||||
MessageBoxA((HWND)0x0, lpText_005b6598, s_Erreur_Rayman_3_005b65e4, 0x10);
|
||||
return -1;
|
||||
}
|
||||
iVar13 = strcmpi(aCStack_71c, s_Spanish_005b67a0);
|
||||
if (iVar13 == 0) {
|
||||
MessageBoxA((HWND)0x0, lpText_005b6540, s_Rayman_3_005b6588, 0x10);
|
||||
return -1;
|
||||
}
|
||||
iVar13 = strcmpi(aCStack_71c, s_Italian_005b6730);
|
||||
if (iVar13 == 0) {
|
||||
MessageBoxA((HWND)0x0, lpText_005b64f0, s_Rayman_3_005b6588, 0x10);
|
||||
return -1;
|
||||
}
|
||||
iVar13 = strcmpi(aCStack_71c, s_German_005b66c4);
|
||||
if (iVar13 != 0) {
|
||||
MessageBoxA((HWND)0x0, s_Check_your_version_of_DirectX__V_005b6430,
|
||||
s_Rayman_3_Error_005b68bc, 0x10);
|
||||
return -1;
|
||||
}
|
||||
MessageBoxA((HWND)0x0, lpText_005b6478, s_Rayman_3_005b6588, 0x10);
|
||||
return -1;
|
||||
}
|
||||
g_setInitVar0();
|
||||
FUN_00401320();
|
||||
spawnThread();
|
||||
gfx_init2();
|
||||
lpRect = &tStack_820;
|
||||
hWnd = GetDesktopWindow();
|
||||
GetWindowRect(hWnd, lpRect);
|
||||
BVar18 = 1;
|
||||
iVar13 = r3_get_gli_height1();
|
||||
iVar13 = iVar13 + 0x20;
|
||||
iVar10 = r3_get_gli_width1();
|
||||
iVar10 = iVar10 + 0xc;
|
||||
iVar11 = r3_get_gli_height1();
|
||||
iVar11 = (tStack_820.bottom - iVar11) / 2;
|
||||
iVar12 = r3_get_gli_width1();
|
||||
MoveWindow(g_gameHWND, (tStack_820.right - iVar12) / 2, iVar11, iVar10,
|
||||
iVar13, BVar18);
|
||||
FUN_004010b0();
|
||||
SystemParametersInfoA(0x10, 0, &UStack_830, 0);
|
||||
SystemParametersInfoA(0x11, 0, (PVOID)0x0, 0);
|
||||
ShowCursor(0);
|
||||
uStack_83c = 0;
|
||||
SystemParametersInfoA(0x61, 1, &uStack_83c, 0);
|
||||
g_engineRunning = 1;
|
||||
r3_initEngine();
|
||||
FUN_004725a0();
|
||||
FUN_005038e0();
|
||||
FUN_00503710();
|
||||
FUN_004fb300();
|
||||
FUN_00472150();
|
||||
FUN_00470db0();
|
||||
uStack_83c = 0;
|
||||
SystemParametersInfoA(0x61, 0, &uStack_83c, 0);
|
||||
ShowCursor(1);
|
||||
SystemParametersInfoA(0x11, UStack_830, (PVOID)0x0, 0);
|
||||
CloseHandle(pvStack_834);
|
||||
|
||||
return 0;
|
||||
FreeLibrary(hLibModule);
|
||||
#endif
|
||||
p_cTxt1 = (void *)0x401e2a;
|
||||
CreateMutexA((LPSECURITY_ATTRIBUTES)0x0, 1, g_mutexName_Rayman3);
|
||||
DVar7 = GetLastError();
|
||||
if (DVar7 == 0xb7) {
|
||||
/* Mutex already exists */
|
||||
return -1;
|
||||
}
|
||||
p_cTxt2 = (void *)0x401e5a;
|
||||
#if RE_AUTHENTIC == 0
|
||||
GetWindowsDirectoryA(acStack_424, 0x104);
|
||||
iVar13 = -1;
|
||||
/* Append ubi.ini */
|
||||
pcVar4 = acStack_424;
|
||||
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];
|
||||
#else
|
||||
strcpy(acStack_424, config.gameRootDir.c_str());
|
||||
strcat(acStack_424, "/ubi.ini");
|
||||
instance = hInstance;
|
||||
#endif
|
||||
/* Read graphics settings */
|
||||
GetPrivateProfileStringA(lpAppName_005b68f0, s_Adapter_005b68e4,
|
||||
(LPCSTR)&lpDefault_005cf96c, acStack_320, 0xff,
|
||||
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>
|
||||
|
||||
extern "C" {
|
||||
undefined r3_config_setIdentifier(
|
||||
const char *param_1); // 00470570 // r3_config_setIdentifier
|
||||
undefined
|
||||
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(
|
||||
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
|
||||
undefined
|
||||
r3_read_game_config_udp_port(void); // 00446040 // r3_read_game_config_udp_port
|
||||
undefined
|
||||
r3_config_setGLIMode(const char *param_1); // 004704e0 // r3_config_setGLIMode
|
||||
undefined r3_set_GameDataBinPath(
|
||||
const char *param_1); // 0055a8d0 // r3_set_GameDataBinPath
|
||||
r3_config_setGLIMode(char *param_1); // 004704e0 // r3_config_setGLIMode
|
||||
undefined r3_read_game_config_modem_quality(
|
||||
void); // 00445fc0 // r3_read_game_config_modem_quality
|
||||
|
||||
// 004460c0
|
||||
void r3_read_gli_config(void) {
|
||||
R3Config &config = getDefaultConfig();
|
||||
r3_config_setGLIMode(config.gfxGliMode.c_str());
|
||||
r3_config_setIdentifier(config.gfxIdentifier.c_str());
|
||||
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());
|
||||
/* WARNING: Inlined function: r3_config_set_adapter */
|
||||
/* WARNING: Inlined function: r3_config_setTexturesCompressed */
|
||||
/* WARNING: Inlined function: r3_config_setTnl */
|
||||
/* WARNING: Inlined function: r3_config_setTrilinearFiltering */
|
||||
|
||||
// GetPrivateProfileStringA
|
||||
// (sectionName,s_SingleProcessor_005be308,&lpDefault_005be318,stringBuffer,0x104,local_204
|
||||
// );
|
||||
// /* Set single processor mode */
|
||||
// iVar4 = strcmpi(stringBuffer,(char *)&s_Yes);
|
||||
// if (iVar4 == 0) {
|
||||
// sectionName[4] = '\x01';
|
||||
// sectionName[5] = '\0';
|
||||
// sectionName[6] = '\0';
|
||||
// sectionName[7] = '\0';
|
||||
// sectionName[0] = -0x1a;
|
||||
// sectionName[1] = 'c';
|
||||
// sectionName[2] = 'D';
|
||||
// sectionName[3] = '\0';
|
||||
// sectionName + Field<0, 4>() = GetCurrentProcess();
|
||||
// SetProcessAffinityMask((HANDLE)sectionName + Field<0, 4>(),sectionName +
|
||||
// Field<4, 4>());
|
||||
// }
|
||||
// sectionName[4] = -0xe;
|
||||
// sectionName[5] = 'c';
|
||||
// sectionName[6] = 'D';
|
||||
// sectionName[7] = '\0';
|
||||
// r3_read_game_config_modem_quality();
|
||||
// r3_read_game_config_udp_port();
|
||||
void r3_read_gli_config(void)
|
||||
|
||||
{
|
||||
UINT tempOutVal;
|
||||
void *pcVar2;
|
||||
void *pcVar3;
|
||||
HANDLE hProcess;
|
||||
int iVar4;
|
||||
char *pcVar1;
|
||||
char *pcVar4;
|
||||
void *in_stack_fffffce0;
|
||||
char *ptr0;
|
||||
char *ptr1;
|
||||
char local_218[20];
|
||||
char local_204[168];
|
||||
char local_15c[32];
|
||||
char stringBuffer[256];
|
||||
char cVar1;
|
||||
DWORD_PTR dwProcessAffinityMask;
|
||||
|
||||
const char *iniPath = getIniPath();
|
||||
|
||||
GetPrivateProfileStringA(lpAppName_005b68f0, s_GLI_Mode_005be3e0,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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>
|
||||
|
||||
extern "C" {
|
||||
undefined FUN_004013a0(void); // 004013a0 // FUN_004013a0
|
||||
undefined FUN_00401320(void); // 00401320 // FUN_00401320
|
||||
undefined r3_windowLockCursor(void); // 00401320 // r3_windowLockCursor // cdecl
|
||||
undefined r3_windowUnlockCursor(void); // 004013a0 // r3_windowUnlockCursor // cdecl
|
||||
|
||||
// 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;
|
||||
@@ -16,14 +16,14 @@ long r3_windowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
||||
if (uMsg < WM_SETCURSOR + 1) {
|
||||
if (uMsg == WM_SETCURSOR) {
|
||||
if (((g_engineShouldRun != 0) && (g_engineRunning != 0)) && (g_runMaximized != 0)) {
|
||||
FUN_00401320();
|
||||
r3_windowLockCursor();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uMsg == WM_CLOSE) {
|
||||
FUN_004013a0();
|
||||
DAT_0077d0b8 = 1;
|
||||
r3_windowUnlockCursor();
|
||||
g_windowCloseRequested = 1;
|
||||
if (g_drawSemaphore != (HANDLE)0x0) {
|
||||
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
|
||||
|
||||
#include <r3/binders/auto.h>
|
||||
#include <r3/binders/stub.h>
|
||||
#include <gh_global.h>
|
||||
#include <stdexcept>
|
||||
|
||||
// 00401320
|
||||
// FUN_00401320
|
||||
extern "C" undefined FUN_00401320(void) {
|
||||
// TODO: Implement this function
|
||||
throw GHStubException("Function not implemented: FUN_00401320");
|
||||
// 0043e1d0
|
||||
// Erm_fn_ucInitErrMsg
|
||||
extern "C" byte Erm_fn_ucInitErrMsg(void) {
|
||||
return gh_stub_impl_cdecl<(stub_t)0x0043e1d0, byte>();
|
||||
}
|
||||
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
|
||||
|
||||
#include <r3/binders/auto.h>
|
||||
#include <r3/binders/stub.h>
|
||||
#include <gh_global.h>
|
||||
#include <stdexcept>
|
||||
|
||||
// 004010b0
|
||||
// FUN_004010b0
|
||||
extern "C" undefined FUN_004010b0(void) {
|
||||
// TODO: Implement this function
|
||||
throw GHStubException("Function not implemented: FUN_004010b0");
|
||||
return gh_stub_impl_cdecl<(stub_t)0x004010b0, undefined>();
|
||||
}
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
// with possible manualy fixes
|
||||
|
||||
#include <r3/binders/auto.h>
|
||||
#include <r3/binders/stub.h>
|
||||
#include <gh_global.h>
|
||||
#include <stdexcept>
|
||||
|
||||
// 004464f0
|
||||
// r3_checkDisc
|
||||
extern "C" undefined r3_checkDisc(void) {
|
||||
// TODO: Implement this function
|
||||
throw GHStubException("Function not implemented: r3_checkDisc");
|
||||
// 00401270
|
||||
// FUN_00401270
|
||||
extern "C" undefined FUN_00401270(void) {
|
||||
return gh_stub_impl_cdecl<(stub_t)0x00401270, undefined>();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user