I edited the script to implement some optmizations I use for similar scripts I made.
Mainly, I see 3 main changes you can make:
-1)
Avoid drawing outside the emu screen, because you won't see it anyway;
-2)
Avoid reading memory in sequence inside for loops, by reading the whole memory region of interest in one call and only when some address of this region changes;
-3)
Drawing polygons merging similar tiles, instead of multiple boxes.
For optmization 1), I simply did a check if px or py is inside the emu screen:
Language: lua
if px + 4 > 0 and px <256> 0 and py < 232 then
-- draw tiles
end
For optmization 2), I changed the
readbytes of the nametable loop by simply getting the value from a table previously loaded. This table,
nametable_tiles, is loaded with readbyterange, with a special conversion for FCEUX:
Language: lua
local nametable_tiles = memory.readbyterange(0x6000, 0x7C0)
if (FCEU ~= nil) then
nametable_tiles = {string.byte(nametable_tiles, 1, 0x7C0)} -- FCEUX readbyterange returns a byte string, this is a convertion to table
end
This table is updated only when the hash of this region changes. BizHawk already has a memory hash function, which is fast. FCEUX tho doesn't, so my workaround is simply concatenation the whole nametable table into a single string, which will definitely be unique for that nametable configuration, so I can still compare:
Language: lua
local nametable_hash, nametable_hash_prev
local function Get_nametable_hash()
if (FCEU ~= nil) then
nametable_hash = table.concat({string.byte(memory.readbyterange(0x6000, 0x7C0), 1, 0x7C0)}) -- concatenating the whole table serves the purpose of a hash for comparison
elseif (bizstring ~= nil) then
nametable_hash = memory.hash_region(0x6000, 0x7C0) -- memory hash is BizHawk only
end
end
In order to check the hash change, every frame I compare the current hash with the previous frame hash:
Language: lua
if nametable_hash ~= nametable_hash_prev then
nametable_tiles = memory.readbyterange(0x6000, 0x7C0)
if (FCEU ~= nil) then
nametable_tiles = {string.byte(nametable_tiles, 1, 0x7C0)} -- FCEUX readbyterange returns a byte string, this is a convertion to table
end
end
I didn't do optmization 3), because I forgot how it's done, I never did but I know jlun or ThunderAxe did for Wario Land, it should be simple.
Anyway, just by implementing 1) and 2), the FPS for the first room of the game jumped from 30 to 55.