Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lua support #878

Draft
wants to merge 140 commits into
base: master
Choose a base branch
from
Draft

Lua support #878

wants to merge 140 commits into from

Conversation

ihaveamac
Copy link
Contributor

@ihaveamac ihaveamac commented Nov 27, 2024

Very very work in progress! This was originally at https://github.com/ihaveamac/GM9-lua-attempt but I have moved it to a fork of this repo. (This also means there's currently some changes that should not be here, like the temporary README.)

API proposal and status

Thinking about this again, I want to figure out what a GM9 lua API would look like. So let's try this out...

Most of these should be self-explanatory, I put notes next to ones that aren't.

For functions I have actually implemented on real-lua-attempt, there will be a ✅ with the actual function signature. Ones I think could be delayed until later I have a ➡️ next to it.

Function naming

I'm not sure what's the best way to name these functions. For example, one that could check if the SD is mounted could be called:

  • sdmounted()
  • sd_mounted()
  • sd_is_mounted()
  • is_sd_mounted()
  • SDMounted()
  • SD_Mounted()
  • IsSDMounted()
  • maybe more

I decided to go with the first one where possible but I'm not invested in that being the format.

API proposal

Global constants

  • GM9VER
  • SCRIPT
  • CURRDIR
  • GM9OUT
  • HAX
  • NANDSIZE
  • CONSOLE_TYPE - "O3DS" or "N3DS"
  • IS_DEVKIT

ui

  • void ui.echo(string text)
  • bool ui.ask(string text)
  • int ui.ask_hex(string text, int initial, int n_digits)
  • int ui.ask_number(string text, int initial)
  • string ui.ask_text(string prompt, string initial, int max_length)
  • int ui.ask_selection(string prompt, array options)
  • void ui.clear()
  • void ui.show_png(string path)
  • void ui.show_text(string text)
  • void ui.show_game_info(string path)
  • void ui.show_qr(string text, string data)
  • void ui.show_text_viewer(string text)
  • void ui.show_file_text_viewer(string path)
  • string ui.format_bytes(int bytes)
  • bool ui.check_key(string key)

fs

  • void fs.move(string src, string dst[, table opts {bool no_cancel, bool silent, bool overwrite, bool skip_all}])
  • void fs.remove(string path[, table opts {bool recursive}])
  • void fs.copy(string src, string dst[, table opts {bool calc_sha, bool sha1, bool no_cancel, bool silent, bool overwrite, bool skip_all, bool append, bool recursive}])
  • void fs.mkdir(string path)
  • array fs.list_dir(string path)
  • array fs.stat(string path)
  • array fs.stat_fs(string path)
  • array fs.dir_info(string path)
  • string fs.ask_select_file(string prompt, string path[, bool opts {bool include_dirs, bool explorer}])
  • string fs.ask_select_dir(string prompt, string path[, bool opts {bool explorer}])
  • string fs.find(string pattern[, bool opts {bool first}])
  • string fs.find_not(string pattern)
  • array fs.find_all(string dir, string pattern[, table opts {bool recursive}])
  • bool fs.allow(string path[, table flags {bool ask_all}]) - will prompt for permission
  • void fs.img_mount(string path)
  • void fs.img_umount()
  • string fs.get_img_mount()
  • string fs.hash_file(string path, int offset, int size[, table opts {bool sha1}])
  • string fs.hash_data(string data[, table opts {bool sha1}])
  • bool fs.verify(string path)
  • bool fs.verify_with_sha_file(string path) - Check a file's hash with a .sha file next to it. true if passed, false if corrupt, nil if no sha file
  • bool fs.exists(string path)
  • bool fs.is_dir(string path)
  • bool fs.is_file(string path)
  • bool fs.sd_is_mounted()
  • void fs.sd_switch([string message])
  • void fs.fix_cmacs(string path)
  • string fs.read_file(string path, int offset, int size)
  • int fs.write_file(string path, int offset, string data)
  • void fs.fill_file(string path, int offset, int size, int byte) - byte should be an integer between 0x00 and 0xFF
  • void fs.make_dummy_file(string path, int size)
  • void fs.truncate(string path, int size)
  • void fs.key_dump(string file[, table opts {bool overwrite}])
  • void fs.cart_dump(string path, int size[, table opts {bool encrypted}])

title

  • ➡️ array title.get_installed(int media) - some way to determine SD or NAND, as well as EmuNAND
  • void title.decrypt(string path)
  • void title.encrypt(string path)
  • void title.install(string path[, table opts {bool to_emunand}])
  • void title.build_cia(string path[, table opts {bool legit}])
  • void title.extract_code(string src, string dst)
  • void title.compress_code(string src, string dst)
  • void title.apply_ips(string patch, string src, string target)
  • void title.apply_bps(string patch, string src, string target)
  • void title.apply_bpm(string patch, string src, string target)

sys

  • void sys.boot(string path)
  • void sys.reboot()
  • void sys.power_off()
  • string sys.region
  • string sys.serial
  • string sys.secureinfo_letter - A or B, whichever is found, or nil if somehow it's missing
  • string sys.sys_id0
  • string sys.emu_id0
  • int sys.emu_base
  • void sys.refresh_info() - refreshes the upper six variables, automatically called by preload script, but can be manually invoked if SecureInfo_* is changed
  • void sys.next_emu() - calls sys.refresh_info() automatically
  • bool sys.check_embedded_backup() - true if found or created, false if failed or user declines, nil if NCSD genuine check fails
  • bool sys.check_raw_rtc() - true if set, false if user declines

util

  • string util.bytes_to_hex(string data)
  • string util.hex_to_bytes(string hexstring)
  • string util.get_datestamp()
  • string util.get_timestamp()
  • bool util.running_as_module()

io

This is a Lua built-in module but liolib.c can't be used as-is due to fopen and friends not working properly. To have this module we need to either:

  • make fopen/etc. work (maybe with a newlib device? i don't know what i'm doing here)
  • update liolib.c to use fatfs functions (this is much harder than it seems, i already tried this before, and could make it harder to update Lua)
  • create a custom io library in C
  • create a custom io library in Lua, calling some internal interface for file i/o (this would probably be the easiest to write)

os

This is also a Lua built-in module, but @Gruetzig has already re-implemented most, if not all, of it.

Other stuff

  • The original README needs to go back, with more information about Lua added.
  • How should flags like silent, no_cancel, etc. be handled? I can think of a few ways:
    • Call a function like set_flags() before
    • Use a table as an extra argument e.g. fs.copy("S:/nand.bin", "0:/nand.bin", {silent=true, no_cancel=true})
    • Use bit flags as an extra argument e.g. fs.copy("S:/nand.bin", "0:/nand.bin", CMD_SILENT | CMD_NO_CANCEL)
  • Is there an example of the cartdump command being used?
  • ➡️ The SHA engine supports SHA224, but I can't see any place that it's actually used. I could probably add it though.

GM9Script and Lua comparison

GM9 Lua Notes
goto http://lua-users.org/wiki/GotoStatement  
labelsel ui.ask_selection  
for fs.find_all Recursive searching does not work exactly the same, it will search for the filename in all directories
keychk ui.check_key  
echo ui.echo  
qr ui.show_qr  
ask ui.ask  
input ui.ask_input  
filesel fs.ask_select_file  
dirsel fs.ask_select_dir  
set local var = value More details on variables and scoping: https://www.lua.org/pil/4.2.html
strsplit string.find and string.sub  
strrep string.gsub https://www.lua.org/manual/5.4/manual.html#pdf-string.gsub
allow fs.allow  
cp fs.copy  
mv fs.move  
inject fs.write_file  
fill fs.fill_file  
fdummy fs.make_dummy_file  
rm fs.remove  
mkdir fs.mkdir  
mount fs.img_mount  
umount fs.img_umount  
find fs.find  
findnot fs.find_not  
fget fs.write_file  
fset fs.write_file  
sha fs.hash_file OR fs.verify_with_sha_file hash_file simply returns a hash, verify_with_sha_file compares it with a corresponding .sha file
shaget fs.hash_file  
dumptxt fs.write_file Use "end" for offset to append data
fixcmac fs.fix_cmacs  
verify fs.verify  
decrypt title.decrypt  
encrypt title.encrypt  
buildcia title.build_cia  
install title.install  
extrcode title.extract_code  
cmprcode title.compress_code  
sdump fs.key_dump  
applyips target.apply_ips  
applybps target.apply_bps  
applybpm target.apply_bpm  
textview fs.show_file_text_viewer fs.show_text_viewer can be used to show text from a variable
cartdump fs.cart_dump  
isdir fs.is_dir  
exist fs.exists  
boot sys.boot  
switchsd fs.sd_switch  
nextemu sys.next_emu  
reboot sys.reboot  
poweroff sys.power_off  
bkpt bkpt  

Preview

Unlike the PREVIEW_MODE GM9Script variable, this has been split into multiple functions.

Setting Lua
“quick” and “full” (There is no alternative to view a Lua script as it’s running.)
“off” ui.clear
text ui.show_text
png file ui.show_png
game icon ui.show_game_info

Other constants

GM9 Lua Notes
DATESTAMP util.get_datestamp() Formatted like “241202”, equivalent to os.date("%y%m%d")
TIMESTAMP util.get_timestamp() Formatted like “010828”, equivalent to os.date("%H%M%S")
SYSID0 sys.sys_id0  
EMUID0 sys.emu_id0  
EMUBASE sys.emu_base  
SERIAL sys.serial  
REGION sys.region  
SDSIZE fs.stat_fs("0:/").total int instead of string (use util.format_bytes to format it)
SDFREE fs.stat_fs("0:/").free int instead of string (use util.format_bytes to format it)
NANDSIZE NANDSIZE int instead of string (use util.format_bytes to format it)
GM9OUT GM9OUT  
CURRDIR CURRDIR nil instead of “(null)” if it can’t be found
ONTYPE CONSOLE_TYPE “O3DS” or “N3DS”
RDTYPE IS_DEVKIT boolean instead of a string
HAX HAX  
GM9VER GM9VER  

ihaveamac and others added 30 commits July 23, 2023 11:34
@ihaveamac
Copy link
Contributor Author

I wrote a bunch of documentation which I think is complete for now: https://github.com/ihaveamac/GodMode9/blob/real-lua-attempt/resources/lua-doc.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants