From 6c080c486f987ba30e7efe209f1310c6cfca0beb Mon Sep 17 00:00:00 2001 From: dweller Date: Wed, 31 Jul 2024 02:37:41 +0300 Subject: initial commit --- LICENSE | 30 +++++++++++ README | 19 +++++++ bin2c.c | 78 +++++++++++++++++++++++++++++ example/build.sh | 7 +++ example/cli.c | 31 ++++++++++++ example/common.h | 29 +++++++++++ example/example.c | 27 ++++++++++ example/image.tga | Bin 0 -> 1068 bytes example/tga.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 366 insertions(+) create mode 100644 LICENSE create mode 100644 README create mode 100644 bin2c.c create mode 100755 example/build.sh create mode 100644 example/cli.c create mode 100644 example/common.h create mode 100644 example/example.c create mode 100644 example/image.tga create mode 100644 example/tga.c 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 + +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 + * + * BSD 3-Clause License (BSD-3-Clause) + * See LICENSE for details + */ + +#define _XOPEN_SOURCE 500 + +#include +#include +#include + + +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 + * + * 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 + * + * 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 + * + * BSD 3-Clause License (BSD-3-Clause) + * See LICENSE for details + */ + +#include + +#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 Binary files /dev/null and b/example/image.tga 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 + * + * BSD 3-Clause License (BSD-3-Clause) + * See LICENSE for details + */ + +#include +#include +#include + +#include +#include +#include +#include + + +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; +} -- cgit v1.2.3