Posts for deltaphc

Experienced Forum User
Joined: 3/15/2009
Posts: 8
Been a little while since I last posted. http://gens-lua.pastebin.com/f6da2e320 What's changed: - Fancy new menu system. - '+' menu gives you contextual options depending on which Mode you're in. - Added ability to duplicate and delete objects. - Added new 'Game' mode, where you can modify various variables, restart the level, toggle level select/debug, and Go Super. - Added ability to dump level layout to a file. Useful if you're into Sonic hacking. - Tiles are now changed using left/right mouse buttons. - Other little tweaks and polish. ---- Edit by FractalFusion: Removed an image that was oddly out of place and oversized. It is linked here: http://imgur.com/A2XPJ.png
Experienced Forum User
Joined: 3/15/2009
Posts: 8
Thanks for the insight! S3/K tile editing works fine now, but I still can't quite fix the redraw problem. The problem with saving a state, doing invisible frames, etc, is that from Lua, Gens doesn't allow you to load a state without redrawing the screen. So if I were to load a state afterwards, it'd just bring me back to where I started (if I'm understanding it correctly). Also, some unrelated suggestions for Gens' Lua support because I'm not sure where else to post it: - We have the ability to get mouse clicks, but no way to get mousewheel activity. Maybe a couple more fields in the input.get() table for wheelup and wheeldown. - And perhaps hotkey status added to input.get() as well; so that there's a way to check for hotkeys without using callbacks. - Could it be possible for scripts to extend the menubar? It could go something like this:
gens.registermenu("NewMenu/SubMenu/MenuItem", function() end)
- Having multiple Lua windows is fine, but if it were instead a tabbed dialog, it'd save both screen space and taskbar space. ;)
Experienced Forum User
Joined: 3/15/2009
Posts: 8
Updated above post with fix. Also, added tiles mode while I was at it. For now, tile editing is disabled on S3/K due to its slightly more complicated way of getting row length. Also, tiles in S1 won't visually update themselves until you scroll away and back. This is solved in S2 by setting the "dirty flag", but I can't find any such flag in S1. Any ideas?
Experienced Forum User
Joined: 3/15/2009
Posts: 8
Cool stuff, guys. For the past day or so, I've been working on something similar to Xk's SMB1 mouse control script. Due to the length of the script, I put it on pastebin: http://pastebin.ca/1364116 Objects mode: Drag stuff around, right-click to pin objects. Tiles mode: Pretty self-explanatory. A minor problem though; dragging an object too quickly will likely "let go" of it, because the mouse position is outside of the box. I know there's a solution to this, but it's escaping me at the moment. Edit: Fixed. Thanks upthorn.
Experienced Forum User
Joined: 3/15/2009
Posts: 8
Double post. A useful double post, though. ;) Updated OP with third revision. Just a couple minor changes. Also, been messing around with other things. Here's a script that lets you change the zone/act in Sonic 1/2/3/K via clickable buttons:
addr_zone = 0xfffe10
addr_act = 0xfffe11
addr_restartflag = 0xfffe02

input_state = {}

gui.register( function()
	input_state = input.get()
	
	local zone = memory.readbyte(addr_zone)
	local act = memory.readbyte(addr_act)
	local restartflag = memory.readbyte(addr_restartflag)
	
	gui.text(0, 217, string.format("Zone %X", zone))
	if restartflag == 0 then
		if do_button("-", 32, 216, 6, 7) then
			memory.writebyte(addr_zone, zone - 1)
			memory.writebyte(addr_restartflag, 1)
		end
		if do_button("+", 39, 216, 6, 7) then
			memory.writebyte(addr_zone, zone + 1)
			memory.writebyte(addr_restartflag, 1)
		end
	end
	
	gui.text(52, 217, string.format("Act %X", act))
	if restartflag == 0 then
		if do_button("-", 80, 216, 6, 7) then
			memory.writebyte(addr_act, act - 1)
			memory.writebyte(addr_restartflag, 1)
		end
		if do_button("+", 87, 216, 6, 7) then
			memory.writebyte(addr_act, act + 1)
			memory.writebyte(addr_restartflag, 1)
		end
	end
	
	if restartflag == 0 then
		if do_button("Restart", 100, 216, 30, 7) then
			memory.writebyte(addr_restartflag, 1)
		end
	end
end)

function do_button(text, x, y, width, height)
	local return_value, fill_color, outline_color
	
	if (input_state.xmouse >= x and input_state.ymouse >= y) and
		(input_state.xmouse <= x + width and input_state.ymouse <= y + height) then
		outline_color = {255, 255, 255, 255}
		
		if input_state.leftclick then
			return_value = true
			fill_color = {127, 0, 0, 255}
		else
			fill_color = {0, 0, 192, 255}
		end
	else
		fill_color = {0, 0, 127, 255}
		outline_color = {0, 0, 255, 255}
	end

	gui.box(x, y, x + width, y + height, fill_color, outline_color)
	gui.text(x + 2, y + 2, text, {255, 255, 255, 255}, {0, 0, 0, 0})
	
	return return_value
end
Screenshot:
Experienced Forum User
Joined: 3/15/2009
Posts: 8
Edit: Yes, it was indeed referring to the post above yours. :) 1. When it's recording (i.e. not rewinding), it continually saves states into the 'states' table until it reaches max_states. 2. When it reaches max_states, what it does is remove element #1 (first element) from the states table using table.remove(). As a side-effect this also pushes all of the existing elements back, freeing up the very last slot in the states table. It then inserts a new state into the last slot. 3. When it rewinds, it decrements current_state, loads the state at that position, then removes the slot that was previously loaded. 4. When it resumes recording, it just continues where it left off at current_state, incrementing until it reaches max_states. Repeat from step 2.
Experienced Forum User
Joined: 3/15/2009
Posts: 8
Updated OP with revised script. Though I suppose the three-stage approach is better in the long-run; it would conserve memory while allowing much longer rewinds. I'll probably implement it when I become un-lazy. :P
Post subject: Rewind Lua script (and other fun scripts)
Experienced Forum User
Joined: 3/15/2009
Posts: 8
Hello everyone. Having recently discovered the new release of Gens Rerecording (11a) with Lua support and all, I decided to have some fun with it. I noticed that Rerecording has pause and slowdown, but no rewind. So I took a look at the various Lua samples and documentation, and noticed that I could implement it myself. After I was successful, I decided to post it here.
-- Rewind script
-- Rewinds emulation in realtime (or faster)
-- Written by: deltaphc

-- Constants
max_states = 300    -- maximum number of states allowed
rewind_interval = 3 -- save state every N frames

states = {}
current_state = 1
rewind_counter = 1
rewinding = false

input.registerhotkey(1, function()
	rewinding = not rewinding
	
	if rewinding then
		gens.message("Rewind: On")
	else
		gens.message("Rewind: Off")
	end
end)

gens.registerafter( function()
	if rewinding then
		current_state = current_state - 1
		if current_state < 1 then
			current_state = 1
			rewinding = false
			gens.message("Rewind: Off")
		end

		savestate.load(states[current_state])
		table.remove(states, current_state + 1)
	else
		if rewind_counter == rewind_interval then
			rewind_counter = 1

			if current_state < max_states then
				local state = savestate.create()
				savestate.save(state)
				table.insert(states, state)

				current_state = current_state + 1
			else
				table.remove(states, 1)

				local state = savestate.create()
				savestate.save(state)
				table.insert(states, state)
			end
		end
		
		rewind_counter = rewind_counter + 1
	end
end)
Start a game, run script, play for awhile, then press Lua Hotkey 1. Everything goes backwards! :) By default it saves states for up to 10 seconds, but the limit is adjustable via the max_states and rewind_interval variables at the top. A warning: This script tends to use up a lot of memory. Set the limits too high, and you could run into OS problems depending upon how much RAM you have. Enjoy. ;) Edit 1: Revised script (thanks Xk). Rewind is now a toggle (Lua Hotkey 1), and save interval is adjustable (defaults to 6). Edit 2: Fixed freeze when rewind reached the beginning; it automatically leaves rewind mode. Also, changed defaults to something slightly more sensible. A 6 frame interval seemed a bit too fast. Old versions: Revision 1, Revision 2