1 2
5 6 7 8 9
Amaraticando
It/Its
Editor, Player (158)
Joined: 1/10/2012
Posts: 673
Location: Brazil
Good idea! Edited the post.
Editor, Expert player (2315)
Joined: 5/15/2007
Posts: 3856
Location: Germany
I can't find a lua function that closes the script. Does it exist?
Amaraticando
It/Its
Editor, Player (158)
Joined: 1/10/2012
Posts: 673
Location: Brazil
AFAIK, there's no way to do it. If you're inside a while true do end outside any function, simply use return or do return end. If there's any registered function in BizHawk, use event.unregisterbyname or event.unregisterbyid. os.exit() is not suitable for this, because it closes the emulator as well.
Skilled player (1707)
Joined: 9/17/2009
Posts: 4952
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
What's a "good" way to assign values on the fly depending on the rom? Right now, this game has 2 versions: Power and Speed. The addresses for the former are basically the same as Speed version, but everything is +0x10 position-wise. Right now, I'm hopping back and forth between the 2 games, so I made while loops that check if one of the values in ROM say "SPEED/POWER", then copying the display code twice: Example:
Language: lua

while true do while version() == "Speed" do gui.text(0,45,"BOSS: "..memory.readbyte(Speed.Boss).." State: "..memory.readbyte(Speed.State)) gui.text(0,250,"MAP: "..memory.readbyte(Speed.Map).."("..string.format('%.6f',memory.read_u32_le(Speed.Player_X)/65536.0)..","..string.format('%.6f',memory.read_u32_le(Speed.Player_Y)/65536.0)..")") gui.text(0,265,"$: "..memory.read_u32_le(Speed.Money)) emu.frameadvance() end while version() == "Power" do gui.text(0,45,"BOSS: "..memory.readbyte(Power.Boss).." State: "..memory.readbyte(Power.State)) gui.text(0,250,"MAP: "..memory.readbyte(Power.Map).."("..string.format('%.6f',memory.read_u32_le(Power.Player_X)/65536.0)..","..string.format('%.6f',memory.read_u32_le(Power.Player_Y)/65536.0)..")") gui.text(0,265,"$: "..memory.read_u32_le(Power.Money)) emu.frameadvance() end emu.frameadvance() end
Is there a way such that I can make this more compact rather than copy-paste twice? Naively wrapping it into version() instead simply moves this code into that function, which doesn't solve it.
Editor, Skilled player (1172)
Joined: 9/27/2008
Posts: 1085
Language: lua

local MemoryMap= { Speed= { --Version name. Boss = 0x00000000, --Your list of addresses. State = 0x00000001, Map = 0x00000002, Player_X= 0x00000003, Player_Y= 0x00000004, Money = 0x00000005 }, Power= { --The other version's name. Boss = 0x00000010, State = 0x00000011, Map = 0x00000012, Player_X= 0x00000013, Player_Y= 0x00000014, Money = 0x00000015 } } while true do local v= version() if v and MemoryMap[v] then v= MemoryMap[v] gui.text(0,45,"BOSS: "..memory.readbyte(v.Boss).." State: "..memory.readbyte(v.State)) gui.text(0,250,"MAP: "..memory.readbyte(v.Map).."("..string.format('%.6f',memory.read_u32_le(v.Player_X)/65536.0)..","..string.format('%.6f',memory.read_u32_le(v.Player_Y)/65536.0)..")") gui.text(0,265,"$: "..memory.read_u32_le(v.Money)) end emu.frameadvance() end
This would be my attempt. Basically, create a table with more tables inside, keyed to "Power" and "Speed". Once you know which version you're using, fetch the appropriate table using the key string, then use that fetched table like you did in your copied code. Naturally, you'll need to know the addresses of each version, but in case there's a few variables that aren't simply 0x10 apart between versions, you can specify that in your tables.
Skilled player (1707)
Joined: 9/17/2009
Posts: 4952
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
Skilled player (1707)
Joined: 9/17/2009
Posts: 4952
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
Sorry to bother again, but how do I save a text file as unicode encoding? Right now, if I had a line such as
local file = io.open("test.txt", "w+")
io.output(file)
io.write("(ドーン)")
io.close(file)
Opening back the test.txt file gives (???). How do I save the text file using lua as unicode encoded? Edit: I did it. At the beginning of the file write this:
io.write("\239\187\191")
This saves as UTF-8. Open a new text file in notepad or whatever and copy paste the unicode character. Now save that as UTF-8. Open in a hex editor and see how it looks like. It should appear after the bytes "EF BB BF". In my case, ドーン corresponds to. "E3 83 89 E3 83 BC E3 83 B3". Change every byte to decimal, and escape them as /ddd where d is a digit. For instance, "E3 83 89 E3 83 BC E3 83 B3" becomes "\227\131\137\227\131\188\227\131\179". Do that for every single unicode character you wish to encode. So the code for instance would now look like this
local file = io.open("test.txt", "w+")
io.output(file)
io.write("\239\187\191(\227\131\137\227\131\188\227\131\179)")
io.close(file)
This outputs a txt file that shows (ドーン).
Masterjun
He/Him
Site Developer, Skilled player (1971)
Joined: 10/12/2010
Posts: 1179
Location: Germany
Or you just save the script file in UTF-8 encoding and later open the created file in UTF-8 encoding, too. Sounds easier doesn't it? Btw, in Lua 5.3 you can insert a specific UTF-8 encoding of a Unicode character into a string by using the escape \u{XXX} where XXX are one or more hexadecimal digits. It also provides a native utf8 library with for example utf8.char().
Warning: Might glitch to credits I will finish this ACE soon as possible (or will I?)
Skilled player (1707)
Joined: 9/17/2009
Posts: 4952
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
Masterjun wrote:
Or you just save the script file in UTF-8 encoding and later open the created file in UTF-8 encoding, too. Sounds easier doesn't it? Btw, in Lua 5.3 you can insert a specific UTF-8 encoding of a Unicode character into a string by using the escape \u{XXX} where XXX are one or more hexadecimal digits. It also provides a native utf8 library with for example utf8.char().
Oh thanks! And the reason I'm doing this is because I want to output certain stats of a japanese game into a text file so I can copy paste it to another site.
Editor, Expert player (2315)
Joined: 5/15/2007
Posts: 3856
Location: Germany
I'm trying to figure out a problem. This picture should sum it up nicely Can't pastebin the code because for some reason my browser hangs when I use pastebin. But here is the most important code. Hope someone can help
Language: Lua

local NPCPreviewTable = {} local AddressTableNPC = { ["FPC"] = {[1]= {0,"FPC",0xFFB0B0B0}, [2] = {1,"X",0xFFFFD080,"EWRAM",0x10,4,true,nil,nil,nil}, [3] = {1,"Y",0xFFFFD080,"EWRAM",0x14,4,true,nil,nil,nil}, [4] = {1,"Z",0xFFFFD080,"EWRAM",0x18,4,true,nil,nil,nil}, [5] = {1,"Altitude",0xFFFFD080,"EWRAM",0x1C,4,true,nil,nil,nil}, }, ["FCHR"] = {[1]= {0,"FCHR",0xFFB0B0B0}, [2] = {1,"X",0xFFFFD080,"EWRAM",0x10,4,true,nil,nil,nil}, [3] = {1,"Y",0xFFFFD080,"EWRAM",0x14,4,true,nil,nil,nil}, }, ["FBRD"] = {[1]= {0,"FBRD",0xFFB0B0B0}, [2] = {1,"X",0xFFFFD080,"EWRAM",0x10,4,true,nil,nil,nil}, [3] = {1,"Y",0xFFFFD080,"EWRAM",0x14,4,true,nil,nil,nil}, }, ["FMON"] = {[1]= {0,"FMON",0xFFB0B0B0}, [2] = {1,"X",0xFFFFD080,"EWRAM",0x10,4,true,nil,nil,nil}, [3] = {1,"Y",0xFFFFD080,"EWRAM",0x14,4,true,nil,nil,nil}, }, ["FMCH"] = {[1]= {0,"FMCH",0xFFB0B0B0}, [2] = {1,"X",0xFFFFD080,"EWRAM",0x10,4,true,nil,nil,nil}, [3] = {1,"Y",0xFFFFD080,"EWRAM",0x14,4,true,nil,nil,nil}, }, ["FBRL"] = {[1]= {0,"FBRL",0xFFB0B0B0}, [2] = {1,"X",0xFFFFD080,"EWRAM",0x10,4,true,nil,nil,nil}, [3] = {1,"Y",0xFFFFD080,"EWRAM",0x14,4,true,nil,nil,nil}, }, ["FRCK"] = {[1]= {0,"FRCK",0xFFB0B0B0}, [2] = {1,"X",0xFFFFD080,"EWRAM",0x10,4,true,nil,nil,nil}, [3] = {1,"Y",0xFFFFD080,"EWRAM",0x14,4,true,nil,nil,nil}, }, ["FSPL"] = {[1]= {0,"FSPL",0xFFB0B0B0}, [2] = {1,"X",0xFFFFD080,"EWRAM",0x10,4,true,nil,nil,nil}, [3] = {1,"Y",0xFFFFD080,"EWRAM",0x14,4,true,nil,nil,nil}, }, ["FBLK"] = {[1]= {0,"FBLK",0xFFB0B0B0}, [2] = {1,"X",0xFFFFD080,"EWRAM",0x10,4,true,nil,nil,nil}, [3] = {1,"Y",0xFFFFD080,"EWRAM",0x14,4,true,nil,nil,nil}, }, ["FPSB"] = {[1]= {0,"FPSB",0xFFB0B0B0}, [2] = {1,"X",0xFFFFD080,"EWRAM",0x10,4,true,nil,nil,nil}, [3] = {1,"Y",0xFFFFD080,"EWRAM",0x14,4,true,nil,nil,nil}, }, ["SBLK"] = {[1]= {0,"SBLK",0xFFB0B0B0}, [2] = {1,"X",0xFFFFD080,"EWRAM",0x10,4,true,nil,nil,nil}, [3] = {1,"Y",0xFFFFD080,"EWRAM",0x14,4,true,nil,nil,nil}, }, } local updateNPCPreviewTable = function() NPCPreviewTable={} AddressTableDisplayOffset["NPCPreview"]=0 memory.usememorydomain("IWRAM") basepointer=0x0D7C -- this might be version specific basepointer=memory.read_u16_le(basepointer) + 0x28 startingaddress=memory.read_u16_le(basepointer) - 0x04 memory.usememorydomain("EWRAM") --going through the 32 slots for z=1,32,1 do if memory.read_u32_le(startingaddress) == 0x00435046 then npctype="FPC" -- Field Player Character (e.g. Mario, Luigi) nextslot=0x39C elseif memory.read_u32_le(startingaddress) == 0x52484346 then npctype="FCHR" -- Field Character (e.g. NPC) nextslot=0x34C elseif memory.read_u32_le(startingaddress) == 0x44524246 then npctype="FBRD" -- Field Board (e.g. pedal) nextslot=0x34C elseif memory.read_u32_le(startingaddress) == 0x4E4F4D46 then npctype="FMON" -- Field Monster nextslot=0x358 elseif memory.read_u32_le(startingaddress) == 0x48434D46 then npctype="FMCH" -- ? nextslot=0x358 elseif memory.read_u32_le(startingaddress) == 0x4C524246 then npctype="FBRL" -- Field Barrel nextslot=0x34C elseif memory.read_u32_le(startingaddress) == 0x4B435246 then npctype="FRCK" -- Field Rock nextslot=0x34C elseif memory.read_u32_le(startingaddress) == 0x4C505346 then npctype="FSPL" -- Field Special nextslot=0x34C elseif memory.read_u32_le(startingaddress) == 0x4B4C4246 then npctype="FBLK" -- Field Block (e.g. saveblocks, special blocks) nextslot=0x360 elseif memory.read_u32_le(startingaddress) == 0x42535046 then npctype="FPSB" -- ? nextslot=0x5C elseif memory.read_u32_le(startingaddress) == 0x4B4C4253 then npctype="SBLK" -- Block nextslot=0x360 else break end NPCPreviewTable[z]=AddressTableNPC[npctype] print("z: " .. z .. " " .. NPCPreviewTable[1][2][5]) for r=2,table.getn(NPCPreviewTable[z]),1 do print("z: " .. z .. " r: " .. r .. " " .. NPCPreviewTable[1][2][5]) NPCPreviewTable[z][r][5]=NPCPreviewTable[z][r][5]+startingaddress print("z: " .. z .. " r: " .. r .. " " .. NPCPreviewTable[1][2][5]) end if nextslot~=nil then startingaddress=startingaddress+nextslot end end end
Masterjun
He/Him
Site Developer, Skilled player (1971)
Joined: 10/12/2010
Posts: 1179
Location: Germany
Good thing there were those Emoji's in the image or otherwise I wouldn't have been able to understand that I'm supposed to think. Tables in Lua are saved by their references.
Warning: Might glitch to credits I will finish this ACE soon as possible (or will I?)
Editor, Skilled player (1172)
Joined: 9/27/2008
Posts: 1085
Ah, I know the problem! Table references! Mostly, I'm focusing on this line here: NPCPreviewTable[z]=AddressTableNPC[npctype] What is AddressTableNPC? Well, it's a table containing other tables. AddressTableNPC[npctype] gives you the table stored there. It is not a copy of the table. It is the table. Multiple variables assigned to the same table means anything that affects one variable will also affect what other variables return. So, when NPCPreviewTable[2] is set equal to the same table as NPCPreviewTable[1], any changes to the table in NPCPreviewTable[2] will also be reflected in NPCPreviewTable[1], because they are the same table. You just set the two spots equal to the same table, therefore they reference the same table. The solution is likely to construct a new table, copy what you need into that table, rather than setting something equal to the existing table. EDIT: A second look, and you actually have another layer of tables I didn't immediately spot. The copy gets a little more involved, as simply creating one new table and copying elements of the top table means you have references to the sub-tables, as opposed to new sub-tables with their own independent values. Again, the solution is to create a new table for every sub-table and copy those values over, and have this new table in an index of the main copy you're trying to make. Let's not get into recursive tables.
Amaraticando
It/Its
Editor, Player (158)
Joined: 1/10/2012
Posts: 673
Location: Brazil
This code is not very readable.
Editor, Expert player (2315)
Joined: 5/15/2007
Posts: 3856
Location: Germany
Amaraticando wrote:
This code is not very readable.
Yes, I'm sorry. I should probably have explained but the basic idea is this: AddressTableNPC contains a set of addresses (more specifically, a set of offsets) for each type of NPC. This table is hard-coded in the script and never changes. It's only supposed to be read from. NPCPreviewTable is what would be written to and updated - based on AddressTableNPC - each time I enter a new room, as that's the point when NPC memory changes. The line
 NPCPreviewTable[z][r][5]=NPCPreviewTable[z][r][5]+startingaddress
is supposed to write the actual memory address to NPCPreviewTable (calculated by taking the offset and the starting point of a slot). And then I want to read those memory addresses and display their values. I haven't tried coming up with a solution yet, but it should be doable based on your help (reference is written to NPCPreviewTable instead of the table). About readability, I could probably condense the part right after
for z=1,32,1 do
into a table. Everything else seems fine to me.
Editor, Expert player (2315)
Joined: 5/15/2007
Posts: 3856
Location: Germany
Edit: Nevermind. I guess Bizhawk doesn't like luascripts that has a trailing commented block that starts with --[[ but never ends with ]].
Editor, Expert player (2315)
Joined: 5/15/2007
Posts: 3856
Location: Germany
I'd like to run a luascript on a gameboy or GBA ROM to play self-written sound effects. Is this doable and how?
Joined: 10/23/2009
Posts: 545
Location: Where?
Here is a part of my code.
Language: lua

hotkey = input.get() if hotkey[p] == true then gui.drawText(20,20,"Test") end
So I wrote this test code. My final aim is to display stuffs only when I press one key on the keyboard. However, with this code, I'm not seeing "Test" anywhere. Did I forget something?
Skilled player (1707)
Joined: 9/17/2009
Posts: 4952
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
MUGG wrote:
I'd like to run a luascript on a gameboy or GBA ROM to play self-written sound effects. Is this doable and how?
No idea, but did you mean formats like .wav or did you mean writing to memory to play sounds?
Niamek wrote:
Here is a part of my code.
Language: lua

hotkey = input.get() if hotkey[p] == true then gui.drawText(20,20,"Test") end
So I wrote this test code. My final aim is to display stuffs only when I press one key on the keyboard. However, with this code, I'm not seeing "Test" anywhere. Did I forget something?
1. Are you using BizHawk 2.0? I tried a script that uses input.get, and it either crashes or fails. It works in 1.11.4 however. 2. I made a function something like this, and it works in 1.11.4 Download hotkey test.lua
Language: lua

function inputdelay(inputs, delay) local is = input.get() local start = false if inputs ~= nil and (is[tostring(inputs)] ~=nil) then --console.log(is) --debugging while (delay > 0) do emu.frameadvance() delay = delay -1 end start = true return start end return start end local toggle = 0 while true do if inputdelay("C",10) then toggle = 1 elseif inputdelay("V",10) then toggle = 0 end if toggle == 1 then gui.drawText(20,20,"Test") end emu.frameadvance() end
I had to specify "C" and "V" to toggle, but otherwise it worked. I tested very briefly on 2.0 as well, and it didn't immediately crash at least. The toggle is placed outside the while loop so it won't get set back to 0 every frame.
Editor, Expert player (2315)
Joined: 5/15/2007
Posts: 3856
Location: Germany
jlun2 wrote:
MUGG wrote:
I'd like to run a luascript on a gameboy or GBA ROM to play self-written sound effects. Is this doable and how?
No idea, but did you mean formats like .wav or did you mean writing to memory to play sounds?
Writing to memory. In fact, I want to write a game in lua code* and suspend the loaded ROM. I was wondering if I can make the program counter run through my own bytes and create my own sounds that way. ___ * I'm hobbyist and I don't really want to bother with (re)learning better suited languages at the moment. I'd like to see how far I can get with the bizhawk lua functions to realize a game idea I had (a top view board-like game).
Editor, Emulator Coder
Joined: 8/7/2008
Posts: 1156
Youll need to hack bizhawk to add a wav playing function for lua, probably an easy mode one built into .net
Editor, Skilled player (1172)
Joined: 9/27/2008
Posts: 1085
Niamek wrote:
if hotkey[p] == true then
This is asking for a table entry in hotkey referenced by the variable p. If you do not have p = something in your code, then it is nil, and you're not getting the value you're expecting. More likely, you want hotkey.p, which is short-hand for hotkey["p"]. Though, I think BizHawk uses the capital letters, so hotkey.P or hotkey["P"] might be what you actually want. You want table entry "P", I believe. Basically, if you're using brackets, lua will think any letters you're putting inside them are variables, unless you put quotes around them. And if you haven't defined the variable, it's likely nil.
Joined: 10/23/2009
Posts: 545
Location: Where?
I changed to "p" and it froze. IN fact, it keeps freezing each time I run the xscript. Sometimes not instantly. Jlun2 was right about that.
Editor, Skilled player (1172)
Joined: 9/27/2008
Posts: 1085
I have troubles using BizHawk 2.0 for that reason. Basically garbage collection is failing on tables, and from that, a freeze happens. Once in a while, you instead get a strange error that might refer to line negative billion or something. Unfortunately, input.get() constructs a new table every time you need some user key, so you quickly hit the garbage collector. For the moment, some functions will crash BizHawk in short order, and only code that is completely table-free stands the best chance to avoid crashing BizHawk. An older version, something before 1.13 I think, doesn't have this problem.
Joined: 10/23/2009
Posts: 545
Location: Where?
I generate a long table on my script. Should I move that outside of the main loop so it's generated only once?
Editor, Emulator Coder
Joined: 8/7/2008
Posts: 1156
you should not use lua on a version of bizhawk with buggy lua. that's all of them.
1 2
5 6 7 8 9