Quick answer: Use buffer_string (null-terminated UTF-8). Or write a length-prefixed format: 4-byte length then raw bytes. Don’t mix buffer_write_text with reads expecting termination.
Player saves the name “Pál”. Loads “Pæl”. The non-ASCII byte was split across a read that assumed fixed-width. UTF-8 in buffers needs the right type.
The Symptom
Saved strings with non-ASCII characters come back garbled. ASCII works fine. Or strings get truncated at unexpected positions.
The Fix
Pattern 1: buffer_string for null-terminated UTF-8.
/// Write
var buf = buffer_create(1024, buffer_grow, 1);
buffer_write(buf, buffer_string, "Pál");
/// Read
buffer_seek(buf, buffer_seek_start, 0);
var name = buffer_read(buf, buffer_string);
buffer_string is null-terminated UTF-8. Safe for any text without embedded NULs.
Pattern 2: Length-prefixed.
/// Write
var bytes = string_byte_length(name);
buffer_write(buf, buffer_u32, bytes);
buffer_write(buf, buffer_text, name);
/// Read
var bytes = buffer_read(buf, buffer_u32);
var name = "";
repeat (bytes) name += chr(buffer_read(buf, buffer_u8));
This works even if the string contains a NUL. Slightly more code; perfectly portable.
buffer_text vs buffer_string
- buffer_text: writes/reads raw bytes. No terminator, no length. You manage boundaries.
- buffer_string: null-terminated. Convenient. Fragile if the data could contain a NUL.
Verifying
Save and reload a non-ASCII test string (Greek, Japanese, accented Latin). Bytes match. show_debug_message can print before/after to confirm equality.
“buffer_string for safe text. Length-prefixed for binary-safe. UTF-8 round-trips.”
Related Issues
For surface lost, see surface lost. For instance deactivate, see deactivate.
buffer_string or length-prefix. UTF-8 survives.