All pastes #1398291 Raw Edit

gocha

public lua v1 · immutable
#1398291 ·published 2009-04-21 14:28 UTC
rendered paste body
--[[ SNES Madou Monogatari - Hanamaru Daiyouchienji Semi-automated Map Maker, written by gocha. W-I-P! (>_<)]]---- Usually, you don't need to adjust the following size, but if the script-- didn't work properly because of something which begins a dialog,-- decrease the size and try to avoid it (I don't know if it will succeed though).-- The size is originally 256x159, but it must be the multiple of 8.-- Therefore, if you have no problem, just set it to 256x152 (152=8*19).local imagePieceSize = { x = 256, y = 8*19 }local debugDisplay = true-- [ startup ] -----------------------------------------------------------------require("gd")if emu then error("Unknown SNES EmuLua host.") endemu = snes9xif not emu then error("Unknown SNES EmuLua host.") end-- Instant ROM checkif string.char(unpack(memory.readbyterange(0x80ffb2, 4))) ~= "ADYJ" then	error("Unsupported ROM: make sure if the current ROM is Madou Monogatari")end-- [ ROM/RAM addresses ] -------------------------------------------------------RAM = {	fadeLevel = 0x7e0c5b,       -- screen fade level	pauseFlag = 0x7e0266,       -- becomes 1 when the game is paused	overworldFlag = 0x7e0980,   -- becomes 1 when the game is overworld map	frames = 0x7e1300,          -- ingame frame counter	arlePosWord = 0x7e16c5,     -- Arle's position in OW (0byyyyyyyyyxxxxxxx)	arleXPosR = 0x7e0025, arleYPosR = 0x7e0027,	arleXPosW = 0x7e4827, arleYPosW = 0x7e4829,	bgXPosW = 0x7e16e2, bgYPosW = 0x7e16e6,	roomLeft = 0x7e1733, roomTop = 0x7e172f, roomRight = 0x7e1735, roomBottom = 0x7e1731,	disableOWMove = 0x7e1401,	encounter = 0x7e1408}if memory.readbyte(RAM.fadeLevel) ~= 15 or memory.readbyte(RAM.overworldFlag) ~= 1 then	gui.popup("Let the game show the overworld screen, or the script won't run.")	returnendif memory.readword(RAM.arleXPosW) % 8 ~= 0 or memory.readword(RAM.arleYPosW) % 8 ~= 0 then	gui.popup("Arle's position is odd... you cheated?")	returnendif input.popup([[This script scans the game screen continuously, then makes a large map of the current room.Before running the script, you may need to confirm some conditions.  * The game shows the overworld screen. To make Arle stand about the center of the room is good.  * Make sure if "graphic clip windows" is OFF. Usually, you can toggle it by pressing 8.  * Make sure if "text in message" is OFF, or annoying texts will appear in the screenshot.  * [NYI] Auto frameskip is not bad, but if you want to control animated sprites properly, set the frame skip rate to 0.Make sure if the frameskip amount is set to 0 (NOT auto frameskip)Warnings:  * DO NOT LOAD ANY SAVESTATES DURING RUNNING THE SCRIPT.Continue?]], "okcancel") ~= "ok" then	returnendlocal savScriptStart = savestate.create()savestate.save(savScriptStart, "quiet")local snapInfo = { x = 0, y = 0, width = imagePieceSize.x, height = imagePieceSize.y }local room = {	left = memory.readword(RAM.roomLeft),	top = memory.readword(RAM.roomTop),	right = memory.readword(RAM.roomRight),	bottom = memory.readword(RAM.roomBottom)}room.scrollWidth, room.scrollHeight = room.right - room.left, room.bottom - room.toproom.width, room.height = room.scrollWidth + 256, room.scrollHeight + 152 -- why it isn't 159?room.xPieces, room.yPieces = math.ceil(room.width / snapInfo.width), math.ceil(room.height / snapInfo.height)local gdMap = gd.createTrueColor(room.width, room.height)local snapProgress = { x = 0, y = 0 }if not gdMap then	error("Memory allocation error (gd.createTrueColor failed)")end-- [ main routines ] -----------------------------------------------------------local captStates = {	enterPause = 0,	quitPause = 1,	doScreenShot = 2,	didScreenShot = 3,	endMapMaking = 4}local captState = captStates.enterPauselocal stateTimeCount = 0local aborted = trueemu.registerexit( function()	if aborted then		memory.writebyte(RAM.disableOWMove, 0)	endend)emu.registerbefore( function()	local pad = {}	local tookScreenShot = false	if captState == captStates.enterPause then		-- adjust screen position		local targetX, targetY = room.left + (snapProgress.x * snapInfo.width), room.top + (snapProgress.y * snapInfo.height)		local targetStepX, targetStepY = math.floor((targetX + 0x70) / 8), math.floor((targetY + 0x58) / 8)		local stepXMax, stepYMax = math.floor((room.right + 256) / 8), math.floor((room.bottom + 159) / 8)		if targetStepX > stepXMax then targetStepX = stepXMax end		if targetStepY > stepYMax then targetStepY = stepYMax end		local bgX, bgY = memory.readword(RAM.bgXPosW), memory.readword(RAM.bgYPosW)		local arleX, arleY = memory.readword(RAM.arleXPosW), memory.readword(RAM.arleYPosW)		local stepX, stepY = math.floor(arleX/8), math.floor(arleY/8)		local realStepX, realStepY = math.floor(memory.readword(RAM.arlePosWord) % 128), math.floor(memory.readword(RAM.arlePosWord) / 128)		local moveSpeed = 8 -- do not change		if stepX == targetStepX and stepY == targetStepY then			if stateTimeCount >= 4 and memory.readbyte(RAM.overworldFlag) == 1 and memory.readword(RAM.frames) % 2 == 0 then				pad.start = 1 -- autofire the start button				memory.writebyte(RAM.disableOWMove, 0)			end		else			if stepX < targetStepX then				bgX = bgX + moveSpeed				arleX = arleX + moveSpeed				stepX = stepX + 1			elseif stepX > targetStepX then				bgX = bgX - moveSpeed				arleX = arleX - moveSpeed				stepX = stepX - 1			end			if stepY < targetStepY then				bgY = bgY + moveSpeed				arleY = arleY + moveSpeed				stepY = stepY + 1			elseif stepY > targetStepY then				bgY = bgY - moveSpeed				arleY = arleY - moveSpeed				stepY = stepY - 1			end			-- clipping			if bgX < room.left   then bgX = room.left end			if bgY < room.top    then bgY = room.top end			if bgX > room.right  then bgX = room.right end			if bgY > room.bottom then bgY = room.bottom end			memory.writeword(RAM.bgXPosW, bgX)			memory.writeword(RAM.bgYPosW, bgY)			memory.writeword(RAM.arleXPosW, arleX)			memory.writeword(RAM.arleYPosW, arleY)			memory.writebyte(RAM.disableOWMove, 1)			if stepX == targetStepX and stepY == targetStepY then				stateTimeCount = 0			end		end	elseif captState == captStates.quitPause then		if memory.readbyte(RAM.pauseFlag) == 1 and memory.readword(RAM.frames) % 2 == 0 then			pad.start = 1 -- autofire the start button		end	elseif captState == captStates.doScreenShot then		if memory.readbyte(RAM.fadeLevel) == 15 then			if stateTimeCount >= 30 then				local gdSnap = gd.createFromGdStr(gui.gdscreenshot())				local mapX, mapY = snapProgress.x * snapInfo.width, snapProgress.y * snapInfo.height				if (snapProgress.x + 1) == room.xPieces then mapX = room.width - snapInfo.width end				if (snapProgress.y + 1) == room.yPieces then mapY = room.height - snapInfo.height end				gd.copy(gdMap, gdSnap, mapX, mapY, snapInfo.x, snapInfo.y, snapInfo.width, snapInfo.height)				tookScreenShot = true				snapProgress.x = snapProgress.x + 1				if not (snapProgress.x < room.xPieces) then					snapProgress.x = 0					snapProgress.y = snapProgress.y + 1				end			end		else			stateTimeCount = 0		end	elseif captState == captStates.didScreenShot then		savestate.load(savScriptStart, "quiet")	end	joypad.set(1, pad)	stateTimeCount = stateTimeCount + 1	-- state transition	local newState = captState	if captState == captStates.enterPause then		if memory.readbyte(RAM.pauseFlag) == 1 then			newState = captStates.quitPause		end	elseif captState == captStates.quitPause then		if memory.readbyte(RAM.overworldFlag) == 1 and memory.readbyte(RAM.fadeLevel) == 15 then			newState = captStates.doScreenShot		end	elseif captState == captStates.doScreenShot then		if tookScreenShot then			if not (snapProgress.y < room.yPieces) then				newState = captStates.endMapMaking			else				newState = captStates.didScreenShot			end		end	elseif captState == captStates.didScreenShot then		newState = captStates.enterPause	end	if captState ~= newState then		captState = newState		stateTimeCount = 0	end	memory.writebyte(RAM.encounter, 0)end)emu.registerafter( function()end)gui.register( function()	if not debugDisplay and captState ~= captStates.enterPause then return end	local fadeLevel = memory.readbyte(RAM.fadeLevel)	if fadeLevel > 15 then fadeLevel = 0 end	fadeLevel = 15	gui.opacity(0.68 * fadeLevel / 15.0)	local targetX, targetY = room.left + (snapProgress.x * snapInfo.width), room.top + (snapProgress.y * snapInfo.height)	local targetStepX, targetStepY = math.floor((targetX + 0x70) / 8), math.floor((targetY + 0x58) / 8)	local stepXMax, stepYMax = math.floor((room.right + 256) / 8), math.floor((room.bottom + 159) / 8)	if targetStepX > stepXMax then targetStepX = stepXMax end	if targetStepY > stepYMax then targetStepY = stepYMax end	local bgX, bgY = memory.readword(RAM.bgXPosW), memory.readword(RAM.bgYPosW)	local arleX, arleY = memory.readword(RAM.arleXPosW), memory.readword(RAM.arleYPosW)	local stepX, stepY = math.floor(arleX/8), math.floor(arleY/8)	local realStepX, realStepY = math.floor(memory.readword(RAM.arlePosWord) % 128), math.floor(memory.readword(RAM.arlePosWord) / 128)	gui.text(2, 2, string.format([[ARLE (%03X,%03X)BACK (%03X,%03X)-(%03X,%03X)STEP (%d,%d:%d,%d)-(%d,%d)-(%d,%d)SNAP (%d,%d)-(%d,%d)STAT %d(%d)]],arleX, arleY,bgX, bgY, targetX, targetY,stepX, stepY, realStepX, realStepY, targetStepX, targetStepY, stepXMax, stepYMax,snapProgress.x+1, snapProgress.y+1, room.xPieces, room.yPieces,captState, stateTimeCount))end)while captState ~= captStates.endMapMaking do	emu.frameadvance()endgdMap:pngEx("hanamaroom.png", 1)emu.message("Saved the map of the room.")savestate.load(savScriptStart, "quiet")aborted = false