joeylib2/include/joey/file.h

84 lines
3.9 KiB
C

// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// JoeyLib file access: read-only game data, writable save files, and a disk-
// space query.
//
// Two directories sit next to the executable, staged there by the per-platform
// disk / directory packagers:
// DATA/ -- game content (levels, sprites, audio). jlDataOpen.
// SAVES/ -- writable save / preference files. jlSave*.
// Both are addressed by a bare name relative to their directory; the prefix is
// forced here so callers never hard-code "DATA/" or "SAVES/". Both are found
// in the program's own folder wherever it was started from, before jlInit as
// after: DOS from its start path, the Amiga as PROGDIR:, the X68000 from its
// process block, the IIgs as GS/OS prefix 1, the hosted ports from their
// executable's path. The ST uses the current directory (TOS tells a program
// nothing of its folder); DVX keeps SAVES/ in the program's settings folder
// (docs/ApiFile.adoc).
#ifndef JOEYLIB_FILE_H
#define JOEYLIB_FILE_H
#include <stdio.h>
#include "types.h"
// ----- Read-only game data (DATA/) -----
// Open a data file by its name relative to the DATA/ directory. The DATA/
// prefix is prepended automatically; pass "levels/title.dat", not
// "DATA/levels/title.dat". mode is a standard fopen mode string, passed on
// unchecked (DATA/ is meant to be read, but a writing mode is not refused).
// Returns NULL if mode is NULL, the resulting path would overflow the
// internal buffer, or the file cannot be opened.
FILE *jlDataOpen(const char *name, const char *mode);
// ----- Writable save files (SAVES/) -----
//
// Save / preference data lives under a SAVES/ directory -- a writable
// sibling of the DATA/ tree (where, per port: the top of this file). Names
// are relative to SAVES/: pass "hero.sav", not "SAVES/hero.sav". A name is at
// most 8 letters and digits starting with a letter, then optionally a period
// and up to 3 more, so it fits ProDOS (15 characters, letter first) and DOS
// 8.3; every save call refuses any other name, on every port, as if the file
// could not be opened. Case must match on Linux, Haiku, BeOS, and the web.
//
// A failed open / write is non-fatal and simply reports failure (false / 0),
// so save code can degrade gracefully on a platform or volume where SAVES/ is
// unavailable.
// Open a save file for streaming, name relative to SAVES/. mode is a standard
// fopen mode string; for write / append modes the SAVES/ directory is created
// on demand first. Returns NULL on failure. Use this for large or incremental
// saves; for a whole-file blob prefer jlSaveWrite / jlSaveRead.
FILE *jlSaveOpen(const char *name, const char *mode);
// Write `len` bytes from `buf` to save file `name`, replacing any existing
// contents. Returns true only if all `len` bytes were written. The bytes go to
// a temporary file that takes the save's place only once it is whole, so a
// write that fails part way leaves the old save as it was. buf NULL with
// len > 0 returns false before the save is touched.
bool jlSaveWrite(const char *name, const void *buf, uint32_t len);
// Read up to `max` bytes from save file `name` into `buf`. Returns the number
// of bytes read (0 if the file is missing or empty).
uint32_t jlSaveRead(const char *name, void *buf, uint32_t max);
// True if save file `name` exists and can be opened for reading.
bool jlSaveExists(const char *name);
// Delete save file `name`. Returns true if the file was removed.
bool jlSaveDelete(const char *name);
// ----- Disk space -----
// Free space, in bytes, on the volume that holds SAVES/. Returns 0 if it
// cannot be determined. Saturates at UINT32_MAX (4 GB - 1) on larger
// volumes; DOS's own query (DOS, Win16) stops near 2 GB, and the web's
// figure is a fixed number from Emscripten's file system, not the
// browser's real space.
uint32_t jlDiskFree(void);
#endif