+62
-34
include/keraforge/bini.h
+62
-34
include/keraforge/bini.h
···
5
5
bini.h: endian-independent binary IO.
6
6
License: BSD 3-Clause. See EOF for license text.
7
7
8
-
Version: 1.0
8
+
Version: 1.1
9
9
10
10
Changelog:
11
11
1.0 (Dec 28, 2025): Initial version.
12
+
1.1 (Dec 30, 2025): Use an offset instead of shifting the
13
+
byte buffer so carelessly. _bini_grow will shift the
14
+
buffer on-demand instead so as to conserve CPU time.
12
15
*/
13
16
14
17
/* Used to add functions for version-specific types. */
···
100
103
{
101
104
/* Read mode for the stream. Should be either BINI_STACK or BINI_STREAM. */
102
105
int mode;
106
+
/* Offset from the start of the buffer in bytes. Only used for BINI_STREAM. */
107
+
size_t off;
103
108
size_t cap;
104
109
size_t len;
105
110
uint8_t *buffer;
···
125
130
buffer, and frees the provided variable as well. */
126
131
void bini_close(struct bini_stream *bs);
127
132
133
+
/* Shift a binary stream, resetting the offset and shifting the array. */
134
+
void bini_shift(struct bini_stream *);
128
135
/* Flush a binary stream, clearing its buffer. */
129
136
int bini_flush(struct bini_stream *);
130
137
/* Dump the binary stream's buffer to fp. */
···
255
262
bs->buffer = calloc(BINI_BUFSIZ, 1);
256
263
if (!bs->buffer)
257
264
return BINI_ERR;
265
+
bs->off = 0;
258
266
bs->len = 0;
259
267
bs->cap = BINI_BUFSIZ;
260
268
bs->mode = BINI_STREAM;
···
280
288
free(bs);
281
289
}
282
290
291
+
static
292
+
#if bini_c >= 1999
293
+
inline
294
+
#endif
295
+
void _bini_shiftleft(struct bini_stream *bs, size_t n)
296
+
{
297
+
size_t i;
298
+
_bini_dbg("shift %d: (len=%lu)\n", n, bs->len);
299
+
for (i = 0 ; i < bs->len ; i++)
300
+
{
301
+
if (i+n >= bs->len)
302
+
{
303
+
_bini_dbg(" %d: [%d] (out of bounds) to [%d]\n", n, i+n, i);
304
+
bs->buffer[i] = 0;
305
+
continue;
306
+
}
307
+
_bini_dbg(" %d: [%d] (%02x '%c') to [%d]\n",
308
+
n,
309
+
i+n,
310
+
bs->buffer[i+n],
311
+
bs->buffer[i+n],
312
+
i);
313
+
bs->buffer[i] = bs->buffer[i+n];
314
+
}
315
+
}
316
+
317
+
void bini_shift(struct bini_stream *bs)
318
+
{
319
+
_bini_shiftleft(bs, bs->off);
320
+
bs->off = 0;
321
+
}
322
+
283
323
int bini_flush(struct bini_stream *bs)
284
324
{
285
325
size_t i;
···
307
347
int _bini_grow(struct bini_stream *bs, size_t n)
308
348
{
309
349
uint8_t *newbuf;
350
+
351
+
if (bs->off + bs->len + n < bs->cap)
352
+
return BINI_OK;
353
+
354
+
/* Shifting the array could give enough space to
355
+
fit `n`, avoiding the need to realloc. */
356
+
bini_shift(bs);
357
+
310
358
if (bs->len + n < bs->cap)
311
359
return BINI_OK;
360
+
312
361
while (bs->len + n >= bs->cap)
313
362
{
314
363
newbuf = realloc(bs->buffer, bs->cap * 2);
···
317
366
bs->buffer = newbuf;
318
367
bs->cap *= 2;
319
368
}
369
+
320
370
return BINI_OK;
321
371
}
322
372
···
334
384
return fwrite(bs->buffer, size, n, fp);
335
385
}
336
386
337
-
static
338
-
#if bini_c >= 1999
339
-
inline
340
-
#endif
341
-
void _bini_shiftleft(struct bini_stream *bs, size_t n)
342
-
{
343
-
size_t i;
344
-
_bini_dbg("shift %d: (len=%lu)\n", n, bs->len);
345
-
for (i = 0 ; i < bs->len ; i++)
346
-
{
347
-
if (i+n >= bs->len)
348
-
{
349
-
_bini_dbg(" %d: [%d] (out of bounds) to [%d]\n", n, i+n, i);
350
-
bs->buffer[i] = 0;
351
-
continue;
352
-
}
353
-
_bini_dbg(" %d: [%d] (%02x '%c') to [%d]\n",
354
-
n,
355
-
i+n,
356
-
bs->buffer[i+n],
357
-
bs->buffer[i+n],
358
-
i);
359
-
bs->buffer[i] = bs->buffer[i+n];
360
-
}
361
-
}
362
-
363
387
#define _bini_rwx(_type, _name) \
364
388
void bini_w##_name(struct bini_stream *bs, _type v) \
365
389
{ \
···
376
400
l ? sizeof(v)-i-1 : i, \
377
401
bytes[l ? sizeof(v)-i-1 : i], \
378
402
bytes[l ? sizeof(v)-i-1 : i], \
379
-
bs->len+i); \
380
-
bs->buffer[bs->len+i] = bytes[l ? sizeof(v)-i-1 : i]; \
403
+
bs->off+bs->len+i); \
404
+
bs->buffer[bs->off+bs->len+i] = bytes[l ? sizeof(v)-i-1 : i]; \
381
405
} \
382
406
bs->len += i; \
383
407
_bini_dbg("-> %s: %d (%lu bytes)\n", __FUNCTION__, *(int *)bytes, sizeof(v)); \
···
391
415
int m = bs->mode == BINI_STREAM; \
392
416
for (i = 0 ; i < sizeof(v) ; i++) \
393
417
{ \
418
+
const size_t p = bs->off + (m ? i : (bs->len-sizeof(v)+i)); \
394
419
_bini_dbg("%s: byte index [%lu] from buffer index %lu (= %02x '%c')\n", \
395
420
__FUNCTION__, \
396
421
l ? sizeof(v)-i-1 : i, \
397
-
m ? i : (bs->len-sizeof(v)+i), \
398
-
bs->buffer[m ? i : (bs->len-sizeof(v)+i)], \
399
-
bs->buffer[m ? i : (bs->len-sizeof(v)+i)]); \
400
-
bytes[l ? sizeof(v)-i-1 : i] = bs->buffer[m ? i : (bs->len-sizeof(v)+i)]; \
422
+
p, \
423
+
bs->buffer[p], \
424
+
bs->buffer[p]); \
425
+
bytes[l ? sizeof(v)-i-1 : i] = bs->buffer[p]; \
401
426
} \
402
427
if (m) \
403
-
_bini_shiftleft(bs, i); \
428
+
{ \
429
+
bs->off += i; \
430
+
/* _bini_shiftleft(bs, i); */ \
431
+
} \
404
432
bs->len -= i; \
405
433
return v; \
406
434
}
+10
-4
include/keraforge/world.h
+10
-4
include/keraforge/world.h
···
31
31
32
32
33
33
/* Represents a singular tile in the world. */
34
+
// struct kf_tile
35
+
// {
36
+
// kf_tileid_t subid : KF_TILE_IDWIDTH;
37
+
// kf_tileid_t id : KF_TILE_IDWIDTH;
38
+
// kf_tiledatum_t data : KF_TILE_DATAWIDTH;
39
+
// } __attribute__((packed));
34
40
struct kf_tile
35
41
{
36
-
kf_tileid_t subid : KF_TILE_IDWIDTH;
37
-
kf_tileid_t id : KF_TILE_IDWIDTH;
38
-
kf_tiledatum_t data : KF_TILE_DATAWIDTH;
39
-
} __attribute__((packed));
42
+
kf_tileid_t subid ;//: KF_TILE_IDWIDTH;
43
+
kf_tileid_t id ;//: KF_TILE_IDWIDTH;
44
+
kf_tiledatum_t data ;//: KF_TILE_DATAWIDTH;
45
+
};// __attribute__((packed));
40
46
41
47
/* Represents a world (or a subworld, often called "rooms"). */
42
48
struct kf_world
+10
scripts/run-valgrind.sh
+10
scripts/run-valgrind.sh
+1
-1
src/editor.c
+1
-1
src/editor.c
+1
-1
src/graphics.c
+1
-1
src/graphics.c
+20
-13
src/world.c
+20
-13
src/world.c
···
1
1
#include "keraforge/bini.h"
2
-
#include "keraforge/fs.h"
3
2
#include <keraforge.h>
4
3
#include <raylib.h>
5
4
#include <stdio.h>
···
246
245
char *outfile = compress ? _KF_MAPFILE_TMP : _KF_MAPFILE;
247
246
struct bini_stream *bs = bini_new();
248
247
_kf_world_save_bs(world, bs);
249
-
if (kf_writebin(outfile, bs->buffer, bs->len))
248
+
if (!kf_writebin(outfile, bs->buffer, bs->len))
250
249
KF_THROW("failed to open %s", outfile);
251
250
bini_close(bs);
252
251
···
265
264
}
266
265
267
266
static
268
-
void _kf_world_load_bs(struct kf_world *world, struct bini_stream *bs)
267
+
void _kf_world_load_bs(struct kf_world **pworld, struct bini_stream *bs)
269
268
{
270
-
world->revision = bini_riu(bs);
271
-
world->width = bini_riu(bs);
272
-
world->height = bini_riu(bs);
269
+
u32 r = bini_riu(bs);
270
+
u32 w = bini_riu(bs);
271
+
u32 h = bini_riu(bs);
272
+
struct kf_world *world = malloc(sizeof(*world) + sizeof(struct kf_tile)*w*h);
273
+
world->revision = r;
274
+
world->width = w;
275
+
world->height = h;
273
276
struct kf_tile *t = &world->map[0];
274
277
for (size_t i = 0 ; i < world->width*world->height ; i++)
275
278
{
···
278
281
t->data = bini_rcu(bs);
279
282
t++;
280
283
}
284
+
*pworld = world;
281
285
}
282
286
283
287
int kf_world_load(struct kf_world **pworld, bool compressed)
···
302
306
kf_logdbg("loading world: %s", infile);
303
307
304
308
size_t len = 0;
305
-
struct bini_stream *bs = bini_new();
306
-
free(bs->buffer);
307
-
bs->buffer = kf_readbin(infile, &len);
308
-
if (!bs->buffer)
309
+
struct bini_stream bs = {
310
+
.mode = BINI_STREAM,
311
+
.buffer = kf_readbin(infile, &len),
312
+
};
313
+
if (!bs.buffer)
309
314
KF_THROW("failed to read/open %s", infile);
310
-
bs->len = bs->cap = len;
311
-
_kf_world_load_bs(*pworld, bs);
312
-
bini_close(bs);
315
+
bs.cap = len;
316
+
bs.len = len;
317
+
kf_logdbg("loaded world into binary stream: len=%lu", len);
318
+
_kf_world_load_bs(pworld, &bs);
319
+
free(bs.buffer);
313
320
kf_logdbg("loaded world (%p): r=%d, wh=%dx%d, len=%lu", *pworld, (*pworld)->revision, (*pworld)->width, (*pworld)->height, len);
314
321
315
322
if (compressed)
+3
-2
tools/newgame.c
+3
-2
tools/newgame.c
···
83
83
84
84
size_t len = kf_world_getsize(world);
85
85
kf_loginfo("saving world (%lu bytes uncompressed)", len);
86
-
if (!kf_writebin(worldpath, (u8 *)world, len))
87
-
KF_THROW("failed to save %s", worldpath);
86
+
kf_world_save(world, compress);
87
+
// if (!kf_writebin(worldpath, (u8 *)world, len))
88
+
// KF_THROW("failed to save %s", worldpath);
88
89
89
90
if (compress)
90
91
{