forked from openrs2/openrs2
parent
c9803a9a5c
commit
ed0da80e30
@ -0,0 +1,32 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||||
|
<modelVersion>4.0.0</modelVersion> |
||||||
|
|
||||||
|
<parent> |
||||||
|
<groupId>dev.openrs2</groupId> |
||||||
|
<artifactId>openrs2</artifactId> |
||||||
|
<version>1.0.0-SNAPSHOT</version> |
||||||
|
</parent> |
||||||
|
|
||||||
|
<artifactId>openrs2-decompiler</artifactId> |
||||||
|
<packaging>jar</packaging> |
||||||
|
|
||||||
|
<name>OpenRS2 Decompiler</name> |
||||||
|
|
||||||
|
<dependencies> |
||||||
|
<dependency> |
||||||
|
<groupId>dev.openrs2</groupId> |
||||||
|
<artifactId>openrs2-fernflower</artifactId> |
||||||
|
<version>${project.version}</version> |
||||||
|
</dependency> |
||||||
|
<dependency> |
||||||
|
<groupId>dev.openrs2</groupId> |
||||||
|
<artifactId>openrs2-util</artifactId> |
||||||
|
<version>${project.version}</version> |
||||||
|
</dependency> |
||||||
|
<dependency> |
||||||
|
<groupId>ch.qos.logback</groupId> |
||||||
|
<artifactId>logback-classic</artifactId> |
||||||
|
</dependency> |
||||||
|
</dependencies> |
||||||
|
</project> |
@ -0,0 +1,73 @@ |
|||||||
|
package dev.openrs2.decompiler; |
||||||
|
|
||||||
|
import java.io.Closeable; |
||||||
|
import java.io.IOException; |
||||||
|
import java.nio.file.Path; |
||||||
|
import java.nio.file.Paths; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.function.Function; |
||||||
|
|
||||||
|
import org.jetbrains.java.decompiler.main.Fernflower; |
||||||
|
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; |
||||||
|
|
||||||
|
public final class Decompiler implements Closeable { |
||||||
|
private static final Map<String, Object> OPTIONS = Map.of( |
||||||
|
IFernflowerPreferences.ASCII_STRING_CHARACTERS, "1", |
||||||
|
IFernflowerPreferences.INDENT_STRING, "\t", |
||||||
|
IFernflowerPreferences.SYNTHETIC_NOT_SET, "1" |
||||||
|
); |
||||||
|
|
||||||
|
private static Path getDestination(String archive) { |
||||||
|
archive = archive.replaceAll("_gl[.]jar$", ""); |
||||||
|
if (archive.equals("runescape")) { |
||||||
|
archive = "client"; |
||||||
|
} |
||||||
|
return Paths.get("nonfree").resolve(archive).resolve("src/main/java"); |
||||||
|
} |
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException { |
||||||
|
var libraries = List.of(Paths.get("nonfree/code/jogl.jar")); |
||||||
|
|
||||||
|
var deobOutput = Paths.get("nonfree/code/deob"); |
||||||
|
var sources = List.of( |
||||||
|
deobOutput.resolve("runescape_gl.jar"), |
||||||
|
deobOutput.resolve("loader_gl.jar"), |
||||||
|
deobOutput.resolve("signlink_gl.jar"), |
||||||
|
deobOutput.resolve("unpack_gl.jar"), |
||||||
|
deobOutput.resolve("unpacker_gl.jar") |
||||||
|
); |
||||||
|
|
||||||
|
try (var decompiler = new Decompiler(libraries, sources, Decompiler::getDestination)) { |
||||||
|
decompiler.run(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private final DecompilerIo io; |
||||||
|
private final Fernflower fernflower; |
||||||
|
private final List<Path> libraries, sources; |
||||||
|
|
||||||
|
public Decompiler(List<Path> libraries, List<Path> sources, Function<String, Path> destination) { |
||||||
|
this.io = new DecompilerIo(destination); |
||||||
|
this.fernflower = new Fernflower(io, io, OPTIONS, Slf4jFernflowerLogger.INSTANCE); |
||||||
|
this.libraries = libraries; |
||||||
|
this.sources = sources; |
||||||
|
} |
||||||
|
|
||||||
|
public void run() { |
||||||
|
for (var library : libraries) { |
||||||
|
fernflower.addLibrary(library.toFile()); |
||||||
|
} |
||||||
|
|
||||||
|
for (var source : sources) { |
||||||
|
fernflower.addSource(source.toFile()); |
||||||
|
} |
||||||
|
|
||||||
|
fernflower.decompileContext(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void close() throws IOException { |
||||||
|
io.close(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,97 @@ |
|||||||
|
package dev.openrs2.decompiler; |
||||||
|
|
||||||
|
import java.io.Closeable; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.UncheckedIOException; |
||||||
|
import java.nio.file.Files; |
||||||
|
import java.nio.file.Path; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.function.Function; |
||||||
|
import java.util.jar.JarFile; |
||||||
|
import java.util.jar.Manifest; |
||||||
|
|
||||||
|
import com.google.common.io.ByteStreams; |
||||||
|
import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider; |
||||||
|
import org.jetbrains.java.decompiler.main.extern.IResultSaver; |
||||||
|
|
||||||
|
public final class DecompilerIo implements IBytecodeProvider, IResultSaver, Closeable { |
||||||
|
private final Map<String, JarFile> inputJars = new HashMap<>(); |
||||||
|
private final Function<String, Path> destination; |
||||||
|
|
||||||
|
public DecompilerIo(Function<String, Path> destination) { |
||||||
|
this.destination = destination; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public byte[] getBytecode(String externalPath, String internalPath) throws IOException { |
||||||
|
if (internalPath == null) { |
||||||
|
throw new UnsupportedOperationException(); |
||||||
|
} |
||||||
|
|
||||||
|
var jar = inputJars.get(externalPath); |
||||||
|
if (jar == null) { |
||||||
|
jar = new JarFile(externalPath); |
||||||
|
inputJars.put(externalPath, jar); |
||||||
|
} |
||||||
|
|
||||||
|
try (var in = jar.getInputStream(jar.getJarEntry(internalPath))) { |
||||||
|
return ByteStreams.toByteArray(in); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void saveFolder(String path) { |
||||||
|
/* ignore */ |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void copyFile(String source, String path, String entryName) { |
||||||
|
throw new UnsupportedOperationException(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void saveClassFile(String path, String qualifiedName, String entryName, String content, int[] mapping) { |
||||||
|
throw new UnsupportedOperationException(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void createArchive(String path, String archiveName, Manifest manifest) { |
||||||
|
/* ignore */ |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void saveDirEntry(String path, String archiveName, String entryName) { |
||||||
|
/* ignore */ |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void copyEntry(String source, String path, String archiveName, String entry) { |
||||||
|
/* ignore */ |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content) { |
||||||
|
var p = destination.apply(archiveName).resolve(entryName); |
||||||
|
try { |
||||||
|
Files.createDirectories(p.getParent()); |
||||||
|
try (var writer = Files.newBufferedWriter(p)) { |
||||||
|
writer.write(content); |
||||||
|
} |
||||||
|
} catch (IOException ex) { |
||||||
|
throw new UncheckedIOException(ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void closeArchive(String path, String archiveName) { |
||||||
|
/* ignore */ |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void close() throws IOException { |
||||||
|
for (var jar : inputJars.values()) { |
||||||
|
jar.close(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
package dev.openrs2.decompiler; |
||||||
|
|
||||||
|
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; |
||||||
|
import org.slf4j.Logger; |
||||||
|
import org.slf4j.LoggerFactory; |
||||||
|
|
||||||
|
public final class Slf4jFernflowerLogger extends IFernflowerLogger { |
||||||
|
private static final Logger logger = LoggerFactory.getLogger(Slf4jFernflowerLogger.class); |
||||||
|
|
||||||
|
public static final IFernflowerLogger INSTANCE = new Slf4jFernflowerLogger(); |
||||||
|
|
||||||
|
private Slf4jFernflowerLogger() { |
||||||
|
/* empty */ |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void startClass(String className) { |
||||||
|
logger.info("Decompiling {}", className); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void writeMessage(String message, Severity severity) { |
||||||
|
switch (severity) { |
||||||
|
case TRACE: |
||||||
|
logger.trace(message); |
||||||
|
case INFO: |
||||||
|
logger.info(message); |
||||||
|
case WARN: |
||||||
|
logger.warn(message); |
||||||
|
case ERROR: |
||||||
|
logger.error(message); |
||||||
|
default: |
||||||
|
throw new IllegalArgumentException(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void writeMessage(String message, Severity severity, Throwable t) { |
||||||
|
switch (severity) { |
||||||
|
case TRACE: |
||||||
|
logger.trace(message, t); |
||||||
|
case INFO: |
||||||
|
logger.info(message, t); |
||||||
|
case WARN: |
||||||
|
logger.warn(message, t); |
||||||
|
case ERROR: |
||||||
|
logger.error(message, t); |
||||||
|
default: |
||||||
|
throw new IllegalArgumentException(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue