Skip to content

Instantly share code, notes, and snippets.

@realmonster
Last active December 25, 2018 19:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save realmonster/e7ceadff746750e795822e0a95f42eb1 to your computer and use it in GitHub Desktop.
Save realmonster/e7ceadff746750e795822e0a95f42eb1 to your computer and use it in GitHub Desktop.
Demolition Man Collision Hud Performance Comparison
-- Demolition Man script for gens/bizhawk for TAS
-- by r57shell
local scrollx = 0
local scrolly = 0
local level = 0
local level_prev = -1
local wblocks = 0
local hblocks = 0
local blocks = nil
local indexes = nil
local cdata = nil
local objs = {}
local ru8,ru16,ru32,rs8,rs16,rs32
local colors = {
[0x40] = 0xFFFFFF99, -- left wall
[0x41] = 0x00FFFF99, -- ground
[0x42] = 0xFFFFFF99, -- right wall
[0x43] = 0x00FF0099, -- wire ground
[0x44] = 0x00990099, -- zip line to the right
[0x45] = 0x00999999, -- right close to climb
[0x46] = 0x0000FF99, -- ladder left
[0x47] = 0x0000FF99, -- ladder right
[0x48] = 0xCCCCCC99, -- climb left
[0x49] = 0xCCCCCC99, -- climb right
[0x4A] = 0x00990099, -- horizontal zip line
[0x4B] = 0x00990099, -- zip line to the left
[0x4C] = 0x00999999, -- left close to climb
[0x4D] = 0x99990099,
[0x4E] = 0xCC00CC99, -- obstacle
[0x4F] = 0x9900FF99, -- ??
[0x50] = 0xFF400099,
[0x52] = 0xFF400099,
[0x56] = 0xFF400099,
[0x58] = 0xFF400099,
[0x5F] = 0xFF400099,
}
local gui_text, gui_box, gui_line, gui_pixel
if gens then
ru8 = memory.readbyteunsigned
ru16 = memory.readwordunsigned
ru32 = memory.readlongunsigned
rs8 = memory.readbytesigned
rs16 = memory.readwordsigned
rs32 = memory.readlongsigned
gui_text, gui_line, gui_pixel = gui.text, gui.line, gui.setpixel
local gb = gui.box
function gui_box(x1, y1, x2, y2, c, o)
gb(x1, y1, x2, y2, o, c)
end
else
ru8 = memory.read_u8
ru16 = memory.read_u16_be
ru32 = memory.read_u32_be
rs8 = memory.read_s8
rs16 = memory.read_s16_be
rs32 = memory.read_s32_be
gui_text = gui.pixelText
gui_box = gui.drawBox
gui_line = gui.drawLine
gui_pixel = gui.drawPixel
for i = 0, 0xFF do
if colors[i] then
colors[i] = bit.band(colors[i],0xFFFFFF00)/0x100+bit.band(colors[i],0xFF)*0x1000000
end
end
end
local max,min,floor = math.max, math.min, math.floor
function drawcollision()
if level > 9 then return end
local offs = 0x1AF924 + level*0x52
wblocks, hblocks = ru16(ru32(offs+3*4)), ru16(ru32(offs+3*4)+2)
local blocks_offs, indexes_offs, ctiles, cdata_offs
= ru32(offs+3*4)+4, ru32(offs+2*4), ru32(offs+5*4), ru32(offs+6*4)
for y = 0, hblocks-1 do
local sy = y*256-scrolly
if sy < 224 and sy+256 > 0 then -- is big block visible by y?
for x = 0, wblocks-1 do
local sx = x*512-scrollx
if sx < 320 and sx+512 > 0 then -- is big block visible by x?
local bs = blocks_offs+(y*wblocks+x)*2
local idx = ru16(bs)
local idx1 = indexes_offs+idx*1024
for yy = 0, 15 do
local sy1 = sy+yy*16
if sy1 < 224 and sy1+16 > 0 then -- is block visible by y?
for xx = 0, 31 do
local sx1 = sx+xx*16
if sx1 < 320 and sx1+16 > 0 then -- is block visible by x?
local idx2 = idx1 + (xx+yy*32)*2
local idx3 = ru16(idx2)
local idx4 = ru8(ctiles+2+idx3)
local cd = cdata_offs + 4 + idx4*256
for xxx = 0, 15 do
for yyy = 0, 15 do
local v = ru8(cd+yyy*16+xxx)
if colors[v] then
gui_pixel(sx1+xxx, sy1+yyy, colors[v])
end
end -- for yyy
end -- for xxx
end -- visibility check xx
end -- for xx
end -- visibility check yy
end -- for yy
end -- visibility check x
end -- for x
end -- visibility check y
end -- for y
end
function drawobjs()
local offs = 0x1AF924+level*0x52
local obj = ru32(ru32(offs+11*4))
local objs_count = ru32(ru32(offs+13*4))
for i = 0, objs_count-1 do
local x = ru16(obj+i*6)
local y = ru16(obj+i*6+2)
if x+16 >= scrollx and x < scrollx+320
and y+16 >= scrolly and y < scrolly+224 then -- is object visible on screen?
local t = ru16(obj+i*6+4)
local f = ru32(0x1FFBAA+t*4)
c = 0x00FF00FF
cc = 0x00FF0000
if f == 0x1AEDAE then
c = 0x0000FFFF
cc = 0x0000FF00
end
if f == 0x1BC85E then
c = 0x00FFFFFF
cc = 0x00FFFF00
end
if f == 0 then
c = 0xFFFFFFFF
cc = 0xFFFFFF00
end
if not gens then
c = bit.band(c,0xFFFFFF00)/0x100+bit.band(c,0xFF)*0x1000000
cc = bit.band(cc,0xFFFFFF00)/0x100+bit.band(cc,0xFF)*0x1000000
end
gui_box(x-scrollx,y-scrolly,x+15-scrollx,y+15-scrolly,c)
gui_text(x+2-scrollx,y+1-scrolly,string.format("%X",t),c)
end
end
end
function render()
level = ru16(0xFF0538)
if level > 9 then return end
local player = ru32(0xFF055A)
local xpos = ru32(player+0x26)
local ypos = ru32(player+0x2A)
local hp = rs16(player+0x3C)
local granades = ru8(player+0xDE)
local granades_count = ru8(player+0xDF)
local w = ru8(player+0xE0)
local ammo = ru8(player+0xE1)
local state = ru16(player+0x4A)
local mapa = ru32(player+0x72)
local mapb = ru32(player+0x76)
if ru32(0x1AF924+level*0x52+5*4) ~= mapa
or ru32(0x1AF924+level*0x52+6*4) ~= mapb then
return
end
local text = string.format("%8X %8X %X %d",xpos,ypos,state,hp)
text = text..string.format("\n%d %d %d %d",granades,granades_count,w,ammo)
gui.text(125,0,text)
scrollx = rs16(0xFF04CC)
scrolly = rs16(0xFF04CE)
drawcollision()
drawobjs()
end
if gens then
gui.register(render)
else
event.onframeend(render)
end
-- Demolition Man script for gens/bizhawk for TAS
-- by r57shell
local scrollx = 0
local scrolly = 0
local level = 0
local level_prev = -1
local wblocks = 0
local hblocks = 0
local blocks = nil
local indexes = nil
local cdata = nil
local objs = {}
local ru8,ru16,ru32,rs8,rs16,rs32
local colors = {
[0x40] = 0xFFFFFF99, -- left wall
[0x41] = 0x00FFFF99, -- ground
[0x42] = 0xFFFFFF99, -- right wall
[0x43] = 0x00FF0099, -- wire ground
[0x44] = 0x00990099, -- zip line to the right
[0x45] = 0x00999999, -- right close to climb
[0x46] = 0x0000FF99, -- ladder left
[0x47] = 0x0000FF99, -- ladder right
[0x48] = 0xCCCCCC99, -- climb left
[0x49] = 0xCCCCCC99, -- climb right
[0x4A] = 0x00990099, -- horizontal zip line
[0x4B] = 0x00990099, -- zip line to the left
[0x4C] = 0x00999999, -- left close to climb
[0x4D] = 0x99990099,
[0x4E] = 0xCC00CC99, -- obstacle
[0x4F] = 0x9900FF99, -- ??
[0x50] = 0xFF400099,
[0x52] = 0xFF400099,
[0x56] = 0xFF400099,
[0x58] = 0xFF400099,
[0x5F] = 0xFF400099,
}
local gui_text, gui_box, gui_line, gui_pixel
if gens then
ru8 = memory.readbyteunsigned
ru16 = memory.readwordunsigned
ru32 = memory.readlongunsigned
rs8 = memory.readbytesigned
rs16 = memory.readwordsigned
rs32 = memory.readlongsigned
gui_text, gui_line, gui_pixel = gui.text, gui.line, gui.setpixel
local gb = gui.box
function gui_box(x1, y1, x2, y2, c, o)
gb(x1, y1, x2, y2, o, c)
end
else
ru8 = memory.read_u8
ru16 = memory.read_u16_be
ru32 = memory.read_u32_be
rs8 = memory.read_s8
rs16 = memory.read_s16_be
rs32 = memory.read_s32_be
gui_text = gui.pixelText
gui_box = gui.drawBox
gui_line = gui.drawLine
gui_pixel = gui.drawPixel
for i = 0, 0xFF do
if colors[i] then
colors[i] = bit.band(colors[i],0xFFFFFF00)/0x100+bit.band(colors[i],0xFF)*0x1000000
end
end
end
local max,min,floor = math.max, math.min, math.floor
function drawcollision()
if level > 9 then return end
local offs = 0x1AF924 + level*0x52
wblocks, hblocks = ru16(ru32(offs+3*4)), ru16(ru32(offs+3*4)+2)
local blocks_offs, indexes_offs, ctiles, cdata_offs
= ru32(offs+3*4)+4, ru32(offs+2*4), ru32(offs+5*4), ru32(offs+6*4)
local left,right,top,bottom = scrollx,scrollx+320,scrolly,scrolly+224
for y = max(0,floor(top/256)), min(hblocks-1,floor((bottom-1)/256)) do
local sy = y*256-scrolly
for x = max(0,floor(left/512)), min(wblocks-1,floor((right-1)/512)) do
local sx = x*512-scrollx
local bs = blocks_offs+(y*wblocks+x)*2
local idx = ru16(bs)
local idx1 = indexes_offs+idx*1024
for yy = max(0,floor((top-y*256)/16)), min(15,floor((bottom-1-y*256)/16)) do
local sy1 = sy+yy*16
for xx = max(0,floor((left-x*512)/16)), min(31,floor((right-1-x*512)/16)) do
local sx1 = sx+xx*16
local idx2 = idx1 + (xx+yy*32)*2
local idx3 = ru16(idx2)
local idx4 = ru8(ctiles+2+idx3)
local cd = cdata_offs + 4 + idx4*256
for xxx = 0, 15 do
for yyy = 0, 15 do
local v = ru8(cd+yyy*16+xxx)
if colors[v] then
gui_pixel(sx1+xxx, sy1+yyy, colors[v])
end
end -- for yyy
end -- for xxx
end -- for xx
end -- for yy
end -- for x
end -- for y
end
function drawobjs()
local offs = 0x1AF924+level*0x52
local obj = ru32(ru32(offs+11*4))
local objs_count = ru32(ru32(offs+13*4))
for i = 0, objs_count-1 do
local x = ru16(obj+i*6)
local y = ru16(obj+i*6+2)
if x+16 >= scrollx and x < scrollx+320
and y+16 >= scrolly and y < scrolly+224 then -- is object visible on screen?
local t = ru16(obj+i*6+4)
local f = ru32(0x1FFBAA+t*4)
c = 0x00FF00FF
cc = 0x00FF0000
if f == 0x1AEDAE then
c = 0x0000FFFF
cc = 0x0000FF00
end
if f == 0x1BC85E then
c = 0x00FFFFFF
cc = 0x00FFFF00
end
if f == 0 then
c = 0xFFFFFFFF
cc = 0xFFFFFF00
end
if not gens then
c = bit.band(c,0xFFFFFF00)/0x100+bit.band(c,0xFF)*0x1000000
cc = bit.band(cc,0xFFFFFF00)/0x100+bit.band(cc,0xFF)*0x1000000
end
gui_box(x-scrollx,y-scrolly,x+15-scrollx,y+15-scrolly,c)
gui_text(x+2-scrollx,y+1-scrolly,string.format("%X",t),c)
end
end
end
function render()
level = ru16(0xFF0538)
if level > 9 then return end
local player = ru32(0xFF055A)
local xpos = ru32(player+0x26)
local ypos = ru32(player+0x2A)
local hp = rs16(player+0x3C)
local granades = ru8(player+0xDE)
local granades_count = ru8(player+0xDF)
local w = ru8(player+0xE0)
local ammo = ru8(player+0xE1)
local state = ru16(player+0x4A)
local mapa = ru32(player+0x72)
local mapb = ru32(player+0x76)
if ru32(0x1AF924+level*0x52+5*4) ~= mapa
or ru32(0x1AF924+level*0x52+6*4) ~= mapb then
return
end
local text = string.format("%8X %8X %X %d",xpos,ypos,state,hp)
text = text..string.format("\n%d %d %d %d",granades,granades_count,w,ammo)
gui.text(125,0,text)
scrollx = rs16(0xFF04CC)
scrolly = rs16(0xFF04CE)
drawcollision()
drawobjs()
end
if gens then
gui.register(render)
else
event.onframeend(render)
end
-- Demolition Man script for gens/bizhawk for TAS
-- by r57shell
local scrollx = 0
local scrolly = 0
local level = 0
local level_prev = -1
local wblocks = 0
local hblocks = 0
local blocks = nil
local indexes = nil
local cdata = nil
local objs = {}
local ru8,ru16,ru32,rs8,rs16,rs32
local colors = {
[0x40] = 0xFFFFFF99, -- left wall
[0x41] = 0x00FFFF99, -- ground
[0x42] = 0xFFFFFF99, -- right wall
[0x43] = 0x00FF0099, -- wire ground
[0x44] = 0x00990099, -- zip line to the right
[0x45] = 0x00999999, -- right close to climb
[0x46] = 0x0000FF99, -- ladder left
[0x47] = 0x0000FF99, -- ladder right
[0x48] = 0xCCCCCC99, -- climb left
[0x49] = 0xCCCCCC99, -- climb right
[0x4A] = 0x00990099, -- horizontal zip line
[0x4B] = 0x00990099, -- zip line to the left
[0x4C] = 0x00999999, -- left close to climb
[0x4D] = 0x99990099,
[0x4E] = 0xCC00CC99, -- obstacle
[0x4F] = 0x9900FF99, -- ??
[0x50] = 0xFF400099,
[0x52] = 0xFF400099,
[0x56] = 0xFF400099,
[0x58] = 0xFF400099,
[0x5F] = 0xFF400099,
}
local gui_text, gui_box, gui_line, gui_pixel
if gens then
ru8 = memory.readbyteunsigned
ru16 = memory.readwordunsigned
ru32 = memory.readlongunsigned
rs8 = memory.readbytesigned
rs16 = memory.readwordsigned
rs32 = memory.readlongsigned
gui_text, gui_line, gui_pixel = gui.text, gui.line, gui.setpixel
local gb = gui.box
function gui_box(x1, y1, x2, y2, c, o)
gb(x1, y1, x2, y2, o, c)
end
else
ru8 = memory.read_u8
ru16 = memory.read_u16_be
ru32 = memory.read_u32_be
rs8 = memory.read_s8
rs16 = memory.read_s16_be
rs32 = memory.read_s32_be
gui_text = gui.pixelText
gui_box = gui.drawBox
gui_line = gui.drawLine
gui_pixel = gui.drawPixel
for i = 0, 0xFF do
if colors[i] then
colors[i] = bit.band(colors[i],0xFFFFFF00)/0x100+bit.band(colors[i],0xFF)*0x1000000
end
end
end
local max,min,floor = math.max, math.min, math.floor
function loadlevel()
level_prev = level
local offs = 0x1AF924+level*0x52
wblocks, hblocks = ru16(ru32(offs+3*4)), ru16(ru32(offs+3*4)+2)
local blocks_offs, indexes_offs, ctiles, cdata_offs
= ru32(offs+3*4)+4, ru32(offs+2*4), ru32(offs+5*4), ru32(offs+6*4)
blocks = {}
indexes = {}
cdata = {}
for y = 0, hblocks-1 do
blocks[y] = {}
for x = 0, wblocks-1 do
local bs = blocks_offs+(y*wblocks+x)*2
local idx = ru16(bs)
blocks[y][x] = idx
if indexes[idx] == nil then
local t = {}
local idx1 = indexes_offs+idx*1024
for yy = 0, 15 do
t[yy] = {}
for xx = 0, 31 do
local idx2 = idx1 + (xx+yy*32)*2
local idx3 = ru16(idx2)
local idx4 = ru8(ctiles+2+idx3)
t[yy][xx] = idx4
if cdata[idx4] == nil then
local cd = cdata_offs + 4 + idx4*256
local ts = {}
for xxx = 0, 15 do
local col = {}
for yyy = 0, 15 do
local v = ru8(cd+yyy*16+xxx)
col[yyy+1] = colors[v]
end
ts[xxx+1] = col
end
cdata[idx4] = ts
end -- if
end -- for xx
end -- for yy
indexes[idx] = t
end -- if
end
end
local obj = ru32(ru32(offs+11*4))
local objs_count = ru32(ru32(offs+13*4))
objs = {}
for i = 0, objs_count-1 do
local x = ru16(obj+i*6)
local y = ru16(obj+i*6+2)
local t = ru16(obj+i*6+4)
local f = ru32(0x1FFBAA+t*4)
c = 0x00FF00FF
cc = 0x00FF0000
if f == 0x1AEDAE then
c = 0x0000FFFF
cc = 0x0000FF00
end
if f == 0x1BC85E then
c = 0x00FFFFFF
cc = 0x00FFFF00
end
if f == 0 then
c = 0xFFFFFFFF
cc = 0xFFFFFF00
end
if not gens then
c = bit.band(c,0xFFFFFF00)/0x100+bit.band(c,0xFF)*0x1000000
cc = bit.band(cc,0xFFFFFF00)/0x100+bit.band(cc,0xFF)*0x1000000
end
objs[i+1] = {x,y,string.format("%X",t),c,cc}
end
end
function drawcollision()
if level > 9 then return end
if level_prev ~= level then
loadlevel()
end
local left,right,top,bottom = scrollx,scrollx+320,scrolly,scrolly+224
for y = max(0,floor(top/256)), min(hblocks-1,floor((bottom-1)/256)) do
for x = max(0,floor(left/512)), min(wblocks-1,floor((right-1)/512)) do
local idx = blocks[y][x]
for yy = max(0,floor((top-y*256)/16)), min(15,floor((bottom-1-y*256)/16)) do
for xx = max(0,floor((left-x*512)/16)), min(31,floor((right-1-x*512)/16)) do
local idx1 = indexes[idx][yy][xx]
local sx = x*512+xx*16-scrollx-1
local sy = y*256+yy*16-scrolly-1
local cd = cdata[idx1]
for xxx = 1, 16 do
local xd = cd[xxx]
for yyy = 1, 16 do
if xd[yyy] then
gui_pixel(sx+xxx, sy+yyy, xd[yyy])
end
end
end
end
end
end
end
end
function drawobjs()
for i = 1, #objs do
local x,y,t,c,cc = unpack(objs[i])
if x+16 >= scrollx and x < scrollx+320
and y+16 >= scrolly and y < scrolly+224 then
gui_box(x-scrollx,y-scrolly,x+15-scrollx,y+15-scrolly,c)
gui_text(x+2-scrollx,y+1-scrolly,t,c)
end
end
end
function render()
level = ru16(0xFF0538)
if level > 9 then return end
local player = ru32(0xFF055A)
local xpos = ru32(player+0x26)
local ypos = ru32(player+0x2A)
local hp = rs16(player+0x3C)
local granades = ru8(player+0xDE)
local granades_count = ru8(player+0xDF)
local w = ru8(player+0xE0)
local ammo = ru8(player+0xE1)
local state = ru16(player+0x4A)
local mapa = ru32(player+0x72)
local mapb = ru32(player+0x76)
if ru32(0x1AF924+level*0x52+5*4) ~= mapa
or ru32(0x1AF924+level*0x52+6*4) ~= mapb then
return
end
local text = string.format("%8X %8X %X %d",xpos,ypos,state,hp)
text = text..string.format("\n%d %d %d %d",granades,granades_count,w,ammo)
gui.text(125,0,text)
scrollx = rs16(0xFF04CC)
scrolly = rs16(0xFF04CE)
drawcollision()
drawobjs()
end
if gens then
gui.register(render)
else
event.onframeend(render)
end
-- Demolition Man script for gens/bizhawk for TAS
-- by r57shell
local scrollx = 0
local scrolly = 0
local level = 0
local level_prev = -1
local wblocks = 0
local hblocks = 0
local blocks = nil
local indexes = nil
local cdata = nil
local objs = {}
local ru8,ru16,ru32,rs8,rs16,rs32
local colors = {
[0x40] = 0xFFFFFF99, -- left wall
[0x41] = 0x00FFFF99, -- ground
[0x42] = 0xFFFFFF99, -- right wall
[0x43] = 0x00FF0099, -- wire ground
[0x44] = 0x00990099, -- zip line to the right
[0x45] = 0x00999999, -- right close to climb
[0x46] = 0x0000FF99, -- ladder left
[0x47] = 0x0000FF99, -- ladder right
[0x48] = 0xCCCCCC99, -- climb left
[0x49] = 0xCCCCCC99, -- climb right
[0x4A] = 0x00990099, -- horizontal zip line
[0x4B] = 0x00990099, -- zip line to the left
[0x4C] = 0x00999999, -- left close to climb
[0x4D] = 0x99990099,
[0x4E] = 0xCC00CC99, -- obstacle
[0x4F] = 0x9900FF99, -- ??
[0x50] = 0xFF400099,
[0x52] = 0xFF400099,
[0x56] = 0xFF400099,
[0x58] = 0xFF400099,
[0x5F] = 0xFF400099,
}
local gui_text, gui_box, gui_line, gui_pixel
if gens then
ru8 = memory.readbyteunsigned
ru16 = memory.readwordunsigned
ru32 = memory.readlongunsigned
rs8 = memory.readbytesigned
rs16 = memory.readwordsigned
rs32 = memory.readlongsigned
gui_text, gui_line, gui_pixel = gui.text, gui.line, gui.setpixel
local gb = gui.box
function gui_box(x1, y1, x2, y2, c, o)
gb(x1, y1, x2, y2, o, c)
end
else
ru8 = memory.read_u8
ru16 = memory.read_u16_be
ru32 = memory.read_u32_be
rs8 = memory.read_s8
rs16 = memory.read_s16_be
rs32 = memory.read_s32_be
gui_text = gui.pixelText
gui_box = gui.drawBox
gui_line = gui.drawLine
gui_pixel = gui.drawPixel
for i = 0, 0xFF do
if colors[i] then
colors[i] = bit.band(colors[i],0xFFFFFF00)/0x100+bit.band(colors[i],0xFF)*0x1000000
end
end
end
local max,min,floor = math.max, math.min, math.floor
function loadlevel()
level_prev = level
local offs = 0x1AF924+level*0x52
wblocks, hblocks = ru16(ru32(offs+3*4)), ru16(ru32(offs+3*4)+2)
local blocks_offs, indexes_offs, ctiles, cdata_offs
= ru32(offs+3*4)+4, ru32(offs+2*4), ru32(offs+5*4), ru32(offs+6*4)
blocks = {}
indexes = {}
cdata = {}
for y = 0, hblocks-1 do
blocks[y] = {}
for x = 0, wblocks-1 do
local bs = blocks_offs+(y*wblocks+x)*2
local idx = ru16(bs)
blocks[y][x] = idx
if indexes[idx] == nil then
local t = {}
local idx1 = indexes_offs+idx*1024
for yy = 0, 15 do
t[yy] = {}
for xx = 0, 31 do
local idx2 = idx1 + (xx+yy*32)*2
local idx3 = ru16(idx2)
local idx4 = ru8(ctiles+2+idx3)
t[yy][xx] = idx4
if cdata[idx4] == nil then
local cd = cdata_offs + 4 + idx4*256
local ts = {}
local def = colors[ru8(cd)] -- make default
local same = true
for xxx = 0, 15 do
local col = {}
for yyy = 0, 15 do
local v = ru8(cd+yyy*16+xxx)
col[yyy+1] = colors[v]
if colors[v] ~= def then
same = false
end
end
ts[xxx+1] = col
end
if same then
if def == nil then def = false end
cdata[idx4] = def
else
cdata[idx4] = ts
end
end -- if
end -- for xx
end -- for yy
indexes[idx] = t
end -- if
end
end
local obj = ru32(ru32(offs+11*4))
local objs_count = ru32(ru32(offs+13*4))
objs = {}
for i = 0, objs_count-1 do
local x = ru16(obj+i*6)
local y = ru16(obj+i*6+2)
local t = ru16(obj+i*6+4)
local f = ru32(0x1FFBAA+t*4)
c = 0x00FF00FF
cc = 0x00FF0000
if f == 0x1AEDAE then
c = 0x0000FFFF
cc = 0x0000FF00
end
if f == 0x1BC85E then
c = 0x00FFFFFF
cc = 0x00FFFF00
end
if f == 0 then
c = 0xFFFFFFFF
cc = 0xFFFFFF00
end
if not gens then
c = bit.band(c,0xFFFFFF00)/0x100+bit.band(c,0xFF)*0x1000000
cc = bit.band(cc,0xFFFFFF00)/0x100+bit.band(cc,0xFF)*0x1000000
end
objs[i+1] = {x,y,string.format("%X",t),c,cc}
end
end
function drawcollision()
if level > 9 then return end
if level_prev ~= level then
loadlevel()
end
local left,right,top,bottom = scrollx,scrollx+320,scrolly,scrolly+224
for y = max(0,floor(top/256)), min(hblocks-1,floor((bottom-1)/256)) do
for x = max(0,floor(left/512)), min(wblocks-1,floor((right-1)/512)) do
local idx = blocks[y][x]
for yy = max(0,floor((top-y*256)/16)), min(15,floor((bottom-1-y*256)/16)) do
for xx = max(0,floor((left-x*512)/16)), min(31,floor((right-1-x*512)/16)) do
local idx1 = indexes[idx][yy][xx]
local cd = cdata[idx1]
if cd then
local sx = x*512+xx*16-scrollx-1
local sy = y*256+yy*16-scrolly-1
if type(cd) == "table" then
for xxx = 1, 16 do
local xd = cd[xxx]
for yyy = 1, 16 do
if xd[yyy] then
gui_pixel(sx+xxx, sy+yyy, xd[yyy])
end
end
end
else
gui_box(sx+1,sy+1,sx+16,sy+16,cd,cd)
end
end
end
end
end
end
end
function drawobjs()
for i = 1, #objs do
local x,y,t,c,cc = unpack(objs[i])
if x+16 >= scrollx and x < scrollx+320
and y+16 >= scrolly and y < scrolly+224 then
gui_box(x-scrollx,y-scrolly,x+15-scrollx,y+15-scrolly,c)
gui_text(x+2-scrollx,y+1-scrolly,t,c)
end
end
end
function render()
level = ru16(0xFF0538)
if level > 9 then return end
local player = ru32(0xFF055A)
local xpos = ru32(player+0x26)
local ypos = ru32(player+0x2A)
local hp = rs16(player+0x3C)
local granades = ru8(player+0xDE)
local granades_count = ru8(player+0xDF)
local w = ru8(player+0xE0)
local ammo = ru8(player+0xE1)
local state = ru16(player+0x4A)
local mapa = ru32(player+0x72)
local mapb = ru32(player+0x76)
if ru32(0x1AF924+level*0x52+5*4) ~= mapa
or ru32(0x1AF924+level*0x52+6*4) ~= mapb then
return
end
local text = string.format("%8X %8X %X %d",xpos,ypos,state,hp)
text = text..string.format("\n%d %d %d %d",granades,granades_count,w,ammo)
gui.text(125,0,text)
scrollx = rs16(0xFF04CC)
scrolly = rs16(0xFF04CE)
drawcollision()
drawobjs()
end
if gens then
gui.register(render)
else
event.onframeend(render)
end
-- Demolition Man script for gens/bizhawk for TAS
-- by r57shell
local scrollx = 0
local scrolly = 0
local level = 0
local level_prev = -1
local wblocks = 0
local hblocks = 0
local blocks = nil
local indexes = nil
local cdata = nil
local objs = {}
local ru8,ru16,ru32,rs8,rs16,rs32
local colors = {
[0x40] = 0xFFFFFF99, -- left wall
[0x41] = 0x00FFFF99, -- ground
[0x42] = 0xFFFFFF99, -- right wall
[0x43] = 0x00FF0099, -- wire ground
[0x44] = 0x00990099, -- zip line to the right
[0x45] = 0x00999999, -- right close to climb
[0x46] = 0x0000FF99, -- ladder left
[0x47] = 0x0000FF99, -- ladder right
[0x48] = 0xCCCCCC99, -- climb left
[0x49] = 0xCCCCCC99, -- climb right
[0x4A] = 0x00990099, -- horizontal zip line
[0x4B] = 0x00990099, -- zip line to the left
[0x4C] = 0x00999999, -- left close to climb
[0x4D] = 0x99990099,
[0x4E] = 0xCC00CC99, -- obstacle
[0x4F] = 0x9900FF99, -- ??
[0x50] = 0xFF400099,
[0x52] = 0xFF400099,
[0x56] = 0xFF400099,
[0x58] = 0xFF400099,
[0x5F] = 0xFF400099,
}
local gui_text, gui_box, gui_line, gui_pixel
if gens then
ru8 = memory.readbyteunsigned
ru16 = memory.readwordunsigned
ru32 = memory.readlongunsigned
rs8 = memory.readbytesigned
rs16 = memory.readwordsigned
rs32 = memory.readlongsigned
gui_text, gui_line, gui_pixel = gui.text, gui.line, gui.setpixel
local gb = gui.box
function gui_box(x1, y1, x2, y2, c, o)
gb(x1, y1, x2, y2, o, c)
end
else
ru8 = memory.read_u8
ru16 = memory.read_u16_be
ru32 = memory.read_u32_be
rs8 = memory.read_s8
rs16 = memory.read_s16_be
rs32 = memory.read_s32_be
gui_text = gui.pixelText
gui_box = gui.drawBox
gui_line = gui.drawLine
gui_pixel = gui.drawPixel
for i = 0, 0xFF do
if colors[i] then
colors[i] = bit.band(colors[i],0xFFFFFF00)/0x100+bit.band(colors[i],0xFF)*0x1000000
end
end
end
local max,min,floor = math.max, math.min, math.floor
gui_pixel_, gui_box_, gui_line_ = gui_pixel, gui_box, gui_line
local func_chunk =
[[local gui_box, gui_line, gui_pixel = gui_box_, gui_line_, gui_pixel_
return function (x,y)
]]
-- splits tile into axis aligned rectangles of same color
-- w - width, h - height, data - actual tile colors. nil ignored.
-- returns list of rectangles.
-- all rectangles defined by: type, x1, y1, x2, y2, color
-- type is rectangle color, type should be ignored
-- x1, y1 - minimum x, y inclusive
-- x2, y2 - maximum x, y inclusive
function tile_split_simple(data, w, h)
local arr = {}
for x = 0, w-1 do
for y = 0, h-1 do
local v = data[y*w+x]
if v then
local t,x1,y1,x2,y2,z = unpack(arr[#arr] or {})
if z == v
and t < 2
and x2 == x
and y2 == y-1 then
arr[#arr][1] = 1
arr[#arr][5] = y
local tt,xx1,yy1,xx2,yy2,zz = unpack(arr[#arr-1] or {})
if (tt == 1 or tt == 2)
and zz == z
and yy1 == y1
and yy2 == y
and xx2 == x-1 then
arr[#arr] = nil
arr[#arr][1] = 2
arr[#arr][4] = x
end
else
arr[#arr+1] = {0,x,y,x,y,v}
end
end
end
end
return arr
end
-- flips tile data and splitter list vertically
function tile_splitter_vflip(data, w, h, list)
n = {}
for y = 0, h-1 do
for x = 0, w-1 do
n[(h-1-y)*w+x] = data[y*w+x]
end
end
for i = 1, #list do
local a = list[i]
a[3], a[5] = h-1-a[5], h-1-a[3]
end
return n
end
-- flips tile data and splitter list diagonally
function tile_splitter_dflip(data, w, h, list)
n = {}
for y = 0, h-1 do
for x = 0, w-1 do
n[x*h+y] = data[y*w+x]
end
end
for i = 1, #list do
local a = list[i]
a[2], a[3], a[4], a[5] = a[3], a[2], a[5], a[4]
end
return n
end
-- adds pixel to the tile
function tile_splitter_add(self, x, y, color)
if color then
table.insert(self, x)
table.insert(self, y)
table.insert(self, color)
end
end
function tile_splitter_split(self)
if #self < 3 then return {} end
-- find bound box
local minx, maxx, miny, maxy = self[1], self[1], self[2], self[2]
for i = 4, #self, 3 do
local x, y = unpack(self, i, i+1)
minx = min(minx, x)
maxx = max(maxx, x)
miny = min(miny, y)
maxy = max(maxy, y)
end
-- crop bounding box
maxx = maxx + 1
maxy = maxy + 1
local w, h = maxx-minx, maxy-miny
data = {}
for i = 1, #self, 3 do
local x, y, color = unpack(self, i, i+2)
data[(y-miny)*w+(x-minx)] = color
end
-- try all scan orders and pick the best
local best = nil
for i = 1, 4 do
local list = tile_split_simple(data, w, h)
if best == nil or #list < #best then
best = list
end
data = tile_splitter_vflip(data, w, h, best)
list = tile_split_simple(data, w, h)
if best == nil or #list < #best then
best = list
end
data = tile_splitter_dflip(data, w, h, best)
w, h = h, w -- swap w, h because we flipped it diagonaly
end
-- shift it back to original position
for i = 1, #best do
best[i][2] = best[i][2] + minx
best[i][3] = best[i][3] + miny
best[i][4] = best[i][4] + minx
best[i][5] = best[i][5] + miny
end
return best
end
tile_splitter_metatable = {
__index = {
add = tile_splitter_add,
split = tile_splitter_split,
},
}
function tile_splitter()
local self = {}
setmetatable(self, tile_splitter_metatable)
return self
end
-- converts list returned by splitter into function code.
function tile_generator(arr)
f = ""
for i = 1, #arr do
local t,x1,y1,x2,y2,z = unpack(arr[i])
if x1 == x2 and y1 == y2 then
f = f.."gui_pixel(x+"..x2..",y+"..y2..","..z..")\n"
elseif x1 == x2 or y1 == y2 then
f = f.."gui_line(x+"..x1..",y+"..y1..
",x+"..x2..",y+"..y2..","..z..")\n"
else
f = f.."gui_box(x+"..x1..",y+"..y1..
",x+"..x2..",y+"..y2..","..z..","..z..")\n"
end
end
return f
end
function loadlevel()
level_prev = level
local offs = 0x1AF924+level*0x52
wblocks, hblocks = ru16(ru32(offs+3*4)), ru16(ru32(offs+3*4)+2)
local blocks_offs, indexes_offs, ctiles, cdata_offs
= ru32(offs+3*4)+4, ru32(offs+2*4), ru32(offs+5*4), ru32(offs+6*4)
blocks = {}
indexes = {}
cdata = {}
for y = 0, hblocks-1 do
blocks[y] = {}
for x = 0, wblocks-1 do
local bs = blocks_offs+(y*wblocks+x)*2
local idx = ru16(bs)
blocks[y][x] = idx
if indexes[idx] == nil then
local t = {}
local idx1 = indexes_offs+idx*1024
for yy = 0, 15 do
t[yy] = {}
for xx = 0, 31 do
local idx2 = idx1 + (xx+yy*32)*2
local idx3 = ru16(idx2)
local idx4 = ru8(ctiles+2+idx3)
t[yy][xx] = idx4
if cdata[idx4] == nil then
local cd = cdata_offs + 4 + idx4*256
local ts = tile_splitter()
for xxx = 0, 15 do
for yyy = 0, 15 do
local v = ru8(cd+yyy*16+xxx)
ts:add(xxx, yyy, colors[v])
end
end
local arr = ts:split()
local f = tile_generator(arr)
f = func_chunk..f.."end"
cdata[idx4] = loadstring(f)()
end -- if
end -- for xx
end -- for yy
indexes[idx] = t
end -- if
end
end
local obj = ru32(ru32(offs+11*4))
local objs_count = ru32(ru32(offs+13*4))
objs = {}
for i = 0, objs_count-1 do
local x = ru16(obj+i*6)
local y = ru16(obj+i*6+2)
local t = ru16(obj+i*6+4)
local f = ru32(0x1FFBAA+t*4)
c = 0x00FF00FF
cc = 0x00FF0000
if f == 0x1AEDAE then
c = 0x0000FFFF
cc = 0x0000FF00
end
if f == 0x1BC85E then
c = 0x00FFFFFF
cc = 0x00FFFF00
end
if f == 0 then
c = 0xFFFFFFFF
cc = 0xFFFFFF00
end
if not gens then
c = bit.band(c,0xFFFFFF00)/0x100+bit.band(c,0xFF)*0x1000000
cc = bit.band(cc,0xFFFFFF00)/0x100+bit.band(cc,0xFF)*0x1000000
end
objs[i+1] = {x,y,string.format("%X",t),c,cc}
end
end
function drawcollision()
if level > 9 then return end
if level_prev ~= level then
loadlevel()
end
local left,right,top,bottom = scrollx,scrollx+320,scrolly,scrolly+224
for y = max(0,floor(top/256)), min(hblocks-1,floor((bottom-1)/256)) do
for x = max(0,floor(left/512)), min(wblocks-1,floor((right-1)/512)) do
local idx = blocks[y][x]
for yy = max(0,floor((top-y*256)/16)), min(15,floor((bottom-1-y*256)/16)) do
for xx = max(0,floor((left-x*512)/16)), min(31,floor((right-1-x*512)/16)) do
local idx1 = indexes[idx][yy][xx]
cdata[idx1](x*512+xx*16-scrollx,y*256+yy*16-scrolly)
end
end
end
end
end
function drawobjs()
for i = 1, #objs do
local x,y,t,c,cc = unpack(objs[i])
if x+16 >= scrollx and x < scrollx+320
and y+16 >= scrolly and y < scrolly+224 then
gui_box(x-scrollx,y-scrolly,x+15-scrollx,y+15-scrolly,c)
gui_text(x+2-scrollx,y+1-scrolly,t,c)
end
end
end
function render()
level = ru16(0xFF0538)
if level > 9 then return end
local player = ru32(0xFF055A)
local xpos = ru32(player+0x26)
local ypos = ru32(player+0x2A)
local hp = rs16(player+0x3C)
local granades = ru8(player+0xDE)
local granades_count = ru8(player+0xDF)
local w = ru8(player+0xE0)
local ammo = ru8(player+0xE1)
local state = ru16(player+0x4A)
local mapa = ru32(player+0x72)
local mapb = ru32(player+0x76)
if ru32(0x1AF924+level*0x52+5*4) ~= mapa
or ru32(0x1AF924+level*0x52+6*4) ~= mapb then
return
end
local text = string.format("%8X %8X %X %d",xpos,ypos,state,hp)
text = text..string.format("\n%d %d %d %d",granades,granades_count,w,ammo)
gui.text(125,0,text)
scrollx = rs16(0xFF04CC)
scrolly = rs16(0xFF04CE)
drawcollision()
drawobjs()
end
if gens then
gui.register(render)
else
event.onframeend(render)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment