Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

File I/O

CLOSE · SAVETEXT · SQL · WRITE · call_sql · deserialize · eof · fetch · fileexists · files · isopen · jmes · loadjson · loadtext · loc · lof · open · open_database · readline · serialize


CLOSE

Finishes with a file. What was written to it is saved now.

CLOSE file
close(file)

Parameters

  • file

Example

SCREEN 320, 240
file = OPEN("save.txt") !! output
WRITE file, "checkpoint", 2
CLOSE file
PRINT EXISTS("save.txt")

Notes

It’s also the function close, for when you want what it gives back.

SAVETEXT

Saves text as a file in the game’s folder, in place of what was there.

SAVETEXT path, content
savetext(path, content)

Parameters

  • path AS STRING
  • content AS STRING

Example

SCREEN 320, 240
SAVETEXT "notes.txt", "remember the key"
PRINT LOADTEXT("notes.txt")

Notes

It’s also the function savetext, for when you want what it gives back.

SQL

Defines a statement for a database, by name: USE lines for its parameters, NULLS lines, then the SQL itself, with each parameter as @name.

A USE line’s DEFAULT and a NULLS value are a number of 0 or more, or a string. For a negative one, let the SQL choose it: SELECT COALESCE(seconds, -1) AS seconds. A USE or NULLS line that can’t be read stops the program at the block, naming the line.

SQL name
    ...
END SQL

Parameters

  • name AS STRING - What the statement is called, for CALL_SQL.

Example

SCREEN 320, 240
SQL "make"
    CREATE TABLE IF NOT EXISTS scores (name TEXT, points INTEGER)
END SQL
SQL "add"
    USE STRING name
    USE NUMBER points
    INSERT INTO scores (name, points) VALUES (@name, @points)
END SQL
SQL "all"
    SELECT name, points FROM scores ORDER BY points DESC
END SQL
db = OPEN_DATABASE("scores.db") !! writable
CALL_SQL(db, "make")
CALL_SQL db, "add" !! name("ada") points(100)
FOR row = CALL_SQL(db, "all")
    PRINT row.name, row.points
END FOR
CLOSE db

Notes

Opens a block of text. I don’t read it: I hand it over just as you wrote it. It’s sql.

WRITE

Writes its values to a file as one line, with a space between them.

WRITE file, values...
write(file, values...)

Parameters

  • file
  • values…

Example

SCREEN 320, 240
file = OPEN("log.txt") !! output
WRITE file, "level", 3, "cleared"
CLOSE file
PRINT LOADTEXT("log.txt")

Notes

It’s also the function write, for when you want what it gives back.

call_sql

Runs a statement a SQL block named. A statement that reads gives its rows, each a map of its columns; one that writes gives rows_affected and last_id.

call_sql(database, name AS STRING, values = NULL)

Parameters

  • database - What OPEN_DATABASE gave.
  • name AS STRING - The SQL block’s name.
  • values = NULL - The statement’s parameters. Each is written by its name after !!.

Example

SCREEN 320, 240
SQL "make"
    CREATE TABLE IF NOT EXISTS scores (name TEXT, points INTEGER)
END SQL
SQL "add"
    USE STRING name
    USE NUMBER points
    INSERT INTO scores (name, points) VALUES (@name, @points)
END SQL
SQL "top"
    USE NUMBER least DEFAULT 0
    SELECT name, points FROM scores
    WHERE points >= @least
    ORDER BY points DESC
END SQL
db = OPEN_DATABASE("scores.db") !! writable
CALL_SQL(db, "make")
CALL_SQL db, "add" !! name("ada") points(100)
CALL_SQL db, "add" !! name("bob") points(80)
best = CALL_SQL(db, "top") !! least(90)
FOR row = best
    PRINT row.name, row.points
END FOR
CLOSE db

deserialize

Parses a JSON string back into its original data structure. Used to restore game state, player data, settings, and other complex data from storage. Accepts any valid JSON, including data from external APIs or files.

deserialize(serialized_data)

Parameters

  • serialized_data - A JSON string, typically from serialize or LOADTEXT

Example

SCREEN 320, 240
saved = "{\"name\": \"ada\", \"level\": 3, \"items\": [\"key\", \"map\"]}"
player = deserialize(saved)
PRINT player.name, player.level, player.items(1)

eof

Returns TRUE (1) if the handle is exhausted, FALSE (0) otherwise. Works for both DATA block handles (exhausted when every value has been READ) and file-stream handles opened FOR INPUT (exhausted when every line has been read). For a closed or invalid handle, EOF returns TRUE — so a stray WHILE NOT EOF(n) on a never-opened handle terminates immediately rather than spinning.

eof(filenumber)

Parameters

  • filenumber - A file that OPEN gave

Example

SCREEN 320, 240
SAVETEXT "notes.txt", "one\ntwo\nthree"
file = OPEN("notes.txt")
WHILE NOT eof(file)
    PRINT READLINE(file)
END WHILE
PRINT eof(file)
CLOSE file

fetch

Synchronous HTTP client. Returns an Object with exactly two fields: STATUSCODE (Integer) and MESSAGE (String). On success, STATUSCODE is the HTTP status (200, 404, 500, …) and MESSAGE is the response body as text. On failure to complete an HTTP exchange (DNS failure, connection refused, TLS error, invalid URL, invalid method, timeout), STATUSCODE is 0 and MESSAGE is a human-readable error description. Network errors do NOT halt the interpreter — the BASIC program detects them via STATUSCODE. A non-Object headers argument is handled the same way (STATUSCODE=0 with the error in MESSAGE; it does not halt). Only a wrong argument count halts.

fetch(url, method, body = NULL, headers = NULL)

Parameters

  • url - Full URL of the resource
  • method - HTTP method (case-insensitive: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, …)
  • body = NULL - Optional body. String sent as-is. Object/Array auto-encode as JSON with Content-Type: application/json. Other types stringified.
  • headers = NULL - Optional 4th-arg Object of header names → values (e.g. {“Authorization”: “Bearer xyz”})

Example

SCREEN 320, 240
answer = fetch("not a url", "GET")
// A request that never reached a server answers 0, with why in MESSAGE
IF answer.statuscode = 0
    PRINT "no answer:", LEN(answer.message) > 0
ELSE
    PRINT answer.statuscode
END IF

fileexists

Checks whether a file exists in the project’s local storage (the same VFS that LOADTEXT, SAVETEXT, and OPEN use). Returns 1 if the file is present, 0 otherwise.

fileexists(filename)

Parameters

  • filename - Path to test, same form accepted by LOADTEXT / OPEN

Example

SCREEN 320, 240
PRINT fileexists("save.txt")
SAVETEXT "save.txt", "checkpoint 2"
PRINT fileexists("save.txt")

files

Returns a 1D array of filenames in the bus root or in path. Used to discover what’s loadable / saved / available without hardcoding lists in BASIC.

files
files(path = NULL)

Parameters

  • path = NULL - Optional directory inside the bus root. Omit (or pass empty) for the root.

Example

SCREEN 320, 240
SAVETEXT "notes.txt", "hello"
FOR name = files()
    IF name = "notes.txt" THEN PRINT "found", name
END FOR

isopen

Returns 1 if the given file or DATA block handle is currently open, 0 otherwise. Useful for cleanup paths that may run without knowing whether OPEN succeeded, and for guarding a CLOSE against an unopened handle (which would otherwise be a silent no-op rather than an error, but the guard reads more clearly).

isopen(filenumber)

Parameters

  • filenumber - Handle to test (1-255)

Example

SCREEN 320, 240
file = OPEN("log.txt") !! output
PRINT isopen(file)
WRITE file, "started"
CLOSE file
PRINT isopen(file)

jmes

Runs a JMESPath query against an array or object (or any value) and returns the result. JMESPath is a compact query language for JSON-like data — it reaches into nested fields, slices and filters arrays, projects values, and applies built-in functions such as max, length, and sort_by. The data is matched as if it were JSON, so objects, arrays, numbers, strings, and booleans all work.

jmes(data, query)

Parameters

  • data - An array, object, or any value to query (commonly the result of deserialize or LOADJSON)
  • query - A JMESPath query string

Example

SCREEN 320, 240
scores = [{name: "ada", points: 100}, {name: "bob", points: 80}, {name: "cy", points: 95}]
PRINT jmes(scores, "[?points > `90`].name")
PRINT jmes(scores, "max_by(@, &points).name")
PRINT jmes(scores, "length(@)")

loadjson

Loads and parses JSON data from files in the project bundle. Returns the parsed data as CrashBasic objects and arrays. Excellent for loading structured game data, level definitions, sprite configurations, and complex settings. The object comes back untyped, with no user TYPE and therefore no methods. Ending the assignment with AS typename turns it into an instance of a declared type — every declared field present, the file’s values laid over the type’s defaults. See TYPE.

loadjson(filename)

Parameters

  • filename - Name of JSON file in project bundle (relative to project root)

Example

SCREEN 320, 240
level = loadjson("level.map.json")
PRINT level.mapwidth, level.mapheight, level.tileset

loadtext

Loads text content from files in the project bundle. Returns the complete file content as a string. Ideal for loading game data, configuration files, level definitions, dialog text, and any text-based resources.

loadtext(filename)

Parameters

  • filename - Name of text file in project bundle (relative to project root)

Example

SCREEN 320, 240
notes = loadtext("input-files-notes.txt")
PRINT LEN(notes) > 0
SAVETEXT "hello.txt", "hi there"
PRINT loadtext("hello.txt")

loc

Returns the current read/write position of an open handle. For a DATA block handle, this is the 0-based index of the next value to be read. For a file-stream handle (OPEN … FOR INPUT / OUTPUT / APPEND), this is the 0-based line number — how many lines have been read or written so far. Returns -1 if the handle is closed or invalid.

loc(filenumber)

Parameters

  • filenumber - Handle from OPEN or OPEN DATA

Example

SCREEN 320, 240
SAVETEXT "notes.txt", "one\ntwo\nthree"
file = OPEN("notes.txt")
PRINT loc(file)
first = READLINE(file)
second = READLINE(file)
// Two lines read
PRINT loc(file)
CLOSE file

lof

Returns the total size of the resource backing an open handle. For a DATA block handle, this is the total number of values in the block. For a file-stream handle, this is the total number of lines in the buffered file. Returns -1 if the handle is closed or invalid.

lof(filenumber)

Parameters

  • filenumber - Handle from OPEN or OPEN DATA

Example

SCREEN 320, 240
SAVETEXT "notes.txt", "one\ntwo\nthree"
file = OPEN("notes.txt")
PRINT lof(file), "lines"
CLOSE file

open

Opens a file in the game’s folder, and gives the file to read from or write to. Without a modifier it is opened to read.

open(path AS STRING, output = FALSE, append = FALSE)

Also documents: append, output

Parameters

  • path AS STRING - The file, in the game’s folder.
  • output = FALSE
  • append = FALSE

After !!

  • append(on = TRUE) - Add to the end of the file, keeping what is there.
  • output(on = TRUE) - Write the file afresh, in place of what was there.

Example

SCREEN 320, 240
file = OPEN("scores.txt") !! output
WRITE file, "ada", 100
CLOSE file
file = OPEN("scores.txt") !! append
WRITE file, "bob", 80
CLOSE file
file = OPEN("scores.txt")
WHILE NOT EOF(file)
    PRINT READLINE(file)
END WHILE
CLOSE file

open_database

Opens a database in the game’s folder, and gives it, for CALL_SQL and CLOSE. Without a modifier it is opened to read.

open_database(path AS STRING, writable = FALSE)

Also documents: writable

Parameters

  • path AS STRING - The file, in the game’s folder.
  • writable = FALSE

After !!

  • writable(on = TRUE) - Open it to change as well as to read.

Example

SCREEN 320, 240
SQL "make"
    CREATE TABLE IF NOT EXISTS scores (name TEXT, points INTEGER)
END SQL
db = OPEN_DATABASE("scores.db") !! writable
CALL_SQL(db, "make")
CLOSE db

readline

The next line of a file, or NULL when there are no more.

readline(file)

Parameters

  • file

Example

SCREEN 320, 240
SAVETEXT "notes.txt", "first\nsecond"
file = OPEN("notes.txt")
PRINT READLINE(file)
PRINT READLINE(file)
PRINT READLINE(file) = NULL
CLOSE file

serialize

Converts objects, arrays, or any data structure to a JSON string for storage or transmission. Essential for saving game state, player progress, settings, and complex data structures to persistent storage. The output is standard JSON, so it can be used with external tools or APIs that accept JSON.

serialize(data)

Parameters

  • data - Any data type (Object, Array, String, Number, Boolean, TYPE structure)

Example

SCREEN 320, 240
player = {name: "ada", level: 3, items: ["key", "map"]}
SAVETEXT "save.json", serialize(player)
PRINT LOADTEXT("save.json")
back = deserialize(LOADTEXT("save.json"))
PRINT back.items(0)