JAPS1ME/docs/FORMATS.md

3.6 KiB
Raw Blame History

PS1 Save and Memory-Card Formats

This guide describes the formats JAPS1ME currently reads or writes. The notes were informed by the MemcardRex project, which is also credited in the main README. Corresponding JAPS1ME implementations: src/gme.rs and src/ps1/.

DexDrive .gme

A .gme file is a 3904-byte header followed by a 131072-byte raw card image (134976 bytes total). JAPS1ME identifies the format by length plus the MC signature at offset 3904.

Header

Offset Size Meaning
0x00 11 Magic: 123-456-STD (canonical files)
0x12–0x15 — Version/status bytes written by MemcardRex (0x01, 0x01/M)
0x16–0x25 15 Per-slot type bytes (copies of each directory frame's type)
0x26–0x35 15 Per-slot next-pointer bytes
0x40–0xF3F 15 × 256 Per-slot comments (system-codepage text, NUL-terminated)

Some files in the wild have a zeroed or otherwise non-canonical header. Like MemcardRex, JAPS1ME accepts those when the size is 134976 and bytes at 3904 are MC, and reports a missing DexDrive header magic warning. Comments are decoded as Windows-1252 and are informational only; convert never modifies them.

Raw card image (.srm/.mcr)

The raw image is 131072 bytes (1024 frames of 128 bytes). RetroArch .srm, ePSXe .mcr, and similar formats share this layout; only the file extension differs. convert writes exactly the .gme payload bytes 3904.. with no modification, so directory checksums and save data are preserved verbatim.

Geometry

Raw offset Size Meaning
0x00 128 Card header frame (MC magic)
0x80–0x7FF 15 × 128 Directory frames (slots 1–15)
0x2000– 15 × 8192 Save data blocks

Directory frames

Each 128-byte frame describes one slot. Relevant fields:

Offset Size Meaning
0x00 1 Slot type: 0xA0 formatted, 0x51 initial, 0x52/0x53 middle/end link, 0xA1–0xA3 deleted variants
0x04 3 Payload size, little-endian
0x08 1 Next-slot pointer (0xFF = end of chain)
0x0A 2 Region (BA America, BE Europe, BI Japan)
0x0C 10 Product code
0x16 8 Save identifier
0x7F 1 XOR checksum over bytes 0x00..0x7F

A save is an initial slot plus its link chain (up to 15 slots). Links not reachable from any initial slot are orphaned; list reports them and counts them as free, matching MemcardRex's broken-link handling.

Save titles

Each data block carries a 64-byte Shift-JIS title at block offset 4, NUL-terminated on an even byte boundary. JAPS1ME decodes it with a malformed-sequence replacement and falls back to the save name (region + product code + identifier) when no usable title exists.

Imports

import copies a save's directory frames and data blocks from a source card into the target's first free slots in slot order. Link bytes are relinked (0x51 initial, 0x52 middle, 0x53 end, 0xFF-terminated), the initial frame's size field is recomputed as blocks * 8192, and each touched frame's XOR checksum is regenerated. Imports from a deleted source slot are normalized to active link types. The updated card is re-parsed before it replaces the target.

References

  • MemcardRex: MemcardRex.Core/ps1card.cs (getGmeHeader, OpenMemoryCard, calculateXOR, loadStringData, FindSaveLinks) and MemcardRex.Core/Hardware/DexDrive.cs (128-byte frame protocol and XOR framing on the wire).
  • The corresponding JAPS1ME implementations: src/gme.rs, src/ps1/.