summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE30
-rw-r--r--README19
-rw-r--r--bin2c.c78
-rwxr-xr-xexample/build.sh7
-rw-r--r--example/cli.c31
-rw-r--r--example/common.h29
-rw-r--r--example/example.c27
-rw-r--r--example/image.tgabin0 -> 1068 bytes
-rw-r--r--example/tga.c145
9 files changed, 366 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..b1530d2
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+BSD 3-Clause License (BSD-3-Clause)
+
+Copyright (C) 2024 dwlr <dweller@cabin.digital>
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/README b/README
new file mode 100644
index 0000000..7288c41
--- /dev/null
+++ b/README
@@ -0,0 +1,19 @@
+bin2c
+-----
+
+Converts files to a C char array ready to be #include'ed into your source code a la C23's #embed.
+See: https://cabin.digital/log/c89_embed.html
+ or http://retro.cabin.digital/log/c89_embed.html
+
+See example/ for, well, example.
+
+Build: cc bin2c.c -o bin2c
+
+Install: idk put it in your $PATH
+
+Usage: bin2c [filename]
+ If filename is empty will read from stdin and outout to stdout on EOF.
+ Otherwise will create filename.h and write into it.
+
+Bugs: https://cabin.digital/whoami.html#contact
+ (http://retro.cabin.digital/whoami.html#contact)
diff --git a/bin2c.c b/bin2c.c
new file mode 100644
index 0000000..3e6aaa2
--- /dev/null
+++ b/bin2c.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2024 dwlr <dweller@cabin.digital>
+ *
+ * BSD 3-Clause License (BSD-3-Clause)
+ * See LICENSE for details
+ */
+
+#define _XOPEN_SOURCE 500
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+
+int main(int argc, char** argv)
+{
+ int rc = 0;
+ int ret = EXIT_SUCCESS;
+ FILE* in = stdin;
+ FILE* out = stdout;
+ const char* name = "stdin";
+ char buffer[4096] = {0};
+ size_t got = 0;
+
+ if(argc == 2)
+ {
+ name = argv[1];
+ in = fopen(name, "r");
+ if(!in)
+ {
+ perror("fopen");
+ exit(EXIT_FAILURE);
+ }
+
+ rc = snprintf(buffer, sizeof(buffer) - 1, "%s.h", name);
+ if(rc < 0)
+ {
+ perror("snprintf");
+ exit(EXIT_FAILURE);
+ }
+
+ out = fopen(buffer, "w");
+ if(!out)
+ {
+ perror("fopen");
+ fclose(in);
+ exit(EXIT_FAILURE);
+ }
+
+ }
+ else if(argc > 2) fprintf(stderr, "warning: ignoring excess paramters\n");
+
+ for(;;)
+ {
+ size_t i;
+
+ got = fread(buffer, 1, sizeof(buffer), in);
+ rc = ferror(in);
+ if(rc)
+ {
+ perror("fread");
+ ret = EXIT_FAILURE;
+ goto end;
+ }
+
+ for(i = 0; i < got; i++) fprintf(out, "'\\x%02x',", (unsigned char)buffer[i]);
+
+ rc = feof(in);
+ if(rc) break;
+ }
+
+ fprintf(out, "\n");
+
+end:
+ fclose(in);
+ fclose(out);
+ return ret;
+}
diff --git a/example/build.sh b/example/build.sh
new file mode 100755
index 0000000..26383e2
--- /dev/null
+++ b/example/build.sh
@@ -0,0 +1,7 @@
+#!/bin/sh -e
+
+cc -std=c89 -Wall -Wextra -pedantic -O3 ../bin2c.c -o bin2c
+./bin2c image.tga
+cc -std=c89 -Wall -Wextra -pedantic -O3 example.c -o example
+
+./example
diff --git a/example/cli.c b/example/cli.c
new file mode 100644
index 0000000..f3e81e0
--- /dev/null
+++ b/example/cli.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 dwlr <dweller@cabin.digital>
+ *
+ * BSD 3-Clause License (BSD-3-Clause)
+ * See LICENSE for details
+ */
+
+#define ESC "\x1B"
+#define CSI ESC"["
+
+void cli_draw_tex(texture* tex, bool bw)
+{
+ ssize x, y;
+
+ for(y = 0; y < tex->height; y++)
+ {
+ for(x = 0; x < tex->width; x++)
+ {
+ rgba* p = tex->texels + (x + tex->width * y);
+ if(p->A == 0) printf(CSI"0m ");
+ else
+ {
+ if(bw) printf("##");
+ else printf(CSI"48;2;%d;%d;%dm ", p->R, p->G, p->B);
+ }
+ }
+
+ printf(CSI"0m\n");
+ }
+}
+
diff --git a/example/common.h b/example/common.h
new file mode 100644
index 0000000..9e6f7b9
--- /dev/null
+++ b/example/common.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 dwlr <dweller@cabin.digital>
+ *
+ * BSD 3-Clause License (BSD-3-Clause)
+ * See LICENSE for details
+ */
+
+#pragma once
+#pragma GCC diagnostic ignored "-Wlong-long"
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long long u64; /* XXX: GCC extension */
+typedef signed char s8;
+typedef signed short s16;
+typedef signed int s32;
+typedef signed long long s64; /* XXX: GCC extension */
+
+typedef s8 bool;
+
+typedef u64 usize;
+typedef s64 ssize;
+
+#define true 1
+#define false 0
+
+#define packed __attribute__((packed))
+
diff --git a/example/example.c b/example/example.c
new file mode 100644
index 0000000..8f6a1bc
--- /dev/null
+++ b/example/example.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 dwlr <dweller@cabin.digital>
+ *
+ * BSD 3-Clause License (BSD-3-Clause)
+ * See LICENSE for details
+ */
+
+#include <stdio.h>
+
+#include "common.h"
+#include "tga.c"
+#include "cli.c"
+
+
+const u8 image[] =
+{
+ #include "image.tga.h"
+};
+
+int main(void)
+{
+ texture tex = {0};
+ tga2tex_from_mem(&tex, image, sizeof(image));
+ cli_draw_tex(&tex, true); /* true - Black&White, false - True Color */
+
+ return 0;
+}
diff --git a/example/image.tga b/example/image.tga
new file mode 100644
index 0000000..b9eff45
--- /dev/null
+++ b/example/image.tga
Binary files differ
diff --git a/example/tga.c b/example/tga.c
new file mode 100644
index 0000000..6e8eb34
--- /dev/null
+++ b/example/tga.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2024 dwlr <dweller@cabin.digital>
+ *
+ * BSD 3-Clause License (BSD-3-Clause)
+ * See LICENSE for details
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+
+typedef struct packed tga_hdr
+{
+ u8 id_len;
+ u8 cmap_type;
+ u8 img_type;
+
+ struct packed
+ {
+ u16 first_entry_idx;
+ u16 length;
+ u8 entry_size;
+
+ } cmap_spec;
+
+ struct packed
+ {
+ u16 xorig;
+ u16 yorig;
+ u16 width;
+ u16 height;
+ u8 depth;
+ u8 desc;
+
+ } img_spec;
+
+} tga_hdr;
+
+typedef enum tga_img_type
+{
+ TGA_IMG_NONE,
+ TGA_IMG_RAW_CMAP,
+ TGA_IMG_RAW_TRUE,
+ TGA_IMG_RAW_BW,
+ TGA_IMG_RLE_CMAP,
+ TGA_IMG_RLE_TRUE,
+ TGA_IMG_RLE_BW,
+
+ TGA_IMG_TYPE_SIZE
+
+} tga_img_type;
+
+typedef union rgba
+{
+ u32 rgba;
+ struct
+ {
+ u8 b;
+ u8 g;
+ u8 r;
+ u8 a;
+ } c;
+
+} rgba;
+
+#define A c.a
+#define R c.r
+#define G c.g
+#define B c.b
+
+typedef struct texture
+{
+ ssize width;
+ ssize height;
+
+ rgba* texels;
+
+} texture;
+
+
+bool tga2tex_from_mem(texture* tex, const u8* data, ssize sz)
+{
+ tga_hdr* hdr = NULL;
+ rgba* img_dat = NULL;
+
+ assert(tex);
+ assert(data);
+ assert(sz > 0);
+
+ hdr = (tga_hdr*)data;
+ if(hdr->img_type != TGA_IMG_RAW_TRUE) return false;
+ if(hdr->cmap_type) return false;
+
+ /* FIXME(dwlr): check pixel depth */
+ /* FIXME(dwlr): check bit 5 and 4 of img_spec.desc (ordering) */
+
+ tex->width = hdr->img_spec.width;
+ tex->height = hdr->img_spec.height;
+
+ sz = sizeof(*tex->texels) * tex->width * tex->height;
+ tex->texels = malloc(sz);
+
+ img_dat = (rgba*)(((u8*)hdr) + sizeof(*hdr) + hdr->id_len);
+
+ /* FIXME(dwlr): convert if needed */
+ memcpy(tex->texels, img_dat, sz);
+
+ return true;
+}
+
+
+bool tga2tex_from_file(texture* tex, const char* path)
+{
+ struct stat stat = {0};
+
+ bool ret = false;
+ s32 fd = -1;
+ ssize sz = 0;
+ u8* file = NULL;
+
+ assert(tex);
+ assert(path);
+
+ fd = open(path, O_RDONLY);
+ if(fd < 0) goto clean_close;
+
+ if(fstat(fd, &stat) != 0) goto clean_close;
+
+ file = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if(file == MAP_FAILED) goto clean_close;
+
+ ret = tga2tex_from_mem(tex, file, sz);
+
+ munmap(file, stat.st_size);
+clean_close:
+ close(fd);
+
+ return ret;
+}