Full Metal
C(++) Developer.
- 810
- Posts
- 17
- Years
- In my mind.
- Seen Aug 19, 2018
This is just a fun experiment on my part. Something that troubled me when I was more active in the ROM hacking scene was that scripting many practical things involved annoying practices (re: loops, and similar.)
My solution for this is fairly simple: create a pre-processor / compiler. Obviously I didn't want to put effort into writing a lexer or anything; others exist and are far better than one I could make. So I made a super simple library in python that would allow you to use python to make pokemon scripts (though it could easily be modified to make something like brainfuck or other vm based languages.)
The github repository can be found here.
Here's the code from my sample script which displays a text box at some arbitrary location:
I created the frlg module using data provided here. that I extracted using this javascript in the browser console window:
Usage is simple enough:
Which will (currently) give you a compiled bytecode that you can paste in a hex editor. Plans for the future involve a free space searcher which will allow you to reference other script blocks that are dynamically allocated and output this as an IPS patch, or Darthatrons patch format which is easily undone, which allows for simpler debugging.
If I really want to make this thing cool, I will add memory inspection for VBA to modify the ROMS runtime memory, but I would not hold my breath as that's a lot of effort and time I don't have really.
If you would like to contribute, making a json file similar to the one I made for fr/lg for other games would be appreciated. I believe many of the commands are shared, but I don't know for sure which ones are and are not.
My solution for this is fairly simple: create a pre-processor / compiler. Obviously I didn't want to put effort into writing a lexer or anything; others exist and are far better than one I could make. So I made a super simple library in python that would allow you to use python to make pokemon scripts (though it could easily be modified to make something like brainfuck or other vm based languages.)
The github repository can be found here.
Here's the code from my sample script which displays a text box at some arbitrary location:
Code:
import frlg
from scripting import script_section
@script_section
def sample_text_display(text_location):
yield frlg.lock()
yield frlg.faceplayer()
yield frlg.preparemsg(text_location)
yield frlg.closeonkeypress()
yield frlg.release()
yield frlg.end()
if __name__=="__main__":
import sys
# I don't actually know of any text locations off the top of my head lol
TEXT_LOCATION = 0x08123456
if len(sys.argv) > 1:
TEXT_LOCATION = int(sys.argv[1])
sys.stdout.buffer.write(sample_text_display(TEXT_LOCATION))
I created the frlg module using data provided here. that I extracted using this javascript in the browser console window:
Code:
function translate_command_entry(entry_element) {
arg_els = entry_element.querySelectorAll(".args > ul > li");
r = {args:[],structure:"<B",cmd:0,doc_string:"",name:''}
for(var i=0;i<arg_els.length;i++) {
a = {}
a['kind'] = arg_els[i].querySelector("span:first-child").textContent;
a['name'] = arg_els[i].lastChild.nodeValue;
r.args.push(a)
}
h = entry_element.querySelector("h3").textContent
r['cmd'] = parseInt('0x' +h);
name_start = h.indexOf(' ') + 1;
name_end = h.indexOf(' ',name_start);
if(name_end < 0) {
r['name'] = h.slice(name_start);
} else {
r['name'] = h.slice(name_start,name_end);
}
doc_els = entry_element.querySelectorAll("p");
for(var i =0;i<doc_els.length;i++) {
r['doc_string'] += doc_els[i].textContent;
r['doc_string'] += '\n\n';
}
kind_to_struct_tbl = {
word: "H",
byte: 'B',
dword: 'I',
pointer: 'I',
variable: 'H',
flag: 'H',
bank: 'B',
buffer: 'B',
'hidden-variable': 'B',
'pointer-or-bank': 'I',
'pointer-or-bank-0': 'I',
'flag-or-variable': "H",
'word-or-variable': "H",
'byte-or-variable': 'H'
}
for(var i=0;i<r['args'].length;i++) {
r['structure'] += kind_to_struct_tbl[r['args'][i]['kind']];
r['doc_string'] += r['args'][i]['kind'] + ':\t' + r['args'][i]['name'] + '\n';
}
r['doc_string'] = r['doc_string'].trim();
return r;
}
var all_cmds = [];
for(var i=0;i<e_list.length;i++) {
all_cmds.push(translate_command_entry(e_list[i]));
}
clear();
console.log(JSON.stringify(all_cmds))
Usage is simple enough:
Code:
sample.py >script.bin
Which will (currently) give you a compiled bytecode that you can paste in a hex editor. Plans for the future involve a free space searcher which will allow you to reference other script blocks that are dynamically allocated and output this as an IPS patch, or Darthatrons patch format which is easily undone, which allows for simpler debugging.
If I really want to make this thing cool, I will add memory inspection for VBA to modify the ROMS runtime memory, but I would not hold my breath as that's a lot of effort and time I don't have really.
If you would like to contribute, making a json file similar to the one I made for fr/lg for other games would be appreciated. I believe many of the commands are shared, but I don't know for sure which ones are and are not.