From: Brendan Hansen Date: Sun, 1 Mar 2020 06:19:53 +0000 (-0600) Subject: cleaner ui and code X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=201dc74d83107affa8694899bab1dec5b7c1dffa;p=wasm-analyzer.git cleaner ui and code --- diff --git a/data/index.wasm b/data/index.wasm new file mode 100755 index 0000000..c135716 Binary files /dev/null and b/data/index.wasm differ diff --git a/data/main.wasm b/data/main.wasm index 1c41dc8..2e254e9 100755 Binary files a/data/main.wasm and b/data/main.wasm differ diff --git a/decompile.lua b/decompile.lua index fee1557..b08a4a1 100644 --- a/decompile.lua +++ b/decompile.lua @@ -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 } diff --git a/main.lua b/main.lua index 1dc3e36..67be148 100644 --- 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 c9aa260..1d3f1b7 100644 --- 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) diff --git a/utils.lua b/utils.lua index ec4b5e0..d5ff427 100644 --- 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; }