|
| 1 | +-- example_file_io.lua |
| 2 | +-- Demonstrates the file I/O API available to Lua scripts. |
| 3 | +-- |
| 4 | +-- All paths are relative to the configured base directory (ScriptDirectory by default). |
| 5 | +-- Paths that attempt to escape the base directory (e.g. "../") are blocked and return nil. |
| 6 | +-- |
| 7 | +-- Read operations are always allowed: |
| 8 | +-- file.read(name) -> string (text content) or nil |
| 9 | +-- file.read_bytes(name) -> table of integers 0-255 (1-indexed) or nil |
| 10 | +-- file.exists(name) -> boolean |
| 11 | +-- file.list([pattern]) -> table of filenames (1-indexed), pattern defaults to "*" |
| 12 | +-- |
| 13 | +-- Write operations require AllowFileWrite: true in the "Highbyte.DotNet6502.Scripting" config section: |
| 14 | +-- file.write(name, text) -> writes/overwrites a text file |
| 15 | +-- file.append(name, text) -> appends text to a file (creates if not exists) |
| 16 | +-- file.delete(name) -> deletes a file (no-op if not found) |
| 17 | +-- |
| 18 | +-- Binary loading into emulator memory: |
| 19 | +-- emu.load(name) -> loads binary file; reads 2-byte little-endian PRG load address from header |
| 20 | +-- emu.load(name, address) -> loads raw binary file at the given address (no header parsing) |
| 21 | + |
| 22 | +-- ---- List files in the script directory ---- |
| 23 | +log.info("Files in script directory:") |
| 24 | +local files = file.list("*.lua") |
| 25 | +for i, name in ipairs(files) do |
| 26 | + log.info(" " .. i .. ": " .. name) |
| 27 | +end |
| 28 | + |
| 29 | +-- ---- Read a text file ---- |
| 30 | +local readme = "README.txt" |
| 31 | +if file.exists(readme) then |
| 32 | + local content = file.read(readme) |
| 33 | + log.info("README.txt: " .. (content or "(empty)")) |
| 34 | +else |
| 35 | + log.info("README.txt not found (skipping read)") |
| 36 | +end |
| 37 | + |
| 38 | +-- ---- Write a log file (requires AllowFileWrite: true) ---- |
| 39 | +-- If AllowFileWrite is false, file.write() raises a runtime error and this script is auto-disabled. |
| 40 | +local log_file = "frame_log.csv" |
| 41 | +file.write(log_file, "frame,pc,a,x,y\n") |
| 42 | +log.info("Logging CPU state every 60 frames to " .. log_file) |
| 43 | + |
| 44 | +-- ---- Binary load example (commented out — requires a PRG file in the scripts directory) ---- |
| 45 | +-- emu.load("my_program.prg") -- auto-detects load address from 2-byte PRG header |
| 46 | +-- emu.load("raw_data.bin", 0xC000) -- loads raw binary at address $C000 (no header) |
| 47 | + |
| 48 | +-- ---- Read binary bytes ---- |
| 49 | +-- local bytes = file.read_bytes("patch.bin") |
| 50 | +-- if bytes then |
| 51 | +-- log.info("patch.bin: " .. #bytes .. " bytes") |
| 52 | +-- -- Example: apply the first 16 bytes as a patch at $8000 |
| 53 | +-- for i = 1, math.min(16, #bytes) do |
| 54 | +-- mem.write(0x8000 + i - 1, bytes[i]) |
| 55 | +-- end |
| 56 | +-- end |
| 57 | + |
| 58 | +-- ---- Coroutine loop: append a CSV row every 60 frames ---- |
| 59 | +while true do |
| 60 | + emu.frameadvance() |
| 61 | + local frame = emu.framecount() |
| 62 | + if frame % 60 == 0 then |
| 63 | + -- log.debug(string.format("Frame %d: PC=$%04X A=$%02X X=$%02X Y=$%02X", |
| 64 | + -- frame, cpu.pc, cpu.a, cpu.x, cpu.y)) |
| 65 | + local row = string.format("%d,$%04X,$%02X,$%02X,$%02X\n", |
| 66 | + frame, cpu.pc, cpu.a, cpu.x, cpu.y) |
| 67 | + file.append(log_file, row) |
| 68 | + end |
| 69 | +end |
0 commit comments