1 2
5 6 7 8 9
Joined: 10/24/2005
Posts: 1080
Location: San Jose
arflech wrote:
With respect to the 0.07 release of Snes9x+lua: <big picture that says "I want to believe">
Jeez. Jun 01 10:03:33 <arflech> DeHackEd, got an ETA on Snes9x+lua 0.07? Jun 01 10:04:24 <nitsujrehtona> oh yeah! *pester, pester* :) Jun 01 10:04:32 <DeHackEd> after people stop pestering me
<agill> banana banana banana terracotta pie! <Shinryuu> ho-la terracotta barba-ra anal-o~
Editor, Skilled player (1941)
Joined: 6/15/2005
Posts: 3247
Here are some sample scripts that I made. The first one keys in second-player input based on first-player input. Select key changes the symmetry. This allows the two players to sync with each other. Motivated by the game Strike Gunner: S.T.G. (SNES autoscroller), but can be done with any game.
local d=0
local e=0

local key={}

while true do

  key=joypad.read(1)

  if key.select==1 then
  d=d+1
  end

  if d==4 then
  d=0
  end

  if d==1 or d==2 then
  e=key.left
  key.left=key.right
  key.right=e
  end

  if d==2 or d==3 then
  e=key.up
  key.up=key.down
  key.down=e
  end

  joypad.set(2,key)

  if d==0 then
  gui.text(1,20,"normal")
  end

  if d==1 then
  gui.text(1,20,"hmirror")
  end

  if d==2 then
  gui.text(1,20,"rotate")
  end

  if d==3 then
  gui.text(1,20,"vmirror")
  end

  snes9x.frameadvance()

end
The second one is a bot. This particular one is specific to Vegas Stakes (SNES) and tries to find combinations for the slot machine. It must be run from a .000 (F1) savestate which is in "The 2020" casino and points at the game option "Slots". This bot requires manual monitoring. The first line is a commented line. It is a list of timings.
-- 0 A 150 v_v_v_A 300 A_A 320 X

local c=savestate.create(1)
local d=0
local offset=0
local e=0

local ak={}
local vk={}
local xk={}

ak.A=1
vk.down=1
xk.X=1

savestate.load(c)

while true do

  while e>0 do
    e=e-1
    snes9x.frameadvance()
  end

  if d==0 or d==156 or d==300 or d==302 then
  joypad.set(1,ak)
  end

  if d==150 or d==152 or d==154 then
  joypad.set(1,vk)
  end

  if d==320 then
  joypad.set(1,xk)
  end

  d=d+1

  snes9x.frameadvance()

  if d==1200 then
  d=0
  offset=offset+1
  savestate.load(c)
  e=offset
  end

end
Former player
Joined: 2/19/2007
Posts: 424
Location: UK
I have made another script, this time for ff6. Though it is not as complete as I would have wanted, perhaps someone will find it useful. Features: 1. Encounter prediction: predicts steps until encounter, and what will be encountered. Does not predict front/back/pincer/side/preemptive variants, not will it work properly on the floating continent. (there is tentative support for this (which actually makes up a good part of the code), but it is buggy, and only works well when one is on the world map, and has 3 or 4 chars in party, so it is disabled by default) 2. Outline treasure chests and show their contents and status (green = untaken, red = taken) 3. Outline squares that trigger events. Blue = transition to new area, light blue = transition to same area, very light blue = transition to map, yellow = unclassified event. 4. In battle, hp and mp bars are displayed over the enemies, as well as their battle gauges. Their level is also displayed. On Gau's turns, a "?" is displayed by any monster whose rage is not known. Additionally, the enemies' resistances etc. are displayed in a compact but hopefully readable manner, as a set of 4 3x3 squares of pixels, where each has the following format: fil ; fire (red) ice (blue) lightning (yellow) pwp ; poison (green) wind (gray) holy (white) ew ; earth (brown) water (blue) The order of the squares is, from left to right, absorb, nullify, resist, weak. 5. Extra information is displayed for the currently selected monster. Normally, only its drops and hp/mp are displayed, but if Locke is selecting the monster with the steal command, its steals are also listed. If Relm is selecting a monster with control or sketch, that information will also be indicated. 6. While in the rage menu, information about what the selected rage does is displayed. Only the attack part of the rage is displayed so far, since I haven't thought of a compact way of displaying all the status information associated with a rage. This time, I have tested it on an unmodified snes9x improvement, and it should work there (as opposed to my super metroid script, which I am tempted to rewrite to accommodate the lacks of the current snes9x). The script is available at http://folk.uio.no/sigurdkn/ff6.lua Suggestions for improvements are welcome, but it is unlikely that anything that has to do with 0x7e00be will be implemented, as I've been stuck on predicting what it will be for half a week now.
Joined: 8/27/2006
Posts: 883
Would be nice to see a little video of this script.
Former player
Joined: 2/19/2007
Posts: 424
Location: UK
I have now back-ported the super metroid script, which could not be used in current versions of snes9x-lua due to use of the not yet implemented movie.open command. Usage is mostly as described earlier. Run recorder.lua (which has not been changed) once for each movie you want to compare to, edit the configuration section at the top of player.lua to fit your needs, load player.lua in snes9x, and then run the movie file when prompted. If the lua version is less than 0.06, savestates are not supported, otherwise they work, as long as they were created while the script was running. I guess I should try to create a short example movie, too... When it comes to configuration, I recommend ingame=2 and room = true. As described in my original post, 2 pages back, this only shows ingame frames, and lets you compare the movies' performance in each room. But the other modes are also interesting. The files can be found at http://folk.uio.no/sigurdkn/recorder.lua and http://folk.uio.no/sigurdkn/player.lua Edit: I have created two test avis of the script: http://folk.uio.no/sigurdkn/sm_ingame_room.avi http://folk.uio.no/sigurdkn/sm_realtime_room.avi Both use room=true, but the first has ingame=2, and the second has ingame=0. The orange box is herooftheday-smetroid.smv, the yellow is herooftheday2-smetroid.smv, the blue is cpadolf-smetroid.smv, and the white is cpadolf2-smetroid.smv. Notice how all runs exit the room at approximately the same time in the first, while there is a large difference between hero of the day and cpadolf in the second. This illustrates that item pickups are much more expensive in realtime oriented runs than in ingame oriented runs. Edit2: Here are two similar movies with room = false. The runs are now synced by absolute frame/ingame frame, and not by room entry. herooftheday's first run is far behind in this case, since it doesn't do the torizo skip. http://folk.uio.no/sigurdkn/sm_ingame_abs.avi http://folk.uio.no/sigurdkn/sm_realtime_abs.avi Nb. There is no sound in those videos due to snes9x refusing to output an avi with sound on a computer without a sound card. Edit3: Embarrassingly, I forgot that the recorder script also needed to be fixed. It should be fixed now.
Post subject: Automated hacking!
Joined: 10/3/2005
Posts: 1332
I wrote a(nother) script for FF2(U). This one allows you to prevent changes to the party by pressing Start on player 2's gamepad. Basically, when a scripted event happens (like Kain being taken out of the party near the start of the game) you press Start (on pad 2) and the script saves an image of the party as it was when you pressed the button. It will then watch the RAM for any changes to the party lineup and undo anything that happens until this "cheatmode" is turned off. Anyway, here's the script. In theory it's fairly simple to record movies with a custom hack like this turned on, and have it play back the way it was recorded, but apparently joypad.read doesn't intercept movie inputs. :( Oh well- that's for next time. :)
Former player
Joined: 2/19/2007
Posts: 424
Location: UK
That's a pretty original script idea, and sounds like something that can open up for many interesting situations, like fighting Zeromus with Dark Knight Cecil, Palom and Porom, for example. Have you tested how crash-prone such unintended party configurations are? I'll try to give this script a test during the next week :)
Joined: 10/3/2005
Posts: 1332
Haven't exactly tested it much, other than to make sure that it actually works, in general. I used to cheat like this all the time, just using ZSNES' PAR code window, though, and I don't believe this game ever actually crashed because of a weird party. I do recall having to use the item "chain reaction" in scripted fights, under certain circumstances... I think Rydia was supposed to drop in, but the party was full, or she was already in the party or something. And I don't imagine the game would be pleased if Tellah weren't around for his own death scene. Otherwise, it tends to let you do whatever you like.
Player (120)
Joined: 2/11/2007
Posts: 1522
Don't know if it will work in this situation, but there's usually a memory address that reflects which buttons are being pressed. If you can find a fairly unused button that will affect this address you can AND it appropriately to detect the button press... and then during the movie it would work the same way. That said, I'm hoping there will be a way to have scripts look at input from a movie at some point, it would be very useful.
I make a comic with no image files and you should read it. While there is a lower class, I am in it, and while there is a criminal element I am of it, and while there is a soul in prison, I am not free. -Eugene Debs
Joined: 4/25/2004
Posts: 615
Location: The Netherlands
You have four pads, you're using only one, that leaves 12*3=36 buttons you can assign for various scripting actions :)
qfox.nl
Player (120)
Joined: 2/11/2007
Posts: 1522
But as far as I know, input from a movie file does not register. So playing it is fine, but replaying it isn't. Maybe you can fix that for FCEU Mr. qFox :)
I make a comic with no image files and you should read it. While there is a lower class, I am in it, and while there is a criminal element I am of it, and while there is a soul in prison, I am not free. -Eugene Debs
Joined: 10/3/2005
Posts: 1332
Alden wrote:
Don't know if it will work in this situation, but there's usually a memory address that reflects which buttons are being pressed.
That's true, and most games have bytes like that (usually for only players 1 and 2, I'd think), and you probably could read those bytes as input. My plan is to write a parser for the movie format, and read the pads that way.
Player (120)
Joined: 2/11/2007
Posts: 1522
That would be cool and I would steal said parser for other purposes ;)
I make a comic with no image files and you should read it. While there is a lower class, I am in it, and while there is a criminal element I am of it, and while there is a soul in prison, I am not free. -Eugene Debs
Joined: 10/3/2005
Posts: 1332
Alden wrote:
That would be cool and I would steal said parser for other purposes ;)
So far so good: I have a function that can (theoretically) pull any given input stream from an SMV and return it as a table. Now I just need to add the bit checks for each button, support for 1.51, FCM, and unlikely cases... and then test it a little to make sure it actually works properly. More importantly, I ran into a really annoying problem that I couldn't figure out: lack of a Lua equivalent to fread. There's io.read, but this returns strings in all cases, except where the input is a number to begin with. So, at a complete loss for any other way of doing it, I wrote this delightful kludge, which I'm sure you will all enjoy:
function getint(moviedata, offset)
	local result = 0
	local powersoftwo = { 1, 256, 65536, 16777216 }
	for i=1,4 do
		result = result + powersoftwo[i]*moviedata:byte(offset+i)
	end
	return result
end
This really doesn't seem the way this task was meant to be done. Edit: Okay, maybe it is.
xPi
Joined: 8/1/2008
Posts: 58
For Super Metroid, this script skips cutscenes, messages and transitions while not skipping lag frames, file select, options, pause screens and game over screens.
msgboxflag = 0
snes9x.speedmode("normal")
while not movie.mode() do
	gui.text(8,40,"Waiting for movie" )
	snes9x.frameadvance()
end
function msgbox()
	msgboxflag = 1
end
function timerchange()
	if msgboxflag == 1 then
		snes9x.speedmode("normal")
		msgboxflag = 0
	end
end
memory.register(0x7E1C1F,msgbox)
memory.register(0x7E1842,timerchange)
while movie.mode() do
	elevator = memory.readword(0x7E0E18)
	mode = memory.readbyte(0x7E0998)
	if mode == 8 and elevator == 0 and msgboxflag == 0 then
		snes9x.speedmode("normal")
	else
		snes9x.speedmode("maximum")
	end
	if mode >= 12 and mode <18>= 4 and mode <5>= 20 and mode <= 27 then snes9x.speedmode("normal") end
	-- 12-18: pause screens. change 12 to 11 if you want door transitions
	-- 4-5:   save data and option screens
	-- 20-27: game over screens. change 27 to 26 to exclude reserve tank
	snes9x.frameadvance()
end
snes9x.speedmode("normal") 
snes9x.pause()
AVIs made with this shows the skip more smoothly than emulated live. There are a few missile pickups at floor level where running through them does not affect running speed. (eg room outside wave beam room) Message box skipping is done quite smoothly here when watching the AVI.
Player (88)
Joined: 11/14/2005
Posts: 1057
Location: United States
The script seems great, but for some reason I get an error when I try to run a large movie. For example when I try to run Cp's 100% run and use the script a message appears saying "attempt to compare number with boolean." When I use the script on a short demo movie or something, it works fine. edit: Well the error message seems like it has to do with using the lua script at the beginning of the game. If you turn it on later in the run it works..
They're off to find the hero of the day...
arflech
He/Him
Joined: 5/3/2008
Posts: 1120
Did DeHackEd give up finishing the new version of Snes9x+Lua?
i imgur com/QiCaaH8 png
Active player (354)
Joined: 1/16/2008
Posts: 358
Location: The Netherlands
I realize I'm asking for things that require huge amounts of effort and time... but I just need to know :) what are the chances of having LUA support in the latest Snes9x v1.51? (when i did Mr Nutz, I recorded in 1.51 and did the LUA stuff in 1.43... not very convenient :P)
TASes: [URL=http://tasvideos.org/Movies-298up-Obs.html]Mr. Nutz (SNES), Young Merlin 100% (SNES), Animaniacs 100% (SNES)[/URL]
Emulator Coder, Site Developer, Former player
Joined: 11/6/2004
Posts: 833
Okay, I had free time and a cross-compiler handy, so I beat on Lua a bit. I added a movie.playback and .record function pair and need to know what else people want/need. Let's assume I'm working from a fresh 0.06 slate and havn't looked at the thread since that day... holy crap has it been that long?
Joined: 4/25/2004
Posts: 615
Location: The Netherlands
Some new functions added to FCEUX: rom.readbyte(n) and rom.readbytesigned(n) This is new, but will return currently return a byte from the file (including the header and what not) because there were a lot of requests for ROM reading. Only in the interim build so it may change a little. memory.readbyterange(start, len) returns a table with these addresses savestate.persist(state) savestates are now anonymous memory only by default, you can make them optionally persistent. although this will break backward compatibility so i think we should make them persistent by default and optionaly temporary (as an optimilization) movie.framecount() movie.rerecordcounting() movie.stop() I think these are new, but I'm not sure And FCEUX has iup, but I'm not sure whether you want to walk through that minefield... :) I think this is new?
qfox.nl
Emulator Coder, Site Developer, Former player
Joined: 11/6/2004
Posts: 833
SNES Lua can access full ROM by specifying the full 24 bit address, so that's a moot point from my point of view. It's just a matter of finding the address. The actual SNES program has more trouble because it's a 16 bit system and the address prefix of the data needs to be loaded. Savestates (in snes9x) are kept in the temporary directory. If you want them to persist, load it and then immediately save to a player's slot. While I COULD give you the filename and then you could copy it, that does defeat the purpose of being anonymous. As for iup, if it's available as an extension to Lua, you can load it. I'm taking the position that the emulator itself should have the absolute minimal set of add-ons. What's what LuaForge is for. I did take a look at "iup" before, and it needs some kind of "Cd" dependency I don't have a clue what it wants and there's nothing in the readme or website documentation. Not to mention the source code tarball has some very broken permissions. Nice.
Joined: 4/25/2004
Posts: 615
Location: The Netherlands
I've created an EmuLua reference. You can find it at http://cbc.qfox.nl/emulua Please let me know if there are any problems or additions :)
qfox.nl
Emulator Coder, Site Developer, Former player
Joined: 11/6/2004
Posts: 833
Cool. I'm adding memory.readbyterange. Snes9x allows for up to 5 players. Wow, anonymous fceu savestates are discarded immediately upon loading? Snes9x savestates persist forever. (Not true since once the savestate object falls out of use, the Lua memory garbage collector eats it, but it's close enough) You have a emu.framecount() function that links to movie.framecount() Transparency as int [1] is deprecated and to be deleted at some point in the near future. In the meantime, it will still work. I don't know WHY I ever did that since I always had support for "clear". If I'm reading the source code to snes9x right, SRAM is at 0x700000 and goes up to 0x702000 though it's mirrored a few times. It also varies by game and cart type, but this address seems stable enough. You might want to check out gui.drawpixel, gui.drawpixel and gui.drawpixel
Former player
Joined: 2/19/2007
Posts: 424
Location: UK
Have made the drawing functions more lentinent, so that any script that draws to the screen does not need to include the same boring screen boundary checking? I also suggest adding control over which sound channels are played and which backgrounds/sprites are on.
Joined: 4/25/2004
Posts: 615
Location: The Netherlands
DeHackEd wrote:
Wow, anonymous fceu savestates are discarded immediately upon loading? Snes9x savestates persist forever. (Not true since once the savestate object falls out of use, the Lua memory garbage collector eats it, but it's close enough)
That's how they used to work in fceux. But now states are kept in memory unless you call persist. But I still think it's not so great that the states are destroyed on load. So I'd want that not to be the default behavior (but optional).
DeHackEd wrote:
You have a emu.framecount() function that links to movie.framecount()
Yeah it's exactly the same thing except nitsuja decided it'd be more logically under the gens table for some reason.
DeHackEd wrote:
Transparency as int [1] is deprecated and to be deleted at some point in the near future. In the meantime, it will still work. I don't know WHY I ever did that since I always had support for "clear".
I was wondering why there was no "transparent" color. I never knew about "clear".
DeHackEd wrote:
You might want to check out gui.drawpixel, gui.drawpixel and gui.drawpixel
Doh. Fixed And I updated everything else you mentioned. Thanks :)
qfox.nl
1 2
5 6 7 8 9