Post subject: Lua scripting
Joined: 1/22/2008
Posts: 319
Location: Brasil
Im totaly new in this stuff. But seen this lua thing is very helpfull. But i cant undertand at all how to write my own lua script. i tryed google and everything else. Im makeing a tas and i realy want to improve in everyaspect. So i would like to know the basics of what the lua can do for me. I thinking of to display the boss hp in the screen would be awsome so i can see the damage (and not using the ram watcher). Also i was thinking of to show the caracter position in the screen, so i can use perfect jumps. Here i got the address for the boss hp (1C5E) i found this adress with other 3 adress (but this is the one that chage first. Im having problems to find the character position on the screen. Then here comes the big problem how can i write the lua with the address i already find.
Run..Run...Run.....
Post subject: Re: Lua scripting
Joined: 10/3/2005
Posts: 1332
wicked wrote:
Im makeing a tas and i realy want to improve in everyaspect. So i would like to know the basics of what the lua can do for me.
The two basic things are "generate input" and "display information". Those are some pretty powerful building blocks. The emulua reference lists the functions available in each emulator, and that should give you an idea of what Lua is meant for.
I thinking of to display the boss hp in the screen would be awsome so i can see the damage (and not using the ram watcher). Also i was thinking of to show the caracter position in the screen, so i can use perfect jumps.
You should refer to some of the other scripts that have been posted over the years. I think FCEUX also comes with some example scripts that will probably help you.
Here i got the address for the boss hp (1C5E) i found this adress with other 3 adress (but this is the one that chage first. Im having problems to find the character position on the screen. Then here comes the big problem how can i write the lua with the address i already find.
The code to display the boss HP is as follows:
while true do
    gui.text(0, 0, "Boss: " .. 0x1C5E)
    emu.frameadvance()
end
That will put the display at the top-left corner. If you want the HP display to follow the boss, you just replace the two zeroes with the X and Y coordinates of the boss. Depending on the emulator, you might need to do some other stuff, but that's the basics.
Joined: 1/22/2008
Posts: 319
Location: Brasil
thanks is cool to display in the corner, but isnt working... its shows anohter number...while i sse in ram watch hows me the real number , the lua scripit show me another.. (here is the 4 adrersses i found for the bosses 045e, 0c5e, 145e,1c5e) the lua show me a huge number (5214) i dont know what is about..
Run..Run...Run.....
Player (210)
Joined: 7/7/2006
Posts: 798
Location: US
While we are on the topic. I created this page a while ago: http://tasvideos.org/LuaScripting.html It should very briefly cover the basics of what wicked is looking for. These other two pages need integrated with each other, and then referenced within the Lua Scripting. These may be helpful in finding your position value. http://tasvideos.org/MemorySearch.html http://tasvideos.org/EmulatorResources/RamSearch.html If anyone has ideas on what to do with these pages, I'd be interested in discussing it. Obviously I need to finish the LuaScripting page sometime. It became a bit time consuming to write simple code for games everyone has played and then explain it simply. I'll try to work on this some more soon. I have some notes since I last updated it. Obviously I need to include qfox's command list as a reference. Does anyone know any commands that should thoroughly be covered? I think everything I listed is the most necessary, but other things that I don't typically use are probably still useful to list. Correction:
while true do
    gui.text(0, 0, "Boss: " .. memory.readbyte(0x1C5E))
    emu.frameadvance()
end
Joined: 1/22/2008
Posts: 319
Location: Brasil
this time i got this message
...fceux-2.1.2-win 32 \Bananan Ouji no Dai Bouken (J ).lua:2 :attempt to call field 'readword'(a nil value )
its sens to be harder than i thought. what is the solution?
Run..Run...Run.....
Player (210)
Joined: 7/7/2006
Posts: 798
Location: US
I assumed you were on an emulator with 'word' length values. You want readbyte. All values in the NES are bytes. SNES can have 'word' type values, and GBA/others can even have doublewords.
Joined: 1/22/2008
Posts: 319
Location: Brasil
Kirkq wrote:
I assumed you were on an emulator with 'word' length values. You want readbyte. All values in the NES are bytes. SNES can have 'word' type values, and GBA/others can even have doublewords.
idont undertand nothing about this. what should i do ?
Run..Run...Run.....
Player (210)
Joined: 7/7/2006
Posts: 798
Location: US
I changed the code to reflect the correction after that last post. Also, go read the lua scripting page, maybe it gives a better overview.
Joined: 1/22/2008
Posts: 319
Location: Brasil
i cant at all, i guess i going back to the old ram watch
Run..Run...Run.....
Skilled player (1827)
Joined: 4/20/2005
Posts: 2161
Location: Norrköping, Sweden
Try copying this to a .lua-file and run it:
while true do
    gui.text(10, 10, "Boss HP: " .. memory.readbyte(0x1C5E))
   FCEU.frameadvance().
end 
You should see the text in the top left corner of the screen. Do you still get an error?
Joined: 1/22/2008
Posts: 319
Location: Brasil
this lua dont load. i got this error this time ...fceux-2.1.2-win 32 \Bananan Ouji no Dai Bouken (J ).lua:4:'<name>' expected near 'end'
Run..Run...Run.....
Banned User
Joined: 3/10/2004
Posts: 7698
Location: Finland
Not having ever used Lua scripting in emulators, I'm curious about a few things (it could perhaps be a good idea to write some kind of tutorial somewhere where these things get explained): - Where is the script written to and how do you tell the emulator to use it when running a certain game? - Can you have more than one distinct Lua script running, or is it just one? - Seemingly the emulator starts running the script immediately when the game starts and keeps running it for as long as the execution proceeds in the script (deducing from the use of "while true" in all the examples in this thread). Is there a way to hook scripts to run on certain events instead (eg. keypresses or such)? - What variables and functions are available for the script to use? What does "frameadvance()" actually do? (Does it, perhaps, mean "wait until the next frame"? If so, shouldn't it be named like that? As it's named now, it sounds like an instruction for the emulator to advance to the next frame.)
Joined: 1/22/2008
Posts: 319
Location: Brasil
here im using notepad to paste the lua script code, then i save in .lua
Run..Run...Run.....
Joined: 8/22/2009
Posts: 58
EDIT: Nevermind, i did not see the above posts. I was too quick.
Joined: 10/3/2005
Posts: 1332
/me facepalms at forgetting readbyte. Randil: your code has a period on the end of frameadvance(). That's why the interpreter looking for a <name>, I reckon.
Warp wrote:
- Where is the script written to and how do you tell the emulator to use it when running a certain game?
There's either a menu item or a commandline option to load a .lua file, depending on the emu, platform, version, etc. You can only run one script.
- Seemingly the emulator starts running the script immediately when the game starts and keeps running it for as long as the execution proceeds in the script (deducing from the use of "while true" in all the examples in this thread). Is there a way to hook scripts to run on certain events instead (eg. keypresses or such)?
To my knowledge (which is out of date and only includes FCEUX and Snes9x) there is no such hooking mechanism. At least, not until some super-sexy C coder adds it. *nudge-nudge wink-wink*
- What variables and functions are available for the script to use?
Lots. You should check the emulator docs and/or emulua reference for a list. As for the naming of "frameadvance", I'll point out that if you have an endless loop without at least one such call, the script will hang on the same frame until termination. In other words, regardless of what's going on under the hood, it effectively advances to the next frame.
Emulator Coder, Skilled player (1310)
Joined: 12/21/2004
Posts: 2687
Warp wrote:
- Where is the script written to and how do you tell the emulator to use it when running a certain game?
You save it wherever you want and generally browse to it or choose it from a menu after you start the game you want to run it in.
Warp wrote:
- Can you have more than one distinct Lua script running, or is it just one?
It depends on the emulator. In Gens (and possibly some others) you can run more than one at a time.
Warp wrote:
Is there a way to hook scripts to run on certain events instead (eg. keypresses or such)?
You can run a script that hooks various events such as a certain memory location being written to or the beginning of every frame or when a special hotkey is pressed, then the emulator will call the appropriate function your script defined whenever those events happen.
Warp wrote:
- What variables and functions are available for the script to use?
Gens has detailed documentation on what every available function does (it comes with the emulator but gocha is also currently hosting it here). I suggest looking through it because it has some more general information too that might answer many of your questions. Many of those functions are also available in the other Lua-capable emulators, which tend to have their own specific documentation as well.
Warp wrote:
What does "frameadvance()" actually do? (Does it, perhaps, mean "wait until the next frame"? If so, shouldn't it be named like that? As it's named now, it sounds like an instruction for the emulator to advance to the next frame.)
It is precisely an instruction for the emulator to advance to the next frame.
Player (210)
Joined: 7/7/2006
Posts: 798
Location: US
while memory.readbyte(0x7e0001) == 0 do 
snes9x.frameadvance() 
end
This will hold the script in a loop before actually executing the bulk of the code when byte 0001 becomes nonzero. Similarly this could be tied into the joypad.get function in any emulator for reading game input or the input.get function in Gens for reading keyboard input. As most of these questions remain unanswered by the currently incomplete LuaScripting page, it is obvious to me that I need to work on a bit of an overhaul soon.
Banned User
Joined: 3/10/2004
Posts: 7698
Location: Finland
nitsuja wrote:
Warp wrote:
What does "frameadvance()" actually do? (Does it, perhaps, mean "wait until the next frame"? If so, shouldn't it be named like that? As it's named now, it sounds like an instruction for the emulator to advance to the next frame.)
It is precisely an instruction for the emulator to advance to the next frame.
I don't quite understand it. If it's the script which is telling the emulator to advance to the next frame and not the player (by pressing the . button, or whatever it might be bound to), then doesn't it mean the player loses control? The script is continuously telling the emulator to advance to the next frame, in an infinite loop. How do you stop that? Or is there an implied pause somewhere? (But if there is, then wouldn't the function actually mean "wait for the next frame", because then it would be the player who decides when to go to the next frame with the . key, rather than the script?)
adelikat
He/Him
Emulator Coder, Site Developer, Site Owner, Expert player (3574)
Joined: 11/3/2004
Posts: 4754
Location: Tennessee
I think most of your confusion and questions would be cured by picking any of our rerecording emulators and spending 5 minutes messing with a lua script.
It's hard to look this good. My TAS projects
Banned User
Joined: 3/10/2004
Posts: 7698
Location: Finland
Would it be a big trouble to just explain how it works? I'm pretty sure I'm not the only one who doesn't understand what that "frameadvance()" function does. It just sounds to me like it really means "wait until the next frame before continuing executing the script", because that would be the most logical interpretation, but the name of the function says otherwise.
Joined: 7/2/2007
Posts: 3960
As I understand it, you're thinking that all scripts are run while the player is still controlling the emulator. This is not necessarily the case. Some scripts take control of everything and run the game automatically; in this situation they have to set input, then tell the game to advance, then set input again, etc. A common use case for this kind of script would be an RNG manipulator which tries permutations of input until it finds the input that achieves the desired RNG seed.
Pyrel - an open-source rewrite of the Angband roguelike game in Python.
Banned User
Joined: 3/10/2004
Posts: 7698
Location: Finland
So if the lua script does indeed command the emulator to advance to the next frame in an infinite loop, like in all the examples in this page, the user does indeed lose control? That's how I read these example scripts to mean, and nobody has given any other explanation. From your description I also have to deduce that the emulator does so as fast as possible, without any delays or pauses. So the game would just fly by as fast as your computer can emulate it... But the example scripts given in this thread wouldn't make any sense that way, so there's obviously something else going on.
Former player
Joined: 2/19/2007
Posts: 424
Location: UK
When you call framadvance (at least in snes9x, which is what I have experience with), control returns from the lua script to the emulator. The current location in the lua script is remembered, and execution continues there the next time lua the lua main section is invoked (it is a coroutine yield). So yes, a more accurate name would be wait_for_next_frame. There is no point of changing this now, though. If you want a new name for it you can just define an alias. Entirely separate from this issue, it is possible for the script to control the speed of the emulator. Typically, the choices are: Normal speed (as if the script weren't controlling the speed, so you can frame advance, fast forward etc. as you please), turbo (which is like holding down the turbo button) and maximum (full speed emulation with no frames rendered). Usually a script will use either normal or maximum, there is little use for the turbo setting. It is also possible for the script to override the user's keypresess with its own ones. So all in all, it is pretty flexible. You should give it a try - figuring it out that way is much simpler than trying to make sense of it through this thread.
Joined: 10/20/2006
Posts: 1248
frame_advance is an irritating name though because I highly doubt that if it's called twice during the same frame by two different lua scripts that it'll really advance two frames. I would have probably gone for lua_finished(this) (which would then call frame_advance only once all of them are finished) or something similar, though I must say I'm not really an expert at this. Also, while(running), but that's just because I've learned using while(true) loops was regarded as bad style. :p
Skilled player (1652)
Joined: 11/15/2004
Posts: 2202
Location: Killjoy
Actually, I've encountered this problem before. This code fails for this exact problem.
BackTrack = savestate.create();


while true do
    savestate.save(BackTrack);
    x = memory.readword(0x7e0b1d)
    y = memory.readword(0x7e0ff9)
    memory.writeword(0x7e1a62,x-0x80)
    memory.writeword(0x7e1a4c,0-y+0x6f87)
    gui.text(10,10,"" .. x)
    gui.text(10,20,"" .. y)
    snes9x.frameadvance()
    keys = joypad.get(1);    
   savestate.load(BackTrack);
   joypad.set(1,keys);
   gui.text(10,50,"Don't Touch Joypad!");
   snes9x.frameadvance();      --replace with snes9x.emulateframeinvisible() if it becomes available
end
The savestate.load() executes even after the frameadvance() command. So thus, you never see the frame emulated with the 'cam-hack' memory addresses written. You need a second frameadvance() command before the savestate.load() to ever see the cam-hack frame. I thought frameadvance() served as a 'wait for next frame' button. However, it appears that it executse all code until it hits the next frame advance.
adelikat wrote:
I think most of your confusion and questions would be cured by picking any of our rerecording emulators and spending 5 minutes messing with a lua script.
Quoted for truth.
Sage advice from a friend of Jim: So put your tinfoil hat back in the closet, open your eyes to the truth, and realize that the government is in fact causing austismal cancer with it's 9/11 fluoride vaccinations of your water supply.