From 189a668a8af4f6a34f5f2484eec9714b954cce98 Mon Sep 17 00:00:00 2001 From: crazzmc Date: Thu, 14 Jul 2022 02:46:01 -0400 Subject: [PATCH 1/8] #206 support --- src/main/java/dawn/cs2/CS2Reader.java | 2 +- src/main/resources/cs2/opcode/database/osrs.ini | 1 + src/main/resources/cs2/opcode/unscramble/179.txt | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/main/java/dawn/cs2/CS2Reader.java b/src/main/java/dawn/cs2/CS2Reader.java index 4320d21..92e1af8 100644 --- a/src/main/java/dawn/cs2/CS2Reader.java +++ b/src/main/java/dawn/cs2/CS2Reader.java @@ -90,7 +90,7 @@ private CS2 readScript(int scriptID, byte[] data, Map unscramb Integer n = unscramble.get(opcode); if (n == null) { // n = opcode; - throw new DecompilerException("Unknown scrambling " + opcode); + throw new DecompilerException("Unknown scrambling " + opcode + " " + opcode); } opcode = n; if (opcode == Opcodes.PUSH_STRING) { diff --git a/src/main/resources/cs2/opcode/database/osrs.ini b/src/main/resources/cs2/opcode/database/osrs.ini index f286671..95b1633 100644 --- a/src/main/resources/cs2/opcode/database/osrs.ini +++ b/src/main/resources/cs2/opcode/database/osrs.ini @@ -1973,6 +1973,7 @@ 7006 cs2method7006 void + # OSRS 21000 setPosition void int x int y 21001 setSize void int w int h diff --git a/src/main/resources/cs2/opcode/unscramble/179.txt b/src/main/resources/cs2/opcode/unscramble/179.txt index 69fc855..c727189 100644 --- a/src/main/resources/cs2/opcode/unscramble/179.txt +++ b/src/main/resources/cs2/opcode/unscramble/179.txt @@ -182,6 +182,19 @@ 1117 1117 1118 1118 1119 1119 +1130 1130 +1434 1434 +6231 6231 +3178 3178 +3500 3500 +1707 1707 +4213 4213 +6232 6232 +1928 1928 + +1131 1131 +3212 3212 +3214 3214 1120 1120 1200 1200 1201 1201 @@ -407,6 +420,8 @@ 3207 3207 3208 3208 3209 3209 +3213 3213 +3215 3215 3300 3300 3301 3301 3302 3302 @@ -830,6 +845,7 @@ 6304 6304 6305 6305 6306 6306 +6307 6307 6405 6405 6406 6406 6500 6500 From 18ea217de158d49b8c0a63b1b7b44205297fab50 Mon Sep 17 00:00:00 2001 From: crazzmc Date: Thu, 14 Jul 2022 02:47:09 -0400 Subject: [PATCH 2/8] recent paths support --- .../editor/controller/MainController.kt | 97 ++++++++++++++++++- src/main/resources/fxml/main.fxml | 8 +- 2 files changed, 100 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/displee/editor/controller/MainController.kt b/src/main/java/com/displee/editor/controller/MainController.kt index a0e2192..c95a404 100644 --- a/src/main/java/com/displee/editor/controller/MainController.kt +++ b/src/main/java/com/displee/editor/controller/MainController.kt @@ -33,9 +33,14 @@ import org.fxmisc.richtext.CodeArea import org.fxmisc.richtext.LineNumberFactory import org.fxmisc.richtext.model.StyleSpans import org.fxmisc.richtext.model.StyleSpansBuilder +import java.awt.Menu +import java.awt.MenuItem +import java.awt.SystemColor.menu +import java.awt.TextField import java.io.File import java.io.PrintWriter import java.io.StringWriter +import java.lang.StringBuilder import java.net.URL import java.text.SimpleDateFormat import java.time.Instant @@ -48,6 +53,18 @@ class MainController : Initializable { @FXML private lateinit var openMenuItem: MenuItem + @FXML + private lateinit var openRecentPaths: Menu + + @FXML + private lateinit var path1: MenuItem + + @FXML + private lateinit var path2: MenuItem + + @FXML + private lateinit var path3: MenuItem + @FXML private lateinit var saveMenuItem: MenuItem @@ -92,6 +109,7 @@ class MainController : Initializable { private val cachedScripts = mutableMapOf() + private final val fileName = System.getProperty("user.dir") + "/paths.txt" private var temporaryAssemblyPane: Node? = null lateinit var cacheLibrary: CacheLibrary @@ -104,6 +122,21 @@ class MainController : Initializable { private var currentScript: CS2? = null override fun initialize(location: URL?, resources: ResourceBundle?) { + var file = File(fileName) + if (!file.exists()) file.createNewFile() + else { + var readLines = file.readLines() + if (readLines != null && !readLines.isEmpty()) { + path1.text = readLines.get(0) + if (readLines.size > 1) { + path2.text = readLines.get(1) + } + if (readLines.size > 2) { + path3.text = readLines.get(2) + } + } + } + rootPane.addEventHandler(KeyEvent.KEY_PRESSED) { e: KeyEvent -> if (e.isControlDown && e.code == KeyCode.N) { if (!this::cacheLibrary.isInitialized) { @@ -115,6 +148,13 @@ class MainController : Initializable { openMenuItem.setOnAction { openCache() } + + path1.setOnAction { openCacheFromRecentPaths(1) } + + path2.setOnAction { openCacheFromRecentPaths(2) } + + path3.setOnAction { openCacheFromRecentPaths(3) } + saveMenuItem.setOnAction { compileScript() } @@ -208,12 +248,56 @@ class MainController : Initializable { AutoCompleteUtils } + private fun openCacheFromRecentPaths(lineNumber: Int) { + val fileName = System.getProperty("user.dir") + "/paths.txt" + var file = File(fileName) + if (file.exists()) { + if (file.readLines() == null || file.readLines().isEmpty()) { + Platform.runLater { + Notification.error("No recent paths saved, open a new cache") + clearCache() + } + } else { + openCache(File(file.readLines()[lineNumber-1])) + } + } + } + + private fun shiftLines() { + if (path1.text.isEmpty()) return; + path3.text = path2.text + path2.text = path1.text + } + + private fun savePaths() { + var file = File(fileName) + if (!file.exists()) file.createNewFile() + val string = StringBuilder() + string.append(path1.text).append("\n").append(path2.text).append("\n").append(path3.text) + + file.writeText(string.toString()) + } + private fun openCache(f: File? = null) { var mehFile = f if (mehFile == null) { val chooser = DirectoryChooser() mehFile = chooser.showDialog(mainWindow()) ?: return + shiftLines() + path1.text = mehFile!!.path } + savePaths() +// val string = StringBuilder() +// if (file.readLines() != null && file.readLines().isNotEmpty()) { +// for ((index, readLine) in file.readLines().withIndex()) { +// string.append(readLine) +// if (index == 2) break; +// string.append("\n") +// } +// file.writeText(string.toString()) +// } + + scriptList.isDisable = true GlobalScope.launch { try { @@ -348,13 +432,18 @@ class MainController : Initializable { try { CS2Reader.readCS2ScriptNewFormat(data, id, config.unscrambled, config.disableSwitches, config.disableLongs) } catch(e: Throwable) { - error++ - if (error >= 2) { - break + if (config.version == 179) { + println(e) + println("id $id") + } +// error++ +// if (error >= 2) { +// break +// } } } - println("config: ${config.version} $error") +// println("config: ${config.version} $error") error < 2 } var configuration: ScriptConfiguration? = null diff --git a/src/main/resources/fxml/main.fxml b/src/main/resources/fxml/main.fxml index 1ad032a..e9f35b8 100644 --- a/src/main/resources/fxml/main.fxml +++ b/src/main/resources/fxml/main.fxml @@ -21,7 +21,13 @@ - + + + + + + + From d93a383b9d2a3baa0a07e1223b57441b464492d9 Mon Sep 17 00:00:00 2001 From: crazzmc Date: Thu, 14 Jul 2022 03:09:51 -0400 Subject: [PATCH 3/8] app --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index 5aff52b..0212823 100644 --- a/build.gradle +++ b/build.gradle @@ -13,6 +13,7 @@ buildscript { plugins { id 'java' id 'org.jetbrains.kotlin.jvm' version "$kotlin_version" + id 'application' } archivesBaseName = 'cs2-editor' @@ -35,6 +36,8 @@ compileTestKotlin { } } +mainClassName = 'com.displee.editor.Editor' + dependencies { compile fileTree(dir: 'lib', include: '*.jar') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" From b945dac592c5c5b2c801f8b5a6c5c3bf3559e3f7 Mon Sep 17 00:00:00 2001 From: crazzmc Date: Thu, 14 Jul 2022 03:28:25 -0400 Subject: [PATCH 4/8] the dumbest fix ever --- .../java/com/displee/editor/controller/MainController.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/displee/editor/controller/MainController.kt b/src/main/java/com/displee/editor/controller/MainController.kt index c95a404..f9aae3f 100644 --- a/src/main/java/com/displee/editor/controller/MainController.kt +++ b/src/main/java/com/displee/editor/controller/MainController.kt @@ -1,5 +1,6 @@ package com.displee.editor.controller +import javafx.event.ActionEvent import com.displee.cache.CacheLibrary import com.displee.cache.ProgressListener import com.displee.editor.config.ScriptConfiguration @@ -33,10 +34,6 @@ import org.fxmisc.richtext.CodeArea import org.fxmisc.richtext.LineNumberFactory import org.fxmisc.richtext.model.StyleSpans import org.fxmisc.richtext.model.StyleSpansBuilder -import java.awt.Menu -import java.awt.MenuItem -import java.awt.SystemColor.menu -import java.awt.TextField import java.io.File import java.io.PrintWriter import java.io.StringWriter @@ -145,6 +142,7 @@ class MainController : Initializable { newScript(notifyChooseScriptId(cacheLibrary.index(SCRIPTS_INDEX).nextId())) } } + openMenuItem.setOnAction { openCache() } From 588e0c90ca1fadf4931a46e360be286fea9d21e5 Mon Sep 17 00:00:00 2001 From: crazzmc Date: Thu, 14 Jul 2022 03:28:49 -0400 Subject: [PATCH 5/8] path file gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 75afc96..6e9543a 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,5 @@ sources # Ignore Gradle build output directory build -.idea \ No newline at end of file +.idea +paths.txt From bbf1d7f7b640c8a233e617396c9c2615154adc91 Mon Sep 17 00:00:00 2001 From: crazzmc Date: Sun, 17 Jul 2022 12:22:38 -0400 Subject: [PATCH 6/8] new string push opcode --- src/main/java/dawn/cs2/FlowBlocksGenerator.java | 2 +- src/main/java/dawn/cs2/ast/GlobalVariable.java | 2 +- src/main/java/dawn/cs2/instructions/Opcodes.java | 1 + src/main/resources/cs2/opcode/database/osrs.ini | 3 ++- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/dawn/cs2/FlowBlocksGenerator.java b/src/main/java/dawn/cs2/FlowBlocksGenerator.java index 7cf926e..55bf753 100644 --- a/src/main/java/dawn/cs2/FlowBlocksGenerator.java +++ b/src/main/java/dawn/cs2/FlowBlocksGenerator.java @@ -262,7 +262,7 @@ private void processFlowBlock(FlowBlock block) { ExpressionNode value = stack.pop(); ExpressionNode index = CS2Type.cast(stack.pop(), CS2Type.INT); block.write(new PopableNode(new ArrayStoreNode(intInstr.getConstant(), index, value))); - } else if (opcode == 47) { + } else if (opcode == 47 || opcode == 49) { stack.push(new VariableLoadNode(GlobalVariable.VARC_STRING(intInstr.getConstant()))); } else if (opcode == 106) { stack.push(new VariableLoadNode(GlobalVariable.find("CLAN", intInstr.getConstant(), CS2Type.INT))); diff --git a/src/main/java/dawn/cs2/ast/GlobalVariable.java b/src/main/java/dawn/cs2/ast/GlobalVariable.java index 7628940..13a9176 100644 --- a/src/main/java/dawn/cs2/ast/GlobalVariable.java +++ b/src/main/java/dawn/cs2/ast/GlobalVariable.java @@ -102,7 +102,7 @@ public AbstractInstruction generateLoadInstruction() { op = Opcodes.LOAD_VARC; break; case "STRING": - op = Opcodes.LOAD_VARCSTR; + op = Opcodes.LOAD_VARCSTR_NEW; break; //These are READONLY, some are not even used case "CLANDEF_STRING115": diff --git a/src/main/java/dawn/cs2/instructions/Opcodes.java b/src/main/java/dawn/cs2/instructions/Opcodes.java index 866c992..73a19e6 100644 --- a/src/main/java/dawn/cs2/instructions/Opcodes.java +++ b/src/main/java/dawn/cs2/instructions/Opcodes.java @@ -25,6 +25,7 @@ public class Opcodes { public static final int STORE_VARP = 2; public static final int LOAD_VARC = 42; public static final int LOAD_VARCSTR = 47; + public static final int LOAD_VARCSTR_NEW = 49; public static final int STORE_VARC = 43; public static final int LOAD_VARPBIT = 25; public static final int SWITCH = 51; diff --git a/src/main/resources/cs2/opcode/database/osrs.ini b/src/main/resources/cs2/opcode/database/osrs.ini index 95b1633..c4c7818 100644 --- a/src/main/resources/cs2/opcode/database/osrs.ini +++ b/src/main/resources/cs2/opcode/database/osrs.ini @@ -1972,7 +1972,8 @@ 7006 cs2method7006 void - +10034 cs2Method10034 string int arg0 int arg1 string string2 string string3 +10035 cs2Method10035 int arg0 # OSRS 21000 setPosition void int x int y From caaa46797b40167d9caf17218ce8de1ac4542a09 Mon Sep 17 00:00:00 2001 From: crazzmc Date: Wed, 20 Jul 2022 17:49:29 -0400 Subject: [PATCH 7/8] new opcodes + refactoring --- .../editor/controller/MainController.kt | 9 +- src/main/java/dawn/cs2/CS2Compiler.java | 112 +++++++++--------- src/main/java/dawn/cs2/CS2Reader.java | 6 +- src/main/java/dawn/cs2/CS2ScriptParser.java | 4 +- src/main/java/dawn/cs2/CS2Type.java | 50 +++++--- .../java/dawn/cs2/FlowBlocksGenerator.java | 51 ++++---- .../java/dawn/cs2/ast/GlobalVariable.java | 12 +- src/main/java/dawn/cs2/ast/LocalVariable.java | 8 +- .../java/dawn/cs2/ast/NewLocationNode.java | 2 +- .../dawn/cs2/ast/NewWidgetPointerNode.java | 2 +- src/main/java/dawn/cs2/ast/Underscore.java | 4 +- .../java/dawn/cs2/instructions/Opcodes.java | 103 ++++++++-------- .../cs2/instructions/SwitchInstruction.java | 2 +- 13 files changed, 186 insertions(+), 179 deletions(-) diff --git a/src/main/java/com/displee/editor/controller/MainController.kt b/src/main/java/com/displee/editor/controller/MainController.kt index f9aae3f..b9925e6 100644 --- a/src/main/java/com/displee/editor/controller/MainController.kt +++ b/src/main/java/com/displee/editor/controller/MainController.kt @@ -1,6 +1,5 @@ package com.displee.editor.controller -import javafx.event.ActionEvent import com.displee.cache.CacheLibrary import com.displee.cache.ProgressListener import com.displee.editor.config.ScriptConfiguration @@ -549,7 +548,7 @@ class MainController : Initializable { } var list: MutableList? = AutoCompleteUtils.dynamicItems if (FlowBlocksGenerator.isObjectOpcode(opcode) || FlowBlocksGenerator.isObjectWidgetOpcode(opcode)) { - list = AutoCompleteUtils.getObject(WIDGET_PTR, true)?.dynamicChildren + list = AutoCompleteUtils.getObject(COMPONENT, true)?.dynamicChildren } val name = split[1] val returnTypes = if (split[2].contains("|")) { @@ -736,11 +735,11 @@ class MainController : Initializable { SPRITE, MODEL, MIDI, - DATAMAP, + ENUM, ATTRIBUTEMAP, CONTAINER, - WIDGET_PTR, - LOCATION, + COMPONENT, + COORD, ITEM, COLOR, IDENTIKIT, diff --git a/src/main/java/dawn/cs2/CS2Compiler.java b/src/main/java/dawn/cs2/CS2Compiler.java index 47c596f..6d2cf36 100644 --- a/src/main/java/dawn/cs2/CS2Compiler.java +++ b/src/main/java/dawn/cs2/CS2Compiler.java @@ -169,10 +169,10 @@ private void compileNode(AbstractCodeNode node) { if (supportEq01) { instructions.add(new JumpInstruction(Opcodes.EQ1, ifLabel)); } else { - instructions.add(new IntInstruction(Opcodes.PUSH_INT, 1)); - instructions.add(new JumpInstruction(Opcodes.INT_EQ, ifLabel)); + instructions.add(new IntInstruction(Opcodes.PUSH_CONSTANT_INT, 1)); + instructions.add(new JumpInstruction(Opcodes.BRANCH_EQUALS, ifLabel)); } - instructions.add(new JumpInstruction(Opcodes.GOTO, i.hasElseScope() ? elseLabel : afterIf)); + instructions.add(new JumpInstruction(Opcodes.BRANCH, i.hasElseScope() ? elseLabel : afterIf)); } //For IF and ELSE scopes @@ -187,7 +187,7 @@ private void compileNode(AbstractCodeNode node) { instructions.add(elseLabel); //ELSE BODY compileNode(i.elseScope); - instructions.add(new JumpInstruction(Opcodes.GOTO, afterIf)); + instructions.add(new JumpInstruction(Opcodes.BRANCH, afterIf)); } instructions.add(ifLabel); @@ -207,14 +207,14 @@ private void compileNode(AbstractCodeNode node) { if (supportEq01) { instructions.add(new JumpInstruction(Opcodes.EQ1, bodyLabel)); } else { - instructions.add(new IntInstruction(Opcodes.PUSH_INT, 1)); - instructions.add(new JumpInstruction(Opcodes.INT_EQ, bodyLabel)); + instructions.add(new IntInstruction(Opcodes.PUSH_CONSTANT_INT, 1)); + instructions.add(new JumpInstruction(Opcodes.BRANCH_EQUALS, bodyLabel)); } - instructions.add(new JumpInstruction(Opcodes.GOTO, afterWhile)); + instructions.add(new JumpInstruction(Opcodes.BRANCH, afterWhile)); } instructions.add(bodyLabel); compileNode(loop.getScope()); - instructions.add(new JumpInstruction(Opcodes.GOTO, conditionLabel)); + instructions.add(new JumpInstruction(Opcodes.BRANCH, conditionLabel)); instructions.add(afterWhile); } else if (node instanceof SwitchNode) { if (!supportSwitch) { @@ -232,7 +232,7 @@ private void compileNode(AbstractCodeNode node) { SwitchInstruction instr = new SwitchInstruction(Opcodes.SWITCH, cases, labels); instructions.add(instr); - instructions.add(new JumpInstruction(Opcodes.GOTO, defCase)); + instructions.add(new JumpInstruction(Opcodes.BRANCH, defCase)); while ((c = sw.getScope().read()) != null) { if (c instanceof CaseAnnotation) { @@ -253,18 +253,18 @@ private void compileNode(AbstractCodeNode node) { caseEntry = null; } if (c instanceof BreakNode) { - instructions.add(new JumpInstruction(Opcodes.GOTO, afterSwitch)); + instructions.add(new JumpInstruction(Opcodes.BRANCH, afterSwitch)); } else { compileNode(c); } } } instr.sort(); - instructions.add(new JumpInstruction(Opcodes.GOTO, afterSwitch)); //incase last case didnt have a break. always jump to afterswitch TODO: probably remove this?? doesnt seem correct (fallthrough to default case??) + instructions.add(new JumpInstruction(Opcodes.BRANCH, afterSwitch)); //incase last case didnt have a break. always jump to afterswitch TODO: probably remove this?? doesnt seem correct (fallthrough to default case??) if (defCase != null) { //If there was no default case, insert the label anyway (we already made the jump), it will be merged with afterswitch label in optimizer instructions.add(defCase); - instructions.add(new JumpInstruction(Opcodes.GOTO, afterSwitch)); + instructions.add(new JumpInstruction(Opcodes.BRANCH, afterSwitch)); } instructions.add(afterSwitch); } else { @@ -290,20 +290,20 @@ private boolean compileConditionalJmp(ExpressionNode expr, Label ifJump, Label e if (supportEq01) { instructions.add(new JumpInstruction(Opcodes.EQ1, ifTrue)); } else { - instructions.add(new IntInstruction(Opcodes.PUSH_INT, 1)); - instructions.add(new JumpInstruction(Opcodes.INT_EQ, ifTrue)); + instructions.add(new IntInstruction(Opcodes.PUSH_CONSTANT_INT, 1)); + instructions.add(new JumpInstruction(Opcodes.BRANCH_EQUALS, ifTrue)); } - instructions.add(new JumpInstruction(Opcodes.GOTO, ifFalse)); + instructions.add(new JumpInstruction(Opcodes.BRANCH, ifFalse)); } instructions.add(secondaryCondition); if (!compileConditionalJmp(c.getRight(), ifJump, elseJump)) { if (supportEq01) { instructions.add(new JumpInstruction(Opcodes.EQ1, ifJump)); } else { - instructions.add(new IntInstruction(Opcodes.PUSH_INT, 1)); - instructions.add(new JumpInstruction(Opcodes.INT_EQ, ifJump)); + instructions.add(new IntInstruction(Opcodes.PUSH_CONSTANT_INT, 1)); + instructions.add(new JumpInstruction(Opcodes.BRANCH_EQUALS, ifJump)); } - instructions.add(new JumpInstruction(Opcodes.GOTO, elseJump)); + instructions.add(new JumpInstruction(Opcodes.BRANCH, elseJump)); } return true; } @@ -323,28 +323,28 @@ private boolean compileConditionalJmp(ExpressionNode expr, Label ifJump, Label e int op = -1; switch (c.conditional) { case NEQ: - op = longInstr ? Opcodes.LONG_NE : Opcodes.INT_NE; + op = longInstr ? Opcodes.LONG_NE : Opcodes.BRANCH_NOT; break; case EQ: - op = longInstr ? Opcodes.LONG_EQ : Opcodes.INT_EQ; + op = longInstr ? Opcodes.LONG_EQ : Opcodes.BRANCH_EQUALS; break; case GT: - op = longInstr ? Opcodes.LONG_GT : Opcodes.INT_GT; + op = longInstr ? Opcodes.LONG_GT : Opcodes.BRANCH_GREATER_THAN; break; case LT: - op = longInstr ? Opcodes.LONG_LT : Opcodes.INT_LT; + op = longInstr ? Opcodes.LONG_LT : Opcodes.BRANCH_LESS_THAN; break; case GE: - op = longInstr ? Opcodes.LONG_GE : Opcodes.INT_GE; + op = longInstr ? Opcodes.LONG_GE : Opcodes.BRANCH_GREATER_THAN_OR_EQUALS; break; case LE: - op = longInstr ? Opcodes.LONG_LE : Opcodes.INT_LE; + op = longInstr ? Opcodes.LONG_LE : Opcodes.BRANCH_LESS_THAN_OR_EQUALS; break; default: throw new DecompilerException("unknown conditional op " + c.conditional); } instructions.add(new JumpInstruction(op, ifJump)); - instructions.add(new JumpInstruction(Opcodes.GOTO, elseJump)); + instructions.add(new JumpInstruction(Opcodes.BRANCH, elseJump)); return true; } else { if (expr instanceof BooleanConditionalExpressionNode) { @@ -358,10 +358,10 @@ private boolean compileConditionalJmp(ExpressionNode expr, Label ifJump, Label e if (supportEq01) { instructions.add(new JumpInstruction(Opcodes.EQ1, elseJump)); } else { - instructions.add(new IntInstruction(Opcodes.PUSH_INT, 1)); - instructions.add(new JumpInstruction(Opcodes.INT_EQ, elseJump)); + instructions.add(new IntInstruction(Opcodes.PUSH_CONSTANT_INT, 1)); + instructions.add(new JumpInstruction(Opcodes.BRANCH_EQUALS, elseJump)); } - instructions.add(new JumpInstruction(Opcodes.GOTO, ifJump)); + instructions.add(new JumpInstruction(Opcodes.BRANCH, ifJump)); } } else { if (!compileConditionalJmp(bool.getCondition(), ifJump, elseJump)) { @@ -369,10 +369,10 @@ private boolean compileConditionalJmp(ExpressionNode expr, Label ifJump, Label e if (supportEq01) { instructions.add(new JumpInstruction(Opcodes.EQ1, ifJump)); } else { - instructions.add(new IntInstruction(Opcodes.PUSH_INT, 1)); - instructions.add(new JumpInstruction(Opcodes.INT_EQ, ifJump)); + instructions.add(new IntInstruction(Opcodes.PUSH_CONSTANT_INT, 1)); + instructions.add(new JumpInstruction(Opcodes.BRANCH_EQUALS, ifJump)); } - instructions.add(new JumpInstruction(Opcodes.GOTO, elseJump)); + instructions.add(new JumpInstruction(Opcodes.BRANCH, elseJump)); } } return true; @@ -419,7 +419,7 @@ private void compileExpression(ExpressionNode expression, boolean pop) { } } if (call.info.isScript) { - instructions.add(new IntInstruction(Opcodes.CALL_CS2, op)); + instructions.add(new IntInstruction(Opcodes.GOSUB_WITH_PARAMS, op)); } else { instructions.add(new BooleanInstruction(op, constant)); } @@ -428,9 +428,9 @@ private void compileExpression(ExpressionNode expression, boolean pop) { for (int i = composite.size() - 1; i >= 0; i--) { CS2Type ret = composite.get(i); if (ret.isCompatible(CS2Type.INT)) { - instructions.add(new BooleanInstruction(Opcodes.POP_INT, false)); + instructions.add(new BooleanInstruction(Opcodes.POP_INT_DISCARD, false)); } else if (ret.isCompatible(CS2Type.STRING)) { - instructions.add(new BooleanInstruction(Opcodes.POP_STRING, false)); + instructions.add(new BooleanInstruction(Opcodes.POP_STRING_DISCARD, false)); } else if (ret.isCompatible(CS2Type.LONG)) { instructions.add(new IntInstruction(Opcodes.POP_LONG, 0)); } @@ -441,9 +441,9 @@ private void compileExpression(ExpressionNode expression, boolean pop) { CallbackExpressionNode callback = (CallbackExpressionNode) expression; StringBuilder types = new StringBuilder(); if (callback.call == null) { - instructions.add(new IntInstruction(Opcodes.PUSH_INT, -1)); + instructions.add(new IntInstruction(Opcodes.PUSH_CONSTANT_INT, -1)); } else { - instructions.add(new IntInstruction(Opcodes.PUSH_INT, callback.call.info.id)); + instructions.add(new IntInstruction(Opcodes.PUSH_CONSTANT_INT, callback.call.info.id)); for (ExpressionNode arg : callback.call.arguments) { compileExpression(arg); //Multiple return value call might be used as an argument @@ -454,11 +454,11 @@ private void compileExpression(ExpressionNode expression, boolean pop) { } if (callback.trigger != null) { compileExpression(callback.trigger); - instructions.add(new IntInstruction(Opcodes.PUSH_INT, callback.trigger.arguments.size())); + instructions.add(new IntInstruction(Opcodes.PUSH_CONSTANT_INT, callback.trigger.arguments.size())); types.append("Y"); } - instructions.add(new StringInstruction(Opcodes.PUSH_STRING, types.toString())); + instructions.add(new StringInstruction(Opcodes.PUSH_CONSTANT_STRING, types.toString())); } else if (expression instanceof ExpressionList) { // assert !pop : "Not a statement " + expression; for (ExpressionNode sub : ((ExpressionList) expression).arguments) { @@ -483,7 +483,7 @@ private void compileExpression(ExpressionNode expression, boolean pop) { } } else if (expression instanceof PlaceholderValueNode) { assert !pop : "Not a statement " + expression; - instructions.add(new IntInstruction(Opcodes.PUSH_INT, ((PlaceholderValueNode) expression).magic)); + instructions.add(new IntInstruction(Opcodes.PUSH_CONSTANT_INT, ((PlaceholderValueNode) expression).magic)); } else if (expression instanceof NewWidgetPointerNode) { assert !pop : "Not a statement " + expression; NewWidgetPointerNode w = (NewWidgetPointerNode) expression; @@ -499,7 +499,7 @@ private void compileExpression(ExpressionNode expression, boolean pop) { } else if (expression instanceof CharExpressionNode) { assert !pop : "Not a statement " + expression; CharExpressionNode c = (CharExpressionNode) expression; - instructions.add(new IntInstruction(Opcodes.PUSH_INT, c.getData())); + instructions.add(new IntInstruction(Opcodes.PUSH_CONSTANT_INT, c.getData())); } else if (expression instanceof CastNode) { assert !pop : "Not a statement " + expression; CastNode c = (CastNode) expression; @@ -507,19 +507,19 @@ private void compileExpression(ExpressionNode expression, boolean pop) { compileExpression(c.getExpression()); } else if (expression instanceof IntExpressionNode) { assert !pop : "Not a statement " + expression; - instructions.add(new IntInstruction(Opcodes.PUSH_INT, ((IntExpressionNode) expression).getData())); + instructions.add(new IntInstruction(Opcodes.PUSH_CONSTANT_INT, ((IntExpressionNode) expression).getData())); } else if (expression instanceof LongExpressionNode) { assert !pop : "Not a statement " + expression; instructions.add(new LongInstruction(Opcodes.PUSH_LONG, ((LongExpressionNode) expression).getData())); } else if (expression instanceof NullableIntExpressionNode) { assert !pop : "Not a statement " + expression; - instructions.add(new IntInstruction(Opcodes.PUSH_INT, ((NullableIntExpressionNode) expression).getData())); + instructions.add(new IntInstruction(Opcodes.PUSH_CONSTANT_INT, ((NullableIntExpressionNode) expression).getData())); } else if (expression instanceof BooleanExpressionNode) { assert !pop : "Not a statement " + expression; - instructions.add(new IntInstruction(Opcodes.PUSH_INT, ((BooleanExpressionNode) expression).getData() ? 1 : 0)); + instructions.add(new IntInstruction(Opcodes.PUSH_CONSTANT_INT, ((BooleanExpressionNode) expression).getData() ? 1 : 0)); } else if (expression instanceof StringExpressionNode) { assert !pop : "Not a statement " + expression; - instructions.add(new StringInstruction(Opcodes.PUSH_STRING, ((StringExpressionNode) expression).getData())); + instructions.add(new StringInstruction(Opcodes.PUSH_CONSTANT_STRING, ((StringExpressionNode) expression).getData())); } else if (expression instanceof BuildStringNode) { assert !pop : "Not a statement " + expression; //TODO: If multiple literals, we can just merge them at compile time this happens a lot because all tags (
) appear in seperate strings (they have some special syntax for it i guess) @@ -527,7 +527,7 @@ private void compileExpression(ExpressionNode expression, boolean pop) { for (ExpressionNode n : build.arguments) { compileExpression(n); } - instructions.add(new IntInstruction(Opcodes.MERGE_STRINGS, build.arguments.size())); + instructions.add(new IntInstruction(Opcodes.JOIN_STRING, build.arguments.size())); } else if (expression instanceof VariableLoadNode) { assert !pop : "Not a statement " + expression; instructions.add(((VariableLoadNode) expression).getVariable().generateLoadInstruction()); @@ -548,18 +548,18 @@ private void compileExpression(ExpressionNode expression, boolean pop) { assert pop; NewArrayNode init = (NewArrayNode) expression; compileExpression(init.getExpression()); - instructions.add(new IntInstruction(Opcodes.ARRAY_NEW, init.arrayId << 16 | init.getType().charDesc)); + instructions.add(new IntInstruction(Opcodes.DEFINE_ARRAY, init.arrayId << 16 | init.getType().charDesc)); } else if (expression instanceof ArrayStoreNode) { assert pop; ArrayStoreNode store = (ArrayStoreNode) expression; compileExpression(store.getIndex()); compileExpression(store.getValue()); - instructions.add(new IntInstruction(Opcodes.ARRAY_STORE, store.arrayId)); + instructions.add(new IntInstruction(Opcodes.POP_ARRAY_INT, store.arrayId)); } else if (expression instanceof ArrayLoadNode) { assert !pop : "Not a statement " + expression; ArrayLoadNode load = (ArrayLoadNode) expression; compileExpression(load.getIndex()); - instructions.add(new IntInstruction(Opcodes.ARRAY_LOAD, load.arrayId)); + instructions.add(new IntInstruction(Opcodes.PUSH_ARRAY_INT, load.arrayId)); } else if (expression instanceof ConditionalExpressionNode) { assert !pop : "Not a statement " + expression; //Compile a conditional expression. But leave the result on the stack rather than making a jump based on the result @@ -570,10 +570,10 @@ private void compileExpression(ExpressionNode expression, boolean pop) { if (compileConditionalJmp(expression, push1, push0)) { //It did have to jump. push results back onto the stack instructions.add(push1); - instructions.add(new IntInstruction(Opcodes.PUSH_INT, 1)); - instructions.add(new JumpInstruction(Opcodes.GOTO, merge)); + instructions.add(new IntInstruction(Opcodes.PUSH_CONSTANT_INT, 1)); + instructions.add(new JumpInstruction(Opcodes.BRANCH, merge)); instructions.add(push0); - instructions.add(new IntInstruction(Opcodes.PUSH_INT, 0)); + instructions.add(new IntInstruction(Opcodes.PUSH_CONSTANT_INT, 0)); //(flows to merge) instructions.add(merge); } @@ -597,14 +597,14 @@ private void optimize() { continue; } //Remove label if instruction after label is GOTO. Rewrite all jumps to this label to the GOTO target - if ((next instanceof JumpInstruction) && next.getOpcode() == Opcodes.GOTO) { + if ((next instanceof JumpInstruction) && next.getOpcode() == Opcodes.BRANCH) { rewriteJumps((Label) instr, ((JumpInstruction) next).getTarget()); instructions.remove(instr); continue; } } //Remove GOTO if next instruction is that label - if (instr instanceof JumpInstruction && instr.getOpcode() == Opcodes.GOTO) { + if (instr instanceof JumpInstruction && instr.getOpcode() == Opcodes.BRANCH) { AbstractInstruction next = instructions.get(i + 1); if (next instanceof Label && ((JumpInstruction) instr).getTarget() == next) { instructions.remove(instr); @@ -618,7 +618,7 @@ private void optimize() { int opposite = Opcodes.oppositeJump(instr.getOpcode()); if (instr instanceof JumpInstruction && opposite != -1) { AbstractInstruction next = instructions.get(i + 1); - if (next instanceof JumpInstruction && next.getOpcode() == Opcodes.GOTO) { + if (next instanceof JumpInstruction && next.getOpcode() == Opcodes.BRANCH) { AbstractInstruction nn = instructions.get(i + 2); if (nn instanceof Label && ((JumpInstruction) instr).getTarget() == nn) { instr.setOpcode(opposite); @@ -631,9 +631,9 @@ private void optimize() { } if (supportEq01) { //change push int 0/1 INT_EQ to EQ0/1 without push - if (instr instanceof IntInstruction && instr.getOpcode() == Opcodes.PUSH_INT) { + if (instr instanceof IntInstruction && instr.getOpcode() == Opcodes.PUSH_CONSTANT_INT) { AbstractInstruction next = instructions.get(i + 1); - if (next instanceof JumpInstruction && next.getOpcode() == Opcodes.INT_EQ) { + if (next instanceof JumpInstruction && next.getOpcode() == Opcodes.BRANCH_EQUALS) { if (((IntInstruction) instr).getConstant() == 0) { instructions.remove(instr); next.setOpcode(Opcodes.EQ0); diff --git a/src/main/java/dawn/cs2/CS2Reader.java b/src/main/java/dawn/cs2/CS2Reader.java index 92e1af8..fa180b9 100644 --- a/src/main/java/dawn/cs2/CS2Reader.java +++ b/src/main/java/dawn/cs2/CS2Reader.java @@ -93,11 +93,11 @@ private CS2 readScript(int scriptID, byte[] data, Map unscramb throw new DecompilerException("Unknown scrambling " + opcode + " " + opcode); } opcode = n; - if (opcode == Opcodes.PUSH_STRING) { + if (opcode == Opcodes.PUSH_CONSTANT_STRING) { script.getInstructions()[(writeOffset * 2) + 1] = new StringInstruction(opcode, buffer.readString()); } else if (opcode == Opcodes.PUSH_LONG) { script.getInstructions()[(writeOffset * 2) + 1] = new LongInstruction(opcode, buffer.readLong()); - } else if (opcode == Opcodes.RETURN || opcode == Opcodes.POP_INT || opcode == Opcodes.POP_STRING) { + } else if (opcode == Opcodes.RETURN || opcode == Opcodes.POP_INT_DISCARD || opcode == Opcodes.POP_STRING_DISCARD) { //TODO: this might aswell be booleaninstructions, but decompiler kind of expects them to be intinstructions right now script.getInstructions()[(writeOffset * 2) + 1] = new IntInstruction(opcode, buffer.readUnsignedByte()); } else if (opcode >= (hasLongs ? 150 : 100)) { // || opcode == 21 || opcode == 38 || opcode == 39) @@ -119,7 +119,7 @@ private CS2 readScript(int scriptID, byte[] data, Map unscramb script.getInstructions()[(writeOffset * 2) + 1] = new SwitchInstruction(opcode, cases, targets); if (script.getInstructions()[writeOffset * 2 + 2] == null) script.getInstructions()[(writeOffset * 2) + 2] = new Label(); //always insert label after switch - } else if (opcode == Opcodes.GOTO || opcode == Opcodes.INT_NE || opcode == Opcodes.INT_EQ || opcode == Opcodes.INT_LT || opcode == Opcodes.INT_GT || opcode == Opcodes.INT_LE || opcode == Opcodes.INT_GE || opcode == Opcodes.LONG_NE || opcode == Opcodes.LONG_EQ || opcode == Opcodes.LONG_LT || opcode == Opcodes.LONG_GT || opcode == Opcodes.LONG_LE || opcode == Opcodes.LONG_GE || opcode == Opcodes.EQ1 || opcode == Opcodes.EQ0) { + } else if (opcode == Opcodes.BRANCH || opcode == Opcodes.BRANCH_NOT || opcode == Opcodes.BRANCH_EQUALS || opcode == Opcodes.BRANCH_LESS_THAN || opcode == Opcodes.BRANCH_GREATER_THAN || opcode == Opcodes.BRANCH_LESS_THAN_OR_EQUALS || opcode == Opcodes.BRANCH_GREATER_THAN_OR_EQUALS || opcode == Opcodes.LONG_NE || opcode == Opcodes.LONG_EQ || opcode == Opcodes.LONG_LT || opcode == Opcodes.LONG_GT || opcode == Opcodes.LONG_LE || opcode == Opcodes.LONG_GE || opcode == Opcodes.EQ1 || opcode == Opcodes.EQ0) { int fullAddr = writeOffset + buffer.readInt() + 1; if (script.getInstructions()[fullAddr * 2] == null) script.getInstructions()[fullAddr * 2] = new Label(); diff --git a/src/main/java/dawn/cs2/CS2ScriptParser.java b/src/main/java/dawn/cs2/CS2ScriptParser.java index 3b36785..9b20ee7 100644 --- a/src/main/java/dawn/cs2/CS2ScriptParser.java +++ b/src/main/java/dawn/cs2/CS2ScriptParser.java @@ -941,7 +941,7 @@ private ExpressionNode parsePrimitive() { return new PlaceholderValueNode(value, -2147483646, CS2Type.INT); case "CTX_WIDGET": advance(); - return new PlaceholderValueNode(value, -2147483645, CS2Type.WIDGET_PTR); + return new PlaceholderValueNode(value, -2147483645, CS2Type.COMPONENT); case "CTX_MENU_OPTION": advance(); return new PlaceholderValueNode(value, -2147483644, CS2Type.INT); @@ -950,7 +950,7 @@ private ExpressionNode parsePrimitive() { return new PlaceholderValueNode(value, -2147483643, CS2Type.INT); case "DRAG_WIDGET": advance(); - return new PlaceholderValueNode(value, -2147483642, CS2Type.WIDGET_PTR); + return new PlaceholderValueNode(value, -2147483642, CS2Type.COMPONENT); case "DRAG_WIDGET_CHILD": advance(); return new PlaceholderValueNode(value, -2147483641, CS2Type.INT); diff --git a/src/main/java/dawn/cs2/CS2Type.java b/src/main/java/dawn/cs2/CS2Type.java index b1c8985..f275b5e 100644 --- a/src/main/java/dawn/cs2/CS2Type.java +++ b/src/main/java/dawn/cs2/CS2Type.java @@ -3,7 +3,6 @@ import dawn.cs2.ast.*; import java.io.BufferedReader; -import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; @@ -20,6 +19,19 @@ public class CS2Type { private boolean structure; //BASE TYPES + + public static CS2Type AREA = new CS2Type(0, 0, 0, "area", 'R'); + public static CS2Type DBROW = new CS2Type(0, 0, 0, "dbrow", 'c'); + public static CS2Type INTERFACE = new CS2Type(0, 0, 0, "interface", 'a'); + public static CS2Type LOC = new CS2Type(0, 0, 0, "loc", 'l'); + public static CS2Type LOCSHAPE = new CS2Type(0, 0, 0, "locshape", 'H'); + public static CS2Type MAPELEMENT = new CS2Type(0, 0, 0, "mapelement", 'µ'); + public static CS2Type NEWVAR = new CS2Type(0, 0, 0, "newvar", '-'); + public static CS2Type OVERLAYINTERFACE = new CS2Type(0, 0, 0, "overlayinterface", 'L'); + public static CS2Type PLAYER_UID = new CS2Type(0, 0, 0, "playeruid", 'p'); + public static CS2Type TOPLEVELINTERFACE = new CS2Type(0, 0, 0, "toplevelinterface", 'F'); + + public static CS2Type VOID = new CS2Type(0, 0, 0, "void", '\0'); public static CS2Type BOOLEAN = new CS2Type(1, 0, 0, "boolean", '1'); public static CS2Type INT = new CS2Type(1, 0, 0, "int", 'i'); @@ -27,14 +39,14 @@ public class CS2Type { public static CS2Type SPRITE = new CS2Type(1, 0, 0, "Sprite", 'd'); public static CS2Type MODEL = new CS2Type(1, 0, 0, "Model", 'm'); public static CS2Type MIDI = new CS2Type(1, 0, 0, "Midi", 'M'); - public static CS2Type DATAMAP = new CS2Type(1, 0, 0, "DataMap", 'g'); + public static CS2Type ENUM = new CS2Type(1, 0, 0, "DataMap", 'g'); public static CS2Type ATTRIBUTEMAP = new CS2Type(1, 0, 0, "AttrMap", 'J'); public static CS2Type CHAR = new CS2Type(1, 0, 0, "char", 'z'); public static CS2Type CONTAINER = new CS2Type(1, 0, 0, "Container", 'v'); public static CS2Type STRING = new CS2Type(0, 1, 0, "string", 's'); public static CS2Type LONG = new CS2Type(0, 0, 1, "long", '§'); - public static CS2Type WIDGET_PTR = new CS2Type(1, 0, 0, "Widget", 'I'); - public static CS2Type LOCATION = new CS2Type(1, 0, 0, "Location", 'c'); + public static CS2Type COMPONENT = new CS2Type(1, 0, 0, "Widget", 'I'); + public static CS2Type COORD = new CS2Type(1, 0, 0, "Location", 'c'); public static CS2Type ITEM = new CS2Type(1, 0, 0, "Item", 'o'); // public static CS2Type ITEM_NAMED = new CS2Type(1, 0, 0, "Item", 'O', false); public static CS2Type COLOR = new CS2Type(1, 0, 0, "Color", 'i'); //Not a real type, but helps us know where we need to convert int to hex notation @@ -61,7 +73,7 @@ public class CS2Type { public static CS2Type UNKNOWN = new CS2Type(0, 0, 0, "??", '\0'); - public static CS2Type[] TYPE_LIST = new CS2Type[]{VOID, CALLBACK, BOOLEAN, INT, FONTMETRICS, SPRITE, MODEL, MIDI, LOCATION, CHAR, STRING, LONG, UNKNOWN, WIDGET_PTR, ITEM, COLOR, CONTAINER, DATAMAP, ATTRIBUTEMAP, IDENTIKIT, ANIM, MAPID, GRAPHIC, SKILL, NPCDEF, QCPHRASE, CHATCAT, TEXTURE, STANCE, SPELL, CATEGORY, SOUNDEFFECT, INT_ARRAY, LONG_ARRAY, STRING_ARRAY}; + public static CS2Type[] TYPE_LIST = new CS2Type[]{AREA, DBROW, INTERFACE, LOC, LOCSHAPE, MAPELEMENT, NEWVAR, OVERLAYINTERFACE, PLAYER_UID, TOPLEVELINTERFACE, VOID, CALLBACK, BOOLEAN, INT, FONTMETRICS, SPRITE, MODEL, MIDI, COORD, CHAR, STRING, LONG, UNKNOWN, COMPONENT, ITEM, COLOR, CONTAINER, ENUM, ATTRIBUTEMAP, IDENTIKIT, ANIM, MAPID, GRAPHIC, SKILL, NPCDEF, QCPHRASE, CHATCAT, TEXTURE, STANCE, SPELL, CATEGORY, SOUNDEFFECT, INT_ARRAY, LONG_ARRAY, STRING_ARRAY}; private static List cache = new ArrayList(); //TODO: Refactor this @@ -137,9 +149,9 @@ public static ExpressionNode cast(ExpressionNode expr, CS2Type type) { return expr; } - if (type.equals(LOCATION)) + if (type.equals(COORD)) return new NewLocationNode(expr); - if (type.equals(WIDGET_PTR)) + if (type.equals(COMPONENT)) return new NewWidgetPointerNode(expr); if (type.equals(COLOR)) return new NewColorNode(expr instanceof NewWidgetPointerNode ? ((NewWidgetPointerNode) expr).getExpression() : expr); @@ -244,16 +256,24 @@ public static CS2Type forJagexDesc(char desc) { case '\0': return CS2Type.UNKNOWN; // return VOID; + case '1': + return BOOLEAN; + case 'y': + return CATEGORY; + case 'z': + return CHAR; + case 'I': + return COMPONENT; + case 'c': + return COORD; + case 'g': + return ENUM; case '§': return LONG; case 'i': return INT; - case 'z': - return CHAR; case 's': return STRING; - case '1': - return BOOLEAN; case 'o': case 'O': //One of these is actually NAMED_ITEM? @@ -264,14 +284,10 @@ public static CS2Type forJagexDesc(char desc) { return SKILL; case 't': return GRAPHIC; - case 'c': - return LOCATION; case 'n': return NPCDEF; case 'J': return ATTRIBUTEMAP; - case 'g': - return DATAMAP; case 'f': return FONTMETRICS; case 'd': @@ -284,8 +300,6 @@ public static CS2Type forJagexDesc(char desc) { return IDENTIKIT; case 'v': return CONTAINER; - case 'I': - return WIDGET_PTR; case 'e': return QCPHRASE; case 'k': @@ -298,8 +312,6 @@ public static CS2Type forJagexDesc(char desc) { return SPELL; case '`': return MAPID; - case 'y': - return CATEGORY; case '«': return SOUNDEFFECT; // case 'P': diff --git a/src/main/java/dawn/cs2/FlowBlocksGenerator.java b/src/main/java/dawn/cs2/FlowBlocksGenerator.java index 55bf753..e25d37e 100644 --- a/src/main/java/dawn/cs2/FlowBlocksGenerator.java +++ b/src/main/java/dawn/cs2/FlowBlocksGenerator.java @@ -5,11 +5,9 @@ import dawn.cs2.util.FunctionInfo; import dawn.cs2.util.IOUtils; import dawn.cs2.util.OpcodeUtils; -import kotlin.ranges.RangesKt; import org.apache.commons.lang3.Range; import java.io.*; -import java.time.temporal.ValueRange; import java.util.*; import static dawn.cs2.ast.LocalVariable.CHILD; @@ -92,7 +90,7 @@ private void processFlowBlock(FlowBlock block) { target.parents.add(block); block.children.add(target); block.write(new ConditionalFlowBlockJump(conditional, target)); - } else if (opcode == Opcodes.GOTO) { + } else if (opcode == Opcodes.BRANCH) { FlowBlock target = generateFlowBlock(jmp.getTarget(), stack.copy()); target.parents.add(block); block.children.add(target); @@ -120,18 +118,18 @@ private void processFlowBlock(FlowBlock block) { } CS2Type currentType = stackTypes.pollLast(); - if (opcode == POP_INT || opcode == Opcodes.POP_STRING || opcode == Opcodes.POP_LONG) { - var = opcode == POP_INT ? Underscore.UNDERSCORE_I : opcode == POP_STRING ? Underscore.UNDERSCORE_S : Underscore.UNDERSCORE_L; - } else if (opcode == Opcodes.STORE_VARP) { + if (opcode == POP_INT_DISCARD || opcode == Opcodes.POP_STRING_DISCARD || opcode == Opcodes.POP_LONG) { + var = opcode == POP_INT_DISCARD ? Underscore.UNDERSCORE_I : opcode == POP_STRING_DISCARD ? Underscore.UNDERSCORE_S : Underscore.UNDERSCORE_L; + } else if (opcode == Opcodes.POP_VAR) { var = GlobalVariable.VARP(intInstr.getConstant(), currentType); - } else if (opcode == Opcodes.STORE_VARPBIT) { + } else if (opcode == Opcodes.POP_VARBIT) { var = GlobalVariable.VARPBIT(intInstr.getConstant(), currentType); - } else if (opcode == Opcodes.STORE_VARC) { + } else if (opcode == Opcodes.POP_VARC_INT) { var = GlobalVariable.VARC(intInstr.getConstant(), currentType); } else if (opcode == STORE_VARCSTR) { var = GlobalVariable.VARC_STRING(intInstr.getConstant()); - } else if (opcode == Opcodes.STORE_INT || opcode == Opcodes.STORE_STRING || opcode == Opcodes.STORE_LONG) { - int stackType = opcode == Opcodes.STORE_INT ? 0 : (opcode == Opcodes.STORE_LONG ? 2 : 1); + } else if (opcode == Opcodes.POP_INT_LOCAL || opcode == Opcodes.POP_STRING_LOCAL || opcode == Opcodes.STORE_LONG) { + int stackType = opcode == Opcodes.POP_INT_LOCAL ? 0 : (opcode == Opcodes.STORE_LONG ? 2 : 1); var = function.getMainScope().getLocalVariable(LocalVariable.makeIdentifier(intInstr.getConstant(), stackType)); //dont do boolean? if (var.getType() == CS2Type.INT && currentType != CS2Type.INT && currentType != CS2Type.UNKNOWN) { @@ -163,24 +161,24 @@ private void processFlowBlock(FlowBlock block) { } } while (true); // - assert stack.getSize() == 0 : "Whole stack should be popped after assign"; +// assert stack.getSize() == 0 : "Whole stack should be popped after assign. Opcode: " + opcode; assert stackTypes.size() == 0 : "Only half result of expression used"; //TODO: if all vars are underscores, we could make normal expressions out of this and remove the underscore part (eg _, _ = get2ValuesAndSomeSideEffects()). Doesn't appear to be used much though, so i think its fine for clarity block.write(new PopableNode(new VariableAssignationNode(vars, assignments.size() == 1 ? assignments.get(0) : new ExpressionList(assignments)))); - } else if (opcode == Opcodes.PUSH_INT) { // push int. + } else if (opcode == Opcodes.PUSH_CONSTANT_INT) { // push int. //TODO: Technically only in delegate methods if (val == -2147483647) { stack.push(new PlaceholderValueNode("MOUSE_X", val, CS2Type.INT)); } else if (val == -2147483646) { stack.push(new PlaceholderValueNode("MOUSE_Y", val, CS2Type.INT));//Either mouse y pos, or scroll ticks } else if (val == -2147483645) { - stack.push(new PlaceholderValueNode("CTX_WIDGET", val, CS2Type.WIDGET_PTR)); + stack.push(new PlaceholderValueNode("CTX_WIDGET", val, CS2Type.COMPONENT)); } else if (val == -2147483644) { stack.push(new PlaceholderValueNode("CTX_MENU_OPTION", val, CS2Type.INT)); } else if (val == -2147483643) { stack.push(new PlaceholderValueNode("CTX_WIDGET_CHILD", val, CS2Type.INT)); } else if (val == -2147483642) { - stack.push(new PlaceholderValueNode("DRAG_WIDGET", val, CS2Type.WIDGET_PTR)); + stack.push(new PlaceholderValueNode("DRAG_WIDGET", val, CS2Type.COMPONENT)); } else if (val == -2147483641) { stack.push(new PlaceholderValueNode("DRAG_WIDGET_CHILD", val, CS2Type.INT)); } else if (val == -2147483640) { @@ -190,9 +188,10 @@ private void processFlowBlock(FlowBlock block) { } else { stack.push(new IntExpressionNode(val)); } - } else if (opcode == Opcodes.LOAD_VARP) { + } else if (opcode == Opcodes.PUSH_VAR) { stack.push(new VariableLoadNode(GlobalVariable.find("VARP", intInstr.getConstant(), CS2Type.INT))); } else if (opcode == Opcodes.RETURN) { + if (stack.getSize() <= 0) { block.write(new ReturnNode(null)); assert CS2Type.VOID.isCompatible(this.function.getReturnType()); @@ -217,7 +216,7 @@ private void processFlowBlock(FlowBlock block) { while (stack.getSize() > 0) { ExpressionNode expr = stack.pop(); if (expr.getType() == CS2Type.UNKNOWN) { - throw new DecompilerException("Unknown return type"); + throw new DecompilerException("Unknown return type, opcode: " + opcode + " TYPE: " + expr.getType()); } // assert !expr.getType().isStructure() : "no support yet for returning structs together with other values"; expressions.addFirst(expr); @@ -227,19 +226,19 @@ private void processFlowBlock(FlowBlock block) { } // if ((ptr + 1) >= cs2.getInstructions().length) //uncomment this to decompile some dead code break; - } else if (opcode == Opcodes.LOAD_VARPBIT) { + } else if (opcode == Opcodes.PUSH_VARBIT) { stack.push(new VariableLoadNode(GlobalVariable.find("VARPBIT", intInstr.getConstant(), CS2Type.INT))); - } else if (opcode == Opcodes.LOAD_INT || opcode == Opcodes.LOAD_STRING || opcode == Opcodes.LOAD_LONG) { - int stackType = opcode == Opcodes.LOAD_INT ? 0 : (opcode == Opcodes.LOAD_LONG ? 2 : 1); + } else if (opcode == Opcodes.PUSH_INT_LOCAL || opcode == Opcodes.PUSH_STRING_LOCAL || opcode == Opcodes.LOAD_LONG) { + int stackType = opcode == Opcodes.PUSH_INT_LOCAL ? 0 : (opcode == Opcodes.LOAD_LONG ? 2 : 1); LocalVariable var = function.getMainScope().getLocalVariable(LocalVariable.makeIdentifier(intInstr.getConstant(), stackType)); stack.push(new VariableLoadNode(var)); - } else if (opcode == Opcodes.MERGE_STRINGS) { + } else if (opcode == Opcodes.JOIN_STRING) { int amount = intInstr.getConstant(); LinkedList exprs = new LinkedList<>(); for (int i = amount - 1; i >= 0; i--) exprs.addFirst(CS2Type.cast(stack.pop(), CS2Type.STRING)); stack.push(new BuildStringNode(exprs)); - } else if (opcode == Opcodes.CALL_CS2) { + } else if (opcode == Opcodes.GOSUB_WITH_PARAMS) { FunctionInfo info = decompiler.getScriptsDatabase().getInfo(intInstr.getConstant()); if (info == null) { throw new DecompilerException("Function for opcode " + instruction.getOpcode() + " is missing."); @@ -248,17 +247,17 @@ private void processFlowBlock(FlowBlock block) { int ret = this.analyzeCall(info, block, stack, ptr, true, false, false, intInstr.getConstant(), false); if (ret != -1) ptr = ret; - } else if (opcode == Opcodes.LOAD_VARC) { + } else if (opcode == Opcodes.PUSH_VARC_INT) { stack.push(new VariableLoadNode(GlobalVariable.VARC(intInstr.getConstant(), CS2Type.INT))); - } else if (opcode == Opcodes.ARRAY_NEW) { + } else if (opcode == Opcodes.DEFINE_ARRAY) { int arrayID = intInstr.getConstant() >> 16; char type = (char) (intInstr.getConstant() & 0xFFFF); CS2Type array = CS2Type.forJagexDesc(type);//.getArrayType(); ExpressionNode length = CS2Type.cast(stack.pop(), CS2Type.INT); block.write(new PopableNode(new NewArrayNode(arrayID, length, array))); - } else if (opcode == Opcodes.ARRAY_LOAD) { + } else if (opcode == Opcodes.PUSH_ARRAY_INT) { stack.push(new ArrayLoadNode(intInstr.getConstant(), CS2Type.INT/*.getArrayType()*/, CS2Type.cast(stack.pop(), CS2Type.INT))); - } else if (opcode == Opcodes.ARRAY_STORE) { + } else if (opcode == Opcodes.POP_ARRAY_INT) { ExpressionNode value = stack.pop(); ExpressionNode index = CS2Type.cast(stack.pop(), CS2Type.INT); block.write(new PopableNode(new ArrayStoreNode(intInstr.getConstant(), index, value))); @@ -439,7 +438,7 @@ private FunctionInfo analyzeSpecialCall(FlowBlock block, CS2Stack stack, int opc args[i] = stack.pop(); if (!(args[1] instanceof IntExpressionNode) || !(args[0] instanceof IntExpressionNode)) throw new DecompilerException("Dynamic type"); - return new FunctionInfo(fi.getName(), opcode, new CS2Type[]{CS2Type.CHAR, CS2Type.CHAR, CS2Type.DATAMAP, CS2Type.forJagexDesc((char) ((IntExpressionNode) args[0]).getData())}, CS2Type.forJagexDesc((char) ((IntExpressionNode) args[1]).getData()), fi.getArgumentNames(), false); + return new FunctionInfo(fi.getName(), opcode, new CS2Type[]{CS2Type.CHAR, CS2Type.CHAR, CS2Type.ENUM, CS2Type.forJagexDesc((char) ((IntExpressionNode) args[0]).getData())}, CS2Type.forJagexDesc((char) ((IntExpressionNode) args[1]).getData()), fi.getArgumentNames(), false); } else if (opcode == 4019) { //math function ExpressionNode[] args = new ExpressionNode[2]; for (int i = 1; i >= 0; i--) diff --git a/src/main/java/dawn/cs2/ast/GlobalVariable.java b/src/main/java/dawn/cs2/ast/GlobalVariable.java index 13a9176..a778548 100644 --- a/src/main/java/dawn/cs2/ast/GlobalVariable.java +++ b/src/main/java/dawn/cs2/ast/GlobalVariable.java @@ -76,11 +76,11 @@ public CS2Type getType() { public AbstractInstruction generateStoreInstruction() { switch (name) { case "VARP": - return new IntInstruction(Opcodes.STORE_VARP, idx); + return new IntInstruction(Opcodes.POP_VAR, idx); case "VARPBIT": - return new IntInstruction(Opcodes.STORE_VARPBIT, idx); + return new IntInstruction(Opcodes.POP_VARBIT, idx); case "VARC": - return new IntInstruction(Opcodes.STORE_VARC, idx); + return new IntInstruction(Opcodes.POP_VARC_INT, idx); case "STRING": return new IntInstruction(Opcodes.STORE_VARCSTR, idx); default: @@ -93,13 +93,13 @@ public AbstractInstruction generateLoadInstruction() { int op = -1; switch (name) { case "VARP": - op = Opcodes.LOAD_VARP; + op = Opcodes.PUSH_VAR; break; case "VARPBIT": - op = Opcodes.LOAD_VARPBIT; + op = Opcodes.PUSH_VARBIT; break; case "VARC": - op = Opcodes.LOAD_VARC; + op = Opcodes.PUSH_VARC_INT; break; case "STRING": op = Opcodes.LOAD_VARCSTR_NEW; diff --git a/src/main/java/dawn/cs2/ast/LocalVariable.java b/src/main/java/dawn/cs2/ast/LocalVariable.java index d9ed29d..7c95e58 100644 --- a/src/main/java/dawn/cs2/ast/LocalVariable.java +++ b/src/main/java/dawn/cs2/ast/LocalVariable.java @@ -72,9 +72,9 @@ public AbstractInstruction generateStoreInstruction() { int type = getIdentifier() >> 16; int id = getIdentifier() & 0xffff; if (type == 0) { - return new IntInstruction(Opcodes.STORE_INT, id); + return new IntInstruction(Opcodes.POP_INT_LOCAL, id); } else if (type == 1) { - return new IntInstruction(Opcodes.STORE_STRING, id); + return new IntInstruction(Opcodes.POP_STRING_LOCAL, id); } else if (type == 2) { return new IntInstruction(Opcodes.STORE_LONG, id); } @@ -87,9 +87,9 @@ public AbstractInstruction generateLoadInstruction() { int type = getIdentifier() >> 16; int id = getIdentifier() & 0xffff; if (type == 0) { - return new IntInstruction(Opcodes.LOAD_INT, id); + return new IntInstruction(Opcodes.PUSH_INT_LOCAL, id); } else if (type == 1) { - return new IntInstruction(Opcodes.LOAD_STRING, id); + return new IntInstruction(Opcodes.PUSH_STRING_LOCAL, id); } else if (type == 2) { return new IntInstruction(Opcodes.LOAD_LONG, id); } diff --git a/src/main/java/dawn/cs2/ast/NewLocationNode.java b/src/main/java/dawn/cs2/ast/NewLocationNode.java index 2cdb681..bb2fc0e 100644 --- a/src/main/java/dawn/cs2/ast/NewLocationNode.java +++ b/src/main/java/dawn/cs2/ast/NewLocationNode.java @@ -13,7 +13,7 @@ public NewLocationNode(ExpressionNode expr) { @Override public CS2Type getType() { - return CS2Type.LOCATION; + return CS2Type.COORD; } @Override diff --git a/src/main/java/dawn/cs2/ast/NewWidgetPointerNode.java b/src/main/java/dawn/cs2/ast/NewWidgetPointerNode.java index 0588488..2d76a09 100644 --- a/src/main/java/dawn/cs2/ast/NewWidgetPointerNode.java +++ b/src/main/java/dawn/cs2/ast/NewWidgetPointerNode.java @@ -14,7 +14,7 @@ public NewWidgetPointerNode(ExpressionNode expr) { @Override public CS2Type getType() { - return CS2Type.WIDGET_PTR; + return CS2Type.COMPONENT; } @Override diff --git a/src/main/java/dawn/cs2/ast/Underscore.java b/src/main/java/dawn/cs2/ast/Underscore.java index 8f7d520..ab09e9e 100644 --- a/src/main/java/dawn/cs2/ast/Underscore.java +++ b/src/main/java/dawn/cs2/ast/Underscore.java @@ -43,9 +43,9 @@ public static Underscore forType(CS2Type other) { @Override public AbstractInstruction generateStoreInstruction() { if (this == UNDERSCORE_I) { - return new BooleanInstruction(Opcodes.POP_INT, false); + return new BooleanInstruction(Opcodes.POP_INT_DISCARD, false); } else if (this == UNDERSCORE_S) { - return new BooleanInstruction(Opcodes.POP_STRING, false); + return new BooleanInstruction(Opcodes.POP_STRING_DISCARD, false); } else if (this == UNDERSCORE_L) { return new IntInstruction(Opcodes.POP_LONG, 0); } else { diff --git a/src/main/java/dawn/cs2/instructions/Opcodes.java b/src/main/java/dawn/cs2/instructions/Opcodes.java index 73a19e6..6b68318 100644 --- a/src/main/java/dawn/cs2/instructions/Opcodes.java +++ b/src/main/java/dawn/cs2/instructions/Opcodes.java @@ -6,44 +6,41 @@ public class Opcodes { - public static final int PUSH_INT = 0; - public static final int PUSH_STRING = 3; - public static final int PUSH_LONG = 54; - public static final int POP_INT = 38; - public static final int POP_STRING = 39; - public static final int POP_LONG = 55; + public static final int PUSH_CONSTANT_INT = 0; + public static final int PUSH_VAR = 1; + public static final int POP_VAR = 2; + public static final int PUSH_CONSTANT_STRING = 3; + public static final int BRANCH = 6; + public static final int BRANCH_NOT = 7; + public static final int BRANCH_EQUALS = 8; + public static final int BRANCH_LESS_THAN = 9; + public static final int BRANCH_GREATER_THAN = 10; public static final int RETURN = 21; - public static final int LOAD_INT = 33; - public static final int STORE_INT = 34; - public static final int LOAD_STRING = 35; - public static final int STORE_STRING = 36; - public static final int MERGE_STRINGS = 37; - public static final int LOAD_LONG = 66; - public static final int STORE_LONG = 67; - public static final int STORE_VARPBIT = 27; - public static final int LOAD_VARP = 1; - public static final int STORE_VARP = 2; - public static final int LOAD_VARC = 42; + public static final int PUSH_VARBIT = 25; + public static final int POP_VARBIT = 27; + public static final int BRANCH_LESS_THAN_OR_EQUALS = 31; + public static final int BRANCH_GREATER_THAN_OR_EQUALS = 32; + public static final int PUSH_INT_LOCAL = 33; + public static final int POP_INT_LOCAL = 34; + public static final int PUSH_STRING_LOCAL = 35; + public static final int POP_STRING_LOCAL = 36; + public static final int JOIN_STRING = 37; + public static final int POP_INT_DISCARD = 38; + public static final int POP_STRING_DISCARD = 39; + public static final int GOSUB_WITH_PARAMS = 40; + public static final int PUSH_VARC_INT = 42; + public static final int POP_VARC_INT = 43; + public static final int DEFINE_ARRAY = 44; + public static final int PUSH_ARRAY_INT = 45; + public static final int POP_ARRAY_INT = 46; public static final int LOAD_VARCSTR = 47; + public static final int STORE_VARCSTR = 48; public static final int LOAD_VARCSTR_NEW = 49; - public static final int STORE_VARC = 43; - public static final int LOAD_VARPBIT = 25; public static final int SWITCH = 51; - - public static final int ARRAY_NEW = 44; - public static final int ARRAY_LOAD = 45; - public static final int ARRAY_STORE = 46; - - - public static final int STORE_VARCSTR = 48; - public static final int CALL_CS2 = 40; - public static final int GOTO = 6; - public static final int INT_EQ = 8; - public static final int INT_NE = 7; - public static final int INT_LT = 9; - public static final int INT_GT = 10; - public static final int INT_LE = 31; - public static final int INT_GE = 32; + public static final int PUSH_LONG = 54; + public static final int POP_LONG = 55; + public static final int LOAD_LONG = 66; + public static final int STORE_LONG = 67; public static final int LONG_EQ = 69; public static final int LONG_NE = 68; public static final int LONG_LT = 70; @@ -74,33 +71,33 @@ public static String getOpcodeName(int opcode) { public static int oppositeJump(int op) { switch (op) { - case INT_EQ: - return INT_NE; - case INT_NE: - return INT_EQ; - case INT_GE: - return INT_LT; - case INT_LT: - return INT_GE; - case INT_GT: - return INT_LE; - case INT_LE: - return INT_GT; + case BRANCH_EQUALS: + return BRANCH_NOT; + case BRANCH_NOT: + return BRANCH_EQUALS; + case BRANCH_GREATER_THAN_OR_EQUALS: + return BRANCH_LESS_THAN; + case BRANCH_LESS_THAN: + return BRANCH_GREATER_THAN_OR_EQUALS; + case BRANCH_GREATER_THAN: + return BRANCH_LESS_THAN_OR_EQUALS; + case BRANCH_LESS_THAN_OR_EQUALS: + return BRANCH_GREATER_THAN; } return -1; } public static boolean isAssign(int op) { switch (op) { - case POP_INT: - case POP_STRING: + case POP_INT_DISCARD: + case POP_STRING_DISCARD: case POP_LONG: - case STORE_INT: - case STORE_STRING: + case POP_INT_LOCAL: + case POP_STRING_LOCAL: case STORE_LONG: - case STORE_VARP: - case STORE_VARPBIT: - case STORE_VARC: + case POP_VAR: + case POP_VARBIT: + case POP_VARC_INT: case STORE_VARCSTR: // case ARRAY_STORE: return true; diff --git a/src/main/java/dawn/cs2/instructions/SwitchInstruction.java b/src/main/java/dawn/cs2/instructions/SwitchInstruction.java index 9afaed0..fae8559 100644 --- a/src/main/java/dawn/cs2/instructions/SwitchInstruction.java +++ b/src/main/java/dawn/cs2/instructions/SwitchInstruction.java @@ -44,7 +44,7 @@ public String toString() { bld.append("switch { \r\n"); for (int i = 0; i < cases.size(); i++) { bld.append("\tcase " + cases.get(i) + ": "); - bld.append("\t").append(Opcodes.getOpcodeName(Opcodes.GOTO)).append("\t").append(targets.get(i).toString()).append(" \r\n"); + bld.append("\t").append(Opcodes.getOpcodeName(Opcodes.BRANCH)).append("\t").append(targets.get(i).toString()).append(" \r\n"); } bld.append("}"); return bld.toString(); From 9827b20360d85d91f9dfcce568fa76ebcfd459e8 Mon Sep 17 00:00:00 2001 From: crazzmc Date: Sun, 22 Jan 2023 14:51:16 -0500 Subject: [PATCH 8/8] adding back in error break, removing 179 check --- .../editor/controller/MainController.kt | 18 +++++++++--------- .../java/dawn/cs2/instructions/Opcodes.java | 3 +++ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/displee/editor/controller/MainController.kt b/src/main/java/com/displee/editor/controller/MainController.kt index b9925e6..bd14dda 100644 --- a/src/main/java/com/displee/editor/controller/MainController.kt +++ b/src/main/java/com/displee/editor/controller/MainController.kt @@ -429,18 +429,12 @@ class MainController : Initializable { try { CS2Reader.readCS2ScriptNewFormat(data, id, config.unscrambled, config.disableSwitches, config.disableLongs) } catch(e: Throwable) { - if (config.version == 179) { - println(e) - println("id $id") - + error++ + if (error >= 2) { + break } -// error++ -// if (error >= 2) { -// break -// } } } -// println("config: ${config.version} $error") error < 2 } var configuration: ScriptConfiguration? = null @@ -574,6 +568,12 @@ class MainController : Initializable { if (list != null && list.firstOrNull { it.name == name } == null) { list.add(function) } + + if (list != null) { + run { + list.add(function); + } + } } } diff --git a/src/main/java/dawn/cs2/instructions/Opcodes.java b/src/main/java/dawn/cs2/instructions/Opcodes.java index 6b68318..04200d4 100644 --- a/src/main/java/dawn/cs2/instructions/Opcodes.java +++ b/src/main/java/dawn/cs2/instructions/Opcodes.java @@ -50,6 +50,9 @@ public class Opcodes { public static final int EQ1 = 86; public static final int EQ0 = 87; + public static final int CC_SETONTIMER = 1408; + + public static final int IF_SETONTIMER = 2408; public static FunctionDatabase opcodesDb = null; // public static FunctionDatabase scriptsDb = null;