Compare commits

..

9 Commits

11 changed files with 218 additions and 141 deletions

View File

@@ -11,7 +11,7 @@ note: UUID are stored as an integer array.
|-----:|:-------------|:------------------------------------|
| `0` | `end` | - |
| `1` | `byte` | `int8_t` |
| `2` | `short` | `int16_t` (BE) |
| `2` | `short` | `int16_t` (BE[^be]) |
| `3` | `int` | `int32_t` (BE) |
| `4` | `long` | `int64_t` (BE) |
| `5` | `float` | `float` (BE) |
@@ -22,6 +22,7 @@ note: UUID are stored as an integer array.
| `10` | `compound` | list of tags delimited with end tag |
| `11` | `int array` | `int32_t` (len) -> `int32_t` |
| `12` | `long array` | `int32_t` (len) -> `int64_t` |
[^be] [big-endian](https://en.wikipedia.org/wiki/Endianness)
## world data
There is a difference between \*.mca and \*.mcr files.
@@ -85,10 +86,10 @@ unsigned offs = bit & 63; // calc the offset within the segment
// calculate the correct index
uint16_t idx;
idx = (block_states->dat[sgmt] >> offs); // acquire the data in the segment
idx |= !((offs + w) > 64) ? 0 : block_states->dat[sgmt+1] << (64-offs); // complete with the data from the other segment, if present
idx |= -!!((offs + w) > 64) & (block_states->dat[sgmt+1] << (64-offs)); // complete with the data from the other segment, if present
idx &= (1 << w) - 1; // truncate the data to only contain what we desire.
blockdat blk = block_states->palette.dat[idx];
struct blockdat blk = block_states->palette.dat[idx];
```
### MCR format specification

19
src/dat/mcx.h Normal file
View File

@@ -0,0 +1,19 @@
// Copyright (c) 2025 Quinn
// Licensed under the MIT Licence. See LICENSE for details
#pragma once
/* the MCR (Minecraft region) and MCA (Minecraft anvil) files are similar
* MCA is the newer variant, where it includes:
* - a world height of 256, rather than 128.
* - block IDs have been extended to 4096 from 256
* - block ordering is now YZX, rather than XZY.
* - biomes are included in the data per XZ column.
* MCR start with an 8KiB header, split in two 4KiB tables
* - the first containing the offsets of chunks in the region file itself.
* - the second providing timestamps on when they were last updated.
* -
*
*
*
*
*/

29
src/dat/nbt.h Normal file
View File

@@ -0,0 +1,29 @@
// Copyright (c) 2025 Quinn
// Licensed under the MIT Licence. See LICENSE for details
#pragma once
/* NBT (named binary tag) is a tree data structure. Tags have a numeric type ID, name and a payload.
* NBT files are a compressed `compound` tag. GZip is the compression used in most cases,
* in some (rare) cases it's stored uncompressed.
* A tag is an individual part of the data tree.
* The first byte is the ID, followed by a `u16`, for the length of the name.
* Then the name as `UTF-8`. (end tag does not contain name) */
/* specifies the NBT tag IDs.
* NOTE: every type is stored as BE (big-endian) in the file. */
enum nbt_tagid {
NBT_END, // signifies the end of a compound tag
NBT_I8, // next byte is for an 8 bit signed integer.
NBT_I16, // next 2 bytes are for a 16 bit signed integer
NBT_I32, // next 4 bytes are for a 32 bit signed integer
NBT_I64, // next 8 bytes are for a 64 bit signed integer
NBT_F32, // next 4 bytes are for a single-precision floating-point
NBT_F64, // next 8 bytes are for a double-precision floating-point
NBT_ARR_I8, // starts with a i32, denoting size, followed by the i8 data
NBT_STR, // starts with a u16, denoting size, followed by the UTF-8 data
NBT_LIST, // starts with an ID, followed by a 32 bit signed integer denoting the size
NBT_COMPOUND, // compound tag, contains tags and is delimited by `NBT_END`
NBT_ARR_I32, // starts with a i32, denoting size, followed by the i32 data
NBT_ARR_I64, // starts with a i32, denoting size, followed by the u32 data
};

68
src/io/render/mapcolour.c Normal file
View File

@@ -0,0 +1,68 @@
#include "mapcolour.h"
#include "../../util/vec.h"
u8vec4 map_colours[MAP_COLOUR_COUNT] = {
{0, 0, 0, 0 },
{127, 178, 56, 255},
{247, 233, 163, 255},
{199, 199, 199, 255},
{255, 0, 0, 255},
{160, 160, 255, 255},
{167, 167, 167, 255},
{0, 124, 0, 255},
{255, 255, 255, 255},
{164, 168, 184, 255},
{151, 109, 77, 255},
{112, 112, 112, 255},
{64, 64, 255, 255},
{143, 119, 72, 255},
{255, 252, 245, 255},
{216, 127, 51, 255},
{178, 76, 216, 255},
{102, 153, 216, 255},
{229, 229, 51, 255},
{127, 204, 25, 255},
{242, 127, 165, 255},
{76, 76, 76, 255},
{153, 153, 153, 255},
{76, 127, 153, 255},
{127, 63, 178, 255},
{51, 76, 178, 255},
{102, 76, 51, 255},
{102, 127, 51, 255},
{153, 51, 51, 255},
{25, 25, 25, 255},
{250, 238, 77, 255},
{92, 219, 213, 255},
{74, 128, 255, 255},
{0, 217, 58, 255},
{129, 86, 49, 255},
{112, 2, 0, 255},
{209, 177, 161, 255},
{159, 82, 36, 255},
{149, 87, 108, 255},
{112, 108, 138, 255},
{186, 133, 36, 255},
{103, 117, 53, 255},
{160, 77, 78, 255},
{57, 41, 35, 255},
{135, 107, 98, 255},
{87, 92, 92, 255},
{122, 73, 88, 255},
{76, 62, 92, 255},
{76, 50, 35, 255},
{76, 82, 42, 255},
{142, 60, 46, 255},
{37, 22, 16, 255},
{189, 48, 49, 255},
{148, 63, 97, 255},
{92, 25, 29, 255},
{22, 126, 134, 255},
{58, 142, 140, 255},
{86, 44, 62, 255},
{20, 180, 133, 255},
{100, 100, 100, 255},
{216, 175, 147, 255},
{127, 167, 150, 255},
};

74
src/io/render/mapcolour.h Normal file
View File

@@ -0,0 +1,74 @@
#pragma once
#include "../../util/vec.h"
enum map_colour_id {
MAP_COLOUR_NONE,
MAP_COLOUR_GRASS,
MAP_COLOUR_SAND,
MAP_COLOUR_WOOL,
MAP_COLOUR_FIRE,
MAP_COLOUR_ICE,
MAP_COLOUR_METAL,
MAP_COLOUR_PLANT,
MAP_COLOUR_SNOW,
MAP_COLOUR_CLAY,
MAP_COLOUR_DIRT,
MAP_COLOUR_STONE,
MAP_COLOUR_WATER,
MAP_COLOUR_WOOD,
MAP_COLOUR_QUARTZ,
MAP_COLOUR_ORANGE,
MAP_COLOUR_MAGENTA,
MAP_COLOUR_LIGHT_BLUE,
MAP_COLOUR_YELLOW,
MAP_COLOUR_LIGHT_GREEN,
MAP_COLOUR_PINK,
MAP_COLOUR_GREY,
MAP_COLOUR_LIGHT_GREY,
MAP_COLOUR_CYAN,
MAP_COLOUR_PURPLE,
MAP_COLOUR_BLUE,
MAP_COLOUR_BROWN,
MAP_COLOUR_GREEN,
MAP_COLOUR_RED,
MAP_COLOUR_BLACK,
MAP_COLOUR_GOLD,
MAP_COLOUR_DIAMOND,
MAP_COLOUR_LAPIS,
MAP_COLOUR_EMERALD,
MAP_COLOUR_PODZOL,
MAP_COLOUR_NETHER,
MAP_COLOUR_TERRACOTTA_WHITE,
MAP_COLOUR_TERRACOTTA_ORANGE,
MAP_COLOUR_TERRACOTTA_MAGENTA,
MAP_COLOUR_TERRACOTTA_LIGHT_BLUE,
MAP_COLOUR_TERRACOTTA_YELLOW,
MAP_COLOUR_TERRACOTTA_LIGHT_GREEN,
MAP_COLOUR_TERRACOTTA_PINK,
MAP_COLOUR_TERRACOTTA_GREY,
MAP_COLOUR_TERRACOTTA_LIGHT_GREY,
MAP_COLOUR_TERRACOTTA_CYAN,
MAP_COLOUR_TERRACOTTA_PURPLE,
MAP_COLOUR_TERRACOTTA_BLUE,
MAP_COLOUR_TERRACOTTA_BROWN,
MAP_COLOUR_TERRACOTTA_GREEN,
MAP_COLOUR_TERRACOTTA_RED,
MAP_COLOUR_TERRACOTTA_BLACK,
MAP_COLOUR_CRIMSON_NYLIUM,
MAP_COLOUR_CRIMSON_STEM,
MAP_COLOUR_CRIMSON_HYPHAE,
MAP_COLOUR_WARPED_NYLIUM,
MAP_COLOUR_WARPED_STEM,
MAP_COLOUR_WARPED_HYPHAE,
MAP_COLOUR_WARPED_WART_BLOCK,
MAP_COLOUR_DEEPSLATE,
MAP_COLOUR_RAW_IRON,
MAP_COLOUR_GLOW_LICHEN,
// contains count, leave last
MAP_COLOUR_COUNT,
};
/* contains the colours of the map on their' respective index - 1. (NONE should be handled separately) */
extern u8vec4 map_colours[MAP_COLOUR_COUNT];

View File

@@ -3,36 +3,19 @@
#pragma once
#include <stdint.h>
#include "types.h"
#include "vec.h"
// stores colour in a rgba format stored as little-endian, each channel being a 8 bits wide.
typedef union colour32 {
u32 dat; // full colour data; little-endian
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
// colour channel information for little-endian systems
struct {
u8 a, b, g, r;
} ch;
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
// colour channel information for big-endian systems
struct {
u8 r, g, b, a;
} ch;
#endif
} colour32;
#define COLOUR32_BLACK ((colour32){0x000000FF})
#define COLOUR32_RED ((colour32){0xFF0000FF})
#define COLOUR32_YELLOW ((colour32){0xFFFF00FF})
#define COLOUR32_ORANGE ((colour32){0xFF6D00FF})
#define COLOUR32_GREEN ((colour32){0x00FF00FF})
#define COLOUR32_CYAN ((colour32){0x00FFFFFF})
#define COLOUR32_BLUE ((colour32){0x0000FFFF})
#define COLOUR32_MAGENTA ((colour32){0xFF00FFFF})
#define COLOUR32_WHITE ((colour32){0xFFFFFFFF})
#define COLOUR32_BLACK ((u8vec4){0x00, 0x00, 0x00, 0xFF})
#define COLOUR32_RED ((u8vec4){0xFF, 0x00, 0x00, 0xFF})
#define COLOUR32_YELLOW ((u8vec4){0xFF, 0xFF, 0x00, 0xFF})
#define COLOUR32_ORANGE ((u8vec4){0xFF, 0x6D, 0x00, 0xFF})
#define COLOUR32_GREEN ((u8vec4){0x00, 0xFF, 0x00, 0xFF})
#define COLOUR32_CYAN ((u8vec4){0x00, 0xFF, 0xFF, 0xFF})
#define COLOUR32_BLUE ((u8vec4){0x00, 0x00, 0xFF, 0xFF})
#define COLOUR32_MAGENTA ((u8vec4){0xFF, 0x00, 0xFF, 0xFF})
#define COLOUR32_WHITE ((u8vec4){0xFF, 0xFF, 0xFF, 0xFF})
// american macros:
#define color32 colour32
#define COLOR32_BLACK COLOUR32_BLACK
#define COLOR32_RED COLOUR32_RED
#define COLOR32_YELLOW COLOUR32_YELLOW

View File

@@ -1,44 +0,0 @@
#pragma once
#include "../types.h"
#if defined(__GNUC__) || defined(__clang__)
#define bswap16 __builtin_bswap16
#define bswap32 __builtin_bswap32
#define bswap64 __builtin_bswap64
#elif __has_include(<byteswap.h>)
#include <byteswap.h>
#define bswap16 bswap_16
#define bswap32 bswap_32
#define bswap64 bswap_64
#else
#define bswap16 bswap16_impl
#define bswap32 bswap32_impl
#define bswap64 bswap64_impl
#define IMPL_BSWAP
#endif
#if defined(IMPL_BSWAP) || !defined(NDEBUG)
static inline u16 bswap16_impl(u16 x) {
return (x << 8) | (x >> 8);
}
static inline u32 bswap32_impl(u32 x) {
return (x << 24) |
((0x0000FF00U & x) << 8) |
((0x00FF0000U & x) >> 8) |
(x >> 24);
}
static inline u64 bswap64_impl(u64 x) {
return (x << 56) |
((0x000000000000FF00ULL & x) << 40) |
((0x0000000000FF0000ULL & x) << 24) |
((0x00000000FF000000ULL & x) << 8) |
((0x000000FF00000000ULL & x) >> 8) |
((0x0000FF0000000000ULL & x) >> 24) |
((0x00FF000000000000ULL & x) >> 40) |
(x >> 56);
}
#endif
#undef IMPL_BSWAP

View File

@@ -6,7 +6,6 @@
#include "../atrb.h"
#include "../types.h"
#include "bswap.h"
/* little endian */
atrb_const static inline u16 le16ton(u16); // converts little-endian (LE) encoding to native for a 16 bit integer. (NOOP if native is LE)
@@ -31,19 +30,19 @@ u64 le64ton(u64 x) { return x; }
u16 ntole16(u16 x) { return x; }
u32 ntole32(u32 x) { return x; }
u64 ntole64(u64 x) { return x; }
u16 be16ton(u16 x) { return bswap16(x); }
u32 be32ton(u32 x) { return bswap32(x); }
u64 be64ton(u64 x) { return bswap64(x); }
u16 ntobe16(u16 x) { return bswap16(x); }
u32 ntobe32(u32 x) { return bswap32(x); }
u64 ntobe64(u64 x) { return bswap64(x); }
u16 be16ton(u16 x) { return __builtin_bswap16(x); }
u32 be32ton(u32 x) { return __builtin_bswap32(x); }
u64 be64ton(u64 x) { return __builtin_bswap64(x); }
u16 ntobe16(u16 x) { return __builtin_bswap16(x); }
u32 ntobe32(u32 x) { return __builtin_bswap32(x); }
u64 ntobe64(u64 x) { return __builtin_bswap64(x); }
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
u16 le16ton(u16 x) { bswap_16(x); }
u32 le32ton(u32 x) { bswap_32(x); }
u64 le64ton(u64 x) { bswap_64(x); }
u16 ntole16(u16 x) { bswap_16(x); }
u32 ntole32(u32 x) { bswap_32(x); }
u64 ntole64(u64 x) { bswap_64(x); }
u16 le16ton(u16 x) { __builtin_bswap16(x); }
u32 le32ton(u32 x) { __builtin_bswap32(x); }
u64 le64ton(u64 x) { __builtin_bswap64(x); }
u16 ntole16(u16 x) { __builtin_bswap16(x); }
u32 ntole32(u32 x) { __builtin_bswap32(x); }
u64 ntole64(u64 x) { __builtin_bswap64(x); }
u16 be16ton(u16 x) { return x; }
u32 be32ton(u32 x) { return x; }
u64 be64ton(u64 x) { return x; }

View File

@@ -4,11 +4,9 @@
#if defined(__has_attribute) && __has_attribute(vector_size)
typedef float fvec2 __attribute__((vector_size(sizeof(float) * 2))); // SMID vector for 2 `float`
typedef float fvec3 __attribute__((vector_size(sizeof(float) * 3))); // SMID vector for 3 `float`
typedef float fvec4 __attribute__((vector_size(sizeof(float) * 3))); // SMID vector for 4 `float`
typedef float fvec4 __attribute__((vector_size(sizeof(float) * 4))); // SMID vector for 4 `float`
typedef u8 u8vec2 __attribute__((vector_size(sizeof(u8) * 2))); // SMID vector for 2 `u8`
typedef u8 u8vec3 __attribute__((vector_size(sizeof(u8) * 2))); // SMID vector for 3 `u8`
typedef u8 u8vec4 __attribute__((vector_size(sizeof(u8) * 4))); // SMID vector for 4 `u8`
#else
#error the platform is unsupported, attribute vector_size must be available (and so does __has_attribute)

View File

@@ -3,16 +3,9 @@
#include "../src/util/conf.h"
#include "../src/util/types.h"
#include "t_conf.h"
#include "t_util.h"
#include "test.h"
testdat tests[] = {
{"", test_bswap16, (u16[]){0x11EE, 0xEE11} },
{"", test_bswap32, (u32[]){0x1142ADEE, 0xEEAD4211} },
{"", test_bswap64, (u64[]){0x114266897799ADEE, 0xEEAD997789664211} },
{"", test_bswap16_impl, (u16[]){0x11EE, 0xEE11} },
{"", test_bswap32_impl, (u32[]){0x1142ADEE, 0xEEAD4211} },
{"", test_bswap64_impl, (u64[]){0x114266897799ADEE, 0xEEAD997789664211} },
{"k=v", test_procbuf, &(struct test_procbuf){"key=val", "key", "val", 0} },
{"sometxt", test_procbuf, &(struct test_procbuf){"sometxt", "sometxt", "", CONF_ESYNTAX} },
{"comment", test_procbuf, &(struct test_procbuf){"# comment", "", "", CONF_ENODAT} },
@@ -23,7 +16,7 @@ testdat tests[] = {
{"k=v (CRLF)", test_procbuf, &(struct test_procbuf){"k=v\r\na", "k", "v", 0} },
{"get", test_matchopt, &(struct test_matchopt){"key3", 2} },
{"invalid", test_matchopt, &(struct test_matchopt){"nono", -1} },
{"", test_colour32_endianess, NULL }, // NOTE: formatter is fucking with alignment making it use tabs @.@
// NOTE: formatter is fucking with alignment making it use tabs @.@
{"i32", test_procval_int, &(struct test_procval_int){"42", 42, CONF_I32} },
{"i32_neg", test_procval_int, &(struct test_procval_int){"-42", (u32)-42, CONF_I32} },
{"u32_max", test_procval_int, &(struct test_procval_int){"4294967295", UINT32_MAX, CONF_U64} },

View File

@@ -1,43 +0,0 @@
#pragma once
#include <stdint.h>
#include "../src/util/colour32.h"
#include "../src/util/compat/bswap.h"
#include "../src/util/types.h"
#include "test.h"
int test_colour32_endianess(void *d) {
(void)d;
colour32 c = {0xFF000000}; // setting just the red channel
return assert_true(c.ch.r == 0xFF);
}
int test_bswap16(void *d) {
u16 *arg = d;
return assert_true(bswap16(arg[0]) == arg[1]);
}
int test_bswap32(void *d) {
u32 *arg = d;
return assert_true(bswap32(arg[0]) == arg[1]);
}
int test_bswap64(void *d) {
u64 *arg = d;
return assert_true(bswap64(arg[0]) == arg[1]);
}
int test_bswap16_impl(void *d) {
u16 *arg = d;
return assert_true(bswap16_impl(arg[0]) == arg[1]);
}
int test_bswap32_impl(void *d) {
u32 *arg = d;
return assert_true(bswap32_impl(arg[0]) == arg[1]);
}
int test_bswap64_impl(void *d) {
u64 *arg = d;
return assert_true(bswap64_impl(arg[0]) == arg[1]);
}