
Prev | Project Journal Entries | Github | Next
One of the first requirements of the bot app will be having the ability to read and write from the NES memory dynamically. The easiest way to accomplish this will be to use the built in ability of the FCEUX emulator to use LUA scripts to manipulate the RAM. We will eventually also need to catalog the memory addresses of interest that we will want to read and write to. Since an LLM will need to understand what each memory address does, I have a JSON catalog with descriptions of what each address controls in mind.
The FFBot will use a RAMdisk to provide a location for the LUA scripts to write NES memory for the bot app to read and consume, as well as provide a location for the bot app to drop executable LUA scripts when it wants to write to NES memory. Since the main LUA daemon will need to execute at least once a second (possibly more frequently) to create a real-time communication between the bot and the NES, RAMdisk will be a faster approach than doing so many reads and writes on a physical disk.
I envision a JSON catalog on the RAMdisk that maps NES RAM addresses to verbose descriptions of what each memory location controls, so that the LLM will be able to better understand how to manipulate the RAM based on requests it gets. The LUA scripts will also dump the real-time memory values in JSON format for the LLM to consume. This means LUA will need to interact with JSON, which it cannot natively. After doing some research I settled on using the lunajson library. I updated the README with instructions to install.
I also decided to create a bash script that will contain configuration and set up the environment for the user. The script is so far responsible for:
I've also created the first version of the LUA daemon. So far only capable of writing to the NES memory (not yet capable of dumping the NES RAM). The first version of the LUA daemon looks like this:
local RAMDISK_DIR = os.getenv("RAMDISK_DIR")
local LUA_PACKAGE_DIR = os.getenv("LUA_PACKAGE_DIR")
local EXECUTION_CADENCE = 30 -- NES / FCEUX runs at about 60 frames per second
local frame_count = 0
package.path = package.path .. ";" .. LUA_PACKAGE_DIR .. "?.lua"
local json = require("lunajson")
while true do
if (frame_count < EXECUTION_CADENCE) then
frame_count = frame_count + 1
else
frame_count = 0
local result = dofile(RAMDISK_DIR .. "execute.lua")
if (result) then
print("Executed a script")
io.open(RAMDISK_DIR .. "execute.lua","w"):close() -- clear contents of execute.lua
end
end
emu.frameadvance() -- crucial for allowing the emulator to advance a frame
end
So far the daemon successfully loads the lunajson package (which it does not yet use, that is yet to come), and implements a main execution loop. I've learned that the NES runs at approximately 60 frames per second (FPS). I created an EXECUTION_CADENCE constant to specify how many frames should execute before the daemon actually does something itself. It's currently set to 30, meaning the daemon will actually "do it's thing" twice per second. What it currently does is check the contents of a file called execute.lua on the RAMdisk. In the future, the LLM / FFBot app will be able to place lua script contents into this file to update NES RAM.