User File #51685216242376410

Upload All User Files

#51685216242376410 - Donald Land block-map script

Donald_Land_RAM_blockmap.lua
Game: Donald Land ( NES, see all files )
500 downloads
Uploaded 12/6/2018 3:23 PM by Warepire (see all 18)
fantastic 4 DTC7 script.
-- HOWTO:
-- For the level you want to highlight specific IDs
-- Create a line like this:
-- interesting_blocks[<level>] = { <block>[, <block>, ...] }
-- e.g.
-- interesting_blocks[2] = { 0x79, 0x1b }
local interesting_blocks = {}
interesting_blocks[1] = { 0x47, 0x1b }
interesting_blocks[2] = { 0x79, 0x1b }
interesting_blocks[3] = { 0x79, 0x1b }
interesting_blocks[4] = { 0x79 }
interesting_blocks[5] = { 0x38 }

-- HACKY: Emulator detection, global because a deeper namespace can't read
--				from a shallower namespace?
is_fceux = nil
if FCEU ~= nil then	 -- FCEU unique module, not available on BizHawk
	is_fceux = true
else
	is_fceux = false
end
local EAL = {}
do
	local mem = nil
	local ROM = nil
	local GUI = nil
end
-- EAL Memory namespace functions
EAL.mem = {}
do
	function EAL.mem.read_u8(addr)
		if is_fceux then
			return memory.readbyte(addr)
		else
			return memory.read_u8(addr)
		end
	end
	function EAL.mem.read_s8(addr)
		if is_fceux then
			return memory.readbytesigned(addr)
		else
			return memory.read_s8(addr)
		end
	end
	function EAL.mem.read_u16_be(addr)
		if is_fceux then
			return memory.readword(addr + 1, addr)
		else
			return memory.read_u16_be(addr)
		end
	end
	function EAL.mem.read_s16_be(addr)
		if is_fceux then
			return memory.readwordsigned(addr + 1, addr)
		else
			return memory.read_s16_be(addr)
		end
	end
	function EAL.mem.read_s16_be_scatter(hi, lo)
		if is_fceux then
			return memory.readwordsigned(lo, hi)
		else
			local val = memory.read_u8(hi)
			val = bit.lshift(val, 8)
			val = bit.bor(val, memory.read_u8(lo))
			if val > 0x7FFF then
				return val - 0x10000
			else
				return val
			end
		end
	end
	function EAL.mem.read_u16_le(addr)
		if is_fceux then
			return memory.readword(addr)
		else
			return memory.read_u16_le(addr)
		end
	end
end
EAL.ROM = {}
do
	-- `addr` is the address as seen from the system bus
	local function get_addr_in_bank(bank, addr)
		local bank_addr = addr - 0x8000
		if addr > 0xC000 then -- high region
			bank_addr = bank_addr - 0x4000
		end
		return bank_addr
	end
	-- `addr` is the address as seen from the system bus
	local function get_offset_in_prg(bank, addr)
		local bank_addr = get_addr_in_bank(bank, addr)
		local offset = (bank * 0x4000) + bank_addr
		return offset
	end
	-- Usage note: `addr` is the address as seen from the system bus
	function EAL.ROM.read_u8(bank, addr)
		local offset = get_offset_in_prg(bank, addr)
		if is_fceux then
			offset = offset + 16 -- FCEUX includes the header
			return rom.readbyte(offset)
		else
			return memory.read_u8(offset, "PRG ROM")
		end
	end

	-- Usage note: `addr` is the address as seen from the system bus
	function EAL.ROM.read_u16_be(bank, addr)
		local offset = get_offset_in_prg(bank, addr)
		if is_fceux then
			offset = offset + 16 -- FCEUX includes the header
			local val = rom.readbyteunsigned(offset)
			val = bit.lshift(val, 8)
			val = bit.bor(val, rom.readbyteunsigned(offset + 1))
			return val
		else
			return memory.read_u16_be(offset, "PRG ROM")
		end
	end

	function EAL.ROM.read_u16_le(bank, addr)
		local offset = get_offset_in_prg(bank, addr)
		if is_fceux then
			offset = offset + 16 -- FCEUX includes the header
			local val = rom.readbyteunsigned(offset + 1)
			val = bit.lshift(val, 8)
			val = bit.bor(val, rom.readbyteunsigned(offset))
			return val
		else
			return memory.read_u16_le(offset, "PRG ROM")
		end
	end
end
EAL.GUI = {}
do
	function EAL.GUI.box(x1, x2, y1, y2)
		if is_fceux then
			gui.box(x1, y1, x2, y2)
		else
			gui.drawBox(x1, y1, x2, y2)
		end

	end
end

function get_screen_x_coordinate()
	return EAL.mem.read_u16_le(0x00CC)
end

function get_level_info()
	local level = EAL.mem.read_u8(0x0051)
	local section = EAL.mem.read_u8(0x0052)
	return level, section
end

function get_block_id_addr(level)
	local bank = 7
	local lvl_bank = EAL.ROM.read_u8(bank, 0xC5AD + level)
	local offset_table_addr = EAL.ROM.read_u16_le(bank, 0xD102 + (level * 2)) + 3
	local data_table_addr = EAL.ROM.read_u16_le(bank, 0xCD9F + (level * 2))

	return lvl_bank, offset_table_addr, data_table_addr
end

function get_column_addr(x_pos)
	local ram_bank = math.floor(x_pos / 256) % 2
	local ram_start = 0x240
	if (ram_bank == 1) then
		ram_start = 0x330
	end

	return ram_start + math.floor((x_pos % 256) / 16)
end

function draw_block_id_map(screenx)
	local level, section = get_level_info()

	if interesting_blocks[level] == nil then
		return
	end

	local x_steps = 17
	local x_offset = -(screenx % 16)

	if (screenx % 16 == 0) then
		x_steps = 16
		x_offset = 0
	end

	for i=0,x_steps do
		local desired_screen_x = screenx + (i * 16)
		local column_addr = get_column_addr(desired_screen_x)

		for y=0,13 do
			local block_addr = column_addr + (y * 16)

			local id = EAL.mem.read_u8(block_addr)
			for k,v in ipairs(interesting_blocks[level]) do
				if id == v then
					local box_x = x_offset + (i * 16)
					local box_y = 32 + (y * 16)
					EAL.GUI.box(box_x, box_x + 16, box_y, box_y + 16)
				end
			end
		end
	end
end

while true do
	local screenx = get_screen_x_coordinate()
	emu.frameadvance()
	draw_block_id_map(screenx)
end