···5bini.h: endian-independent binary IO.
6License: BSD 3-Clause. See EOF for license text.
78-Version: 1.0
910Changelog:
11 1.0 (Dec 28, 2025): Initial version.
00012*/
1314/* Used to add functions for version-specific types. */
···100{
101 /* Read mode for the stream. Should be either BINI_STACK or BINI_STREAM. */
102 int mode;
00103 size_t cap;
104 size_t len;
105 uint8_t *buffer;
···125 buffer, and frees the provided variable as well. */
126void bini_close(struct bini_stream *bs);
12700128/* Flush a binary stream, clearing its buffer. */
129int bini_flush(struct bini_stream *);
130/* Dump the binary stream's buffer to fp. */
···255 bs->buffer = calloc(BINI_BUFSIZ, 1);
256 if (!bs->buffer)
257 return BINI_ERR;
0258 bs->len = 0;
259 bs->cap = BINI_BUFSIZ;
260 bs->mode = BINI_STREAM;
···280 free(bs);
281}
28200000000000000000000000000000000283int bini_flush(struct bini_stream *bs)
284{
285 size_t i;
···307int _bini_grow(struct bini_stream *bs, size_t n)
308{
309 uint8_t *newbuf;
00000000310 if (bs->len + n < bs->cap)
311 return BINI_OK;
0312 while (bs->len + n >= bs->cap)
313 {
314 newbuf = realloc(bs->buffer, bs->cap * 2);
···317 bs->buffer = newbuf;
318 bs->cap *= 2;
319 }
0320 return BINI_OK;
321}
322···334 return fwrite(bs->buffer, size, n, fp);
335}
336337-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#define _bini_rwx(_type, _name) \
364 void bini_w##_name(struct bini_stream *bs, _type v) \
365 { \
···376 l ? sizeof(v)-i-1 : i, \
377 bytes[l ? sizeof(v)-i-1 : i], \
378 bytes[l ? sizeof(v)-i-1 : i], \
379- bs->len+i); \
380- bs->buffer[bs->len+i] = bytes[l ? sizeof(v)-i-1 : i]; \
381 } \
382 bs->len += i; \
383 _bini_dbg("-> %s: %d (%lu bytes)\n", __FUNCTION__, *(int *)bytes, sizeof(v)); \
···391 int m = bs->mode == BINI_STREAM; \
392 for (i = 0 ; i < sizeof(v) ; i++) \
393 { \
0394 _bini_dbg("%s: byte index [%lu] from buffer index %lu (= %02x '%c')\n", \
395 __FUNCTION__, \
396 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)]; \
401 } \
402 if (m) \
403- _bini_shiftleft(bs, i); \
000404 bs->len -= i; \
405 return v; \
406 }
···5bini.h: endian-independent binary IO.
6License: BSD 3-Clause. See EOF for license text.
78+Version: 1.1
910Changelog:
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.
15*/
1617/* Used to add functions for version-specific types. */
···103{
104 /* Read mode for the stream. Should be either BINI_STACK or BINI_STREAM. */
105 int mode;
106+ /* Offset from the start of the buffer in bytes. Only used for BINI_STREAM. */
107+ size_t off;
108 size_t cap;
109 size_t len;
110 uint8_t *buffer;
···130 buffer, and frees the provided variable as well. */
131void bini_close(struct bini_stream *bs);
132133+/* Shift a binary stream, resetting the offset and shifting the array. */
134+void bini_shift(struct bini_stream *);
135/* Flush a binary stream, clearing its buffer. */
136int bini_flush(struct bini_stream *);
137/* Dump the binary stream's buffer to fp. */
···262 bs->buffer = calloc(BINI_BUFSIZ, 1);
263 if (!bs->buffer)
264 return BINI_ERR;
265+ bs->off = 0;
266 bs->len = 0;
267 bs->cap = BINI_BUFSIZ;
268 bs->mode = BINI_STREAM;
···288 free(bs);
289}
290291+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+323int bini_flush(struct bini_stream *bs)
324{
325 size_t i;
···347int _bini_grow(struct bini_stream *bs, size_t n)
348{
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+358 if (bs->len + n < bs->cap)
359 return BINI_OK;
360+361 while (bs->len + n >= bs->cap)
362 {
363 newbuf = realloc(bs->buffer, bs->cap * 2);
···366 bs->buffer = newbuf;
367 bs->cap *= 2;
368 }
369+370 return BINI_OK;
371}
372···384 return fwrite(bs->buffer, size, n, fp);
385}
38600000000000000000000000000387#define _bini_rwx(_type, _name) \
388 void bini_w##_name(struct bini_stream *bs, _type v) \
389 { \
···400 l ? sizeof(v)-i-1 : i, \
401 bytes[l ? sizeof(v)-i-1 : i], \
402 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]; \
405 } \
406 bs->len += i; \
407 _bini_dbg("-> %s: %d (%lu bytes)\n", __FUNCTION__, *(int *)bytes, sizeof(v)); \
···415 int m = bs->mode == BINI_STREAM; \
416 for (i = 0 ; i < sizeof(v) ; i++) \
417 { \
418+ const size_t p = bs->off + (m ? i : (bs->len-sizeof(v)+i)); \
419 _bini_dbg("%s: byte index [%lu] from buffer index %lu (= %02x '%c')\n", \
420 __FUNCTION__, \
421 l ? sizeof(v)-i-1 : i, \
422+ p, \
423+ bs->buffer[p], \
424+ bs->buffer[p]); \
425+ bytes[l ? sizeof(v)-i-1 : i] = bs->buffer[p]; \
426 } \
427 if (m) \
428+ { \
429+ bs->off += i; \
430+ /* _bini_shiftleft(bs, i); */ \
431+ } \
432 bs->len -= i; \
433 return v; \
434 }
+10-4
include/keraforge/world.h
···313233/* Represents a singular tile in the world. */
00000034struct 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));
4041/* Represents a world (or a subworld, often called "rooms"). */
42struct kf_world
···313233/* 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));
40struct kf_tile
41{
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));
4647/* Represents a world (or a subworld, often called "rooms"). */
48struct kf_world
···8384 size_t len = kf_world_getsize(world);
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);
08889 if (compress)
90 {
···8384 size_t len = kf_world_getsize(world);
85 kf_loginfo("saving world (%lu bytes uncompressed)", len);
86+ kf_world_save(world, compress);
87+ // if (!kf_writebin(worldpath, (u8 *)world, len))
88+ // KF_THROW("failed to save %s", worldpath);
8990 if (compress)
91 {