My space game, ever in slow-time development, uses binary data for ship data, character data, map data, and game state data. I load these into high RAM and use them as needed, pulling them into main RAM long enough for a display or whatever.
Perl is really useful for creating binary files -- more useful than C, in that these sorts of tools are scripts, not worthy of dedicated development time with a proper language (like C).
Here's the easiest way to create a one-record binary file.
use strict;
EVERY Perl script should start with that line there. That enforces some discipline in both the developer and the Perl interpreter.
Now let's declare our data and shove it into Perl variables. This gives the data some tweakability, decoupled from the binary file's structure... although it also gives us an idea as to what lengths we want our data to fit into.
my $header = "TEMPLE OF APSHAI GAME STATE"; # fits into 31 characters
my $name = "MATT HEFFERNAN"; # fits into 15 characters
my $gx = 502; # global X, looks like 2 bytes
my $gy = 500; # global Y, looks like 2 bytes
my $sx = 3; # local X, 1 byte
my $sy = 10; # local Y, 1 byte
my $life = 10; # 1 byte
So we have seven pieces of data up there. Now let's write them.
open my $fp, '>', 'GAMESTATE.BIN'; # fopen for writing ('>')
print $fp pack 'AC', 'X', 16; # two byte throwaway 'header'
print $fp pack 'A31x', $header;
print $fp pack 'A15x', $name;
print $fp pack 'vv', $gx, $gy;
print $fp pack 'CC', $sx, $sy;
print $fp pack 'C', $life;
print $fp pack 'x16';
close $fp;
The 'pack' command puts our data into a binary format. We specify that exact format with the string that follows each pack... that string is a template telling the command how to pack in the data.
For example,
pack 'A5', 'HELLO';
tells Perl to pack in 5 ASCII characters from the source string 'HELLO'.
Add a zero value with 'x'. For example,
pack 'A15x', $name;
tells Perl to pack $name into 15 ASCII characters, then add a zero byte to the end of that. Or this line, which simply adds 16 zero bytes to the file:
pack 'x16';
'v' encodes an integer in little-endian format. 'CC' encodes two unsigned char values. And so on.
The trickiest example in my code is
pack 'AC', 'X', 16;
which first encodes a single ASCII character ('A'), an unsigned char value (16). This is the throwaway two bytes that the X16 will ignore when you load the file to a specific address. Since I load the file to a specific address, these two bytes are completely irrelevant. Just on a whim, I put "X16" into them.
The resulting binary file is exactly 73 bytes long, and looks like this:
00000000 58 10 54 45 4d 50 4c 45 20 4f 46 20 41 50 53 48 |X.TEMPLE OF APSH|
00000010 41 49 20 47 41 4d 45 20 53 54 41 54 45 20 20 20 |AI GAME STATE
00000020 20 00 4d 41 54 54 20 48 45 46 46 45 52 4d 41 4e | .MATT HEFFERMAN|
00000030 20 00 f6 01 f4 01 03 0a 0a 00 00 00 00 00 00 00 | ...............|
00000040 00 00 00 00 00 00 00 00 00 |.........|