Storage

#include "libtini/storage.h"

This header reads and writes full ProDOS files in near memory, and loads entries of resource packs into banked memory. The calls use the standard ProDOS MLI at $BF00. They use no private SmartPort service.

FunctionPurpose
ti_file_readRead a full file into a near buffer
ti_file_writeCreate or replace a file from a near buffer
ti_file_last_errorGet the ProDOS error of the last failure
ti_pack_loadLoad one entry of a TPK1 pack into a new resource

How file calls operate

Standard ProDOS can keep its /RAM disk in the AUX bank 0 bytes that also hold the SHR picture. Thus during a video session, each call does these steps:

  1. It saves the picture in a temporary resource and sets SHR off.
  2. It puts the bytes of the OS back and calls ProDOS.
  3. It saves the changes that ProDOS made.
  4. It restores the picture and sets SHR on.

This needs a free slot and 32,768 resource bytes. Without them, the call returns TI_E_NOMEM before any ProDOS call. Outside a video session, the call needs no resource, and file calls operate without ti_init.

Only TI_OK means that the transaction is complete. After an error, do not use the data that the call returned. A failed write can leave a changed or partial file. Keep two save slots and check them, as Saved games shows.

Functions

ti_file_read

ti_error ti_file_read(const char *name, void *dst, uint16_t capacity, uint16_t *length);

This function reads the full file into dst and stores its size in *length. When the file is larger than capacity, the function reads nothing. For an empty file, the buffer can be NULL with a zero capacity.

Returns

TI_OKThe full file is in dst.
TI_E_ARGUMENTlength is not writable near memory, or the name is not valid.
TI_E_RANGEdst is not writable near memory for capacity bytes, or the file is larger than capacity.
TI_E_BUSYA different storage call runs.
TI_E_NOMEMDuring a video session, no space is available for the screen loan.
TI_E_IOProDOS did not open, size, read or close the file. See ti_file_last_error.

*length is 0 when the call does not succeed.

ti_file_write

ti_error ti_file_write(const char *name, const void *src, uint16_t length);

When the file does not exist, this function creates it as a binary file (ProDOS type $06). It writes length bytes and sets the end of file to exactly length. Then it closes the file, which writes the data and the directory to the disk. When the old file was longer, the function makes it shorter. A zero length gives an empty file.

Returns

TI_OK; TI_E_RANGE when src is not readable near memory for length bytes; TI_E_ARGUMENT for a name that is not valid; TI_E_BUSY; TI_E_NOMEM as above; TI_E_IO when a ProDOS create, open, write, set-EOF or close fails.

ti_file_last_error

uint8_t ti_file_last_error(void);

This function returns the ProDOS MLI error code of the last failed call. After a successful call, it returns 0. A read or write that is shorter than expected records $4C. Argument, range and memory errors do not record a new ProDOS code. Read this value together with the result of the call.

CodeProDOS meaning
$27I/O error
$2BDisk write-protected
$40Invalid pathname
$44Path not found
$45Volume not found
$46File not found
$48Volume full
$49Volume directory full
$4CEnd of file encountered
$4EAccess error, for example a locked file

ti_pack_load

ti_error ti_pack_load(const char *name, const char *entry,
                      ti_handle *out, uint32_t *size);

This function opens the TPK1 pack name and checks its full directory. It allocates one resource of the size of the entry. Then it moves the bytes of the entry into the resource in pieces of 128 bytes. After a success, the caller owns the handle and frees it with ti_res_free. After an error, the function closes the file, frees a partly loaded resource and sets the two outputs to zero.

An entry name has 1-15 characters: a capital letter, then capitals, digits, periods or underscores. File names keep the narrower ProDOS rule. The function does not interpret the entry. Read its TI4, TIF or TIM header and make the surface, font or map view yourself, as Art, fonts, maps and packs shows. A pack needs an active ti_init grant.

Returns

TI_OK*out owns a resource of *size bytes.
TI_E_ARGUMENTAn output is not writable, or the file or entry name is not valid.
TI_E_UNAVAILABLEThe pack does not have this entry.
TI_E_FORMATThe directory is not correct: header, count, names, order, offsets or sizes. The function also checks the entries that it does not load.
TI_E_NOMEM, TI_E_STATENo slot or space is available for the entry or the screen loan, or there is no ti_init.
TI_E_IOA ProDOS open, read, seek or close failed.
TI_E_BUSYA different storage call runs.
ti_handle art;
uint32_t bytes;
if (ti_pack_load("RESOURCES.TPK", "SHIP", &art, &bytes) != TI_OK) return;
/* ... make views of art; ti_res_free(art) when done ... */

Data formats gives the pack format. tools/assets.py pack writes packs. The disk packager of the repository stores files of a maximum of 131,072 bytes. Use a different ProDOS tool for larger packs. The loader can read them.