cleaner ui and code
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 1 Mar 2020 06:19:53 +0000 (00:19 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 1 Mar 2020 06:19:53 +0000 (00:19 -0600)
data/index.wasm [new file with mode: 0755]
data/main.wasm
decompile.lua
main.lua
ui.lua
utils.lua

diff --git a/data/index.wasm b/data/index.wasm
new file mode 100755 (executable)
index 0000000..c135716
Binary files /dev/null and b/data/index.wasm differ
index 1c41dc82d29da8f1cb0e262d87b36e3d1675ee7a..2e254e94444efadbbcdd2a9b0dfa6e11d7a88244 100755 (executable)
Binary files a/data/main.wasm and b/data/main.wasm differ
index fee15578077838e56f0c4c691cefa0b8d8cf7dc0..b08a4a17fc0959476b39507345678d5969f14f04 100644 (file)
@@ -9,23 +9,18 @@ import {
        pprint = "lualib.pprint";
 
        build_str = "utils:build_str";
-}
-
-VAL_TYPES = {
-       i32 = "i32",
-       i64 = "i64",
-       f32 = "f32",
-       f64 = "f64"
+       random_str = "utils:random_str";
+       Stack = "utils:Stack";
 }
 
 function parse_valtype(r)
        local val = r:read_byte()
 
        local valtypes_map = {
-               [0x7f] = VAL_TYPES.i32;
-               [0x7E] = VAL_TYPES.i64;
-               [0x7D] = VAL_TYPES.f32;
-               [0x7C] = VAL_TYPES.f64;
+               [0x7f] = "i32";
+               [0x7E] = "i64";
+               [0x7D] = "f32";
+               [0x7C] = "f64";
        }
 
        return valtypes_map[val]
@@ -123,6 +118,10 @@ function parse_instr(r)
                [0x02] = function()
                        local rt = parse_blocktype(r)
                        local instrs = {}
+                       local name = random_str(8)
+
+                       local block = { "block", label = name, rt = rt }
+                       r.label_stack:push(block)
 
                        while true do
                                if r:peek_byte() == 0x0B then
@@ -133,11 +132,18 @@ function parse_instr(r)
                                end
                        end
 
-                       return { "block", rt = rt, instrs = instrs }
+                       r.label_stack:pop()
+
+                       block.instrs = instrs
+                       return block
                end;
                [0x03] = function()
                        local rt = parse_blocktype(r)
                        local instrs = {}
+                       local name = random_str(8)
+
+                       local block = { "loop", label = name, rt = rt }
+                       r.label_stack:push(block)
 
                        while true do
                                if r:peek_byte() == 0x0B then
@@ -148,7 +154,10 @@ function parse_instr(r)
                                end
                        end
 
-                       return { "loop", rt = rt, instrs = instrs }
+                       r.label_stack:pop()
+
+                       block.instrs = instrs
+                       return block
                end;
                [0x04] = function()
                        local rt = parse_blocktype(r)
@@ -394,7 +403,11 @@ function parse_tableidx(r)  return r:read_uint(32) end
 function parse_memidx(r)    return r:read_uint(32) end
 function parse_globalidx(r) return r:read_uint(32) end
 function parse_localidx(r)  return r:read_uint(32) end
-function parse_labelidx(r)  return r:read_uint(32) end
+function parse_labelidx(r)
+       local idx = r:read_uint(32)
+       local block = r.label_stack:at(idx)
+       return { "labelidx", labelidx = idx, block = block }
+end
 
 function parse_section(r, expectN, B)
        if r:peek_byte() ~= expectN then return end
@@ -678,9 +691,10 @@ end
 
 -- Reader util class used for interfacing
 -- with the parse_helper c library
-class "Reader" {
+class "Parser" {
        init = function(self, filename)
                self.wasm_file = parse_helper.open_file(filename)
+               self.label_stack = Stack()
        end;
 
        read_byte = function(self)
@@ -701,14 +715,26 @@ class "Reader" {
        end;
 
        read_float = function(self, N)
+               if N >= 32 then
+                       self:read_byte()
+                       self:read_byte()
+                       self:read_byte()
+                       self:read_byte()
+               end
+               if N >= 64 then
+                       self:read_byte()
+                       self:read_byte()
+                       self:read_byte()
+                       self:read_byte()
+               end
                return 0.0;
        end;
 }
 
 function decompile(filepath)
-       local reader = Reader(filepath)
+       local reader = Parser(filepath)
 
        return parse_module(reader)
 end
 
-return module { decompile; VAL_TYPES = VAL_TYPES }
+return module { decompile }
index 1dc3e36806fc9f197f21c107e21be699194289b8..67be1489c5d1ca87dcdd496740eeb392b8d98f93 100644 (file)
--- a/main.lua
+++ b/main.lua
@@ -3,7 +3,6 @@ require "lualib.oop"
 
 import {
        decompile = "decompile:";
-       VAL_TYPES = "decompile:VAL_TYPES";
 
        Ui = "ui:Ui";
        UiRegion = "ui:UiRegion";
@@ -12,34 +11,45 @@ import {
 
        render_text = "ui:render_text";
 
+       scissor_points = "utils:scissor_points";
        pprint = "lualib.pprint";
 }
 
+TEXT_COLORS = {
+       keyword = { 0.7, 0.7, 1.0 };
+       value = { 0.8, 1.0, 0.8 };
+       text = { 0.9, 0.9, 0.9 };
+       jumppoint = { 1, 0.5, 0.5 };
+
+       header_background = { 0.1, 0.1, 0.1 };
+       background = { 0.15, 0.15, 0.15 };
+}
+
 function build_func_header_text(func, mod)
        local text = {}
 
-       table.insert(text, { text = "[" .. func.funcidx .. "] ", color = { 0, 0, 0 } })
-       table.insert(text, { text = func.name, color = { 0, 0, 1 } })
-       table.insert(text, { text = ": ", color = { 0, 0, 0 } })
+       table.insert(text, { text = "[" .. func.funcidx .. "] ", color =  TEXT_COLORS.text })
+       table.insert(text, { text = func.name, color = TEXT_COLORS.keyword })
+       table.insert(text, { text = ": ", color = TEXT_COLORS.text })
 
        local type_ = func.type_
        for _, t in ipairs(type_.param_types) do
-               table.insert(text, { text = t .. " ", color = { 0, 0, 0 } })
+               table.insert(text, { text = t .. " " })
        end
 
        if #type_.param_types == 0 then
-               table.insert(text, { text = "void ", color = { 0, 0, 0 } })
+               table.insert(text, { text = "void " })
        end
 
-       table.insert(text, { text = "-> ", color = { 0, 0, 0 } })
+       table.insert(text, { text = "-> " })
 
        for _, t in ipairs(type_.result_types) do
-               table.insert(text, { text = t .. " ", color = { 0, 0, 0 } })
+               table.insert(text, { text = t .. " " })
        end
 
 
        if #type_.result_types == 0 then
-               table.insert(text, { text = "void", color = { 0, 0, 0 } })
+               table.insert(text, { text = "void" })
        end
 
        table.insert(text, { newline = true })
@@ -52,22 +62,25 @@ local line = 1
 function add_line_number(textlist, newline)
        if newline == nil then newline = true end
        table.insert(textlist, { newline = newline })
-       table.insert(textlist, { text = ("%4d"):format(line), color = { 0.3, 0.3, 0.3 }, background = { 0.7, 0.7, 0.7 }, post_indent = true })
-       table.insert(textlist, { text = " ", color = { 0, 0, 0 }, post_indent = true })
+       table.insert(textlist, { text = ("%4d"):format(line), color = TEXT_COLORS.text, background = TEXT_COLORS.header_background, post_indent = true })
+       table.insert(textlist, { text = " ", post_indent = true })
        line = line + 1
 end
 
 function instr_to_text(textlist, instr, func, mod)
        if instr[1] == "block" then
-               table.insert(textlist, { text = "block", color = { 1, 0, 0 }, change_indent = 1 })
                for _, ins in ipairs(instr.instrs) do
-                       add_line_number(textlist)
                        instr_to_text(textlist, ins, func, mod)
+                       add_line_number(textlist)
                end
-               table.insert(textlist, { change_indent = -1 })
+               table.insert(textlist, { text = "label ", color = TEXT_COLORS.jumppoint })
+               table.insert(textlist, { text = instr.label, color = TEXT_COLORS.value })
+
 
        elseif instr[1] == "loop" then
-               table.insert(textlist, { text = "loop", color = { 1, 0, 0 }, change_indent = 1 })
+               table.insert(textlist, { text = "loop ", color = TEXT_COLORS.jumppoint })
+               table.insert(textlist, { text = instr.label, color = TEXT_COLORS.value, change_indent = 1 })
+
                for _, ins in ipairs(instr.instrs) do
                        add_line_number(textlist)
                        instr_to_text(textlist, ins, func, mod)
@@ -75,7 +88,7 @@ function instr_to_text(textlist, instr, func, mod)
                table.insert(textlist, { change_indent = -1 })
 
        elseif instr[1] == "if" then
-               table.insert(textlist, { text = "if", color = { 1, 0, 0 }, change_indent = 1 })
+               table.insert(textlist, { text = "if", color = TEXT_COLORS.jumppoint, change_indent = 1 })
                for _, ins in ipairs(instr.instrs) do
                        add_line_number(textlist)
                        instr_to_text(textlist, ins, func, mod)
@@ -84,8 +97,8 @@ function instr_to_text(textlist, instr, func, mod)
 
                if #instr.else_instrs > 0 then
                        add_line_number(textlist)
-                       table.insert(textlist, { text = "else", color = { 1, 0, 0 }, change_indent = 1 })
-                       for _, ins in ipairs(instr.instrs) do
+                       table.insert(textlist, { text = "else", color = TEXT_COLORS.jumppoint, change_indent = 1 })
+                       for _, ins in ipairs(instr.else_instrs) do
                                add_line_number(textlist)
                                instr_to_text(textlist, ins, func, mod)
                        end
@@ -93,25 +106,30 @@ function instr_to_text(textlist, instr, func, mod)
                end
 
        elseif instr[1] == "call" then
-               table.insert(textlist, { text = instr[1] .. " ", color = { 0, 0, 1 } })
-               table.insert(textlist, { text = mod.funcs[instr.x].name, color = { 0, 0.5, 0 } })
+               table.insert(textlist, { text = instr[1] .. " ", color = TEXT_COLORS.keyword })
+               table.insert(textlist, { text = mod.funcs[instr.x].name, color = TEXT_COLORS.value })
 
        elseif instr[1]:match("local") then
-               table.insert(textlist, { text = instr[1] .. " ", color = { 0, 0, 1 } })
-               table.insert(textlist, { text = func.locals[instr.x + 1].name, color = { 0, 0.5, 0 } })
+               table.insert(textlist, { text = instr[1] .. " ", color = TEXT_COLORS.keyword })
+               table.insert(textlist, { text = func.locals[instr.x + 1].name, color = TEXT_COLORS.value })
 
        else
-               table.insert(textlist, { text = instr[1] .. " ", color = { 0, 0, 1 } })
+               table.insert(textlist, { text = instr[1] .. " ", color = TEXT_COLORS.keyword })
                if instr.x then
                        if type(instr.x) == "table" then
                                if instr.x[1] == "memarg" then
                                        table.insert(textlist, {
-                                               text = ("align=0x%03x offset=0x%08x"):format(instr.x.align, instr.x.offset);
-                                               color = { 0, 0.5, 0 }
+                                               text = ("align=0x%02x offset=0x%04x"):format(instr.x.align, instr.x.offset);
+                                               color = TEXT_COLORS.value
                                        })
                                end
+
+                               if instr.x[1] == "labelidx" then
+                                       table.insert(textlist, { text = instr.x.block.label .. " ", color = TEXT_COLORS.value })
+                                       table.insert(textlist, { text = ("[0x%02x]"):format(instr.x.labelidx), color = TEXT_COLORS.text })
+                               end
                        else
-                               table.insert(textlist, { text = tostring(instr.x), color = { 0, 0.5, 0 } })
+                               table.insert(textlist, { text = tostring(instr.x), color = TEXT_COLORS.value })
                        end
                end
        end
@@ -123,25 +141,23 @@ function build_func_body_text(func, mod)
        local text = {}
        line = 1
 
-       table.insert(text, { text = "Locals:", color = { 0, 0, 1 }, newline = true, change_indent = 2 })
+       table.insert(text, { text = " Locals:", color = TEXT_COLORS.keyword, newline = true, change_indent = 2 })
        for _, loc in ipairs(func.locals) do
-               table.insert(text, { text = loc.type_ .. " " .. loc.name, color = { 0, 0, 0 }, newline = true })
+               table.insert(text, { text = loc.type_ .. " " .. loc.name, color = TEXT_COLORS.text , newline = true })
        end
 
        if #func.locals == 0 then
-               table.insert(text, { text = "no locals", color = { 1, 0, 0 }, newline = true })
+               table.insert(text, { text = "no locals", color = TEXT_COLORS.text, newline = true })
        end
 
        table.insert(text, { newline = true, change_indent = -2 })
-       table.insert(text, { text = "Body:", color = { 0, 0, 1 } })
+       table.insert(text, { text = " Body:", color = TEXT_COLORS.keyword })
 
        for _, instr in ipairs(func.body) do
                add_line_number(text)
                instr_to_text(text, instr, func, mod)
        end
 
-       -- table.remove(text, #text)
-
        return text
 end
 
@@ -150,7 +166,14 @@ class "FunctionBlock" [DraggableRect] {
                DraggableRect.init(self, x, y, 400, 400)
 
                self.header_text = build_func_header_text(func, mod)
-               self.body_text = build_func_body_text(func, mod)
+               if func.body then
+                       self.body_text = build_func_body_text(func, mod)
+               else
+                       self.rect.h = 48
+                       self.body_text = {
+                               { text = "imported function", color = TEXT_COLORS.text }
+                       }
+               end
                self.scroll = 0
        end;
 
@@ -162,7 +185,7 @@ class "FunctionBlock" [DraggableRect] {
        ondrag = function(self, button, x, y, dx, dy)
                DraggableRect.ondrag(self, button, x, y, dx, dy)
 
-               if button == 2 then
+               if y >= 24 and button == 2 then
                        self.rect.w = math.max(100, x)
                        self.rect.h = math.max(22, y)
                end
@@ -171,18 +194,18 @@ class "FunctionBlock" [DraggableRect] {
        draw = function(self)
                love.graphics.setColor(0, 0, 0)
                love.graphics.rectangle("fill", 0, 0, self.rect.w, self.rect.h)
-               love.graphics.setColor(1, 1, 1)
+               love.graphics.setColor(self.selected and TEXT_COLORS.background or TEXT_COLORS.header_background)
                love.graphics.rectangle("fill", 2, 2, self.rect.w - 4, self.rect.h - 4)
-               love.graphics.setColor(0.8, 0.8, 0.8)
+               love.graphics.setColor(TEXT_COLORS.header_background)
                love.graphics.rectangle("fill", 2, 2, self.rect.w - 4, 18)
 
-               local sx, sy = love.graphics.transformPoint(0, 0)
-               love.graphics.intersectScissor(sx, sy, self.rect.w, self.rect.h)
+               love.graphics.intersectScissor(scissor_points(0, 0, self.rect.w, self.rect.h))
                local x, y = render_text(2, 2, self.header_text)
 
-               local sx, sy = love.graphics.transformPoint(2, y - 1)
-               love.graphics.intersectScissor(sx, sy, self.rect.w - 4, self.rect.h - 22)
-               render_text(2, y + 4 - self.scroll, self.body_text)
+               if self.body_text then
+                       love.graphics.intersectScissor(scissor_points(2, y - 1, self.rect.w - 4, self.rect.h - 22))
+                       render_text(2, y + 4 - self.scroll, self.body_text)
+               end
        end;
 }
 
@@ -199,22 +222,15 @@ function love.load()
        ui_region.rect.w = 1200
        ui_region.rect.h = 900
        ui_region.background_color = { 0.1, 0.1, 0.1 }
-       ui_region.line_color = { 0.2, 0.2, 0.2 }
-
-       -- ui_region:add_object(DraggableRect(100, 100, 100, 100))
-       -- ui_region:add_object(DraggableRect(200, 100, 100, 100))
-       -- ui_region:add_object(DraggableRect(300, 100, 100, 100))
-       -- ui_region:add_object(DraggableRect(400, 100, 300, 100))
+       ui_region.line_color = { 0.15, 0.15, 0.2 }
 
        local x = 0
        local y = 0
        for _, func in pairs(mod.funcs) do
-               if func.body then
-                       local block = FunctionBlock(func, x, y)
-                       block.order = 600 - y
-                       ui_region:add_object(block)
-                       y = y + 20
-               end
+               local block = FunctionBlock(func, x, y)
+               block.order = 600 - y
+               ui_region:add_object(block)
+               y = y + 20
        end
 
        ui:add_region(ui_region)
diff --git a/ui.lua b/ui.lua
index c9aa2605f6569a8b47e5c4f2b85a67846ea83c79..1d3f1b749e9ed996474cba0019b1a62763dd1ba8 100644 (file)
--- a/ui.lua
+++ b/ui.lua
@@ -2,6 +2,7 @@ import {
        Rectangle = "utils:Rectangle";
        uuid = "utils:uuidv4";
        revipairs = "utils:revipairs";
+       scissor_points = "utils:scissor_points";
 }
 
 class "Ui" {
@@ -93,7 +94,7 @@ class "Ui" {
        draw = function(self)
                for _, region in ipairs(self.regions) do
                        love.graphics.push()
-                       love.graphics.setScissor(region.rect.x, region.rect.y, region.rect.w, region.rect.h)
+                       love.graphics.setScissor(scissor_points(region.rect.x, region.rect.y, region.rect.w, region.rect.h))
                        love.graphics.translate(region.rect.x, region.rect.y)
                        region:draw()
                        love.graphics.pop()
@@ -235,18 +236,34 @@ class "ScrollingUiRegion" [UiRegion] {
        end;
 
        _obj_rect = function(self, obj)
-               return Rectangle(
-                       obj.rect.x + self.offset.x,
-                       obj.rect.y + self.offset.y,
-                       obj.rect.w, obj.rect.h)
+               return obj.rect
+       end;
+
+       _transform_mouse = function(self, x, y)
+               return
+                       ((x + self.rect.x) - self.rect.w / 2) / self.zoom + self.rect.w / 2 - self.offset.x - self.rect.x,
+                       ((y + self.rect.y) - self.rect.h / 2) / self.zoom + self.rect.h / 2 - self.offset.y - self.rect.y
+       end;
+
+       onmousedown = function(self, button, x, y)
+               print(x, y)
+               local mx, my = self:_transform_mouse(x, y)
+               print(mx, my)
+               UiRegion.onmousedown(self, button, mx, my)
+       end;
+
+       onmouseup = function(self, button, x, y)
+               local mx, my = self:_transform_mouse(x, y)
+               UiRegion.onmouseup(self, button, mx, my)
        end;
 
        onmousemove = function(self, x, y, dx, dy)
-               UiRegion.onmousemove(self, x, y, dx, dy)
+               local mx, my = self:_transform_mouse(x, y)
+               UiRegion.onmousemove(self, mx, my, dx / self.zoom, dy / self.zoom)
 
                if self.is_mouse_down and self.selected_object == nil then
-                       self.offset.x = self.offset.x + dx
-                       self.offset.y = self.offset.y + dy
+                       self.offset.x = self.offset.x + dx / self.zoom
+                       self.offset.y = self.offset.y + dy / self.zoom
                end
        end;
 
@@ -256,6 +273,7 @@ class "ScrollingUiRegion" [UiRegion] {
                if self.selected_object == nil then
                        self.zoom = self.zoom * (dy > 0 and 1.05 or (1 / 1.05))
                        if self.zoom >= 1 then self.zoom = 1 end
+                       if self.zoom <= (1 / 1.05) ^ 20 then self.zoom = (1 / 1.05) ^ 20 end
                end
        end;
 
@@ -263,7 +281,7 @@ class "ScrollingUiRegion" [UiRegion] {
                UiRegion.update(self, dt)
 
                if self.active then
-                       local speed = 300
+                       local speed = 300 / self.zoom
                        if love.keyboard.isDown "left" then
                                self.offset.x = self.offset.x + speed * dt
                        end
@@ -289,6 +307,11 @@ class "ScrollingUiRegion" [UiRegion] {
                local tmpbgcolor = self.background_color
                self.background_color = nil
 
+               love.graphics.translate(self.rect.w / 2, self.rect.h / 2)
+               love.graphics.scale(self.zoom, self.zoom)
+               love.graphics.translate(-self.rect.w / 2, -self.rect.h / 2)
+
+
                local xoff = self.offset.x
                local yoff = self.offset.y
                local spacing = 64
@@ -299,11 +322,11 @@ class "ScrollingUiRegion" [UiRegion] {
                while yoff <= -spacing do yoff = yoff + spacing end
 
                love.graphics.setColor(self.line_color)
-               for x = 0, 40 do
-                       love.graphics.line(x * spacing + xoff, 0, x * spacing + xoff, self.rect.h)
+               for x = -40, 80 do
+                       love.graphics.line(x * spacing + xoff, -self.rect.h, x * spacing + xoff, self.rect.h * 2)
                end
-               for y = 0, 40 do
-                       love.graphics.line(0, y * spacing + yoff, self.rect.w, y * spacing + yoff)
+               for y = -40, 80 do
+                       love.graphics.line(-self.rect.w, y * spacing + yoff, self.rect.w * 2, y * spacing + yoff)
                end
 
                love.graphics.translate(self.offset.x, self.offset.y)
@@ -319,7 +342,7 @@ class "UiObject" {
                self.rect = Rectangle(0, 0, 0, 0)
                self.uuid = uuid()
                self.selected = false
-               self.order = math.random(1, 128)
+               self.order = math.random(1, 1024)
        end;
 
        onclick = function(self, button, x, y) end;
@@ -403,7 +426,9 @@ function render_text(x, y, text)
                                love.graphics.rectangle("fill", x, y, programming_font:getWidth(txt.text), fheight + 2);
                        end
 
-                       love.graphics.setColor(txt.color)
+                       if txt.color then
+                               love.graphics.setColor(txt.color)
+                       end
                        love.graphics.print(printed, x, y)
 
                        x = x + programming_font:getWidth(printed)
index ec4b5e02ba36ddf1e47294b7a2c429516cd3f5ea..d5ff4279cf91bd97de6743ead1ac023a3c0f7894 100644 (file)
--- a/utils.lua
+++ b/utils.lua
@@ -49,6 +49,14 @@ function uuidv4()
        end)
 end
 
+function random_str(n)
+       local str = ""
+       for i=1, n do
+               str = str .. string.char(math.random(0,25) + 0x41 + 0x20 * math.random(0, 1))
+       end
+       return str
+end
+
 function revipairs(t)
        local max = 1
        while t[max] ~= nil do
@@ -89,13 +97,41 @@ class "Rectangle" {
        __lt = function(self, other) return self:intersects(other) end
 }
 
+class "Stack" {
+       init = function(self)
+               self.data = {}
+       end;
+
+       push = function(self, it)
+               table.insert(self.data, it)
+       end;
+
+       pop = function(self)
+               local rt = table.remove(self.data)
+               return rt
+       end;
+
+       at = function(self, x)
+               return self.data[#self.data - x]
+       end
+}
+
+function scissor_points(x, y, w, h)
+       local nx, ny = love.graphics.transformPoint(x, y)
+       local tx, ty = love.graphics.transformPoint(w + x, h + y)
+       return nx, ny, tx - nx, ty - ny
+end
+
 return module {
        buffered_read = buffered_read;
        build_str = build_str;
+       random_str = random_str;
 
        uuidv4 = uuidv4;
-
        revipairs = revipairs;
 
+       scissor_points = scissor_points;
+
        Rectangle = Rectangle;
+       Stack = Stack;
 }