mirror of
https://codeberg.org/KeybadeBlox/JSRF-Decompilation.git
synced 2026-02-20 10:17:03 +03:00
Compare commits
No commits in common. "522bf8be7fdb6edb96a47e733a30da32b8334ddb" and "fd6815ae427a20cd37fe491c4dec543287c12976" have entirely different histories.
522bf8be7f
...
fd6815ae42
15 changed files with 396 additions and 502 deletions
|
|
@ -38,11 +38,11 @@ src/JSRF/Jet2.exe: $(OBJ) $(LIB)
|
|||
|
||||
|
||||
# Header files used for each object
|
||||
src/JSRF/Jet2.obj: src/JSRF/Core.hpp src/XDK/CRT/stddef.h src/XDK/D3D.h\
|
||||
src/JSRF/Jet2.obj: src/JSRF/Core.hpp src/Std.hpp src/XDK/D3D.h\
|
||||
src/XDK/Win32.h
|
||||
|
||||
src/JSRF/Core.obj: src/JSRF/Core.hpp src/Smilebit/MMatrix.hpp\
|
||||
src/XDK/CRT/stddef.h src/XDK/D3D.h src/XDK/Win32.h
|
||||
src/JSRF/Core.obj: src/JSRF/Core.hpp src/Smilebit/MMatrix.hpp src/Std.hpp\
|
||||
src/XDK/D3D.h src/XDK/Win32.h
|
||||
|
||||
src/JSRF/GameData.obj: src/JSRF/GameData.hpp
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ Game and GameObj classes that form the foundation of the JSRF game code.
|
|||
|
||||
#pragma bss_seg(".data")
|
||||
|
||||
#include "../XDK/CRT/stddef.h"
|
||||
#include "Core.hpp"
|
||||
|
||||
// Declarations for symbols not yet defined in their own source files
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ Game and GameObj classes that form the foundation of the JSRF game code.
|
|||
#define CORE_HPP
|
||||
|
||||
#include "../Smilebit/MMatrix.hpp"
|
||||
#include "../XDK/CRT/stddef.h"
|
||||
#include "../Std.hpp"
|
||||
#include "../XDK/D3D.h"
|
||||
#include "../XDK/Win32.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ Main function.
|
|||
|
||||
#pragma bss_seg(".data")
|
||||
|
||||
#include "../XDK/CRT/stddef.h"
|
||||
#include "Core.hpp"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ Smilebit's stack-based matrix math library.
|
|||
#pragma bss_seg (".data" )
|
||||
|
||||
|
||||
#include "../XDK/CRT/stddef.h"
|
||||
#include "../Std.hpp"
|
||||
#include "../XDK/Win32.h"
|
||||
#include "MMatrix.hpp"
|
||||
|
||||
|
|
|
|||
12
decompile/src/Std.hpp
Normal file
12
decompile/src/Std.hpp
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/* JSRF Decompilation: Std.hpp
|
||||
C(++) standard library definitions. Implemented in the repository instead of
|
||||
linking to an outside stdlib to ensure consistency (this may not actually be
|
||||
possible to accomplish, but we'll go for it for now).
|
||||
*/
|
||||
|
||||
#ifndef STD_HPP
|
||||
#define STD_HPP
|
||||
|
||||
#define NULL 0
|
||||
|
||||
#endif
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
/* JSRF Decompilation: XDK/CRT/stddef.h */
|
||||
|
||||
#ifndef STDDEF_H
|
||||
#define STDDEF_H
|
||||
|
||||
#define NULL 0
|
||||
|
||||
#endif
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
// Creates classes out namespaces with matching structs, and if they have a
|
||||
// vtable, sets the calling convention of the contained function typdefs to
|
||||
// __thiscall.
|
||||
//
|
||||
// For vtables to be found, they must be defined as structs with names ending
|
||||
// in "Vtbl" and be pointed to by the first member of a class struct.
|
||||
//
|
||||
// @category Data Types
|
||||
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.app.util.NamespaceUtils;
|
||||
import ghidra.program.database.data.DataTypeUtilities;
|
||||
import ghidra.program.model.data.DataTypeComponent;
|
||||
import ghidra.program.model.data.FunctionDefinition;
|
||||
import ghidra.program.model.data.Pointer;
|
||||
import ghidra.program.model.data.Structure;
|
||||
import ghidra.program.model.listing.GhidraClass;
|
||||
import ghidra.program.model.symbol.Namespace;
|
||||
import ghidra.program.model.symbol.Symbol;
|
||||
|
||||
|
||||
public class ClassFixup extends GhidraScript {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
fixInNamespace(currentProgram.getGlobalNamespace());
|
||||
}
|
||||
|
||||
private void fixInNamespace(final Namespace parent) throws Exception {
|
||||
for (final Symbol s : currentProgram.getSymbolTable()
|
||||
.getChildren(parent.getSymbol()))
|
||||
if (s.getObject() instanceof Namespace ns) switch (ns.getType()) {
|
||||
case Namespace.Type.NAMESPACE:
|
||||
if (shouldBeClass(ns)) {
|
||||
println("Converting \"" + ns.getName(true) + "\" to class...");
|
||||
NamespaceUtils.convertNamespaceToClass(ns);
|
||||
|
||||
// Re-fetch namespace to get its new class version
|
||||
ns = getNamespace(parent, ns.getName());
|
||||
} else {
|
||||
fixInNamespace(ns);
|
||||
break;
|
||||
}
|
||||
case Namespace.Type.CLASS: // fallthrough
|
||||
// Any ns that makes it here should be a class
|
||||
// (can't bind via pattern match because of the
|
||||
// fallthrough)
|
||||
final GhidraClass cls = (GhidraClass)ns;
|
||||
|
||||
// Fix up methods if first member is a vtable
|
||||
if (
|
||||
DataTypeUtilities.findExistingClassStruct(
|
||||
currentProgram.getDataTypeManager(),
|
||||
cls
|
||||
) instanceof Structure struct &&
|
||||
struct.getDataTypeAt(0) instanceof DataTypeComponent memberType &&
|
||||
memberType.getDataType() instanceof Pointer ptrType &&
|
||||
ptrType .getDataType() instanceof Structure vtblT_maybe &&
|
||||
vtblT_maybe.getName().endsWith("Vtbl")
|
||||
) fixMethods(vtblT_maybe);
|
||||
break;
|
||||
|
||||
default: continue;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldBeClass(final Namespace ns) throws Exception {
|
||||
/* Determine if a namespace should be converted to a class
|
||||
The heuristic is whether Ghidra can find a struct that it would be
|
||||
linked with if it was a class. The process to do so is admittedly a
|
||||
bit byzantine.
|
||||
*/
|
||||
// Change name so the dummy class won't have a conflict
|
||||
final String name = ns.getName();
|
||||
ns.getSymbol()
|
||||
.setName("__" + ns.getName(), ns.getSymbol().getSource());
|
||||
|
||||
// Create a dummy class to check for a matching struct without
|
||||
// converting the namespace (as classes can't be reverted)
|
||||
final GhidraClass cls = createClass(ns.getParentNamespace(), name);
|
||||
|
||||
// Record whether Ghidra could find a matching struct
|
||||
final boolean ret = DataTypeUtilities.findExistingClassStruct(
|
||||
currentProgram.getDataTypeManager(),
|
||||
cls
|
||||
) != null;
|
||||
|
||||
// Clean up
|
||||
cls.getSymbol().delete();
|
||||
ns.getSymbol().setName(name, ns.getSymbol().getSource());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void fixMethods(final Structure vtbl) throws Exception {
|
||||
/* Set all the calling conventions in a vtable to __thiscall */
|
||||
for (final DataTypeComponent member : vtbl.getComponents())
|
||||
if (
|
||||
member.getDataType() instanceof Pointer ptr &&
|
||||
ptr .getDataType() instanceof FunctionDefinition method &&
|
||||
!method.getCallingConventionName().equals("__thiscall")
|
||||
) {
|
||||
println("Fixing calling convention of \"" + method.getDataTypePath().toString() + "\"...");
|
||||
method.setCallingConvention("__thiscall");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ import java.util.Arrays;
|
|||
import java.util.Optional;
|
||||
|
||||
|
||||
public class EnhancedExport extends GhidraScript {
|
||||
public class EnhancedExport extends GhidraScript{
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
final FileWriter out = new FileWriter(askFile("Specify output file", "OK"));
|
||||
|
|
@ -70,14 +70,14 @@ public class EnhancedExport extends GhidraScript {
|
|||
(f.isInline() ? "inline" : "notinline") + "\t" +
|
||||
Optional.ofNullable(f.getCallFixup())
|
||||
.orElse("nofixup") + "\t" +
|
||||
f.getName(true) +
|
||||
f.getName(true) + "\t" +
|
||||
String.join(
|
||||
"",
|
||||
"\t",
|
||||
Arrays.stream(f.getSignature(true)
|
||||
.getArguments())
|
||||
.map(arg ->
|
||||
"\t" + arg.getDataType().getDisplayName() +
|
||||
"\t" + arg.getName()
|
||||
arg.getDataType().getDisplayName() + "\t" +
|
||||
arg.getName()
|
||||
).toArray(String[]::new)
|
||||
) +
|
||||
(f.hasVarArgs() ? "\t..." : "") + "\n"
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.app.services.DataTypeQueryService;
|
||||
import ghidra.app.util.NamespaceUtils;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.ArrayDataType;
|
||||
import ghidra.program.model.data.DataType;
|
||||
|
|
@ -28,7 +27,7 @@ import java.util.List;
|
|||
import java.util.Optional;
|
||||
|
||||
|
||||
public class EnhancedImport extends GhidraScript {
|
||||
public class EnhancedImport extends GhidraScript{
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
final FileReader in = new FileReader(askFile("Select input file", "OK"));
|
||||
|
|
@ -87,17 +86,16 @@ public class EnhancedImport extends GhidraScript {
|
|||
/* Creates namespaces from the given name, returning the deepest one
|
||||
Returns null if the qualified name is in the global namespace.
|
||||
*/
|
||||
return qualifiedName.contains("::") ?
|
||||
NamespaceUtils.createNamespaceHierarchy(
|
||||
qualifiedName.substring( // Cut off symbol name
|
||||
0,
|
||||
qualifiedName.length() - "::".length() -
|
||||
unqualified(qualifiedName).length()
|
||||
),
|
||||
null,
|
||||
currentProgram,
|
||||
SourceType.USER_DEFINED
|
||||
) : null;
|
||||
final String[] parts = qualifiedName.split("::");
|
||||
|
||||
if (parts.length < 2) return null;
|
||||
|
||||
final String[] names = Arrays.copyOfRange(parts, 0, parts.length - 1);
|
||||
|
||||
Namespace ns = null;
|
||||
for (final String name : names) ns = createNamespace(ns, name);
|
||||
|
||||
return ns;
|
||||
}
|
||||
|
||||
private Optional<DataType> makeType(final String type) throws Exception {
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ import java.util.stream.IntStream;
|
|||
import java.util.zip.CRC32;
|
||||
|
||||
|
||||
public class MSVC7Mangle extends GhidraScript {
|
||||
public class MSVC7Mangle extends GhidraScript{
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
// Get selected ranges from arguments if invoked headless
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
function fn_ptr(cls, signature, ret, fname, args) {
|
||||
# Convert the given method signature to a function pointer
|
||||
if ($1 ~ /^~/) # Special case for virtual destructor
|
||||
return "\t\t void * __attribute__((thiscall)) "\
|
||||
return "\t\t" cls " * __attribute__((thiscall)) "\
|
||||
"(*scalar_deleting_destructor)("\
|
||||
cls " *, "\
|
||||
"BOOL"\
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ printf '%s\n' '// Automatically generated mass header file for Ghidra' > jsrf.h
|
|||
# all the headers here by hand in an order that functions properly
|
||||
HEADERS="
|
||||
Std.hpp
|
||||
XDK/Win32.h
|
||||
XDK/D3D.h
|
||||
XDK/Win32.hpp
|
||||
XDK/D3D.hpp
|
||||
Smilebit/MMatrix.hpp
|
||||
JSRF/Core.hpp
|
||||
JSRF/GameData.hpp
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
Object,Delink?,.text,.text$yc,.text$yd,.text$x,D3D,DSOUND,MMATRIX,XGRPH,XPP,.rdata,.rdata$x,.data$CRT,.data,DOLBY
|
||||
Object,Delink?,.text,.text$XC*1,.text$XC*2,.text$x,D3D,DSOUND,MMATRIX,XGRPH,XPP,.rdata,.rdata$x,.data$CRT,.data,DOLBY
|
||||
JSRF/Core.obj,true,0x00011000-0x00013FEB,,,0x00186BA0-0x00186C14,,,,,,0x001C4390-0x001C44F9,0x001E4D20-0x001E4DAB,,0x001EB880-0x001EB933,
|
||||
JSRF/GameData.obj,true,0x00039B50-0x0003B937,0x0018AD60-0x0018AD75,0x0018C9A0-0x0018C9AA,,,,,,,0x001CA16C-0x001CA3DB,,0x001EB790-0x001EB793,0x001EFC88-0x001F7047,
|
||||
JSRF/Jet2.obj,true,0x0006F9E0-0x0006FA6F,,,0x00187710-0x00187724,,,,,,,0x001E620C-0x001E622F,,0x0022FCE0-0x0022FCE3,
|
||||
|
|
|
|||
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue