Skip to content

Instantly share code, notes, and snippets.

@RealDeuce
Created April 18, 2026 11:28
Show Gist options
  • Select an option

  • Save RealDeuce/26dde7fb6253138a18546715bdc072d9 to your computer and use it in GitHub Desktop.

Select an option

Save RealDeuce/26dde7fb6253138a18546715bdc072d9 to your computer and use it in GitHub Desktop.
Simple thing to extract the map for LORE 2.5
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define REC_SIZE 1484
#define GRID 38
#define CELL_COUNT (GRID * GRID) /* 1444 */
#define KEY_OFF CELL_COUNT /* 1444 */
#define KEY_LEN GRID /* 38 */
#define HDR_OFF (KEY_OFF + KEY_LEN)/* 1482 */
static const unsigned char chars[256] = {
0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x18, 0x19, 0x20, 0x56, 0x6F,
0x87, 0x8B, 0x8C, 0x8C, 0x8C, 0x8D, 0x8D, 0x8E, 0x95, 0x9D, 0x9D, 0xA1, 0xA1, 0xA2, 0xA6, 0xB0,
0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1,
0xB1, 0xB1, 0xB1, 0xB1, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB3,
0xB3, 0xB4, 0xB6, 0xB9, 0xBA, 0xBB, 0xBC, 0xBF, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC4, 0xC4,
0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCD, 0xCF,
0xD1, 0xD7, 0xD8, 0xD8, 0xD9, 0xDA, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xE0, 0xE0, 0xE2, 0xE2, 0xE2,
0xE2, 0xE2, 0xE2, 0xE3, 0xE4, 0xE4, 0xE4, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE6, 0xE7, 0xE7,
0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE9, 0xE9, 0xE9, 0xE9,
0xE9, 0xE9, 0xEC, 0xEC, 0xEC, 0xEC, 0xED, 0xEE, 0xEE, 0xEE, 0xEF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0xF0, 0xF0, 0xF1, 0xF2, 0xF2, 0xF2, 0xF3, 0xF3, 0xF3, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF7,
0xF8, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x00, 0x02, 0x0A, 0x06, 0x0C, 0x0F, 0x0B, 0x0D, 0x09, 0x0E,
0x08, 0x07, 0x07, 0x00, 0x0E, 0x0F, 0x01, 0x0A, 0x09, 0x06, 0x08, 0x0E, 0x08, 0x02, 0x0C, 0x0E,
0x02, 0x0E, 0x08, 0x07, 0x0E, 0x01, 0x02, 0x06, 0x04, 0xCC, 0x0E, 0x03, 0x07, 0x0F, 0x01, 0x12,
0x02, 0x07, 0x0F, 0x0A, 0x19, 0x09, 0x6E, 0x06, 0xCC, 0x70, 0x01, 0x02, 0x07, 0x0F, 0x19, 0x09,
0x04, 0x4C, 0xCC, 0x06, 0x08, 0x06, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x06,
};
static const unsigned char attrs[256] = {
0x00, 0x02, 0x0A, 0x06, 0x0C, 0x0F, 0x0B, 0x0D, 0x09, 0x0E, 0x08, 0x07, 0x07, 0x00, 0x0E, 0x0F,
0x01, 0x0A, 0x09, 0x06, 0x08, 0x0E, 0x08, 0x02, 0x0C, 0x0E, 0x02, 0x0E, 0x08, 0x07, 0x0E, 0x01,
0x02, 0x06, 0x04, 0xCC, 0x0E, 0x03, 0x07, 0x0F, 0x01, 0x12, 0x02, 0x07, 0x0F, 0x0A, 0x19, 0x09,
0x6E, 0x06, 0xCC, 0x70, 0x01, 0x02, 0x07, 0x0F, 0x19, 0x09, 0x04, 0x4C, 0xCC, 0x06, 0x08, 0x06,
0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x03, 0x07,
0x0E, 0x0F, 0x08, 0x07, 0x0C, 0x05, 0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x06,
0x06, 0x06, 0x07, 0x06, 0x06, 0x06, 0x00, 0x06, 0x05, 0x0F, 0x01, 0x05, 0x0E, 0x02, 0x0E, 0x07,
0x03, 0x08, 0x09, 0x06, 0x08, 0x04, 0x05, 0x07, 0x08, 0x0D, 0x04, 0x0E, 0x06, 0x09, 0x02, 0x0A,
0x06, 0x04, 0x0C, 0x07, 0x08, 0x0E, 0x09, 0x07, 0x0F, 0x05, 0x0D, 0x08, 0x06, 0x4F, 0x03, 0x0D,
0x0B, 0x02, 0x08, 0x09, 0x0E, 0x05, 0x08, 0x07, 0x04, 0x03, 0x0F, 0x07, 0x06, 0x02, 0x04, 0x05,
0x03, 0x09, 0x05, 0x0E, 0x06, 0x09, 0x06, 0x0E, 0x09, 0x0D, 0x0E, 0x06, 0x02, 0x0A, 0x07, 0x01,
0x0F, 0x0F, 0x70, 0x0E, 0x07, 0x08, 0x00, 0x01, 0x00, 0xC0, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1C,
0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xC3, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xC4, 0x00, 0x00,
};
static void decode_area(const unsigned char *rec, unsigned char ch[GRID][GRID], unsigned char at[GRID][GRID])
{
const unsigned char *key = rec + KEY_OFF;
for (int y = 1; y <= GRID; y++) {
for (int x = 1; x <= GRID; x++) {
unsigned char raw = rec[(y - 1) * GRID + (x - 1)];
unsigned char idx = (unsigned char)(raw - key[x - 1] - key[y - 1]);
ch[y - 1][x - 1] = chars[idx];
at[y - 1][x - 1] = attrs[idx];
}
}
}
static int is_empty(const unsigned char ch[GRID][GRID])
{
unsigned char first = ch[0][0];
for (int y = 0; y < GRID; y++)
for (int x = 0; x < GRID; x++)
if (ch[y][x] != first) return 0;
return 1;
}
static void preview(int rn, int wx, int wy, const unsigned char ch[GRID][GRID])
{
printf("=== record %d world (%d,%d) ===\n", rn, wx, wy);
for (int y = 0; y < GRID; y++) {
for (int x = 0; x < GRID; x++) {
unsigned char c = ch[y][x];
fputc((c >= 0x20 && c < 0x7F) ? c : c < 0x20 ? c + 0x20 : c < 0xA0 ? c - 0x60 : c - 0x7f , stdout);
}
fputc('\n', stdout);
}
}
static char
xlat(unsigned char c)
{
if (c == 0xb0)
return '~'; // Ocean?
if (c == 0xb1)
return '.'; // Plains?
if (c == 0xb2)
return '^'; // Trees?
if (c == 0x0f)
return '*'; // Entry?
if (c == 0xba)
return 'I'; // Road
if (c == 0xcd)
return '='; // Road
if (c >= 0x20 && c < 0x7f)
return c;
if (c < 0x20)
return c + 0x20;
c -= 0x80;
return xlat(c);
}
/*
* World layout (MAP1, verified by edge-match): rec = Y*stride + X with
* X the fast index (stride = world width). For MAP1 stride = 16 → 16 cols x 22 rows.
*/
static void stitch(FILE *f, long nrec, int stride)
{
long ndata = nrec - 1;
int cols = stride;
int rows = (int)((ndata + stride - 1) / stride);
int W = cols * GRID, H = rows * GRID;
unsigned char *world = malloc((size_t)W * H);
if (!world) { perror("malloc"); return; }
memset(world, ' ', (size_t)W * H);
unsigned char rec[REC_SIZE];
unsigned char ch[GRID][GRID], at[GRID][GRID];
for (long rn = 1; rn <= ndata; rn++) {
if (fread(rec, 1, REC_SIZE, f) != REC_SIZE) break;
decode_area(rec, ch, at);
int X = (int)((rn - 1) % stride); /* 0-based column (fast) */
int Y = (int)((rn - 1) / stride); /* 0-based row (slow) */
for (int y = 0; y < GRID; y++) {
unsigned char *dst = world + (size_t)(Y * GRID + y) * W + X * GRID;
for (int x = 0; x < GRID; x++) {
unsigned char c = ch[y][x];
dst[x] = xlat(c);
}
}
}
for (int y = 0; y < H; y++) {
fwrite(world + (size_t)y * W, 1, W, stdout);
fputc('\n', stdout);
}
free(world);
}
int main(int argc, char **argv)
{
if (argc < 2) {
fprintf(stderr,
"usage: %s MAPFILE [-s [STRIDE] | -p | -a]\n"
" -s [N] stitched ASCII world (default; STRIDE defaults to 16)\n"
" -p per-area ASCII preview\n"
" -a per-area binary dumps area_XX_YY.bin\n",
argv[0]);
return 2;
}
const char *path = argv[1];
enum { M_STITCH, M_PREVIEW, M_BIN } mode = M_STITCH;
int stride = 16;
if (argc >= 3) {
if (!strcmp(argv[2], "-p")) mode = M_PREVIEW;
else if (!strcmp(argv[2], "-a")) mode = M_BIN;
else if (!strcmp(argv[2], "-s")) {
mode = M_STITCH;
if (argc >= 4) stride = atoi(argv[3]);
}
}
FILE *f = fopen(path, "rb");
if (!f) { perror(path); return 1; }
fseek(f, 0, SEEK_END);
long sz = ftell(f);
fseek(f, 0, SEEK_SET);
if (sz % REC_SIZE) {
fprintf(stderr, "%s: size %ld not a multiple of %d\n", path, sz, REC_SIZE);
fclose(f);
return 1;
}
long nrec = sz / REC_SIZE;
unsigned char rec[REC_SIZE];
unsigned char ch[GRID][GRID], at[GRID][GRID];
/* Record 0 is the signature header. */
if (fread(rec, 1, REC_SIZE, f) != REC_SIZE) { perror(path); fclose(f); return 1; }
fprintf(stderr, "signature: %.21s\n", (char *)rec);
fprintf(stderr, "data records: %ld\n", nrec - 1);
if (mode == M_STITCH) {
stitch(f, nrec, stride);
fclose(f);
return 0;
}
for (long rn = 1; rn < nrec; rn++) {
if (fread(rec, 1, REC_SIZE, f) != REC_SIZE) break;
decode_area(rec, ch, at);
int wx = rec[HDR_OFF];
int wy = rec[HDR_OFF + 1];
if (is_empty(ch)) continue;
if (mode == M_PREVIEW) preview((int)rn, wx, wy, ch);
if (mode == M_BIN) {
char name[64];
snprintf(name, sizeof name, "area_%02d_%02d.bin", wx, wy);
FILE *o = fopen(name, "wb");
if (!o) { perror(name); continue; }
fwrite(ch, 1, GRID * GRID, o);
fwrite(at, 1, GRID * GRID, o);
fclose(o);
}
}
fclose(f);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment