gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
commit 7fcbf25f39b82e833eacae2f339da44ed1878e37 parent a41adc069ef10dc9b2d7620315dba62fd7cbc44b Author: Toxa <56631470+untoxa@users.noreply.github.com> Date: Sat, 6 Feb 2021 14:15:52 +0300 Merge pull request #128 from bbbbbr/develop_gbcompress gbcompress command line tool (initial version) Diffstat:
| M | Makefile | 10 | +++++++--- |
| M | docs/pages/toolchain.md | 33 | ++++++++++++++++++++++++++------- |
| A | gbdk-support/gbcompress/LICENSE | 24 | ++++++++++++++++++++++++ |
| A | gbdk-support/gbcompress/Makefile | 17 | +++++++++++++++++ |
| A | gbdk-support/gbcompress/files.c | 61 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | gbdk-support/gbcompress/files.h | 7 | +++++++ |
| A | gbdk-support/gbcompress/gbcompress.c | 362 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | gbdk-support/gbcompress/gbcompress.h | 11 | +++++++++++ |
| A | gbdk-support/gbcompress/main.c | 173 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | gbdk-support/png2mtspr/png2mtspr | 0 |
10 files changed, 688 insertions(+), 10 deletions(-)
diff --git a/Makefile b/Makefile @@ -115,11 +115,12 @@ gbdk-support-build: @echo @echo Building ihxcheck @$(MAKE) -C $(GBDKSUPPORTDIR)/ihxcheck TOOLSPREFIX=$(TOOLSPREFIX) TARGETDIR=$(TARGETDIR)/ --no-print-directory - @echo @echo Building bankpack @$(MAKE) -C $(GBDKSUPPORTDIR)/bankpack TOOLSPREFIX=$(TOOLSPREFIX) TARGETDIR=$(TARGETDIR)/ --no-print-directory @echo Building png2mtspr @$(MAKE) -C $(GBDKSUPPORTDIR)/png2mtspr + @echo Building gbcompress + @$(MAKE) -C $(GBDKSUPPORTDIR)/gbcompress TOOLSPREFIX=$(TOOLSPREFIX) TARGETDIR=$(TARGETDIR)/ --no-print-directory @echo gbdk-support-install: gbdk-support-build $(BUILDDIR)/bin @@ -132,13 +133,15 @@ gbdk-support-install: gbdk-support-build $(BUILDDIR)/bin @echo Installing ihxcheck @cp $(GBDKSUPPORTDIR)/ihxcheck/ihxcheck $(BUILDDIR)/bin/ihxcheck$(EXEEXTENSION) @$(TARGETSTRIP) $(BUILDDIR)/bin/ihxcheck* - @echo @echo Installing bankpack @cp $(GBDKSUPPORTDIR)/bankpack/bankpack $(BUILDDIR)/bin/bankpack$(EXEEXTENSION) @$(TARGETSTRIP) $(BUILDDIR)/bin/bankpack* @echo Installing png2mtspr @cp $(GBDKSUPPORTDIR)/png2mtspr/png2mtspr$(EXEEXTENSION) $(BUILDDIR)/bin/png2mtspr$(EXEEXTENSION) @$(TARGETSTRIP) $(BUILDDIR)/bin/bankpack* + @echo Installing gbcompress + @cp $(GBDKSUPPORTDIR)/gbcompress/gbcompress $(BUILDDIR)/bin/gbcompress$(EXEEXTENSION) + @$(TARGETSTRIP) $(BUILDDIR)/bin/gbcompress* @echo gbdk-support-clean: @@ -147,11 +150,12 @@ gbdk-support-clean: @echo @echo Cleaning ihxcheck @$(MAKE) -C $(GBDKSUPPORTDIR)/ihxcheck clean --no-print-directory - @echo @echo Cleaning bankpack @$(MAKE) -C $(GBDKSUPPORTDIR)/bankpack clean --no-print-directory @echo Cleaning png2mtspr @$(MAKE) -C $(GBDKSUPPORTDIR)/png2mtspr clean + @echo Cleaning gbcompress + @$(MAKE) -C $(GBDKSUPPORTDIR)/gbcompress clean --no-print-directory @echo # Rules for gbdk-lib diff --git a/docs/pages/toolchain.md b/docs/pages/toolchain.md @@ -125,9 +125,11 @@ You may also want to read a tutorial on Makefiles. For example: https://makefiletutorial.com/ https://www.tutorialspoint.com/makefile/index.htm +@anchor build_tools +# Build Tools @anchor lcc -# lcc +## lcc lcc is the compiler driver (front end) for the GBDK/sdcc toolchain. It can be used to invoke all the tools needed for building a rom. If preferred, the individual tools can be called directly. @@ -136,19 +138,19 @@ If preferred, the individual tools can be called directly. @anchor sdcc -# sdcc +## sdcc SDCC C Source compiler - Arguments can be passed to it through @ref lcc using `-Wf-<argument>` and `-Wp-<argument>` (pre-processor) @anchor sdasgb -# sdasgb +## sdasgb SDCC Assembler for the gameboy - Arguments can be passed to it through @ref lcc using `-Wa-<argument>` @anchor bankpack -# bankpack +## bankpack Automatic Bank packer When enabled, automatically assigns banks for object files where bank has been set to `255`, see @ref rom_autobanking. @@ -163,7 +165,7 @@ Limitations @anchor sdldgb -# sdldgb +## sdldgb The SDCC linker for the gameboy. Links object files (.o) into a .ihx file which can be processed by @ref makebin @@ -171,7 +173,7 @@ Links object files (.o) into a .ihx file which can be processed by @ref makebin @anchor ihxcheck -# ihxcheck +## ihxcheck IHX file validator Checks .ihx files produced by @ref sdldgb for correctness. @@ -180,9 +182,26 @@ Checks .ihx files produced by @ref sdldgb for correctness. @anchor makebin -# makebin +## makebin IHX to ROM converter Converts .ihx files produced by @ref sdldgb into ROM files (.gb, .gbc). - Arguments can be passed to it through @ref lcc using `-Wm-<argument>` + +@anchor gbdk_utilities +# GBDK Utilities + + +@anchor utility_gbcompress +## GBCompress +Compresssion utility + +Compresses (and decompresses) binary file data with the gbcompress algorithm (also used in GBTD/GBMB). Decompression support is available in GBDK, see @ref gb_decompress(). + + +@anchor png2mtspr +## PNG to Metasprite +Tool for converting PNGs into GBDK format MetaSprites + +@todo Document png2mtspr diff --git a/gbdk-support/gbcompress/LICENSE b/gbdk-support/gbcompress/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to <https://unlicense.org> diff --git a/gbdk-support/gbcompress/Makefile b/gbdk-support/gbcompress/Makefile @@ -0,0 +1,17 @@ +# gbcompress makefile + +ifndef TARGETDIR +TARGETDIR = /opt/gbdk +endif + +CC = $(TOOLSPREFIX)gcc +CFLAGS = -ggdb -O -Wno-incompatible-pointer-types -DGBDKLIBDIR=\"$(TARGETDIR)\" +OBJ = main.o gbcompress.o files.o +BIN = gbcompress + +all: $(BIN) + +$(BIN): $(OBJ) + +clean: + rm -f *.o $(BIN) *~ diff --git a/gbdk-support/gbcompress/files.c b/gbdk-support/gbcompress/files.c @@ -0,0 +1,61 @@ + +#include <stdio.h> +#include <stdbool.h> +#include <stdint.h> +//#include <string.h> +#include <stdlib.h> +//#include <stdint.h> + + +// Read from a file into a buffer (will allocate needed memory) +// Returns NULL if reading file didn't succeed +uint8_t * file_read_into_buffer(char * filename, uint32_t *ret_size) { + + long fsize; + FILE * file_in = fopen(filename, "rb"); + uint8_t * filedata = NULL; + + if (file_in) { + // Get file size + fseek(file_in, 0, SEEK_END); + fsize = ftell(file_in); + if (fsize != -1L) { + fseek(file_in, 0, SEEK_SET); + + filedata = malloc(fsize); + if (filedata) { + if (fsize != fread(filedata, 1, fsize, file_in)) { + printf("gbcompress: Warning: File read size didn't match expected for %s\n", filename); + filedata = NULL; + } + // Read was successful, set return size + *ret_size = fsize; + } else printf("gbcompress: ERROR: Failed to allocate memory to read file %s\n", filename); + + } else printf("gbcompress: ERROR: Failed to read size of file %s\n", filename); + + fclose(file_in); + } else printf("gbcompress: ERROR: Failed to open input file %s\n", filename); + + return filedata; +} + + + +// Writes a buffer to a file +bool file_write_from_buffer(char * filename, uint8_t * p_buf, uint32_t data_len) { + + bool status = false; + size_t wrote_bytes; + FILE * file_out = fopen(filename, "wb"); + + if (file_out) { + if (data_len == fwrite(p_buf, 1, data_len, file_out)) + status = true; + else + printf("gbcompress: Warning: File write size didn't match expected for %s\n", filename); + + fclose(file_out); + } + return status; +} diff --git a/gbdk-support/gbcompress/files.h b/gbdk-support/gbcompress/files.h @@ -0,0 +1,7 @@ +#ifndef _FILES_H +#define _FILES_H + +char * file_read_into_buffer(char * filename, uint32_t *ret_size); +bool file_write_from_buffer(char * filename, uint8_t * p_buf, uint32_t data_len); + +#endif // _FILES_H diff --git a/gbdk-support/gbcompress/gbcompress.c b/gbdk-support/gbcompress/gbcompress.c @@ -0,0 +1,362 @@ +// This is free and unencumbered software released into the public domain. +// For more information, please refer to <https://unlicense.org> +// bbbbbr 2020 + +#include <stdio.h> +//#include <string.h> +#include <stdlib.h> +#include <stdbool.h> +#include <stdint.h> +#include "gbcompress.h" + +const uint8_t len_mask = 0x3F; +const uint8_t token_mask = 0xC0; + +const uint8_t token_byte = 0x00; +const uint8_t token_word = 0x40; +const uint8_t token_str = 0x80; +const uint8_t token_trash = 0xC0; + +const uint8_t EOFMarker = 0x00; + +uint8_t * FinBuf = 0; +uint8_t * FoutBuf = 0; +uint32_t Fsize_in = 0; +uint32_t FOutIndex = 0; +uint32_t Fsize_max = 0; + +static void check_write_size(uint8_t len) { + + if ((FOutIndex + len) >= Fsize_max) { + printf("Error: OutBuf too small"); + exit(EXIT_FAILURE); + } +} + + +static void write_byte(uint8_t len, uint8_t data) { + + check_write_size(2); // writing 2 bytes + + FoutBuf[FOutIndex++] = ((len - 1) & len_mask); + FoutBuf[FOutIndex++] = data; +} + + +static void write_word( uint8_t len, uint16_t data ) { + + check_write_size(3); // writing 3 bytes + + FoutBuf[FOutIndex++] = (((len - 1) & len_mask) | token_word); + FoutBuf[FOutIndex++] = (uint8_t)((data >> 8) & 0xFF); + FoutBuf[FOutIndex++] = (uint8_t)(data & 0xFF); +} + + +static void write_string( uint8_t len, uint16_t data) { + + check_write_size(3); // writing 3 bytes + + // conver's complement does not give the negation, see § Most negative number below. t back-ref offset from positive unsigned to negative signed + data = (data ^ 0xFFFF) + 1; + + FoutBuf[FOutIndex++] = (((len - 1) & len_mask) | token_str); + FoutBuf[FOutIndex++] = (uint8_t)(data & 0xFF); + FoutBuf[FOutIndex++] = (uint8_t)((data >> 8) & 0xFF); +} + + +static void write_trash( uint8_t len, uint8_t * pos) { + + uint8_t i; + + check_write_size(len); // writing len bytes + + FoutBuf[FOutIndex++] = (((len-1) & len_mask) | token_trash); + for (i=0; i < len; i++) + FoutBuf[FOutIndex++] = pos[i]; +} + + +static void write_end(void) { + + check_write_size(1); // writing 1 byte + + FoutBuf[FOutIndex++] = EOFMarker; +} + + +static int read_uint16_t(uint16_t byte_pos, uint16_t * out_data) { + + if ((byte_pos + 2) < Fsize_in) { + *out_data = (uint16_t)((FinBuf[byte_pos] << 8) + (uint32_t)FinBuf[byte_pos+1]); + return true; + } + else return false; +} + + +// Writes out any pending "trash" (non-rle sequence) and resets the counter +static void flush_trash(uint32_t * byte_pos, uint32_t * trash_len) { + + if (*trash_len > 0) { + write_trash(*trash_len, &FinBuf[*byte_pos - *trash_len]); + *trash_len = 0; + } +} + + +// Convert buffer inBuf to gbcompress rle encoding and write out to outBuf +// Returns converted length +uint32_t gbcompress_buf(uint8_t * inBuf, uint32_t size_in, uint8_t * outBuf, uint32_t size_max) { + + uint32_t byte_pos = 0; // bp + + uint8_t rle_u8_match; // x + uint16_t rle_u16_match; // y + + uint32_t rle_u8_len; // r_rb + uint32_t rle_u16_len; // r_rw + uint32_t rle_str_len; // r_rs + uint32_t trash_len; // tb (by "trash" the original author meant, "non-rle sequence of bytes") + + uint32_t rle_str_start; // rr + uint32_t rle_str_back_offset; // sr (this is signed in original code, handled differently to be unsigned now) + uint32_t rle_str_len_work; // rl + + FinBuf = inBuf; + FoutBuf = outBuf; + Fsize_in = size_in; + Fsize_max = size_max; + + byte_pos = 0; + trash_len = 0; + FOutIndex = 0; + + while (byte_pos < Fsize_in) { + + // Check for u8 RLE run up to 63 bytes max + rle_u8_match = FinBuf[byte_pos]; + rle_u8_len = 1; + while ((byte_pos + rle_u8_len) < Fsize_in) { + // If the current u8 matches, increment the length + if ((FinBuf[byte_pos + rle_u8_len] == rle_u8_match) && + (rle_u8_len < 64)) { + rle_u8_len++; + } + else break; + } + + // Check for overlapping uint16_t RLE run up to 63 bytes max + // Read in initial u16 to match against + if (read_uint16_t(byte_pos, &rle_u16_match)) { + uint16_t temp_u16; + rle_u16_len = 1; + // If the current u16 matches, increment the length + while (read_uint16_t(byte_pos + (rle_u16_len * 2), &temp_u16)) { + if ((temp_u16 == rle_u16_match) && + (rle_u16_len < 64)) { + rle_u16_len++; + } + else break; + } + } + + // Check for matching sequences starting at current position + // against all previous data beginning at start up to 63 bytes max + // (back reference "strings") + rle_str_start = 0; // + rle_str_back_offset = 0; + rle_str_len = 0; + while (rle_str_start < byte_pos) { + rle_str_len_work = 0; + + // Check for a matching run at rle_str_start against byte_pos + // and save length to rle_str_len_work + while ((byte_pos + rle_str_len_work) < Fsize_in) { + // Test to see if u8 in current sequence matches the u8 for a previous sequence + // Break out of the current sequence if it would reach 64 bytes + // or it would reach the current byte pos (and cause an overlap) + if ((FinBuf[rle_str_start + rle_str_len_work] == FinBuf[byte_pos + rle_str_len_work]) && + ((rle_str_start + rle_str_len_work) < byte_pos) && + (rle_str_len_work < 64)) { + + rle_str_len_work++; + } + else break; + } + + // If the newly tested sequence length is greater than the previous length + // then save the length and store an negative offset to it in rle_str_back_offset + if (rle_str_len_work > rle_str_len) { + rle_str_back_offset = byte_pos - rle_str_start; // Changed this from neg offset to pos, and gets flipped to negative on writing it out + rle_str_len = rle_str_len_work; + } + + rle_str_start++; + } + + + // Write out any rle data if it's ready + if ((rle_u8_len > 2) && + (rle_u8_len > rle_u16_len) && + (rle_u8_len > rle_str_len)) { + flush_trash(&byte_pos, &trash_len); + write_byte(rle_u8_len, rle_u8_match); + byte_pos = byte_pos + rle_u8_len; + } + else if ((rle_u16_len > 2) && + ((rle_u16_len*2) > rle_str_len)) { + flush_trash(&byte_pos, &trash_len); + write_word(rle_u16_len, rle_u16_match); + byte_pos = byte_pos + rle_u16_len*2; + } + else if (rle_str_len > 3) { + flush_trash(&byte_pos, &trash_len); + write_string(rle_str_len, rle_str_back_offset); + byte_pos = byte_pos + rle_str_len; + } + else if (trash_len >= 64) { + write_trash(trash_len, &FinBuf[byte_pos-trash_len]); + trash_len = 0; + } + else { + trash_len++; + byte_pos++; + } + + } + + // Flush any remaining "trash" bytes + flush_trash(&byte_pos, &trash_len); + + write_end(); + + return FOutIndex; +} + + + +// Decompress buffer inBuf from gbcompress rle encoding and write to outBuf +// Returns converted length +uint32_t gbdecompress_buf(uint8_t * inBuf, uint32_t size_in, uint8_t * outBuf, uint32_t size_max) { + + uint8_t rle_val[2]; + uint8_t token; + uint8_t rle_toggle; + uint8_t * p_rle_backref; + uint8_t * inBuf_end = inBuf + size_in - 1; + + uint32_t rle_len; + uint32_t rle_offset; + uint32_t size_out; + + size_out = 0; + rle_len = 0; + + while (inBuf <= inBuf_end) { + + // Check for EOF token + if (*inBuf == EOFMarker) + break; + + // Load the next RLE token if needed + if (rle_len == 0) { + // Read a RLE token + // First byte should always be a token + token = (*inBuf) & token_mask; + rle_len = ((*inBuf) & len_mask) + 1; + + inBuf++; // Move to next ENCODED byte + + rle_toggle = 0; // Reset RLE decoded byte flipflop + + // Reading a RLE Length zero = END of encoded data + // Then break out of loop and quit + if (rle_len == 0) { + break; + } + + // Read how to handle ENCODED RLE Value + switch (token) { + case token_byte: + // Load only one byte + rle_val[0] = *inBuf; + inBuf++; + break; + + case token_word: + // If token is Word double the RLE decode length + rle_len *= 2; + + // Load LS byte then MS Byte + rle_val[0] = *inBuf; + inBuf++; + rle_val[1] = *inBuf; + inBuf++; + break; + + case token_str: + // This token: copy N bytes from negative offset of current + // DECODED memory location (back reference) + rle_offset = (uint16_t)(*inBuf); + inBuf++; + rle_offset |= (uint16_t)((*inBuf)<<8); + inBuf++; + // Convert input from from Signed to Unsigned + rle_offset = (rle_offset ^ 0xFFFF) + 1; + + // Assign the string back reference relative to the current buffer pointer + p_rle_backref = outBuf - rle_offset; + break; + + case token_trash: // AKA "Trash Bytes" in GBTD + // This token : copy next N bytes directly from ENCODED input + break; + } + } + + while (rle_len) { + + // Abort if decompressed output exceeds output buffer size + if (size_out >= size_max) { + printf("Error: OutBuf too small"); + exit(EXIT_FAILURE); + } + + // Copy the decoded byte into VRAM + switch (token) { + case token_byte: + // Copy from cached repeating RLE value + *outBuf = rle_val[0]; + break; + + case token_word: + // Copy from cached repeating RLE value + // Toggle between MS/LS bytes input values + *outBuf = rle_val[rle_toggle]; + rle_toggle ^= 0x01; + break; + + case token_str: + // Copy byte from the backreferenced VRAM address + // Then increment backreference to next VRAM byte + *outBuf = *p_rle_backref; + p_rle_backref++; + break; + + case token_trash: + // Copy directly from encoded input + *outBuf = *inBuf; + inBuf++; + break; + } + + outBuf++; // Move to next VRAM byte + size_out++; + rle_len--; // Decrement number of RLE bytes remaining + } + } + + return size_out; +} diff --git a/gbdk-support/gbcompress/gbcompress.h b/gbdk-support/gbcompress/gbcompress.h @@ -0,0 +1,11 @@ +// This is free and unencumbered software released into the public domain. +// For more information, please refer to <https://unlicense.org> +// bbbbbr 2020 + +#ifndef _GBCOMPRESS_H +#define _GBCOMPRESS_H + +uint32_t gbcompress_buf(uint8_t * inBuf, uint32_t InSize, uint8_t * outBuf, uint32_t MaxSize); +uint32_t gbdecompress_buf(uint8_t * inBuf, uint32_t size_in, uint8_t * outBuf, uint32_t size_max); + +#endif // _GBCOMPRESS_H diff --git a/gbdk-support/gbcompress/main.c b/gbdk-support/gbcompress/main.c @@ -0,0 +1,173 @@ +// This is free and unencumbered software released into the public domain. +// For more information, please refer to <https://unlicense.org> +// bbbbbr 2020 + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <stdbool.h> +#include <stdint.h> + +#include "gbcompress.h" +#include "files.h" + +#define MAX_STR_LEN 4096 + +char filename_in[MAX_STR_LEN] = {'\0'}; +char filename_out[MAX_STR_LEN] = {'\0'}; + +uint8_t * p_buf_in = NULL; +uint8_t * p_buf_out = NULL; + +bool opt_mode_compress = true; +bool opt_verbose = false; + + +static void display_help(void); +static int handle_args(int argc, char * argv[]); +static int compress(void); +static int decompress(void); +void cleanup(void); + + +static void display_help(void) { + fprintf(stdout, + "gbcompress [options] infile outfile\n" + "Use: Gbcompress a binary file and write it out.\n" + "\n" + "Options\n" + "-h : Show this help screen\n" + "-d : Decompress (default is compress)\n" + "-v : Verbose output\n" + "Example: \"gbcompress binaryfile.bin compressed.bin\"\n" + "Example: \"gbcompress -d compressedfile.bin decompressed.bin\"\n" + ); +} + + +int handle_args(int argc, char * argv[]) { + + int i = 1; // start at first arg + + if( argc < 3 ) { + display_help(); + return false; + } + + // Start at first optional argument + // Last two arguments *must* be input/output files + for (i = 1; i < (argc - 2); i++ ) { + + if (argv[i][0] == '-') { + if (strstr(argv[i], "-h")) { + display_help(); + return false; // Don't parse input when -h is used + } else if (strstr(argv[i], "-v")) { + opt_verbose = true; + } else if (strstr(argv[i], "-d")) { + opt_mode_compress = false; + } else + printf("BankPack: Warning: Ignoring unknown option %s\n", argv[i]); + } + } + + // Copy input and output filenames from last two arguments + // if not preceded with option dash + if (argv[i][0] != '-') { + snprintf(filename_in, sizeof(filename_in), "%s", argv[i++]); + + if (argv[i][0] != '-') { + snprintf(filename_out, sizeof(filename_out), "%s", argv[i++]); + return true; + } + } + + + return false; +} + + +void cleanup(void) { + if (p_buf_in != NULL) { + free(p_buf_in); + p_buf_in = NULL; + } + if (p_buf_out != NULL) { + free(p_buf_out); + p_buf_out = NULL; + } +} + + +static int compress() { + + uint32_t buf_size = 0; + uint32_t out_len = 0; + + p_buf_in = file_read_into_buffer(filename_in, &buf_size); + + // Allocate buffer of same size for rle output + p_buf_out = malloc(buf_size); + + if ((p_buf_out) && (buf_size > 0)) { + out_len = gbcompress_buf(p_buf_in, buf_size, + p_buf_out, buf_size); + if (out_len > 0) + if (file_write_from_buffer(filename_out, p_buf_out, out_len)) { + if (opt_verbose) + printf("Compressed: %d bytes -> %d bytes (%%%.2f)\n", buf_size, out_len, ((double)out_len / (double)buf_size) * 100); + return EXIT_SUCCESS; + } + } + + return EXIT_FAILURE; +} + + +static int decompress() { + + uint32_t buf_size = 0; + uint32_t buf_size_out = 0; + uint32_t out_len = 0; + + p_buf_in = file_read_into_buffer(filename_in, &buf_size); + + // Allocate buffer of same size for rle output + // Todo: replace static buffer allocation with one that grows using realloc + buf_size_out = buf_size * 10; + p_buf_out = malloc(buf_size_out); + + if ((p_buf_out) && (buf_size > 0)) { + out_len = gbdecompress_buf(p_buf_in, buf_size, + p_buf_out, buf_size_out); + if (out_len > 0) + if (file_write_from_buffer(filename_out, p_buf_out, out_len)) { + if (opt_verbose) + printf("Decompressed: %d bytes -> %d bytes (compression was %%%.2f)\n", buf_size, out_len, ((double)buf_size / (double)out_len) * 100); + return EXIT_SUCCESS; + } + } + + return EXIT_FAILURE; +} + + +int main( int argc, char *argv[] ) { + + // Exit with failure by default + int ret = EXIT_FAILURE; + + // Register cleanup with exit handler + atexit(cleanup); + + if (handle_args(argc, argv)) { + + if (opt_mode_compress) + ret = compress(); + else + ret = decompress(); + } + cleanup(); + + return ret; // Exit with failure by default +} diff --git a/gbdk-support/png2mtspr/png2mtspr b/gbdk-support/png2mtspr/png2mtspr Binary files differ.
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.