This is the API from DeHackEd's version of Lua in ZSnes. At the time of writing, FCUE's Lua was based on this API.

Basics

Your code will be run alongside the emulator's main loop. You code should probably look roughly like this:
-- initialization goes here
while condition do
   -- Code executed once per frame
 
   snes9x.frameadvance()


end

-- Cleanup goes here

When Lua execution starts, the emulator will be automatically unpaused if it is currently paused. If so, it will automatically be paused when the script exits, voluntarily or otherwise. This allows you to have a script execute some work on your behalf and then when it exits the emulator will be paused, ready for the player to continue use.

Base library

Handy little things that are not put into a class. Mostly binary operations right now.
int AND(int arg1, int arg2, ..., int argn)
Since Lua lacks binary operators and since binary will come up with memory manipulation, I offer this function. Output is the binary AND of all its parameters together. Minimum 1 argument, all integers.

At a binary level, the AND of two binary bits is 1 if both inputs are 1, and the output is 0 in any other case. Commonly used to test if a bit is set by ANDing with a number with only the desired position set to 1.


int OR(int arg1, int arg2, ..., int argn)
The OR of two bits is 1 if either of the inputs is 1, and 0 if both inputs are 0. Typically used to force a single bit to 1, regardless of its current state.
int XOR(int arg1, int arg2, ..., int argn)
XOR flips bits. An even number of 1s yields a zero and an odd number of 1s yields a 1. Commonly used to toggle a bit by XORing.
int BIT(int which)
Returns a number with only the given bit set. which is in the range from 0 to 15 since the SNES is a 16 bit system. BIT(15) == 32768

... Actually this system will accept a range of 0 to 30, but none of the memory access functions will accept it, so you're on your own for those. 31 is not allowed for now due to signedness risking wreaking havoc.

snes9x

Basic master emulator control.
snes9x.speedmode(string mode)
Selects the speed mode snes9x should run at while Lua is in control of frame advance. It must be set to one of the following: In modes other than normal, pause will have no effect.
snes9x.frameadvance()
Snes9x executes one frame. This function pauses until the execution finishes. General system slowdown when running at normal speed (ie. sleeping for 1/60 seconds) also occurs here when not in high speed mode.

Warning: Due to the way the code is written, the times this function may be called is restricted. Norably, it must not be called within a coroutine or under a [x]pcall(). You can use coroutines for your own purposes, but they must not call this function themselves. Furthermore, this function cannot be called from any "registered" callback function. An error will occur if you do.


snes9x.message(string msg)
Displays the indicated string on the user's screen. snes9x.speedmode("normal") is probably the only way this is of any use, lest the message not be displayed at all
snes9x.pause()
v0.05+ only
Pauses the emulator. This function blocks until the user unpauses.

This function is allowed to be called from outside a frame boundary (ie. when it is not allowed to call snes9x.frameadvance). In this case, the function does not wait for the pause because you can't pause midway through a frame. Your code will continue to execute and the emulator will be paused at the end of the current frame. If you are at a frame boundary, this function acts a lot like snes9x.frameadvance() plus the whole pause thing.

It might be smart to reset the speed mode to "normal" if it is not already so.


snes9x.wait()
v0.06+ only
Skips emulation of the next frame. If your script needs to wait for something to happen before proceeding (eg. input from another application) then you should call this. Otherwise the GUI might jam up and your application will not appear to be responding and need termination. It is expected that this function will pause the script for 1/60 of a second without actually running the emulator itself, though it tends to be OS-dependent right now.

If you're not sufficiently confused yet, think of this as pausing for one frame.

If you need to do a large amount of calculations -- so much that you risk setting off the rampant script warning, just call this function every once in a while.

Might want to avoid using this if you don't need to. If the emulator is running at normal speed, paused and the user presses frame-advance, they might be confused when nothing happens.

memory

Memory access and manipulation.
int memory.readbyte(int address)
int memory.readword(int address)
Reads a number of bits (8 or 16) and returns the memory contents. The address must be a fully qualified memory address. The RAM range is 0x7e0000 through 0x7fffff, but you may use any memory address, including the ROM data itself.
int memory.readbytesigned(int address)
int memory.readwordsigned(int address)
v0.04+ only
Same as its counterparts, except numbers will be treated as signed. Numbers larger than 127 for bytes and 32767 for words will be translated into the correct negative numbers. For reference, an alternate formula is to subtract 256 for bytes and 65536 for words from any number equal to or larger than half that number. For example, a byte at 250 becomes 250-256 = -6.

memory.writebyte(int address, int value)
memory.writebyte(int address, int value)
Writes a number of bits (8 or 16) to the indicated memory address. The address MUST be in the range of 0x7e0000 through 0x7fffff.
memory.register(int address, function func)
When the given memory address is written to (range must be 0x7e0000 to 0x7fffff), the given function will be called. The execution of the CPU will be paused mid-frame to call the given function.

Only one function can be registered with a memory address. 16 bit writes will only trigger the lower address listener. There is no distinction between 8 and 16 bit writes. func may be nil in order to delete a function from listening.

Code called may not call snes9x.frameadvance() or any savestate save/load functions, and any button manipulation results are undefined. Those actions are only meaningful at frame boundaries.

joypad

Access to the gamepads. Note that Lua makes some joysticks do strange things. Setting joypad inputs causes the user input for that frame to be ignored, but only for that one frame.

Joypads are numbered 1 to 5.

Joypad buttons are selected by use of a table with special keys. The table has keys start, select, up, down, left, right, A, B, X, Y, L, R. Note the case is sensetive. Buttons that are pressed are set to a non-nil value (use of the integer 1 is just a convention). Note that "false" is valid, but discouraged as testing for logical true will fail.

Currently reading input from a movie file is not possible, but a movie will record button presses from Lua.

table joypad.read(int which)
Returns a table indicating which buttons are pressed by the user. This is probably the only way to get input to the script by the user. This is always user input, even if the joypads have been set by joypad.set.
joypad.set(int which, table buttons)
Sets the buttons to be pressed. These choices will be made in place of what the user is pressing during the next frame advance; they are then discarded, so this must be called once every frame, even if you just want to keep the same buttons pressed for several frames.

savestate

Control over the savestate process. Savestate objects are opaque structures that represent non-player accessible states (except for the functions that return "official" savesates). Such an object is garbage collectable, in which case the savestate is no longer usable. Recycling of existing