From 3436f1a897d161ccb055842c000c64a841c3b0d5 Mon Sep 17 00:00:00 2001 From: Benjamin Lerman <4838081+quisar@users.noreply.github.com> Date: Fri, 29 Dec 2023 14:03:51 +0100 Subject: [PATCH] Fix label generation for recursive sub functions. --- decompile/disasm.ts | 87 +++++++++++--------------- tests/__snapshots__/disas.test.ts.snap | 43 +++++++++++++ tests/bp_multi_behavior.txt | 1 + tests/recurse.txt | 1 + 4 files changed, 83 insertions(+), 49 deletions(-) create mode 100644 tests/bp_multi_behavior.txt create mode 100644 tests/recurse.txt diff --git a/decompile/disasm.ts b/decompile/disasm.ts index 22301e8..a2c3ebd 100644 --- a/decompile/disasm.ts +++ b/decompile/disasm.ts @@ -4,16 +4,11 @@ import { RawInstruction } from "./RawInstruction"; import { instructions } from "./dsinstr"; import { DesyncedStringToObject } from "../dsconvert"; -interface Work { - t: T; - done: boolean; -} - export class Disassembler { output: string[] = []; - extraBehaviors: Work[] = []; - subs: Work[] = []; - bps: Work[] = []; + mainBehavior?: RawBehavior; + extraBehaviors: RawBehavior[] = []; + bps: RawBlueprint[] = []; nextLabel = 0; constructor(obj: Record) { @@ -21,7 +16,7 @@ export class Disassembler { if ("frame" in obj) { this.blueprint(obj as unknown as RawBlueprint); } else { - this.disasemble(obj as unknown as RawBehavior); + this.mainBehavior = obj as unknown as RawBehavior; } this.#doExtras(); } @@ -62,7 +57,7 @@ export class Disassembler { if (obj.components) { for (const [v, k, code] of obj.components) { if (code) { - this.extraBehaviors.push({ t: code, done: false }); + this.extraBehaviors.push(code); this.#emit( `.component`, k, @@ -76,7 +71,7 @@ export class Disassembler { } } - disasemble(obj: RawBehavior, main = "main") { + disasemble(obj: RawBehavior, main = "main", subOffset = 0) { if (obj.name) { this.#emit(".name", obj.name); } @@ -90,12 +85,6 @@ export class Disassembler { this.#emit(".out", reg); } }); - const subOffset = this.subs.length; - if (obj.subs) { - for (const sub of obj.subs) { - this.subs.push({ t: sub, done: false }); - } - } const labels = this.#buildLabels(obj); for (let i = 0; `${i}` in obj; i++) { this.#emitInstr(obj[`${i}`], i, labels, subOffset, main); @@ -158,7 +147,7 @@ export class Disassembler { if (typeof inst.bp == "string") { inst.bp = DesyncedStringToObject("DSB" + inst.bp) as RawBlueprint; } - this.bps.push({ t: inst.bp, done: false }); + this.bps.push(inst.bp); args.push({ id: `$bp=:bp${this.bps.length}` }); } if (inst.nx != null && inst.ny != null) { @@ -199,39 +188,39 @@ export class Disassembler { } #doExtras() { - let count = 0; - do { - count = 0; - this.extraBehaviors.forEach((w, i) => { - if (!w.done) { - this.#nl(2); - this.#label(`behavior${i + 1}`); - this.#emit(".behavior"); - this.disasemble(w.t, `behavior${i + 1}`); - w.done = true; - count++; - } - }); - this.subs.forEach((w, i) => { - if (!w.done) { - this.#nl(2); - this.#label(`sub${i + 1}`); - this.#emit(".sub"); - this.disasemble(w.t); - w.done = true; - count++; - } + if (this.mainBehavior) { + this.disasemble(this.mainBehavior); + this.mainBehavior.subs?.forEach((sub, i) => { + this.#nl(2); + this.#label(`sub${i + 1}`); + this.#emit(".sub"); + this.disasemble(sub); }); - this.bps.forEach((w, i) => { - if (!w.done) { - this.#nl(2); - this.#label(`bp${i + 1}`); - this.blueprint(w.t); - w.done = true; - count++; - } + } + + let subOffset = 0; + this.extraBehaviors.forEach((behavior, i) => { + let mainName = `behavior${i + 1}`; + + this.#nl(2); + this.#label(mainName); + this.#emit(".behavior"); + this.disasemble(behavior, mainName, subOffset); + + behavior.subs?.forEach((sub, i) => { + this.#nl(2); + this.#label(`sub${i + subOffset + 1}`); + this.#emit(".sub"); + this.disasemble(sub, mainName, subOffset); }); - } while (count); + subOffset += behavior.subs?.length || 0; + }); + + this.bps.forEach((bp, i) => { + this.#nl(2); + this.#label(`bp${i + 1}`); + this.blueprint(bp); + }); } #nl(count = 1) { diff --git a/tests/__snapshots__/disas.test.ts.snap b/tests/__snapshots__/disas.test.ts.snap index a2eef3e..6b179ac 100644 --- a/tests/__snapshots__/disas.test.ts.snap +++ b/tests/__snapshots__/disas.test.ts.snap @@ -1,5 +1,34 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`bp_multi_behavior.txt 1`] = ` +"main: + .blueprint "f_building1x1d" + .component 2, c_behavior, :behavior1 + .component 3, c_behavior, :behavior2 + + +behavior1: + .behavior + .name "Call sub1" + call $sub=:sub1 + + +sub1: + .sub + .name "sub1" + + +behavior2: + .behavior + .name "Call sub2" + call $sub=:sub2 + + +sub2: + .sub + .name "sub2"" +`; + exports[`issue2.txt 1`] = ` "main: .name "foo" @@ -7,3 +36,17 @@ label0: set_reg goto, goto jump :label0" `; + +exports[`recurse.txt 1`] = ` +"main: + .name "foo" + call $sub=:sub1 + .ret + + +sub1: + .sub + .name "bar" + call $sub=:sub1 + .ret " +`; diff --git a/tests/bp_multi_behavior.txt b/tests/bp_multi_behavior.txt new file mode 100644 index 0000000..9b7ba37 --- /dev/null +++ b/tests/bp_multi_behavior.txt @@ -0,0 +1 @@ +DSB7c47wZia0ojrO40gBQMf0KrwDF1Z8gYF36DAbJ2oAQfp3AlOO11PlQrM2g6NRs0PUAgV0tHPAj1Pd9O20EeuWY1d3FA40LVkEI0hFzYB0oI4Im3fl0IM1oPuiG2OUTl90jpKTA10t1qY0dk4vv491mUO2fv13g4SYQyy4Syf1n2X1Bcg3cPVpB4DbAaV32MbnY32aLH902ShHY2XoyoT0Vi71b diff --git a/tests/recurse.txt b/tests/recurse.txt new file mode 100644 index 0000000..4d3e18a --- /dev/null +++ b/tests/recurse.txt @@ -0,0 +1 @@ +DSC3o1r9XCa1mbcCg0ffnYQ2QawfP1nmBRx4cqQm63cYPmE0Dwzqv2oOsnz1MW5bE2dsPxX2qfFxQ1Xm7qs0knnqO1j3MRt3ZamrS318qgc3JGVyE0felf24AeyHfGWfe