Skip to content

Instantly share code, notes, and snippets.

@lincerely
Created December 9, 2023 05:26
Show Gist options
  • Save lincerely/daab69cadaa395b84f14552407446b6b to your computer and use it in GitHub Desktop.
Save lincerely/daab69cadaa395b84f14552407446b6b to your computer and use it in GitHub Desktop.
unpack embedded .rmf objects from .ol WorldCraft prefab library to current directory
// unpack embedded .rmf objects from .ol WorldCraft prefab library to current directory.
// list of names and descriptions would be dump into info.txt.
// reference: https://github.com/LogicAndTrick/sledge-formats/blob/master/Sledge.Formats.Map/Formats/WorldcraftPrefabLibrary.cs
#include <stdio.h>
#include <string.h>
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
struct object {
uint32_t offset, length;
char name[31];
char desc[205];
};
int main(int argc, char** argv)
{
if (argc < 2) {
fprintf(stderr, "usage: unpack FILE\n");
return 1;
}
FILE *p;
p = fopen(argv[1], "rb");
if (!p) {
fprintf(stderr, "failed to open file\n");
return 1;
}
const char *EXPECTED_HEADER = "Worldcraft Prefab Library\r\n\x1A";
char header[28];
fread(header, 28, 1, p);
if (strncmp(header, EXPECTED_HEADER, 28) != 0) {
fprintf(stderr, "error: header unmatch\n");
fclose(p);
return 1;
}
float version;
fread(&version, 4, 1, p);
printf("version: %.1f", version);
uint32_t offset;
fread(&offset, 4, 1, p);
uint16_t nobjects;
fread(&nobjects, 2, 1, p);
struct object objects[nobjects];
FILE *info_p = fopen("info.txt", "w");
if (!p) {
fprintf(stderr, "failed to write info.txt\n");
fclose(p);
return 1;
}
fseek(p, offset, SEEK_SET);
for (int i = 0; i < nobjects; i++) {
fread(&objects[i], sizeof(struct object), 1, p);
fprintf(info_p, "%s : %s\n", objects[i].name, objects[i].desc);
fseek(p, 300, SEEK_CUR);
}
for (int i = 0; i < nobjects; i++) {
char fname[256];
sprintf(fname, "%s.rmf", objects[i].name);
FILE *rmfp = fopen(fname, "wb");
fseek(p, objects[i].offset, SEEK_SET);
for (int j = 0; j < objects[i].length; j++)
fputc(fgetc(p), rmfp);
fclose(rmfp);
}
fclose(info_p);
fclose(p);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment