Compare commits

...

9 Commits

Author SHA1 Message Date
c6c9cc147e rework error.h, to decrease impact on binary size.
We were statically creating a new string per log message, so re-using
the same message would cause duplicate byte sizes.
Now, all prefixes / suffixes are only defined once, the file name is
defined once per file, the line number should be defined once per unique
line.
This just saves some memory in the final binary, allowing things to be
optimised a little better.
2025-09-05 15:17:53 +02:00
63df7430b7 fix: shouldn't multiply by CHUNKS, but by SECTOR 2025-09-04 13:28:13 +02:00
527b1e2b16 change mvchunks parameter order, to be a bit more clear and consistent with functions such as memmove 2025-09-04 13:12:51 +02:00
08ab721622 fix: violating strict aliasing rules in most areas in the new code.
Yes, I am aware there are plenty of violations in `conf.c`, but I'll
likely fix/rewrite those when I will use it. Since there are some other
changes I think I'll want to make.
2025-09-04 13:12:51 +02:00
0baa1ac9e8 add a flag when debugging to generate SIGFPE when signed integer overflow occurs. (this is UB) 2025-09-04 12:54:00 +02:00
9cb0631df8 add comments to point at where strict aliasing rule violations occur in data scripts
this is definitely not all of them, a thorough rewrite must take place
to fix as many as we can.
2025-09-04 12:54:00 +02:00
008604ff5e delete redundant COLOUR32 definitions 2025-09-04 11:35:52 +02:00
56427673cb add quit in main.c to atexit, for added safety 2025-09-04 11:35:52 +02:00
93db7681eb write a portable version of endian.h, to replace the system's endian.h.
utilising GNU C standard library for some of the functionality, or GNU C
extensions.
2025-09-04 11:35:52 +02:00
9 changed files with 204 additions and 101 deletions

View File

@@ -1,9 +1,45 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
#pragma once
#if __has_include(<endian.h>)
#include <endian.h>
#ifndef PORTABLE_ENDIAN_H
#define PORTABLE_ENDIAN_H 1
#if defined(__GNUC__)
/* test for the byteswap header */
#if __has_include(<byteswap.h>)
#include <byteswap.h>
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define le16toh(x) (x)
#define le32toh(x) (x)
#define le64toh(x) (x)
#define htole16(x) (x)
#define htole32(x) (x)
#define htole64(x) (x)
#define be16toh(x) __bswap16(x)
#define be32toh(x) __bswap32(x)
#define be64toh(x) __bswap64(x)
#define htobe16(x) __bswap16(x)
#define htobe32(x) __bswap32(x)
#define htobe64(x) __bswap64(x)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define le16toh(x) __bswap16(x)
#define le32toh(x) __bswap32(x)
#define le64toh(x) __bswap64(x)
#define htole16(x) __bswap16(x)
#define htole32(x) __bswap32(x)
#define htole64(x) __bswap64(x)
#define be16toh(x) (x)
#define be32toh(x) (x)
#define be64toh(x) (x)
#define htobe16(x) (x)
#define htobe32(x) (x)
#define htobe64(x) (x)
#else
#error machine architecture unsupported! Expected either big-endian or little-endian, make sure to use a compiler which defines __BYTE_ORDER__ (like clang or gcc)
#endif /* byte order */
/* otherwise, utilise the compiler built-ins */
#else
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define le16toh(x) __uint16_identity(x)
@@ -33,5 +69,12 @@
#define htobe64(x) __uint64_identity(x)
#else
#error machine architecture unsupported! Expected either big-endian or little-endian, make sure to use a compiler which defines __BYTE_ORDER__ (like clang or gcc)
#endif
#endif
#endif /* byte order */
#endif /* has byteswap.h */
#else
#error GNU C is unavailable
#endif /* __GNUC__ */
#endif /* PORTABLE_ENDIAN_H */

View File

@@ -38,20 +38,20 @@ endif
ifeq ($(DEBUG),1)
PROF = dbg
CFLAGS += -UNDEBUG -Og -g -Wextra -Wpedantic
CFLAGS += $(if $(filter 1,$(ISWIN)),,-fsanitize=address,undefined)
LDFLAGS += $(if $(filter 1,$(ISWIN)),,-fsanitize=address,undefined)
CFLAGS += $(if $(filter 1,$(ISWIN)),,-fsanitize=address,undefined) -ftrapv
LDFLAGS += $(if $(filter 1,$(ISWIN)),,-fsanitize=address,undefined) -ftrapv
# |--profile: testing
else ifeq ($(DEBUG),test)
PROF = test
CFLAGS += -UNDEBUG -O2 -g
CFLAGS += $(if $(filter 1,$(ISWIN)),,-fsanitize=address)
LDFLAGS += $(if $(filter 1,$(ISWIN)),,-fsanitize=address)
CFLAGS += $(if $(filter 1,$(ISWIN)),,-fsanitize=address) -ftrapv
LDFLAGS += $(if $(filter 1,$(ISWIN)),,-fsanitize=address) -ftrapv
else
PROF = rel
CFLAGS += -DNDEBUG -O2
endif
CFLAGS += $(shell pkg-config --cflags glfw3 libarchive) -Ilib/glad/include
CFLAGS += $(shell pkg-config --cflags glfw3 libarchive) -Ilib/include -Ilib/glad/include
LDFLAGS += $(shell pkg-config --libs glfw3 libarchive) -lm
# get source files

View File

@@ -3,22 +3,21 @@
#include "mcx.h"
#include <assert.h>
#include <endian.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "../util/compat/endian.h"
#include "../util/intdef.h"
#define TABLE 0x2000 // table byte size
#define SECTOR 0x1000 // sector size
#define TABLE 0x800 // table (total) element count
#define CHUNKS 0x400 // amount of chunks in a file
/* Moves chunks `src_s` to `src_e` (inclusive) from `src`, back onto `dst`. */
static void mvchunks(u8 *restrict buf, u8 *src, u8 *dst, int src_s, int src_e) {
static void mvchunks(u8 *dst, u8 *src, u32 *restrict table, int src_s, int src_e) {
assert(src > dst);
u32 *table = (u32 *)buf;
size_t len = src - dst; // acquire the amount of bytes that we shall move
assert(!(len % SECTOR));
@@ -34,9 +33,8 @@ static void mvchunks(u8 *restrict buf, u8 *src, u8 *dst, int src_s, int src_e) {
/* Deletes chunk `sidx` by moving chunks up to `eidx` back over `sidx` in `buf`.
* `rmb` is an optional additional offset that can be applied, and signifies bytes already removed.
* Returns the bytes removed by this function. */
static size_t delchunk(u8 *restrict buf, size_t rmb, int sidx, int eidx) {
static size_t delchunk(u8 *restrict buf, u32 *restrict table, size_t rmb, int sidx, int eidx) {
// load the table data
u32 *table = (u32 *)buf;
size_t slen, bidx, blen;
slen = be32toh(table[sidx]) & 0xFF; // acquire the sector length of the chunk
bidx = (be32toh(table[sidx]) >> 8) * SECTOR; // acquire and compute the byte offset the chunk starts at
@@ -49,20 +47,25 @@ static size_t delchunk(u8 *restrict buf, size_t rmb, int sidx, int eidx) {
// move the succeeding chunks over the deleted chunk
u8 *dst = buf + bidx - rmb;
u8 *src = buf + bidx + blen;
mvchunks(buf, src, dst, sidx, eidx - 1);
mvchunks(dst, src, table, sidx, eidx - 1);
return blen;
}
/* Just call `delchunk` with the parameters and some defaults.
/* Call `delchunk` with the parameters and some defaults. Ensuring the table is copied correctly as well.
* This is done instead of `delchunk` being globally linked, because
* `delchunk` requests more specific parameters, which is confusing outside this module. */
size_t mcx_delchunk(u8 *restrict buf, int chunk) {
return delchunk(buf, 0, chunk, CHUNKS);
u32 table[TABLE];
memcpy(table, buf, sizeof(table));
size_t res = delchunk(buf, table, 0, chunk, CHUNKS);
memcpy(buf, table, sizeof(table));
return res;
}
size_t mcx_delchunk_range(u8 *restrict buf, int start, int end) {
assert(start < end && end < CHUNKS);
u32 *table = (u32 *)buf;
u32 table[TABLE];
memcpy(table, buf, sizeof(table));
u8 *dst = buf + (be32toh(table[start]) >> 8) * SECTOR;
u8 *src = buf + (be32toh(table[end]) >> 8) * SECTOR;
src += (be32toh(table[end]) & 0xFF) * SECTOR;
@@ -76,7 +79,8 @@ size_t mcx_delchunk_range(u8 *restrict buf, int start, int end) {
// move the remaining chunks down
if (end < (CHUNKS - 1))
mvchunks(buf, src, dst, end, (CHUNKS - 1));
mvchunks(dst, src, table, end, (CHUNKS - 1));
memcpy(buf, table, sizeof(table));
return src - dst;
}
@@ -96,9 +100,14 @@ size_t mcx_delchunk_bulk(u8 *restrict buf, const u16 *restrict chunks, int chunk
qsort(chunkids, chunkc, sizeof(int), cmp_chunkids);
chunkids[chunkc] = CHUNKS; // set the spare chunk to the max chunks, so the rest of the chunks are moved
u32 table[TABLE];
memcpy(table, buf, sizeof(table));
size_t rmb = 0;
for (int i = 0; i < chunkc; i++)
rmb += delchunk(buf, rmb, chunkids[i], chunkids[i + 1]);
rmb += delchunk(buf, table, rmb, chunkids[i], chunkids[i + 1]);
memcpy(buf, table, sizeof(table));
return rmb;
}
@@ -108,5 +117,5 @@ size_t mcx_calcsize(const u8 *restrict buf) {
size_t size = 0;
for (uint i = 0; i < CHUNKS; i++)
size += *(buf + (i * 4) + 3);
return (size * CHUNKS) + TABLE;
return (size * SECTOR) + (TABLE * 4);
}

View File

@@ -3,37 +3,61 @@
#include "nbt.h"
#include <assert.h>
#include <endian.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "../util/compat/endian.h"
#include "../util/intdef.h"
#define MAX_DEPTH 512
/* Extracts a big endian 16 bit integer from address `buf`, converts it to host byte size if needed and returns. */
static inline u16 buftoh16(const void *restrict buf) {
u16 i;
memcpy(&i, buf, sizeof(i));
return be16toh(i);
}
/* Extracts a big endian 32 bit integer from address `buf`, converts it to host byte size if needed and returns. */
static inline u32 buftoh32(const void *restrict buf) {
u32 i;
memcpy(&i, buf, sizeof(i));
return be32toh(i);
}
/* Extracts a big endian 64 bit integer from address `buf`, converts it to host byte size if needed and returns. */
static inline u64 buftoh64(const void *restrict buf) {
u64 i;
memcpy(&i, buf, sizeof(i));
return be64toh(i);
}
/* Processes the incoming array data in `buf`. Which contains `nmem` items of `size`.
* The data shall be converted to little-endian on little-endian systems
* Outputs the allocated data to `out`, returns where the next pointer would be. */
static const u8 *procarr(const u8 *restrict buf, i32 nmem, uint size, struct nbt_array *restrict *restrict out) {
size_t len = nmem * size;
*out = malloc(sizeof(struct nbt_array) + len);
if (!*out) return buf + len;
static const u8 *procarr(const u8 *restrict buf, i32 nmemb, uint size, struct nbt_array *restrict out) {
size_t len = nmemb * size;
*out = (struct nbt_array){
out->nmemb = nmemb,
out->dat = malloc(len),
};
if (!out->dat)
return buf + len;
memcpy((*out)->dat, buf, len);
(*out)->len = nmem;
memcpy(out->dat, buf, len);
buf += len;
/* Only include this code for little-endian systems. Since only they require this logic.
* Producing optimised code for other platforms. */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
if (size == 1) return buf;
size_t i = 0;
while (i < len) {
i32 i = 0;
while (i < nmemb) {
switch (size) {
case 2: *(u16 *)((*out)->dat + i) = be16toh(*(u16 *)((*out)->dat + i)); break;
case 4: *(u32 *)((*out)->dat + i) = be32toh(*(u32 *)((*out)->dat + i)); break;
case 8: *(u64 *)((*out)->dat + i) = be64toh(*(u64 *)((*out)->dat + i)); break;
case 2: ((u16 *)out->dat)[i] = be16toh(((u16 *)out->dat)[i]); break;
case 4: ((u32 *)out->dat)[i] = be16toh(((u32 *)out->dat)[i]); break;
case 8: ((u64 *)out->dat)[i] = be16toh(((u64 *)out->dat)[i]); break;
default: __builtin_unreachable(); // this should be impossible
}
i += size;
@@ -43,12 +67,10 @@ static const u8 *procarr(const u8 *restrict buf, i32 nmem, uint size, struct nbt
}
/* calls `procarr` for the simple types available. */
static const u8 *proclist(const u8 *restrict buf, struct nbt_array *restrict *restrict out) {
static const u8 *proclist(const u8 *restrict buf, struct nbt_array *restrict out) {
uint size;
*out = NULL;
switch (*buf) {
switch (*(u8 *)buf) {
case NBT_I8: size = 1; break;
case NBT_I16: size = 2; break;
case NBT_I32: // fall through
@@ -59,7 +81,9 @@ static const u8 *proclist(const u8 *restrict buf, struct nbt_array *restrict *re
}
buf++;
i32 len = (i32)be32toh(*(u32 *)buf);
i32 len;
memcpy(&len, buf, 4);
len = be32toh(len);
buf += 4;
return procarr(buf, len, size, out);
}
@@ -73,25 +97,25 @@ const u8 *nbt_proctag(const u8 *restrict buf, u16 slen, void *restrict out) {
switch (*buf) {
case NBT_I8: *(u8 *)out = *ptr; return ptr + 1;
case NBT_I16: *(u16 *)out = be16toh(*(u16 *)ptr); return ptr + 2;
case NBT_I16: *(u16 *)out = buftoh16(ptr); return ptr + 2;
case NBT_I32: // fall through
case NBT_F32: *(u32 *)out = be16toh(*(u32 *)ptr); return ptr + 4;
case NBT_F32: *(u32 *)out = buftoh32(ptr); return ptr + 4;
case NBT_I64: // fall through
case NBT_F64: *(u64 *)out = be16toh(*(u64 *)ptr); return ptr + 8;
case NBT_F64: *(u64 *)out = buftoh64(ptr); return ptr + 8;
case NBT_STR: nmem = be16toh(*(u16 *)ptr), size = 1, ptr += 2; break;
case NBT_ARR_I8: nmem = be32toh(*(u32 *)ptr), size = 1, ptr += 4; break;
case NBT_ARR_I32: nmem = be32toh(*(u32 *)ptr), size = 4, ptr += 4; break;
case NBT_ARR_I64: nmem = be32toh(*(u32 *)ptr), size = 8, ptr += 4; break;
case NBT_STR: nmem = buftoh16(ptr), size = 1, ptr += 2; break;
case NBT_ARR_I8: nmem = buftoh32(ptr), size = 1, ptr += 4; break;
case NBT_ARR_I32: nmem = buftoh32(ptr), size = 4, ptr += 4; break;
case NBT_ARR_I64: nmem = buftoh32(ptr), size = 8, ptr += 4; break;
case NBT_LIST:
return proclist(ptr, (struct nbt_array **)out);
return proclist(ptr, (struct nbt_array *)out);
return tmp;
default: return NULL;
}
return procarr(ptr, nmem, size, (struct nbt_array **)out);
return procarr(ptr, nmem, size, (struct nbt_array *)out);
}
@@ -104,17 +128,17 @@ static const u8 *nexttag_list(const u8 *restrict ptr, uint *restrict const dpt,
ptr++;
switch (*tag) {
case NBT_END: break;
case NBT_I8: ptr += (i32)be32toh(*(u32 *)ptr) * 1; break;
case NBT_I16: ptr += (i32)be32toh(*(u32 *)ptr) * 2; break;
case NBT_I8: ptr += (i32)buftoh32(ptr) * 1; break;
case NBT_I16: ptr += (i32)buftoh32(ptr) * 2; break;
case NBT_I32: // fall through
case NBT_F32: ptr += (i32)be32toh(*(u32 *)ptr) * 4; break;
case NBT_F32: ptr += (i32)buftoh32(ptr) * 4; break;
case NBT_I64: // fall through
case NBT_F64: ptr += (i32)be32toh(*(u32 *)ptr) * 8; break;
case NBT_F64: ptr += (i32)buftoh32(ptr) * 8; break;
default:
// TODO: handle out of bounds... Might not be required if we use flexible array member
(*dpt)++;
tags[*dpt] = *tag;
lens[*dpt] = (i32)be32toh(*(u32 *)ptr);
lens[*dpt] = (i32)buftoh32(ptr);
break;
}
ptr += 4;
@@ -136,7 +160,7 @@ static const u8 *nexttag(const u8 *restrict tag, uint *restrict const dpt, i32 *
*dpt -= !lens[*dpt];
} else {
type = *tag;
ptr += be16toh(*(u16 *)(tag + 1)) + 3;
ptr += buftoh16(tag + 1) + 3;
}
switch (type) {
@@ -147,10 +171,10 @@ static const u8 *nexttag(const u8 *restrict tag, uint *restrict const dpt, i32 *
case NBT_I64: // fall through
case NBT_F64: ptr += 8; break;
case NBT_ARR_I8: ptr += 4 + (i32)be32toh(*(u32 *)ptr) * 1; break;
case NBT_ARR_I32: ptr += 4 + (i32)be32toh(*(u32 *)ptr) * 4; break;
case NBT_ARR_I64: ptr += 4 + (i32)be32toh(*(u32 *)ptr) * 8; break;
case NBT_STR: ptr += 2 + (u16)be16toh(*(u16 *)ptr) * 1; break;
case NBT_ARR_I8: ptr += 4 + (i32)buftoh32(ptr) * 1; break;
case NBT_ARR_I32: ptr += 4 + (i32)buftoh32(ptr) * 4; break;
case NBT_ARR_I64: ptr += 4 + (i32)buftoh32(ptr) * 8; break;
case NBT_STR: ptr += 2 + (u16)buftoh16(ptr) * 1; break;
case NBT_END: (*dpt)--; break;
case NBT_COMPOUND: (*dpt)++; break;

View File

@@ -3,11 +3,11 @@
#pragma once
#include <assert.h>
#include <endian.h>
#include <stdbool.h>
#include <stdlib.h>
#include "../util/atrb.h"
#include "../util/compat/endian.h"
#include "../util/intdef.h"
/* NBT (named binary tag) is a tree data structure. Tags have a numeric type ID, name and a payload.
@@ -37,8 +37,8 @@ enum nbt_tagid {
};
struct nbt_array {
i32 len;
u8 dat[];
i32 nmemb;
void *dat;
};

51
src/error.c Normal file
View File

@@ -0,0 +1,51 @@
#include "error.h"
#include <stdarg.h>
#include <stdio.h>
#include "util/intdef.h"
static void error_log(FILE *restrict stream, const char *restrict pfx, uint ln, const char *restrict file, const char *restrict fmt, va_list ap) {
fprintf(stream, "(%s:%lu) [%s] '", file, ln, pfx);
vfprintf(stream, fmt, ap);
fprintf(stream, "'\n");
}
void error_dbg(uint ln, const char *restrict file, const char *restrict fmt, ...) {
va_list ap;
va_start(ap, fmt);
error_log(stdout, "\033[95mDBG\033[0m", ln, file, fmt, ap);
va_end(ap);
}
void error_inf(uint ln, const char *restrict file, const char *restrict fmt, ...) {
va_list ap;
va_start(ap, fmt);
error_log(stdout, "\033[93mINF\033[0m", ln, file, fmt, ap);
va_end(ap);
}
void error_war(uint ln, const char *restrict file, const char *restrict fmt, ...) {
va_list ap;
va_start(ap, fmt);
error_log(stdout, "\033[91mWAR\033[0m", ln, file, fmt, ap);
va_end(ap);
}
void error_err(uint ln, const char *restrict file, const char *restrict fmt, ...) {
va_list ap;
va_start(ap, fmt);
error_log(stdout, "\033[mFAT\033[0m", ln, file, fmt, ap);
va_end(ap);
}
void error_fat(uint ln, const char *restrict file, const char *restrict fmt, ...) {
va_list ap;
va_start(ap, fmt);
error_log(stdout, "\033[mFAT\033[0m", ln, file, fmt, ap);
va_end(ap);
exit(EXIT_FAILURE);
}

View File

@@ -2,20 +2,21 @@
* Licensed under the MIT Licence. See LICENSE for details */
#pragma once
#if __INCLUDE_LEVEL__ > 0
#include <stdio.h>
#include <stdlib.h>
#include "util/atrb.h"
#include "util/intdef.h"
#include "util/macro.h"
#endif
#define debug(s, ...) printf("\033[95m" __FILE__ ":" MACRO_STR2(__LINE__) ": [DBG]: " s "\033[0m\n", ##__VA_ARGS__)
#define info(s, ...) printf(__FILE__ ":" MACRO_STR2(__LINE__) ": [INF]: " s "\n", ##__VA_ARGS__)
#define warn(s, ...) fprintf(stderr, "\033[93m" __FILE__ ":" MACRO_STR2(__LINE__) ": [WAR]: " s "\033[0m\n", ##__VA_ARGS__)
#define error(s, ...) fprintf(stderr, "\033[91m" __FILE__ ":" MACRO_STR2(__LINE__) ": [ERR]: " s "\033[0m\n", ##__VA_ARGS__)
void error_dbg(uint ln, const char *restrict file, const char *restrict fmt, ...);
void error_inf(uint ln, const char *restrict file, const char *restrict fmt, ...);
void error_war(uint ln, const char *restrict file, const char *restrict fmt, ...);
void error_err(uint ln, const char *restrict file, const char *restrict fmt, ...);
void error_fat(uint ln, const char *restrict file, const char *restrict fmt, ...) NORET;
#define fatal(s, ...) \
do { \
fprintf(stderr, "\033[101m" __FILE__ ":" MACRO_STR2(__LINE__) ": [FAT]: " s "\033[0m\n", ##__VA_ARGS__); \
exit(EXIT_FAILURE); \
} while (0)
#define debug(s, ...) error_dbg(__LINE__, __FILE__, s, ##__VA_ARGS__)
#define info(s, ...) error_inf(__LINE__, __FILE__, s, ##__VA_ARGS__)
#define warn(s, ...) error_war(__LINE__, __FILE__, s, ##__VA_ARGS__)
#define error(s, ...) error_err(__LINE__, __FILE__, s, ##__VA_ARGS__)
#define fatal(s, ...) error_fat(__LINE__, __FILE__, s, ##__VA_ARGS__)

View File

@@ -31,13 +31,15 @@ static inline int init(void) {
return 0;
}
static inline void quit(void) {
static void quit(void) {
glfwTerminate();
}
int main(int argc, char **argv) {
(void)argc, (void)argv;
printf("debug: [DBG], info: [INF], warning: [WAR], error: [ERR], fatal: [FAT]\n");
atexit(quit);
if (init()) fatal("failed to initialize!");
window_loop();

View File

@@ -1,27 +0,0 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
#pragma once
#include <stdint.h>
#include "vec.h"
#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_BLACK COLOUR32_BLACK
#define COLOR32_RED COLOUR32_RED
#define COLOR32_YELLOW COLOUR32_YELLOW
#define COLOR32_ORANGE COLOUR32_ORANGE
#define COLOR32_GREEN COLOUR32_GREEN
#define COLOR32_CYAN COLOUR32_CYAN
#define COLOR32_BLUE COLOUR32_BLUE
#define COLOR32_MAGENTA COLOUR32_MAGENTA
#define COLOR32_WHITE COLOUR32_WHITE