From 78db656a92ead969764b10e114ee58e9404fa9c6 Mon Sep 17 00:00:00 2001 From: Quinn Date: Wed, 27 Aug 2025 11:14:52 +0200 Subject: [PATCH] write function for bulk removal of chunks --- src/dat/mcx.c | 19 +++++++++++++++++++ src/dat/mcx.h | 4 ++++ 2 files changed, 23 insertions(+) diff --git a/src/dat/mcx.c b/src/dat/mcx.c index 46c6f9c..ff9b949 100644 --- a/src/dat/mcx.c +++ b/src/dat/mcx.c @@ -38,6 +38,25 @@ size_t mcx_delchunk(u8 *restrict buf, int chunk) { return delchunk(buf, 0, chunk, 0x400); } +/* comparer function for to be inputted into `qsort` to compare two */ +static int cmp_chunkids(const void *restrict x, const void *restrict y) { + u16 x2 = *(u16 *)x; + u16 y2 = *(u16 *)y; + return (x2 > y2) - (x2 < y2); +} + +void mcx_delchunks(u8 *restrict buf, const u16 *restrict chunks, int chunkc) { + // ensure the chunks ids we're working on are sorted from least to greatest + u16 chunkids[chunkc + 1]; + memcpy(chunkids, chunks, chunkc); + qsort(chunkids, chunkc, sizeof(int), cmp_chunkids); + chunkids[chunkc] = 0; // set the spare chunk to zero, to prevent out-of-bounds access + + size_t rmb = 0; + for (int i = 0; i < chunkc; i++) + rmb += delchunk(buf, rmb, chunkids[i], chunkids[i + 1]); +} + /* Sum together the 4th byte in each location integer to compute the sector size of all chunks. * Multiplying by `0x1000`, and adding the size of the table itself. */ size_t mcx_calcsize(const u8 *restrict buf) { diff --git a/src/dat/mcx.h b/src/dat/mcx.h index 7a84b8d..62ffb9e 100644 --- a/src/dat/mcx.h +++ b/src/dat/mcx.h @@ -17,6 +17,10 @@ struct mcx_chunk { /* Deletes chunk `idx` from `buf`, moving all chunks downwards in the process. */ size_t mcx_delchunk(u8 *restrict buf, int idx); +/* Deletes `chunkc` chunks specified in `chunks` from the `*.mcX` file. + * This is done in a way to perform minimal memmove operations. */ +void mcx_delchunks(u8 *restrict buf, const u16 *restrict chunks, int chunkc); + /* Computes the byte size of the `*.mcX` file in `buf` and returns it. */ size_t mcx_calcsize(const u8 *restrict buf) NONNULL((1)) PURE;