|
Nugget
Bare-metal libraries and examples for the original PlayStation
|
A Sony-compatible memory card filesystem. More...
#include <psyqo/memory-card-filesystem.hh>
Classes | |
| struct | FileEntry |
| A directory listing entry. More... | |
| struct | FileInfo |
| A file's on-card metadata: its title and icon. More... | |
| struct | Icon |
| A save icon, in the native PlayStation format. More... | |
Public Types | |
| using | Error = MemoryCard::Error |
| using | Port = MemoryCard::Port |
Public Member Functions | |
| MemoryCardFileSystem (MemoryCard &card) | |
| bool | isIdle () const |
| Whether the filesystem is ready to accept a new operation. | |
| void | getCardState (Port port, eastl::function< void(Error)> &&callback) |
| Determines whether a usable, formatted card is present. | |
| void | format (Port port, eastl::function< void(Error)> &&callback) |
| Writes a fresh, empty Sony filesystem to the card. | |
| void | getFreeBlockCount (Port port, uint32_t *outFreeBlocks, eastl::function< void(Error)> &&callback) |
| Counts the free 8KiB blocks (0..15) into *outFreeBlocks. | |
| void | listFiles (Port port, FileEntry *out, uint32_t maxEntries, uint32_t *outCount, eastl::function< void(Error)> &&callback) |
| Lists the files on the card. | |
| void | fileExists (Port port, const char *name, bool *outExists, eastl::function< void(Error)> &&callback) |
| Reports whether a named file exists, into *outExists. | |
| void | readFile (Port port, const char *name, void *buffer, uint32_t maxLen, uint32_t *outLen, eastl::function< void(Error)> &&callback) |
| Reads the payload of a file. | |
| void | readFileInfo (Port port, const char *name, FileInfo *out, eastl::function< void(Error)> &&callback) |
| Reads a file's title and icon. | |
| void | writeFile (Port port, const char *name, const char *title, const Icon &icon, const void *data, uint32_t dataLen, eastl::function< void(Error)> &&callback) |
| Creates or overwrites a file. | |
| void | deleteFile (Port port, const char *name, eastl::function< void(Error)> &&callback) |
| Deletes a file, freeing all of its blocks. | |
| Error | getCardStateBlocking (GPU &gpu, Port port) |
| Error | formatBlocking (GPU &gpu, Port port) |
| Error | getFreeBlockCountBlocking (GPU &gpu, Port port, uint32_t *outFreeBlocks) |
| Error | listFilesBlocking (GPU &gpu, Port port, FileEntry *out, uint32_t maxEntries, uint32_t *outCount) |
| Error | fileExistsBlocking (GPU &gpu, Port port, const char *name, bool *outExists) |
| Error | readFileBlocking (GPU &gpu, Port port, const char *name, void *buffer, uint32_t maxLen, uint32_t *outLen) |
| Error | readFileInfoBlocking (GPU &gpu, Port port, const char *name, FileInfo *out) |
| Error | writeFileBlocking (GPU &gpu, Port port, const char *name, const char *title, const Icon &icon, const void *data, uint32_t dataLen) |
| Error | deleteFileBlocking (GPU &gpu, Port port, const char *name) |
A Sony-compatible memory card filesystem.
This class implements the on-card filesystem used by the retail PlayStation BIOS, on top of the raw sector access provided by MemoryCard. Files written through it are 100% compatible with the BIOS memory card manager: they show up with their title and icon, and can be copied or deleted from the BIOS like any other save.
The card is laid out as a 16-block device (block 0 is the directory, blocks 1..15 hold files). A file occupies one or more whole 8KiB blocks, chained through the directory as a linked list. Some third-party cards are only 64KiB and ignore the top sector address bit, so block N+8 is block N. Before it counts or allocates blocks, the filesystem compares sector 0 with sector 512 (and, if those match, 256 and 128); on a card that aliases, only the blocks below the alias are counted as free or handed to new files, so such a card holds 7 one-block files and then reports OutOfSpace. The first block of a file starts with a "title frame" (magic "SC", a Shift-JIS title and a 16-colour palette) followed by 1..3 icon frames (16x16, 4bpp); the rest of the blocks hold the caller's payload.
A whole filesystem operation is a transaction that spans many individual sector transfers and therefore several frames. To avoid stalling the main loop for that whole time, operations are asynchronous, following the same contract as CDRomDevice: only ONE operation may be in flight at a time, and progress is driven by chaining the MemoryCard device's own interrupt-driven sector transfers - each transfer's completion callback issues the next - so the game keeps running between sectors, with no timer. Every operation comes in two forms:
eastl::function callback that is invoked, from the main loop during callback pumping, with the resulting MemoryCard::Error; and*Blocking(GPU&) variant that pumps the GPU until the operation completes and returns the error directly.The SIO0Bus is owned for the entire transaction, so AdvancedPad stands down for its full duration (see the MemoryCard warning: this filesystem is usable with AdvancedPad only, never SimplePad).
|
inlineexplicit |
| void psyqo::MemoryCardFileSystem::deleteFile | ( | Port | port, |
| const char * | name, | ||
| eastl::function< void(Error)> && | callback | ||
| ) |
Deletes a file, freeing all of its blocks.
| name | The Sony filename to delete. Must stay valid until the callback fires. |
| void psyqo::MemoryCardFileSystem::fileExists | ( | Port | port, |
| const char * | name, | ||
| bool * | outExists, | ||
| eastl::function< void(Error)> && | callback | ||
| ) |
Reports whether a named file exists, into *outExists.
A missing file is not an error: the callback gets Error::OK and *outExists is false. Error::FileNotFound is never returned.
| name | The Sony filename to look up. Must stay valid until the callback fires. |
| outExists | Receives the answer. Must stay valid until the callback fires. |
| Error psyqo::MemoryCardFileSystem::fileExistsBlocking | ( | GPU & | gpu, |
| Port | port, | ||
| const char * | name, | ||
| bool * | outExists | ||
| ) |
Writes a fresh, empty Sony filesystem to the card.
This erases the directory; any existing files become unreachable. The file blocks are marked free, as the BIOS does, and only the first sector of blocks 2, 4 and 8 is written (zeroed), so that a stale copy of the header there cannot make the card read as smaller than it is.
| void psyqo::MemoryCardFileSystem::getCardState | ( | Port | port, |
| eastl::function< void(Error)> && | callback | ||
| ) |
Determines whether a usable, formatted card is present.
| void psyqo::MemoryCardFileSystem::getFreeBlockCount | ( | Port | port, |
| uint32_t * | outFreeBlocks, | ||
| eastl::function< void(Error)> && | callback | ||
| ) |
Counts the free 8KiB blocks (0..15) into *outFreeBlocks.
On a 64KiB card the count only covers blocks 1..7.
| outFreeBlocks | Receives the count. Must stay valid until the callback fires. |
| Error psyqo::MemoryCardFileSystem::getFreeBlockCountBlocking | ( | GPU & | gpu, |
| Port | port, | ||
| uint32_t * | outFreeBlocks | ||
| ) |
|
inline |
Whether the filesystem is ready to accept a new operation.
| void psyqo::MemoryCardFileSystem::listFiles | ( | Port | port, |
| FileEntry * | out, | ||
| uint32_t | maxEntries, | ||
| uint32_t * | outCount, | ||
| eastl::function< void(Error)> && | callback | ||
| ) |
Lists the files on the card.
| out | An array to receive up to maxEntries entries. Must stay valid until the callback fires. |
| outCount | Receives the number of files found (may exceed maxEntries, in which case only maxEntries were written). Must stay valid until the callback fires. |
| Error psyqo::MemoryCardFileSystem::listFilesBlocking | ( | GPU & | gpu, |
| Port | port, | ||
| FileEntry * | out, | ||
| uint32_t | maxEntries, | ||
| uint32_t * | outCount | ||
| ) |
| void psyqo::MemoryCardFileSystem::readFile | ( | Port | port, |
| const char * | name, | ||
| void * | buffer, | ||
| uint32_t | maxLen, | ||
| uint32_t * | outLen, | ||
| eastl::function< void(Error)> && | callback | ||
| ) |
Reads the payload of a file.
Returns the bytes that follow the title and icon frames, i.e. exactly the data region passed to writeFile, rounded up to whole frames. The caller is responsible for knowing the logical length of its own payload (typically via a small header it embeds in data).
| name | The Sony filename to read. Must stay valid until the callback fires. |
| buffer | Receives up to maxLen payload bytes. Must stay valid until the callback fires. |
| outLen | Receives the number of payload bytes available (capped at maxLen). Must stay valid until the callback fires. |
| Error psyqo::MemoryCardFileSystem::readFileBlocking | ( | GPU & | gpu, |
| Port | port, | ||
| const char * | name, | ||
| void * | buffer, | ||
| uint32_t | maxLen, | ||
| uint32_t * | outLen | ||
| ) |
| void psyqo::MemoryCardFileSystem::readFileInfo | ( | Port | port, |
| const char * | name, | ||
| FileInfo * | out, | ||
| eastl::function< void(Error)> && | callback | ||
| ) |
Reads a file's title and icon.
Fills *out with the file's title frame (the raw Shift-JIS title and the icon palette) and its icon bitmap frames, so a caller can display saved blocks the way the BIOS manager does. This is the read counterpart to writeFile's title and icon; it reads only the file's first block, never the payload.
| name | The Sony filename to look up. Must stay valid until the callback fires. |
| out | Receives the title and icon. Must stay valid until the callback fires. |
| Error psyqo::MemoryCardFileSystem::readFileInfoBlocking | ( | GPU & | gpu, |
| Port | port, | ||
| const char * | name, | ||
| FileInfo * | out | ||
| ) |
| void psyqo::MemoryCardFileSystem::writeFile | ( | Port | port, |
| const char * | name, | ||
| const char * | title, | ||
| const Icon & | icon, | ||
| const void * | data, | ||
| uint32_t | dataLen, | ||
| eastl::function< void(Error)> && | callback | ||
| ) |
Creates or overwrites a file.
The file is sized to hold the title frame, the icon frames and dataLen payload bytes, rounded up to whole 8KiB blocks. If a file with the same name already exists it is replaced, and no error is reported for it. The data is written first and the directory committed last, so an interrupted write never leaves a referenced but corrupt file.
| name | The Sony filename (up to 20 characters). The pointer must stay valid until the callback fires. |
| title | The save title, as a UTF-8 string, encoded to the 64-byte Shift-JIS field the BIOS manager displays, with printable ASCII promoted to its fullwidth form. Must stay valid until the callback fires. |
| icon | The save icon. Copied, so it need not outlive the call. |
| data | The payload bytes. Must stay valid until the callback fires. |
| dataLen | The number of payload bytes. |
| Error psyqo::MemoryCardFileSystem::writeFileBlocking | ( | GPU & | gpu, |
| Port | port, | ||
| const char * | name, | ||
| const char * | title, | ||
| const Icon & | icon, | ||
| const void * | data, | ||
| uint32_t | dataLen | ||
| ) |