Custom boot intro screen

4

Pablo 2025-02-15 21:00 (Edited)

Here is a little utility to replace the boot intro in the binary builds.

CC0/public domain.


#include <stdio.h>
#include <ctype.h>
#include <string.h>

typedef struct {
    long pos, len;
} chunk_t;

chunk_t findstring(FILE *fp) {
    int nread;
    unsigned char buf[512];
    chunk_t chunk = {-1};

    while ((nread = fread(buf, 1, 512, fp))) {
        int n, st = 0;
        if (chunk.pos == -1) {
            for (st=0; st < nread; st++) {
                if (isprint(buf[st]) || isspace(buf[st])) {
                    chunk.pos = ftell(fp) - nread + st;
                    break;
                }
            }
        }
        if (chunk.pos != -1) {
            for (n=st; n < nread; n++) {
                if (!isprint(buf[n]) && !isspace(buf[n])) break;
            }
            chunk.len += n - st;
            if (n < 512) break;
        }
    }
    if (chunk.len) fseek(fp, chunk.pos + chunk.len, SEEK_SET);
    return chunk;
}

int main(int argc, char *argv[]) {
    int nread;
    unsigned char buf[512];
    chunk_t chunk = {-1};

    FILE *binfile, *txtfile;
    long fsize, readcnt = 0, writecnt = 0;

    if (argc < 3) {
        fprintf(stderr, "usage: %s <exe|elf|wasm|mach-o file> <nx file>\n", argv[0]);
        return 1;
    }
    binfile = fopen(argv[1], "r+b");
    txtfile = fopen(argv[2], "rb");

    if (!binfile || !txtfile) {
        fprintf(stderr, "error: cannot open specified files\n");
        return 1;
    }

    for (;;) {
        chunk_t c = findstring(binfile);
        if (!c.len) break;

        if (c.len > chunk.len) chunk = c;
    }
    if (chunk.len != 5300) {
        fprintf(stderr, "error: invalid binary file\n");
        return 1;
    }

    fseek(txtfile, 0, SEEK_END);
    fsize = ftell(txtfile);
    if (fsize > chunk.len) {
        fprintf(stderr, "error: nx file size exceeds %ld bytes\n", chunk.len);
        return 1;
    }

    fseek(binfile, chunk.pos, SEEK_SET);
    fseek(txtfile, 0, SEEK_SET);

    while ((nread = fread(buf, 1, 512, txtfile))) {
        readcnt += nread;
        fwrite(buf, nread, 1, binfile);
    }
    if (readcnt < chunk.len) {
        int nwrite;
        long padding = chunk.len - readcnt;

        memset(buf, 0x0A, 512);
        while (writecnt < padding) {
            nwrite = 512;
            if (writecnt + nwrite > padding)
                nwrite = padding - writecnt;
            writecnt += nwrite;
            fwrite(buf, nwrite, 1, binfile);
        }
    }
    return 0;
}


Sylveon 2025-02-17 01:41

Replace with what :3


Pablo 2025-02-17 05:15

Here is an example. The size of the nx file should not exceed 5300 bytes.

boot_intro.nx | Open in app
2025-02-17 05:15

Timo 2025-02-17 11:02

This is the original boot intro: https://lowresnx.inutilis.com/topic.php?id=77


Pablo 2025-02-17 12:32 (Edited)

Cool! I noticed that that one is a little (25 bytes) bigger, so it won't fit without recompiling.

Also, the loading screen in my example is actually a splash screen. I omitted the spin animation that you see in the original, after POKE $A000,2.


Timo 2025-02-17 13:18

Probably the 25 bytes are to check for a tap to simulate "cartridge inserted".


Sylveon 2025-02-18 02:05

Cool :3


Log in to reply.