Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local systemres = {["GB"] = {160,144},
- ["NES"] = {256, 224}
- }
- local RAMrange = {["GB"] = {0,0xFFFF,0xC000}, -- The allowable range of RAM organized as {min, max, default}.
- ["NES"] = {0,0xFFFF,0}
- }
- local screendims = systemres[emu.getsystemid()] or {256, 240} -- Default to NES dimensions, I guess.
- local range = RAMrange[emu.getsystemid()] or {0,0xFFFF,0xC000}
- range["min"], range["max"], range["default"] = range[1], range[2], range[3]
- local RAMpage = range["default"]
- local state={
- ["RAMwh"]={64, 64}, -- Default width and height of the box displaying our RAM.
- ["RAMposfun"]="ul", -- The function for placing the RAM onscreen.
- ["RAMpos"]={0,0}, -- Where on screen to display the RAM. Default is top-left corner.
- ["messagepos"]={74, 10}, -- Where to display messages/RAM. I'm "cheating" this into the bottom right corner, but its position might not be correct depending on the system.
- ["persist"]=120, -- How long in frames to display messages for.
- ["minwidth"]=2, -- Minimum allowed width of RAM display.
- ["maxwidth"]=128, -- Maximum allowed width of RAM display.
- ["minheight"]=2, -- Minimum allowed height of RAM display.
- ["maxheight"]=128, -- Maximum allowed height of RAM display.
- ["screendims"]=screendims, -- Dimensions of the screen. Set automatically by the game system but defaults to NES resolution. What are the screen dimensions of some other systems?
- ["range"]=range, -- Minimum and maximum allowable range of the RAM in format {low, high, default}. Depends on the system but defaults to Game Boy values.
- ["hashtype"]="prime", -- Current hash function for drawing RAM.
- ["RAMpage"]=RAMpage, -- Where in the RAM the upper-left corner of our RAM display corresponds to. Default comes from range table.
- ["keys"]={}, -- Keys pressed this frame.
- ["last"]={}, -- Keys pressed previous frame.
- ["message"]="", -- The message to be displayed.
- ["countdown"]=0, -- When countdown reaches 0, stop displaying messages.
- ["nprime"]=5000, -- Which prime number to use for prime hash. Default is the 5000th prime.
- ["showcursor"]=false, -- If true, draw the cursor.
- ["numberformat"]="unsigned" -- The number format of displayed RAM values.
- }
- unpack = unpack or table.unpack
- console.clear()
- -- Make prime numbers and create a color lookup table.
- ---[[
- local n = 5000 -- Which prime to use.
- local nmax = 10000 -- How many primes in our table.
- -- Create a hash by computing p^b, where p is prime.
- local function ptob(b,p)
- local hexc=1
- p = p or 503
- for i=1,b do
- hexc = math.fmod(hexc*p, 0x1000000)
- end
- return 0xFF000000 + hexc
- end
- -- Our table of prime numbers.
- local primetable={2}
- do -- Enclosed in a "do" block to clear up k and p for later use, if wanted.
- local k=3
- local p=2
- while p<=nmax do
- local isprime=true
- local ceiling=math.sqrt(k)
- local pp=1
- while primetable[pp]<=ceiling do
- if k/primetable[pp] == math.floor(k/primetable[pp]) then
- isprime=false
- break
- end
- pp=pp+1
- end
- if isprime then
- primetable[p]=k
- p=p+1
- end
- k=k+1
- end
- end
- -- Makes the color table so we can look up the colors on the fly rather than recalculate them every frame.
- local function primehash(p)
- local colort={}
- for i=0,255 do
- colort[i]=ptob(i,p)
- end
- return colort
- end
- -- In case you wish to just make a random hash.
- local function randomhash()
- local colort={}
- for i=0,255 do
- colort[i]=0xFF000000 + math.random(0xFFFFFF)
- end
- return colort
- end
- -- ... Or maybe you want a monochrome view of the RAM to find counters and such.
- local function monochrome()
- local colort={}
- for i=0,255 do
- colort[i]=0xFF000000 + 0x010101*i
- end
- return colort
- end
- local colort = primehash(primetable[n])
- --]]
- state["palette"] = colort
- state["primetable"]=primetable
- -- Turns a relative memory location into {x,y} coordinate vector.
- local function getcoords(b, RAMwh)
- local w = RAMwh[1]
- local x = math.fmod(b,w)
- local y = math.floor(b/w+0.001)
- return {x, y}
- end
- -- Need to edit these four functions to take into account possibility that pos is right or bottom...
- function state:morewidth()
- local w, page, maxwidth, rmax = self.RAMwh[1], self.RAMpage, self.maxwidth, self.range.max
- local delta = self.RAMwh[1]*self.RAMwh[2]
- w = (w<maxwidth and page+2*delta-1<=rmax) and 2*w or w
- self.RAMwh[1]=w
- self[self.RAMposfun](self) -- Have to re-run the RAM positioning function to make sure we're not off the screen.
- self.message=w
- self.countdown=self.persist
- end
- function state:lesswidth()
- local w, minwidth = self.RAMwh[1], self.minwidth
- w = (w/2>minwidth) and math.floor(w/2 + 0.001) or minwidth
- self.RAMwh[1]=w
- self[self.RAMposfun](self)
- self.message=w
- self.countdown=self.persist
- end
- function state:moreheight()
- local h, page, maxheight, rmax = self.RAMwh[2], self.RAMpage, self.maxheight, self.range.max
- local delta = self.RAMwh[1]*self.RAMwh[2]
- h = (h<maxheight and page+2*delta-1<=rmax) and 2*h or h
- self.RAMwh[2]=h
- self[self.RAMposfun](self)
- self.message=h
- self.countdown=self.persist
- end
- function state:lessheight()
- local h, minheight = self.RAMwh[2], self.minheight
- h = (h/2>minheight) and math.floor(h/2 + 0.001) or minheight
- self.RAMwh[2]=h
- self[self.RAMposfun](self)
- self.message=h
- self.countdown=self.persist
- end
- function state:pageforward()
- local page, rmax=self.RAMpage, self.range[2]
- local delta=self.RAMwh[1]*self.RAMwh[2]
- page = (page+2*delta-1 <= rmax) and page+delta or page
- self.RAMpage = page
- self.message = bizstring.hex(page)
- self.countdown=self.persist
- end
- function state:pageback()
- local page, rmin=self.RAMpage, self.range[1]
- local delta=self.RAMwh[1]*self.RAMwh[2]
- page = (page-delta >= rmin) and page-delta or page
- self.RAMpage = page
- self.message = bizstring.hex(page)
- self.countdown=self.persist
- end
- function state:nextprime()
- if self.hashtype == "prime" then
- self.nprime = (self.nprime<#self.primetable) and self.nprime+1 or #self.primetable
- self.message=self.primetable[self.nprime]
- self.countdown=self.persist
- self.palette = primehash(self.message)
- end
- end
- function state:prevprime()
- if self.hashtype == "prime" then
- self.nprime = (self.nprime>1) and self.nprime-1 or 1
- self.message=self.primetable[self.nprime]
- self.countdown=self.persist
- self.palette = primehash(self.message)
- end
- end
- function state:RAMleft()
- self.RAMpos[1]=0
- end
- function state:RAMcenterh()
- local w, c = self.RAMwh[1], math.floor(self.screendims[1]/2 + 0.01)
- self.RAMpos[1] = c - math.floor(w/2 + 0.01)
- end
- function state:RAMright()
- local w, r = self.RAMwh[1], self.screendims[1]
- self.RAMpos[1] = r - w
- end
- function state:RAMtop()
- self.RAMpos[2]=0
- end
- function state:RAMcenterv()
- local h, c = self.RAMwh[2], math.floor(self.screendims[2]/2 + 0.01)
- self.RAMpos[2] = c - math.floor(h/2 + 0.01)
- end
- function state:RAMbottom()
- local h, b = self.RAMwh[2], self.screendims[2]
- self.RAMpos[2] = b - h
- end
- function state:ul()
- self:RAMleft()
- self:RAMtop()
- self.RAMposfun="ul"
- local x=self.RAMpos[1]+self.RAMwh[1]+10
- local y=self.RAMpos[2]+10
- self.messagepos={x,y}
- end
- function state:uc()
- self:RAMcenterh()
- self:RAMtop()
- self.RAMposfun="uc"
- local x=self.RAMpos[1]+self.RAMwh[1]+10
- local y=self.RAMpos[2]+10
- self.messagepos={x,y}
- end
- function state:ur()
- self:RAMright()
- self:RAMtop()
- self.RAMposfun="ur"
- local x=self.RAMpos[1]-50
- local y=self.RAMpos[2]+10
- self.messagepos={x,y}
- end
- function state:cl()
- self:RAMleft()
- self:RAMcenterv()
- self.RAMposfun="cl"
- local x=self.RAMpos[1]+self.RAMwh[1]+10
- local y=self.RAMpos[2]+10
- self.messagepos={x,y}
- end
- function state:cc()
- self:RAMcenterh()
- self:RAMcenterv()
- self.RAMposfun="cc"
- local x=self.RAMpos[1]+self.RAMwh[1]+10
- local y=self.RAMpos[2]+10
- self.messagepos={x,y}
- end
- function state:cr()
- self:RAMright()
- self:RAMcenterv()
- self.RAMposfun="cr"
- local x=self.RAMpos[1]-50
- local y=self.RAMpos[2]+10
- self.messagepos={x,y}
- end
- function state:bl()
- self:RAMleft()
- self:RAMbottom()
- self.RAMposfun="bl"
- local x=self.RAMpos[1]+self.RAMwh[1]+10
- local y=self.RAMpos[2]+10
- self.messagepos={x,y}
- end
- function state:bc()
- self:RAMcenterh()
- self:RAMbottom()
- self.RAMposfun="bc"
- local x=self.RAMpos[1]+self.RAMwh[1]+10
- local y=self.RAMpos[2]+10
- self.messagepos={x,y}
- end
- function state:br()
- self:RAMright()
- self:RAMbottom()
- self.RAMposfun="br"
- local x=self.RAMpos[1]-50
- local y=self.RAMpos[2]+10
- self.messagepos={x,y}
- end
- function state:togglecursor()
- state.showcursor = not(state.showcursor)
- end
- function state:cyclehash()
- local currhashstyle=self.hashtype
- local cycleorder={"prime", "random", "monochrome"}
- local functionorder={makecolortable, randomhash, monochrome}
- local index = 1 -- Default to monochrome, so calling this function switches to prime.
- for k, v in pairs(cycleorder) do
- if currhashstyle==v then
- index=k
- end
- end
- index = math.fmod(index,3)+1
- currhashstyle = cycleorder[index]
- self.hashtype=currhashstyle
- self.message=currhashstyle
- self.countdown=self.persist
- if self.hashtype == "prime" then
- local p = self.primetable[self.nprime]
- self.palette = primehash(p)
- elseif self.hashtype == "random" then
- self.palette = randomhash()
- elseif self.hashtype == "monochrome" then
- self.palette = monochrome()
- end
- end
- function state:cycleformat()
- -- This time done a little more elegantly than cyclehash, using a table directly.
- local formattable = {["unsigned"] = "signed", ["signed"]="hex", ["hex"]="unsigned"}
- self.numberformat = formattable[self.numberformat]
- end
- function state:disp(x, y, val)
- if self.numberformat == "unsigned" then
- gui.pixelText(x, y, val)
- elseif self.numberformat == "signed" then
- if val>127 then
- val=val-256
- end
- gui.pixelText(x, y, val)
- elseif self.numberformat == "hex" then
- gui.pixelText(x, y, bizstring.hex(val))
- end
- end
- state.KFtable = {["RightBracket"]="morewidth",
- ["LeftBracket"]="lesswidth",
- ["KeypadSubtract"]="lessheight",
- ["KeypadAdd"]="moreheight",
- ["PageDown"]="pageforward",
- ["PageUp"]="pageback",
- ["H"]="cyclehash",
- ["M"]="nextprime",
- ["N"]="prevprime",
- ["K"]="togglecursor",
- ["J"]="cycleformat",
- ["Keypad7"]="ul",
- ["Keypad8"]="uc",
- ["Keypad9"]="ur",
- ["Keypad4"]="cl",
- ["Keypad5"]="cc",
- ["Keypad6"]="cr",
- ["Keypad1"]="bl",
- ["Keypad2"]="bc",
- ["Keypad3"]="br"
- }
- function state:KFs()
- for k, v in pairs(self.pressed) do
- local currfunction=self.KFtable[k]
- if currfunction then
- self[currfunction](self)
- end
- end
- end
- function state:update()
- self.keys, self.last = input.get(), self.keys
- self.pressed = {}
- for k,v in pairs(self.keys) do
- self.pressed[k]=not(self.last[k])
- if not(self.pressed[k]) then self.pressed[k]=nil end
- end
- self:KFs()
- end
- function state:draw()
- local x, y=self.RAMpos[1], self.RAMpos[2]
- local w, h=self.RAMwh[1], self.RAMwh[2]
- gui.drawRectangle(x,y,w-1,h-1,"black","black")
- local page, palette = self.RAMpage, self.palette
- for j = 0, h-1 do
- for i = 0, w-1 do
- local b = memory.readbyte(page + j*w + i)
- if not(b==0) then gui.drawPixel(x+i, y+j, palette[b]) end
- end
- end
- end
- -- Draws a cursor over the current mouse position. Only meant for debugging and demonstration purposes.
- function drawcursor(x,y)
- local c="magenta"
- gui.drawLine(x-3,y,x-1,y,c)
- gui.drawLine(x,y-3,x,y-1,c)
- gui.drawLine(x+1,y,x+3,y,c)
- gui.drawLine(x,y+1,x,y+3,c)
- end
- function state:displaymsgs()
- if self.countdown>0 then
- gui.pixelText(self.messagepos[1], self.messagepos[2], self.message)
- self.countdown = self.countdown-1
- end
- local mouse=input.getmouse()
- local x, y = mouse.X, mouse.Y
- if self.showcursor then drawcursor(x,y) end
- local rx, ry = self.RAMpos[1], self.RAMpos[2]
- local w, h = self.RAMwh[1], self.RAMwh[2]
- local page = self.RAMpage
- if x>=rx and x<rx+w and y>=ry and y<ry+h then
- local ax, ay=x-self.RAMpos[1], y-self.RAMpos[2]
- local b = page+ay*w+x
- local val = memory.readbyte(b)
- gui.pixelText(self.messagepos[1], self.messagepos[2]+10, bizstring.hex(b))
- self:disp(self.messagepos[1], self.messagepos[2]+20, val)
- end
- end
- while true do
- state:update()
- state:draw()
- state:displaymsgs()
- emu.frameadvance()
- keys, last = input.get(), keys
- end
Advertisement
Add Comment
Please, Sign In to add comment