joeylib2/examples/spacetaxi/stLevelFile.c

90 lines
2.9 KiB
C

// Space Taxi -- STL4 level file parser (plain stdio, no JoeyLib), shared
// by the game and the host-side simulation harness.
//
// Layout (all bytes, written by stuff/spacetaxi/romToLevel.py):
// "STL4"
// name[22] $7D78 level name in screen codes
// header[9] $7D00 VIC colour block
// padCount, specialPad, fuelRate
// spawn[5] $7D5B
// templates[8] $7D8F Y accel, X accel, Y gravity, X gravity (LE words)
// pads[10][8] $7D0A raw slots
// screen[1000], color[1000]
// levelIndex
// spriteCount, then spriteCount x (ptr, 63 bytes)
// hookData[616] $7D98..$7FFF
#include <stdio.h>
#include <string.h>
#include "stSim.h"
static bool readBlock(FILE *fp, void *dst, size_t n);
static bool readBlock(FILE *fp, void *dst, size_t n) {
return fread(dst, 1, n, fp) == n;
}
bool stLevelParse(StLevelT *out, FILE *fp) {
uint8_t hdr[4];
uint8_t counts[3];
uint8_t templates[8];
uint8_t slots[ST_MAX_PADS][8];
uint8_t k;
memset(out, 0, sizeof(*out));
if (!readBlock(fp, hdr, 4u) || hdr[0] != 'S' || hdr[1] != 'T' || hdr[2] != 'L' || hdr[3] != '4') {
return false;
}
if (!readBlock(fp, out->name, ST_LEVEL_NAME_CHARS)) {
return false;
}
out->name[ST_LEVEL_NAME_CHARS] = 0u;
if (!readBlock(fp, out->header, 9u) || !readBlock(fp, counts, 3u) || !readBlock(fp, out->spawn, 5u)) {
return false;
}
out->padCount = counts[0];
out->specialPad = counts[1];
out->fuelRate = counts[2];
if (!readBlock(fp, templates, 8u)) {
return false;
}
out->accelY = (uint16_t)(templates[0] | ((uint16_t)templates[1] << 8));
out->accelX = (uint16_t)(templates[2] | ((uint16_t)templates[3] << 8));
out->gravY = (uint16_t)(templates[4] | ((uint16_t)templates[5] << 8));
out->gravX = (uint16_t)(templates[6] | ((uint16_t)templates[7] << 8));
if (!readBlock(fp, slots, sizeof(slots))) {
return false;
}
for (k = 0u; k < ST_MAX_PADS; k++) {
out->pads[k].x1Hi = slots[k][0];
out->pads[k].x1Lo = slots[k][1];
out->pads[k].x2Hi = slots[k][2];
out->pads[k].x2Lo = slots[k][3];
out->pads[k].row = slots[k][4];
out->pads[k].passMsb = slots[k][5];
out->pads[k].passCol = slots[k][6];
out->pads[k].unused = slots[k][7];
}
if (!readBlock(fp, out->screen, ST_SCREEN_CELLS) || !readBlock(fp, out->color, ST_SCREEN_CELLS)) {
return false;
}
if (!readBlock(fp, &out->levelIndex, 1u) || !readBlock(fp, &out->spriteCount, 1u)) {
return false;
}
if (out->spriteCount > ST_MAX_LEVEL_SPRITES) {
return false;
}
for (k = 0u; k < out->spriteCount; k++) {
if (!readBlock(fp, &out->sprites[k].ptr, 1u) || !readBlock(fp, out->sprites[k].bitmap, ST_SPRITE_BYTES)) {
return false;
}
}
if (!readBlock(fp, out->hookData, ST_HOOK_BYTES)) {
return false;
}
return true;
}