I wrote these tools to help me read and edit .s files, maybe you can put them to good use. Simply adding more frames to the animations just caused it to cut out early when I tried it but maybe you can figure that out.
sptdump.c: .s file -> text format
#include <stdio.h>
#include "spt.h"
int main(int argc, char *argv[])
{
FILE *f;
struct spt_header header;
int i;
int j;
if(argc < 2)
{
printf("usage: sptdump <file>\n");
exit(1);
}
f = fopen(argv[1], "rb");
fread(&header, sizeof(header), 1, f);
printf("File type: %p\n", header.file_type);
printf("Version: %p\n", header.version);
printf("Number of SPT entries: %i\n", header.num_spt_entries);
printf("\n");
for(i = 0; i < header.num_spt_entries; i++)
{
struct spt_entry entry;
fread(&entry, sizeof(entry), 1, f);
printf(" SPT Entry %i: %p, %i\n", i, entry.field_0, entry.num_spt_struc_183);
for(j = 0; j < entry.num_spt_struc_183; j++)
{
struct spt_struc_183 struc_183;
fread(&struc_183, sizeof(struc_183), 1, f);
printf(" %i: %p %5i %5i %5i %5i %5i %5i 0x%04x %3u %3u %3u %3u\n", j, struc_183.flags, struc_183.x, struc_183.y, struc_183.field_8, struc_183.field_A, struc_183.texture_page, (struc_183.field_E & 0x3F) << 4, struc_183.field_E >> 6, struc_183.w1, struc_183.w2, struc_183.h1, struc_183.h2);
}
}
return 0;
}
sptbuilder.c: text format -> .s file
#include <stdio.h>
#include <string.h>
#include "spt.h"
const char file_type[] = "File type: ";
const char version[] = "Version: ";
const char num_spt_entries[] = "Number of SPT entries: ";
int main(int argc, char *argv[])
{
FILE *f;
FILE *of;
struct spt_header header;
int i;
int j;
char line[4096];
if(argc < 3)
{
printf("usage: sptbuilder <infile> <outfile>\n");
exit(1);
}
f = fopen(argv[1], "r");
of = fopen(argv[2], "wb");
if(!f)
{
perror("input file");
exit(1);
}
if(!of)
{
perror("output file");
exit(1);
}
while(1)
{
fgets(line, sizeof(line), f);
printf("%s", line);
if(!strncmp(line, file_type, sizeof(file_type) - 1)) sscanf(strstr(&line[sizeof(file_type)], "x") + 1, "%hhx", &header.file_type);
else if(!strncmp(line, version, sizeof(version) - 1)) sscanf(strstr(&line[sizeof(version)], "x") + 1, "%hhx", &header.version);
else if(!strncmp(line, num_spt_entries, sizeof(num_spt_entries) - 1)) sscanf(&line[sizeof(num_spt_entries) - 1], "%i", &header.num_spt_entries);
else break;
}
printf("Done parsing headers\n");
header.field_2 = 0;
fwrite(&header, sizeof(header), 1, of);
for(i = 0; i < header.num_spt_entries; i++)
{
struct spt_entry entry;
printf("Parsing SPT entry %i\n", i);
fgets(line, sizeof(line), f);
printf("%s", line);
strtok(line, ":,");
sscanf(strstr(strtok(0, ":,"), "x") + 1, "%hx", &entry.field_0);
sscanf(strtok(0, ":,"), "%hi", &entry.num_spt_struc_183);
fwrite(&entry, sizeof(entry), 1, of);
for(j = 0; j < entry.num_spt_struc_183; j++)
{
struct spt_struc_183 struc_183;
int tmp1;
int tmp2;
printf("%i\n", j);
fgets(line, sizeof(line), f);
printf("%s\n", strtok(line, ":"));
//printf("%s\n", strtok(0, ":"));
sscanf(strstr(strtok(0, ":"), "x") + 1, "%x %5hi %5hi %5hi %5hi %5hi %5i %p %3hhi %3hhi %3hhi %3hhi", &struc_183.flags, &struc_183.x, &struc_183.y, &struc_183.field_8, &struc_183.field_A, &struc_183.texture_page, &tmp1, &tmp2, &struc_183.w1, &struc_183.w2, &struc_183.h1, &struc_183.h2);
struc_183.field_E = tmp2 << 6;
struc_183.field_E |= tmp1 >> 4;
fwrite(&struc_183, sizeof(struc_183), 1, of);
}
}
fclose(of);
return 0;
}
spt.h: data structures used in both programs
#ifndef _SPT_H_
#define _SPT_H_
struct spt_header
{
unsigned char file_type;
unsigned char version;
unsigned short field_2;
unsigned int num_spt_entries;
} __attribute__((__packed__));
struct spt_entry
{
unsigned short field_0;
unsigned short num_spt_struc_183;
} __attribute__((__packed__));
struct spt_struc_183
{
unsigned int flags;
short x;
short y;
short field_8;
short field_A;
unsigned short texture_page;
short field_E;
unsigned char w1;
unsigned char w2;
unsigned char h1;
unsigned char h2;
} __attribute__((__packed__));
#endif