For the hell of it, I added Lua scripting to the latest (as of when I posted this first) snes9x from gocha's modified snes9x (currently improvement 11 beta 17 (I think)).
Latest version (0.06)Previous version (0.05)Sample scriptsAPI (keep an eye on the version numbers!)
I will be offering some tech support and scripting assistance for anyone who asks in this thread.
Moderation note: this post was split from the thread by gocha.
Scripts exitting normally no longer give a Lua error on shutdown
Savestate functions work well enough to meet the specification set in the API docs
No longer depends on FMOD.dll
Less spam to stdout.txt (whoops!)
Known issues:
C:\Windows\Temp might get filled with anonymous savestates if shutdown of snes9x is not clean.
movie.record and playback not working
Joypad code believed correct but not tested
Link
Edit: Turns out I didn't fix the speed bug as well as I had thought. If your version still exhibits high speed when a script runs, redownload. I've also renamed the executable to snes9x_lua.exe by request so as to not conflict with other emulators.
In an attempt to spark interest, I'll ask the general public:
What features should a scripting language in an emulator support (ie. what should I add)?
Would there be interest in adding this to the NES, N64, or other emulators? I don't think it would be very hard.
My own suggestion would be to support drawing on the screen. If coordinates are calculated by a script, they could be rendered visually. gui.drawpixel(x,y) and gui.drawline(x1,y1,x2,y2) would be simple enough.
It would be nice to have in Mupen. It's better than the current alternative ways of watching memory addresses in that emulator, I think.
As for features... well, I'm just pulling this out of my ass- I have no idea if it's feasible- but it would be extraordinarily cool if it we could compare a character's x/y coordinates (or memory values in general) across two movies, so as to have a constant and precise gauge of whether you've lost frames over a previous video. (As per this thread.)
I'm very impressed by the power of Lua so far. Maybe it can be done?
You have access to the IO library in Lua. Have one script monitor a movie and save stats to a file. Then have a second load the stats.
The IO code in Lua can be a bit confusing though. :/
Yes, I had just assumed the scripts were limited to functions in the host program. I'm thumbing through the index of the reference manual as I type this.
It's getting very interesting.
Hee hee hee...
This would be my own suggestion, although I'd also suggest a gui.drawrectangle(x,y,w,h), or possibly gui.drawrectangle(x,y,w,h,anchorpoint) simply to avoid requiring multiple calls to C from LUA, which would presumably incur a performance hit.
For reference, anchorpoint would be an enumeration representing top-left corner, top-midpoint, top-right, center-left, center, center-right, bottom-left, bottom-midpoint, or bottom-right.
Additionally, I would add an RGB color arguement to each of these, so that, in the case of multiple hitbox and/or hotpoint types, they can be color coded
How fleeting are all human passions compared with the massive continuity of ducks.
Technically speaking yeah, but Lua is pretty fast. It also makes the C code conform pretty close to the actual Lua internal format for function calls. All in all, I don't think it would be a significant hit for any situation where images going on screen would be important (user viewing, AVI encoding)
Still, it's a good idea to include, and colour should be added as well...
Even if I don't TAS, I really liked the movie of Sparster I think, with the hitbox drawn to the screen. it could be really nice for TASer.
I personnaly likes how it was done. And it could be useful in a lot of place. Would it me possible to do gui.writetext(x,y, text)
EDIT : I don't know exactly how it works, but is it possible to enabled and disabled the some part of the scripting ?
Like I can script a convinient way to show information about the main character (like attack, defence etc) but I want it to be shown when I want (once in a while)
Getting input into the script is technically a problem for me since I have no experience with prorgamming into windows at this level. I'd basically need to make new input buttons to go with the normal SNES controllers.
But it can read the normal gamepad. If there's a button that normally does nothing (eg. Select) then you can read it as a secret script command.
I'll see if I can just extend the snes9x input code as is to support additional buttons.
I have no idea what I'm doing when I modify the windows GUI code. That one's going to be put off.
The GUI code is up and working, and I've updated the API spec. I could release an updated version right now if I wanted to.
GUI functions are draw pixel, draw line, draw box (outline only) and write text anywhere.
Edit: would eliminating this one frame drawing delay be worth doing if it made scripts just that little bit more complicated? I can allow you to specify a function to be called just before the image is drawn, allowing the updated state to be viewed and the images drawn.
Joined: 1/16/2008
Posts: 358
Location: The Netherlands
great work!
I've been playing with it for a bit and will do some more soon, but i ran into something
using "Snes9X v1.43+ v11 (beta15 + lua 0.02) for Windows" the game is not unpaused at start of execution and not paused at the end either.
script to reproduce:
framecount = 0
while (framecount<100) do
data = memory.readword(0x7e005a)
snes9x.message("x_coordinate "..data)
framecount = framecount + 1
snes9x.frameadvance()
end
does not matter what game i use
note that the message is being displayed, so the script does indeed run.
=====================================
something else i noticed, I was unable to control/change the emulator speed
script being run:
snes9x.speedmode("maximum")
framecount = 0
while framecount<100 do
framecount = framecount + 1
snes9x.frameadvance()
end
snes9x.speedmode("normal")
would expect to see the game 'skip' 100 frames, instead it just continues as usual
trying changing some settings but nothing changes (e.g. 'toggle fast forward mode' and 'pause when inactive')
Random (lame) comment: Could we have the offset needed to make Snes9x Memory Watcher work with these new Snes9x's? It would make life just a little tiny bit easier for those of us who use it :)
I thought that's what that thing in the Help menu was for. Give it a look.
And if it's not, I don't know how to help you.
(Besides, that just takes away half the point of a scriptable emulator)
I wrote a rudimentary subtitling script for translations, director's commentaries, WIP annotations, and... other purposes. It would need a lot of tweaking to make the display look right in any given game, so I didn't concern myself with making it do anything more than what I specifically needed.
Here's a package containing the script, a movie of Rushing Beat Shura (J), and my accompanying "translation." To use it, you'll need to load the ROM, start the movie, then execute the script. The script and the translation need to be in the same folder.
It was a buttload of work, and not all the kinks have been solved, but there you go.
Is there / will there be a signed version of memory.readword and/or memory.readbyte? Right now, there seems to be only an unsigned version of each.
That would be pretty useful in some scripts. (For example, the speed address in Uniracers, amongst others)
snes9x's memory algorithm only provides unsigned numbers.
If you want to convert to negative, subtract 256 or 65536 from the number as appropriate for the data size.
Eg: -1 will be reported as 255 for a 8 bit value, and 255-256=-1. Of course, the number must be >= 128 or >= 32768 before you can apply this.
Do you still want it provided via the interface anyways? It's not that it's hard, only that it's unnecessary.