mirror of
https://github.com/gbdk-2020/gbdk-2020.git
synced 2026-02-20 00:32:21 +01:00
png2hicolorgb: merge in upstream changes
- Added --palendbit : Sets unused bit .15 = 1 for last u16 entry in palette data indicating end, instead of having to count or check the current scanline. - Added --addendcolor=N: Appends 32 x color N (in hex BGR555, 64 extra bytes total) in the palette data to clear the background and avoid artifacts on source images that are shorter than the screen height. - Added --precompiled mode
This commit is contained in:
@@ -35,7 +35,7 @@ bool file_c_output_write(const char * fname_base, int bank_num, int tile_count,
|
||||
ch++;
|
||||
}
|
||||
|
||||
log_verbose("Writing C format to: %s, %s\n", filename_c, filename_h);
|
||||
VERBOSE("Writing C format to: %s, %s\n", filename_c, filename_h);
|
||||
|
||||
// === C Source output ===
|
||||
FILE * file_out_c = fopen(filename_c, "w");
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#ifndef C_SOURCE_H
|
||||
#define C_SOURCE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool file_c_output_write(const char * fname_base, int bank_num, int tile_count, int height_in_tiles);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#ifndef _COMMON_H
|
||||
#define _COMMON_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define TILE_HEIGHT_PX 8
|
||||
#define TILE_WIDTH_PX 8
|
||||
|
||||
@@ -13,6 +15,15 @@
|
||||
|
||||
#define MAX_PATH (MAX_STR_LEN)
|
||||
|
||||
#ifndef __has_attribute
|
||||
#define __has_attribute(attr) 0
|
||||
#endif
|
||||
#if __has_attribute(format)
|
||||
#define FMT(kind, str_idx, first_to_check) __attribute__((format(kind, str_idx, first_to_check)))
|
||||
#else
|
||||
#define FMT(kind, str_idx, first_to_check)
|
||||
#endif
|
||||
|
||||
enum {
|
||||
IMG_TYPE_PNG
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
// 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) {
|
||||
uint8_t * file_read_into_buffer(char * filename, size_t *ret_size) {
|
||||
|
||||
long fsize;
|
||||
FILE * file_in = fopen(filename, "rb");
|
||||
@@ -22,12 +22,12 @@ uint8_t * file_read_into_buffer(char * filename, uint32_t *ret_size) {
|
||||
|
||||
filedata = (uint8_t *)malloc(fsize);
|
||||
if (filedata) {
|
||||
if (fsize != fread(filedata, 1, fsize, file_in)) {
|
||||
if (fsize != (long)fread(filedata, 1, fsize, file_in)) {
|
||||
printf("Warning: File read size didn't match expected for %s\n", filename);
|
||||
filedata = NULL;
|
||||
}
|
||||
// Read was successful, set return size
|
||||
*ret_size = fsize;
|
||||
*ret_size = (size_t)fsize;
|
||||
} else printf("ERROR: Failed to allocate memory to read file %s\n", filename);
|
||||
|
||||
} else printf("ERROR: Failed to read size of file %s\n", filename);
|
||||
@@ -41,10 +41,9 @@ uint8_t * file_read_into_buffer(char * filename, uint32_t *ret_size) {
|
||||
|
||||
|
||||
// Writes a buffer to a file
|
||||
bool file_write_from_buffer(char * filename, uint8_t * p_buf, uint32_t data_len) {
|
||||
bool file_write_from_buffer(char * filename, uint8_t * p_buf, size_t data_len) {
|
||||
|
||||
bool status = false;
|
||||
size_t wrote_bytes;
|
||||
FILE * file_out = fopen(filename, "wb");
|
||||
|
||||
if (file_out) {
|
||||
@@ -64,7 +63,7 @@ bool file_write_from_buffer(char * filename, uint8_t * p_buf, uint32_t data_len)
|
||||
|
||||
// Read from a file into a buffer (will allocate needed memory)
|
||||
// Returns NULL if reading file didn't succeed
|
||||
char * file_read_into_buffer_char(char * filename, uint32_t *ret_size) {
|
||||
char * file_read_into_buffer_char(char * filename, size_t *ret_size) {
|
||||
|
||||
long fsize;
|
||||
// On windows windows fread() will auto-translate CRLF to just LF and
|
||||
@@ -81,12 +80,12 @@ char * file_read_into_buffer_char(char * filename, uint32_t *ret_size) {
|
||||
|
||||
filedata = (char *)malloc(fsize);
|
||||
if (filedata) {
|
||||
if (fsize != fread(filedata, 1, fsize, file_in)) {
|
||||
if (fsize != (long)fread(filedata, 1, fsize, file_in)) {
|
||||
printf("Warning: File read size didn't match expected for %s\n", filename);
|
||||
filedata = NULL;
|
||||
}
|
||||
// Read was successful, set return size
|
||||
*ret_size = fsize;
|
||||
*ret_size = (size_t)fsize;
|
||||
} else printf("ERROR: Failed to allocate memory to read file %s\n", filename);
|
||||
|
||||
} else printf("ERROR: Failed to read size of file %s\n", filename);
|
||||
@@ -100,10 +99,9 @@ char * file_read_into_buffer_char(char * filename, uint32_t *ret_size) {
|
||||
|
||||
|
||||
// Writes a buffer to a file
|
||||
bool file_write_from_buffer_char(char * filename, char * p_buf, uint32_t data_len) {
|
||||
bool file_write_from_buffer_char(char * filename, char * p_buf, size_t data_len) {
|
||||
|
||||
bool status = false;
|
||||
size_t wrote_bytes;
|
||||
FILE * file_out = fopen(filename, "w");
|
||||
|
||||
if (file_out) {
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#ifndef _FILES_H
|
||||
#define _FILES_H
|
||||
|
||||
uint8_t * 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);
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
char * file_read_into_buffer_char(char * filename, uint32_t *ret_size);
|
||||
bool file_write_from_buffer_char(char * filename, char * p_buf, uint32_t data_len);
|
||||
uint8_t * file_read_into_buffer(char * filename, size_t *ret_size);
|
||||
bool file_write_from_buffer(char * filename, uint8_t * p_buf, size_t data_len);
|
||||
|
||||
char * file_read_into_buffer_char(char * filename, size_t *ret_size);
|
||||
bool file_write_from_buffer_char(char * filename, char * p_buf, size_t data_len);
|
||||
|
||||
#endif // _FILES_H
|
||||
|
||||
|
||||
@@ -47,12 +47,36 @@ enum conversion_types {
|
||||
CONV_TYPE_MAX = CONV_TYPE_WU
|
||||
};
|
||||
|
||||
enum pattern_types {
|
||||
HICOLOR_PATTERN_ADAPTIVE_FAST = 0,
|
||||
HICOLOR_PATTERN_ADAPTIVE_MED = 1,
|
||||
HICOLOR_PATTERN_ADAPTIVE_BEST = 2,
|
||||
|
||||
HICOLOR_PATTERN_ADAPTIVE_COUNT = 3,
|
||||
HICOLOR_PATTERN_FIXED_COUNT = 80,
|
||||
HICOLOR_PATTERN_MIN = 0,
|
||||
HICOLOR_PATTERN_MAX = (HICOLOR_PATTERN_FIXED_COUNT - 1),
|
||||
|
||||
HICOLOR_PATTERN_OPT_MIN = 0,
|
||||
HICOLOR_PATTERN_OPT_MAX = ((HICOLOR_PATTERN_FIXED_COUNT + HICOLOR_PATTERN_ADAPTIVE_COUNT) - 1),
|
||||
|
||||
HICOLOR_PATTERN_NOT_FOUND = 998,
|
||||
HICOLOR_PATTERN_NOT_FOUND_HAS_CHARS = 999
|
||||
};
|
||||
|
||||
#define CONV_SIDE_LEFT 0
|
||||
#define CONV_SIDE_RIGHT 1
|
||||
|
||||
#define CONV_Y_SHIFT_UP_1 1
|
||||
#define CONV_Y_SHIFT_NO 0
|
||||
|
||||
#define SM83_OPCODE_HALT 0x76u
|
||||
#define SM83_OPCODE_LD_HL_B 0x70u
|
||||
#define SM83_OPCODE_LD_HL_C 0x71u
|
||||
#define SM83_OPCODE_LD_HL_D 0x72u
|
||||
#define SM83_OPCODE_LD_HL_E 0x73u
|
||||
#define SM83_OPCODE_LD_HL_IMM8 0x36u
|
||||
#define SM83_OPCODE_RET 0xC9u
|
||||
|
||||
#define PAL_REGION_HEIGHT_PX 2
|
||||
|
||||
@@ -66,4 +90,9 @@ enum conversion_types {
|
||||
#define VALIDATE_WIDTH 160 // (BUF_WIDTH)
|
||||
#define VALIDATE_HEIGHT (BUF_HEIGHT)
|
||||
|
||||
#define BYTES_PER_COLOR 2
|
||||
#define COLORS_PER_PAL 4
|
||||
#define PALS_PER_SIDE 4
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -10,13 +12,13 @@
|
||||
#include "wu.h"
|
||||
|
||||
|
||||
#include <common.h>
|
||||
#include <options.h>
|
||||
#include <files.h>
|
||||
#include <image_info.h>
|
||||
#include <logging.h>
|
||||
#include <c_source.h>
|
||||
#include <tile_dedupe.h>
|
||||
#include "common.h"
|
||||
#include "options.h"
|
||||
#include "files.h"
|
||||
#include "image_info.h"
|
||||
#include "logging.h"
|
||||
#include "c_source.h"
|
||||
#include "tile_dedupe.h"
|
||||
|
||||
/* Gameboy Hi-Colour Convertor */
|
||||
/* Glen Cook */
|
||||
@@ -143,17 +145,23 @@ static uint8_t *pBitsdest = Bitsdest;
|
||||
#define MAX_CONVERSION_TYPES 83
|
||||
#define MAX_QUANTISER_TYPES 4
|
||||
|
||||
int image_y_min;
|
||||
int image_y_max;
|
||||
int image_height;
|
||||
int y_region_count_left;
|
||||
int y_region_count_right;
|
||||
int y_region_count_lr_rndup;
|
||||
int y_region_count_both_sides;
|
||||
int y_height_in_tiles_left;
|
||||
int y_height_in_tiles_right;
|
||||
int y_height_in_tiles;
|
||||
int y_height_in_tiles_lr_rndup;
|
||||
pattern_entry named_patterns[] = {
|
||||
{.num = HICOLOR_PATTERN_ADAPTIVE_FAST, .name="adaptive-fast"},
|
||||
{.num = HICOLOR_PATTERN_ADAPTIVE_MED, .name="adaptive-medium"},
|
||||
{.num = HICOLOR_PATTERN_ADAPTIVE_BEST, .name="adaptive-best"}
|
||||
};
|
||||
|
||||
static unsigned int image_y_min;
|
||||
static unsigned int image_y_max;
|
||||
static unsigned int image_height;
|
||||
static unsigned int y_region_count_left;
|
||||
static unsigned int y_region_count_right;
|
||||
static unsigned int y_region_count_lr_rndup;
|
||||
static unsigned int y_region_count_both_sides;
|
||||
static unsigned int y_height_in_tiles_left;
|
||||
static unsigned int y_height_in_tiles_right;
|
||||
static unsigned int y_height_in_tiles;
|
||||
static unsigned int y_height_in_tiles_lr_rndup;
|
||||
|
||||
|
||||
static void PrepareTileSet(void);
|
||||
@@ -163,6 +171,7 @@ static void PrepareAttributes(void);
|
||||
static void DedupeTileset(void);
|
||||
|
||||
static void ExportPalettes(const char * fname_base);
|
||||
static void ExportPalettesPrecompiled(const char * fname_base);
|
||||
static void ExportTileSet(const char * fname_base);
|
||||
static void ExportMap(const char * fname_base);
|
||||
static void ExportMapAttributes(const char * fname_base);
|
||||
@@ -170,13 +179,14 @@ static void ExportMapAttributes(const char * fname_base);
|
||||
|
||||
void hicolor_init(void) {
|
||||
// Defaults
|
||||
LConversion = 3; // Default Conversion (Fixed 3-2-3-2) Left Screen
|
||||
RConversion = 3; // Default Conversion (Fixed 3-2-3-2) Righ Screen
|
||||
ConvertType = 1; // Normal default is 1 ("Median cut - no dither")
|
||||
LConversion = HICOLOR_PATTERN_ADAPTIVE_MED; // Default Conversion adaptive-medium Left Screen
|
||||
RConversion = HICOLOR_PATTERN_ADAPTIVE_MED; // Default Conversion adaptive-medium Righ Screen
|
||||
ConvertType = CONV_TYPE_MED_CUT_NO_DITHER; // Normal default is 1 ("Median cut - no dither")
|
||||
}
|
||||
|
||||
|
||||
static void hicolor_vars_prep(image_data * p_loaded_image) {
|
||||
log_debug("hicolor_vars_prep()\n");
|
||||
DBG("hicolor_vars_prep()\n");
|
||||
|
||||
image_height = p_loaded_image->height;
|
||||
image_y_min = 0;
|
||||
@@ -204,25 +214,53 @@ static void hicolor_vars_prep(image_data * p_loaded_image) {
|
||||
}
|
||||
|
||||
|
||||
// Look up user specified L/R pattern by name if possible
|
||||
unsigned int hicolor_get_pattern_by_name(const char * opt_str) {
|
||||
char opt_str_lower[MAX_STR_LEN];
|
||||
unsigned int c;
|
||||
|
||||
// Convert user input to lowercase first
|
||||
for(c = 0; (opt_str[c] != '\0') && (c < MAX_STR_LEN); c++)
|
||||
opt_str_lower[c] = tolower(opt_str[c]);
|
||||
opt_str_lower[c] = '\0';
|
||||
|
||||
// Return if it matches any names in the named pattern list
|
||||
for (c = 0; c < ARRAY_LEN(named_patterns); c++) {
|
||||
if (strcmp(opt_str_lower, named_patterns[c].name) == 0)
|
||||
return named_patterns[c].num;
|
||||
}
|
||||
|
||||
// If there was no match, return if it contained any non-digit characters,
|
||||
// meaning it should not later be converted as a raw numeric value for the option
|
||||
while (*opt_str != '\0') {
|
||||
if (isdigit(*opt_str) == 0) {
|
||||
return HICOLOR_PATTERN_NOT_FOUND_HAS_CHARS;
|
||||
}
|
||||
opt_str++;
|
||||
}
|
||||
|
||||
return HICOLOR_PATTERN_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
void hicolor_set_convert_left_pattern(uint8_t new_value) {
|
||||
// IDC_CONVERTLEFT
|
||||
LConversion = new_value;
|
||||
log_verbose("HiColor: Left pattern set to %d\n", new_value);
|
||||
VERBOSE("HiColor: Left pattern set to %d\n", new_value);
|
||||
}
|
||||
|
||||
|
||||
void hicolor_set_convert_right_pattern(uint8_t new_value) {
|
||||
// IDC_CONVERTRIGHT
|
||||
RConversion = new_value;
|
||||
log_verbose("HiColor: Right pattern set to %d\n", new_value);
|
||||
VERBOSE("HiColor: Right pattern set to %d\n", new_value);
|
||||
}
|
||||
|
||||
|
||||
void hicolor_set_type(uint8_t new_value) {
|
||||
// IDC_CONVERTTYPE
|
||||
ConvertType = new_value;
|
||||
log_verbose("HiColor: Convert type set to %d\n", new_value);
|
||||
VERBOSE("HiColor: Convert type set to %d\n", new_value);
|
||||
}
|
||||
|
||||
|
||||
@@ -230,14 +268,14 @@ void hicolor_set_type(uint8_t new_value) {
|
||||
|
||||
// Equivalent of former file loading
|
||||
static void hicolor_image_import(image_data * p_loaded_image) {
|
||||
log_debug("hicolor_image_import()\n");
|
||||
DBG("hicolor_image_import()\n");
|
||||
|
||||
// TODO: input guarding
|
||||
// TODO: deduplicate some of the array copying around
|
||||
uint8_t * p_input_img = p_loaded_image->p_img_data;
|
||||
|
||||
for (int y=0; y< image_height; y++) {
|
||||
for (int x=0; x< 160; x++) {
|
||||
for (unsigned int y=0; y< image_height; y++) {
|
||||
for (unsigned int x=0; x< 160; x++) {
|
||||
|
||||
// Clamp to CGB max R/G/B value in RGB 888 mode (31u << 3)
|
||||
// png_image[].rgb -> pic2[].rgb -> pBitssource[].bgr??
|
||||
@@ -253,9 +291,9 @@ static void hicolor_image_import(image_data * p_loaded_image) {
|
||||
// It's convoluted, but pBitssource & pBitsdest are used for:
|
||||
// - display as windows DIBs (formerly)
|
||||
// - and for some calculations at the end of ConvertRegions()
|
||||
for (int y=0; y<image_height; y++) {
|
||||
for (int x=0; x<160; x++) {
|
||||
for (int z=0; z<3; z++) {
|
||||
for (unsigned int y=0; y<image_height; y++) {
|
||||
for (unsigned int x=0; x<160; x++) {
|
||||
for (unsigned int z=0; z<3; z++) {
|
||||
// TODO: (2-z) seems to be swapping RGB for BGR?
|
||||
*(pBitssource+(image_y_max-y)*3*160+x*3+z) = pic2[x][y][2-z]; // Invert the dib, cos windows likes it like that !!
|
||||
}
|
||||
@@ -268,17 +306,17 @@ static void hicolor_image_import(image_data * p_loaded_image) {
|
||||
// TODO: fix
|
||||
// TODO: Operates on RGB data in pic[] copied from RGB data in pic2
|
||||
static void hicolor_convert(void) {
|
||||
log_debug("hicolor_convert()\n");
|
||||
DBG("hicolor_convert()\n");
|
||||
|
||||
for(int x=0; x<160; x++)
|
||||
for(unsigned int x=0; x<160; x++)
|
||||
{
|
||||
for(int y=0; y<image_height; y++)
|
||||
for(unsigned int y=0; y<image_height; y++)
|
||||
{
|
||||
pic[x][y][0] = pic2[x][y][0];
|
||||
pic[x][y][1] = pic2[x][y][1];
|
||||
pic[x][y][2] = pic2[x][y][2];
|
||||
|
||||
for(int i=0; i<3; i++)
|
||||
for(unsigned int i=0; i<3; i++)
|
||||
{
|
||||
*(Data + y*160*3+x*3+i) = pic[x][y][i];
|
||||
}
|
||||
@@ -294,7 +332,7 @@ static void hicolor_save(const char * fname_base) {
|
||||
// Default tile count to non-deduplicated number
|
||||
int tile_count = y_height_in_tiles * (160 / TILE_WIDTH_PX);
|
||||
|
||||
log_debug("hicolor_save()\n");
|
||||
DBG("hicolor_save()\n");
|
||||
PrepareTileSet();
|
||||
PrepareMap();
|
||||
PrepareAttributes();
|
||||
@@ -305,7 +343,11 @@ static void hicolor_save(const char * fname_base) {
|
||||
}
|
||||
|
||||
ExportTileSet(fname_base);
|
||||
ExportPalettes(fname_base);
|
||||
if (opt_get_precompiled_palette())
|
||||
ExportPalettesPrecompiled(fname_base);
|
||||
else
|
||||
ExportPalettes(fname_base);
|
||||
|
||||
ExportMap(fname_base);
|
||||
ExportMapAttributes(fname_base);
|
||||
|
||||
@@ -317,7 +359,7 @@ static void hicolor_save(const char * fname_base) {
|
||||
|
||||
// Currently expects width x height x 3(RGB888)
|
||||
void hicolor_process_image(image_data * p_loaded_image, const char * fname_base) {
|
||||
log_debug("hicolor_process_image(), fname_base: \"%s\"\n", fname_base);
|
||||
DBG("hicolor_process_image(), fname_base: \"%s\"\n", fname_base);
|
||||
|
||||
hicolor_vars_prep(p_loaded_image);
|
||||
hicolor_image_import(p_loaded_image);
|
||||
@@ -340,8 +382,8 @@ static void DedupeTileset(void)
|
||||
|
||||
TileCountDeduped = 0;
|
||||
// Traverse all tiles in the image/map
|
||||
for (int mapy = 0; mapy < y_height_in_tiles; mapy++) {
|
||||
for (int mapx = 0; mapx < 20; mapx++) {
|
||||
for (unsigned int mapy = 0; mapy < y_height_in_tiles; mapy++) {
|
||||
for (unsigned int mapx = 0; mapx < 20; mapx++) {
|
||||
|
||||
map_tile_id = MapTileIDs[mapx][mapy];
|
||||
map_tile_id += (MapAttributes[mapx][mapy] & CGB_ATTR_TILES_BANK) ? CGB_TILES_START_BANK_1 : CGB_TILES_START_BANK_0;
|
||||
@@ -360,7 +402,7 @@ static void DedupeTileset(void)
|
||||
MapAttributes[mapx][mapy] = (MapAttributes[mapx][mapy] & CGB_ATTR_PALETTES_ONLY) | new_attribs;
|
||||
}
|
||||
}
|
||||
log_verbose("DedupeTileset(): Reduced tiles from %d (%d bytes) to %d (%d bytes) = %d bytes saved. %%%d of original size\n",
|
||||
VERBOSE("DedupeTileset(): Reduced tiles from %d (%d bytes) to %d (%d bytes) = %d bytes saved. %%%d of original size\n",
|
||||
map_tile_id + 1, (map_tile_id + 1) * TILE_SZ, TileCountDeduped, TileCountDeduped * TILE_SZ,
|
||||
((map_tile_id + 1) * TILE_SZ) - (TileCountDeduped * TILE_SZ), (TileCountDeduped * 100) / (map_tile_id + 1));
|
||||
}
|
||||
@@ -370,7 +412,6 @@ static void DedupeTileset(void)
|
||||
|
||||
|
||||
static void PrepareTileSet(void) {
|
||||
uint32_t byteWritten;
|
||||
u32 x, y;
|
||||
u8 c1,c2;
|
||||
u8 dx,dy;
|
||||
@@ -408,11 +449,11 @@ static void PrepareMap(void) {
|
||||
// Set up export Map Tile IDs
|
||||
// Note: The indexes are clipped to 0-255 (instead of 0-512),
|
||||
// the attribute tile index+256 bit is auto-calculated in the attribute map in PrepareAttributes()
|
||||
int tile_id = 0;
|
||||
for (int mapy = 0; mapy < y_height_in_tiles; mapy++) {
|
||||
for (int mapx = 0; mapx < 20; mapx++) {
|
||||
uint8_t tile_id = 0;
|
||||
for (unsigned int mapy = 0; mapy < y_height_in_tiles; mapy++) {
|
||||
for (unsigned int mapx = 0; mapx < 20; mapx++) {
|
||||
|
||||
MapTileIDs[mapx][mapy] = (uint8_t)tile_id;
|
||||
MapTileIDs[mapx][mapy] = tile_id;
|
||||
tile_id++;
|
||||
}
|
||||
}
|
||||
@@ -422,9 +463,9 @@ static void PrepareMap(void) {
|
||||
static void PrepareAttributes(void) {
|
||||
// Set up the Map Attributes table
|
||||
unsigned int tile_id = 0;
|
||||
for(int MastY=0;MastY<y_height_in_tiles_right;MastY++)
|
||||
for(unsigned int MastY=0;MastY<y_height_in_tiles_right;MastY++)
|
||||
{
|
||||
for(int MastX=0;MastX<2;MastX++)
|
||||
for(unsigned int MastX=0;MastX<2;MastX++)
|
||||
{
|
||||
int Line=Best[MastX][MastY];
|
||||
int width=0;
|
||||
@@ -454,7 +495,7 @@ static void ExportTileSet(const char * fname_base)
|
||||
|
||||
strcpy(filename, fname_base);
|
||||
strcat(filename, ".til");
|
||||
log_verbose("Writing Tile Patterns to: %s\n", filename);
|
||||
VERBOSE("Writing Tile Patterns to: %s\n", filename);
|
||||
|
||||
if (opt_get_tile_dedupe()) {
|
||||
|
||||
@@ -473,16 +514,25 @@ static void ExportTileSet(const char * fname_base)
|
||||
static void ExportPalettes(const char * fname_base)
|
||||
{
|
||||
char filename[MAX_PATH * 2];
|
||||
uint32_t byteWritten;
|
||||
uint8_t tmpByte;
|
||||
s32 i, j, k;
|
||||
unsigned int i, j, k;
|
||||
s32 r,g,b,v;
|
||||
|
||||
uint16_t pal_end_color_bgr555 = 0x0000u;
|
||||
int pal_end_color_count = 0;
|
||||
|
||||
strcpy(filename, fname_base);
|
||||
strcat(filename, ".pal");
|
||||
log_verbose("Writing Palette to: %s\n", filename);
|
||||
VERBOSE("Writing Palette to: %s\n", filename);
|
||||
|
||||
// No longer +1 for the trailing 0x2D
|
||||
int outbuf_sz_pals = (y_region_count_both_sides * PALS_PER_SIDE * COLORS_PER_PAL * BYTES_PER_COLOR);
|
||||
|
||||
// Handle resize if trailing end colors have been appended
|
||||
if (opt_get_enable_pal_end_color()) {
|
||||
opt_load_pal_end_color(&pal_end_color_bgr555, &pal_end_color_count);
|
||||
outbuf_sz_pals += (pal_end_color_count * BYTES_PER_COLOR);
|
||||
}
|
||||
|
||||
int outbuf_sz_pals = (((y_region_count_both_sides) * 4 * 4 * 2) + 1);
|
||||
uint8_t output_buf[outbuf_sz_pals];
|
||||
uint8_t * p_buf = output_buf;
|
||||
|
||||
@@ -497,7 +547,7 @@ static void ExportPalettes(const char * fname_base)
|
||||
g = IdealPal[(i%2)*4+j][i/2][k][1];
|
||||
b = IdealPal[(i%2)*4+j][i/2][k][2];
|
||||
|
||||
// TODO: Converting to BGR555 probably
|
||||
// Converting to BGR555
|
||||
v = ((b/8)*32*32) + ((g/8)*32) + (r/8);
|
||||
|
||||
// 2 bytes per color
|
||||
@@ -507,8 +557,22 @@ static void ExportPalettes(const char * fname_base)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: What is this and why? :)
|
||||
*p_buf++ = 0x2d;
|
||||
// Add trailing 32 colors to clear BG if enabled
|
||||
if (opt_get_enable_pal_end_color()) {
|
||||
for (int c = 0; c < pal_end_color_count; c++) {
|
||||
*p_buf++ = (u8)(pal_end_color_bgr555 & 255);
|
||||
*p_buf++ = (u8)(pal_end_color_bgr555 / 256);
|
||||
}
|
||||
}
|
||||
|
||||
// Set unused bit .15 = 1 for last u16 palette entry
|
||||
// to indicate it's the final one
|
||||
if (opt_get_pal_end_bit())
|
||||
output_buf[outbuf_sz_pals - 1] |= 0x80u;
|
||||
|
||||
// This has an unknown purpose and was present in
|
||||
// the original source code, but doesn't appear to be needed.
|
||||
// *p_buf++ = 0x2d;
|
||||
|
||||
if (!file_write_from_buffer(filename, output_buf, outbuf_sz_pals))
|
||||
set_exit_error();
|
||||
@@ -516,6 +580,104 @@ static void ExportPalettes(const char * fname_base)
|
||||
}
|
||||
|
||||
|
||||
#define LDHL_2x_SZ 2 // Scale factor for pal color bytes loaded via `ld [hl], <byte>`
|
||||
#define RET_SZ 1 // Size of ret opcode
|
||||
#define VBLANK_LOAD_LINE_CNT 2 // Number of lines loaded in vblank
|
||||
#define HALT_LOAD_SZ 5 // Size of Halt + LD HL, B/C/D/E on non-vblank scanlines
|
||||
#define STAT_PRELOAD_SAVE_SZ 4 // Number of pal color bytes that get pre-loaded in STAT isr, so don't need 2x sizing for ld [hl], <byte>
|
||||
#define PAL_BYTES_PER_LINE (PALS_PER_SIDE * COLORS_PER_PAL * BYTES_PER_COLOR)
|
||||
|
||||
static void ExportPalettesPrecompiled(const char * fname_base)
|
||||
{
|
||||
char filename[MAX_PATH * 2];
|
||||
unsigned int line, pal, col;
|
||||
s32 r,g,b,v;
|
||||
size_t outbuf_sz_pals = 0;
|
||||
|
||||
strcpy(filename, fname_base);
|
||||
strcat(filename, ".pal");
|
||||
VERBOSE("Writing Pre-compiled Palette to: %s\n", filename);
|
||||
|
||||
// How to calculate output size:
|
||||
//
|
||||
// VBLANK ISR (2 Lines)
|
||||
// ~ No wait + load header code
|
||||
// + Always uses LD [HL] (so 2x num pal bytes)
|
||||
// + 1 ret shared by the 2 lines
|
||||
// = (Pal bytes per line x 2) x (2 lines) + 1 ret
|
||||
// (((4 x 4 x 2) x 2) x 2) + 1 = 129
|
||||
outbuf_sz_pals = ((PAL_BYTES_PER_LINE * LDHL_2x_SZ) * VBLANK_LOAD_LINE_CNT) + RET_SZ;
|
||||
|
||||
// Then...
|
||||
// STAT ISR (Num Lines - 2)
|
||||
// - 4 bytes preload in STAT ISR without LD [HL] (so: 4 pal bytes without 2x sizing)
|
||||
// + Then wait + load header code (so +5 bytes)
|
||||
// + Then remainder of pal bytes get LD [HL] (so 2x num pal bytes)
|
||||
// + 1 ret per line
|
||||
// = (( (Pal bytes per line x 2) - 4 preload bytes + 5 header + 1 ret) x (num lines - 2 vblank lines)
|
||||
// ( ( (4 x 4 x 2) x 2) - 4) + 5 + 1) = 66 x (num lines - 2)
|
||||
outbuf_sz_pals += ((PAL_BYTES_PER_LINE * LDHL_2x_SZ) - STAT_PRELOAD_SAVE_SZ + HALT_LOAD_SZ + RET_SZ) * (y_region_count_both_sides - VBLANK_LOAD_LINE_CNT);
|
||||
|
||||
uint8_t output_buf[outbuf_sz_pals];
|
||||
uint8_t * p_buf = output_buf;
|
||||
|
||||
// Note: "line" 0 is equivalent to something like scanline -1
|
||||
// (due to left side region starting 1 scanline before line 0)
|
||||
for (line = 0; line < (y_region_count_both_sides); line++) // Number of palette sets (left side updates + right side updates)
|
||||
{
|
||||
for (pal = 0; pal < 4; pal++) // Each palette in the line
|
||||
{
|
||||
for(col = 0; col < 4;col++) // Each color in the palette
|
||||
{
|
||||
// Precompiled mode has a "header" inserted after the first two colours of palette 0,
|
||||
// except for the first two scanline lines (which are during VBlank so can load directly without a preload + wait)
|
||||
if (line >= 2 && pal == 0 && col == 2) {
|
||||
*p_buf++ = SM83_OPCODE_HALT;
|
||||
*p_buf++ = SM83_OPCODE_LD_HL_B;
|
||||
*p_buf++ = SM83_OPCODE_LD_HL_C;
|
||||
*p_buf++ = SM83_OPCODE_LD_HL_D;
|
||||
*p_buf++ = SM83_OPCODE_LD_HL_E;
|
||||
}
|
||||
|
||||
r = IdealPal[(line % 2)*4 + pal][line / 2][col][0];
|
||||
g = IdealPal[(line % 2)*4 + pal][line / 2][col][1];
|
||||
b = IdealPal[(line % 2)*4 + pal][line / 2][col][2];
|
||||
|
||||
// Converting to BGR555
|
||||
v = ((b/8)*32*32) + ((g/8)*32) + (r/8);
|
||||
|
||||
// Load 2 bytes per color
|
||||
|
||||
// Insert LD [HL] opcode before pal data bytes... when:
|
||||
// - Any time during first two lines (i.e for all pal bytes in vblank)
|
||||
// - Or is the Second Palette or more (of each Line)
|
||||
// - Or is the Third Color or more (of each Palette. the STAT isr has pre-load code for the first two pal colors)
|
||||
if (line < 2 || pal >= 1 || col >= 2) {
|
||||
*p_buf++ = SM83_OPCODE_LD_HL_IMM8; // ld [hl], <imm8>
|
||||
}
|
||||
*p_buf++ = (u8)(v & 255);
|
||||
|
||||
if (line < 2 || pal >= 1 || col >= 2) {
|
||||
*p_buf++ = SM83_OPCODE_LD_HL_IMM8; // ld [hl], <imm8>
|
||||
}
|
||||
*p_buf++ = (u8)(v / 256);
|
||||
}
|
||||
}
|
||||
|
||||
// Skip return for the first palette line (during vblank)
|
||||
if (line >= 1)
|
||||
*p_buf++ = SM83_OPCODE_RET;
|
||||
}
|
||||
|
||||
// This has an unknown purpose and was present in
|
||||
// the original source code, but doesn't appear to be needed.
|
||||
// *p_buf++ = 0x2d;
|
||||
|
||||
if (!file_write_from_buffer(filename, output_buf, outbuf_sz_pals))
|
||||
set_exit_error();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -525,14 +687,14 @@ static void ExportMap(const char * fname_base)
|
||||
|
||||
strcpy(filename, fname_base);
|
||||
strcat(filename, ".map");
|
||||
log_verbose("Writing Tile Map to: %s\n", filename);
|
||||
VERBOSE("Writing Tile Map to: %s\n", filename);
|
||||
|
||||
int outbuf_sz_map = (20 * y_height_in_tiles);
|
||||
uint8_t output_buf_map[outbuf_sz_map];
|
||||
|
||||
int tile_id = 0;
|
||||
for (int y = 0; y < y_height_in_tiles; y++) {
|
||||
for (int x = 0; x < 20; x++) {
|
||||
for (unsigned int y = 0; y < y_height_in_tiles; y++) {
|
||||
for (unsigned int x = 0; x < 20; x++) {
|
||||
uint8_t tile_num = MapTileIDs[x][y];
|
||||
|
||||
// This needs to happen here, after optional deduplication stage
|
||||
@@ -556,15 +718,15 @@ static void ExportMapAttributes(const char * fname_base)
|
||||
|
||||
strcpy(filename, fname_base);
|
||||
strcat(filename, ".atr");
|
||||
log_verbose("Writing Attribute Map to: %s\n", filename);
|
||||
VERBOSE("Writing Attribute Map to: %s\n", filename);
|
||||
|
||||
int outbuf_sz_map = (20 * y_height_in_tiles);
|
||||
uint8_t output_buf_map[outbuf_sz_map];
|
||||
|
||||
int tile_id = 0;
|
||||
for (int y = 0; y < y_height_in_tiles; y++)
|
||||
for (unsigned int y = 0; y < y_height_in_tiles; y++)
|
||||
{
|
||||
for (int x = 0; x < 20; x++)
|
||||
for (unsigned int x = 0; x < 20; x++)
|
||||
{
|
||||
output_buf_map[tile_id++] = MapAttributes[x][y];
|
||||
}
|
||||
@@ -653,7 +815,7 @@ RGBQUAD translate(uint8_t rgb[3])
|
||||
|
||||
// The higher the adaptive level, the more combinations of attributes are tested.
|
||||
|
||||
u8 SplitData[80][4]=
|
||||
u8 SplitData[HICOLOR_PATTERN_FIXED_COUNT][4]=
|
||||
{
|
||||
{3,2,3,2},{2,3,2,3},{2,2,3,3},{2,3,3,2},{3,2,2,3},{3,3,2,2},{4,2,2,2},{2,2,2,4},{2,2,4,2},{2,4,2,2},{1,1,2,6},
|
||||
{1,1,3,5},{1,1,4,4},{1,1,5,3},{1,1,6,2},{1,2,1,6},{1,2,2,5},{1,2,3,4},{1,2,4,3},{1,2,5,2},{1,2,6,1},{1,3,1,5},
|
||||
@@ -669,7 +831,7 @@ u8 SplitData[80][4]=
|
||||
|
||||
unsigned int ImageRating(u8 *src, u8 *dest, int StartX, int StartY, int Width, int Height)
|
||||
{
|
||||
log_debug("ImageRating()\n");
|
||||
DBG("ImageRating()\n");
|
||||
unsigned int tot;
|
||||
int x,y;
|
||||
unsigned int accum=0;
|
||||
@@ -694,16 +856,15 @@ unsigned int ImageRating(u8 *src, u8 *dest, int StartX, int StartY, int Width, i
|
||||
// TODO: rename to something that aligns with other convert functions
|
||||
void ConvertToHiColor(int ConvertType)
|
||||
{
|
||||
log_debug("ConvertToHiColor()\n");
|
||||
DBG("ConvertToHiColor()\n");
|
||||
int res;
|
||||
int x,y,z,i;
|
||||
unsigned int x,y;
|
||||
// TODO: Change "Adaptive Pattern" settings to be a separate variable so StartSplit doesn't have to be offset by -3
|
||||
// Just set these directly:
|
||||
// * StartSplit (first pattern to start checking with)
|
||||
// * NumSplit (number of patterns to iterate through for testing, 1 = just use the one in StartSplit)
|
||||
int StartSplit=0;
|
||||
int NumSplit=1;
|
||||
int Steps;
|
||||
int MastX,MastY;
|
||||
int Line;
|
||||
int width;
|
||||
unsigned int tile_id;
|
||||
|
||||
switch(LConversion)
|
||||
{
|
||||
@@ -711,55 +872,27 @@ void ConvertToHiColor(int ConvertType)
|
||||
|
||||
StartSplit=0;
|
||||
NumSplit=6;
|
||||
Steps=504;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
||||
StartSplit=0;
|
||||
NumSplit=10;
|
||||
Steps=792;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
StartSplit=0;
|
||||
NumSplit=80;
|
||||
Steps=5832;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
StartSplit=LConversion-3;
|
||||
NumSplit=1;
|
||||
Steps=image_height;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(RConversion)
|
||||
{
|
||||
case 0:
|
||||
|
||||
Steps+=504;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
||||
Steps+=792;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
Steps+=5832;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
Steps+=image_height;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Convert left side with one extra tile of height to fix
|
||||
// the glitching where the last scanline on left bottom region
|
||||
// lacks tile and palette data
|
||||
@@ -823,7 +956,7 @@ void ConvertToHiColor(int ConvertType)
|
||||
raw[1][x][y][2] = GBView.rgbBlue;
|
||||
}
|
||||
}
|
||||
log_progress("\n");
|
||||
VERBOSE("\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -833,12 +966,12 @@ void ConvertToHiColor(int ConvertType)
|
||||
// StartY = 0 - 17 : Starting attribute block
|
||||
// Height = Number of attribute blocks to check / process
|
||||
|
||||
int ConvertRegions(int StartX, int Width, int StartY, int Height, int StartJ, int FinishJ, int ConvertType)
|
||||
int ConvertRegions(unsigned int StartX, unsigned int Width, unsigned int StartY, unsigned int Height, unsigned int StartJ, unsigned int FinishJ, int ConvertType)
|
||||
{
|
||||
log_debug("ConvertRegions()\n");
|
||||
u32 Accum,width,x1,ts,tw,y2,x2,y_offset;
|
||||
s32 x,y;
|
||||
s32 i,j;
|
||||
DBG("ConvertRegions()\n");
|
||||
u32 width,x1,ts,tw,y2,x2,y_offset;
|
||||
unsigned int x,y;
|
||||
unsigned int i,j;
|
||||
u8 col;
|
||||
|
||||
|
||||
@@ -856,7 +989,6 @@ int ConvertRegions(int StartX, int Width, int StartY, int Height, int StartJ, in
|
||||
|
||||
for(j=StartJ;j<(StartJ+FinishJ);j++)
|
||||
{
|
||||
Accum=0;
|
||||
width=0;
|
||||
for(i=0;i<4;i++)
|
||||
{
|
||||
@@ -867,7 +999,7 @@ int ConvertRegions(int StartX, int Width, int StartY, int Height, int StartJ, in
|
||||
|
||||
for(y=StartY*4;y<(StartY+Height)*4;y++)
|
||||
{
|
||||
log_progress(".");
|
||||
VERBOSE(".");
|
||||
|
||||
for(x1=0;x1<4;x1++)
|
||||
{
|
||||
@@ -876,10 +1008,14 @@ int ConvertRegions(int StartX, int Width, int StartY, int Height, int StartJ, in
|
||||
|
||||
for(y2=0;y2<2;y2++)
|
||||
{
|
||||
// Skip case where y_line would evaluate to -1 to avoid unsigned wraparound)
|
||||
// (scanline 0, left side of the image where 80 x 2 pixel box goes from scanline -1 to 0)
|
||||
if (y_offset > ((y*2) + y2)) continue;
|
||||
|
||||
// Skip if Y line is outside image borders (prevents buffer overflow)
|
||||
// (Left side calcs hang off top and bottom of screen
|
||||
// due to Left/Right palette update interleaving)
|
||||
s32 y_line = (y*2+y2-y_offset);
|
||||
unsigned int y_line = (y*2+y2-y_offset);
|
||||
if ((y_line < image_y_min) || (y_line > image_y_max)) continue;
|
||||
|
||||
for(x2=0;x2<tw;x2++)
|
||||
@@ -895,12 +1031,12 @@ int ConvertRegions(int StartX, int Width, int StartY, int Height, int StartJ, in
|
||||
switch(ConvertType)
|
||||
{
|
||||
case 0:
|
||||
to_indexed(Data,4,0,TileWidth[x1],2); // Median Reduction No Dither
|
||||
to_indexed(Data,0,TileWidth[x1],2); // Median Reduction No Dither
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
||||
to_indexed(Data,4,1,TileWidth[x1],2); // Median Reduction With Dither
|
||||
to_indexed(Data,1,TileWidth[x1],2); // Median Reduction With Dither
|
||||
break;
|
||||
|
||||
case 2:
|
||||
@@ -924,9 +1060,13 @@ int ConvertRegions(int StartX, int Width, int StartY, int Height, int StartJ, in
|
||||
{
|
||||
for(x2=0;x2<tw;x2++)
|
||||
{
|
||||
// Skip case where y_line would evaluate to -1 to avoid unsigned wraparound)
|
||||
// (scanline 0, left side of the image where 80 x 2 pixel box goes from scanline -1 to 0)
|
||||
if (y_offset > ((y*2) + y2)) continue;
|
||||
|
||||
// Skip if Y line is outside image borders (prevents buffer overflow)
|
||||
// since Left side calcs hang off top and bottom of image/screen
|
||||
s32 y_line = (y*2+y2-y_offset);
|
||||
unsigned int y_line = (y*2+y2-y_offset);
|
||||
if ((y_line < image_y_min) || (y_line > image_y_max)) continue;
|
||||
|
||||
col=Picture256[y2*tw+x2];
|
||||
|
||||
@@ -13,13 +13,18 @@
|
||||
|
||||
// For displaying available conversion patterns to the user
|
||||
#define HELP_CONV_PATTERN_STR \
|
||||
"Available conversion palette/attribute pattern widths for -cL:N and -cR:N\n" \
|
||||
"Available screen palette arrangement widths for -L=N and -R=N\n" \
|
||||
"\n" \
|
||||
"- Default for Left and Right is 3\n" \
|
||||
"- Fixed pattern widths are faster but less optimal than adaptive\n" \
|
||||
"- Adaptive pattern width speeds are 1: fastest, 2: medium, 3: slowest (slower = higher quality)\n" \
|
||||
"- Default for Left and Right is \"adaptive-medium\"\n" \
|
||||
"- Fixed settings are faster but the converted image tends to have more visual artifacts.\n" \
|
||||
"- Adaptive settings try to find an optimal palette arrangement.\n" \
|
||||
"- The adaptive tiers select between a trade-off of faster conversion or reduced visual artifacts.\n" \
|
||||
"\n" \
|
||||
" 0: Adaptive-1 1: Adaptive-2 2: Adaptive-3 3: 3-2-3-2 4: 2-3-2-3 \n" \
|
||||
" Adaptive screen palette arrangements:\n" \
|
||||
" adaptive-fast, adaptive-medium (**Default**), adaptive-best\n" \
|
||||
"\n" \
|
||||
" Fixed screen palette arrangements:\n" \
|
||||
" 3: 3-2-3-2 4: 2-3-2-3 \n" \
|
||||
" 5: 2-2-3-3 6: 2-3-3-2 7: 3-2-2-3 8: 3-3-2-2 9: 4-2-2-2 \n" \
|
||||
" 10: 2-2-2-4 11: 2-2-4-2 12: 2-4-2-2 13: 1-1-2-6 14: 1-1-3-5 \n" \
|
||||
" 15: 1-1-4-4 16: 1-1-5-3 17: 1-1-6-2 18: 1-2-1-6 19: 1-2-2-5 \n" \
|
||||
@@ -37,6 +42,11 @@
|
||||
" 75: 5-1-2-2 76: 5-1-3-1 77: 5-2-1-2 78: 5-2-2-1 79: 5-3-1-1 \n" \
|
||||
" 80: 6-1-1-2 81: 6-1-2-1 82: 6-2-1-1 \n"
|
||||
|
||||
typedef struct pattern_entry {
|
||||
unsigned int num;
|
||||
const char * name;
|
||||
} pattern_entry;
|
||||
|
||||
|
||||
extern u8 TileOffset[4]; // Offset into screen for attribute start
|
||||
extern u8 TileWidth[4]; // No of character attributes width
|
||||
@@ -46,6 +56,7 @@ extern RGBQUAD GBView;
|
||||
|
||||
void hicolor_init(void);
|
||||
|
||||
unsigned int hicolor_get_pattern_by_name(const char * option_name);
|
||||
void hicolor_set_type(uint8_t new_value);
|
||||
void hicolor_set_convert_left_pattern(uint8_t new_value);
|
||||
void hicolor_set_convert_right_pattern(uint8_t new_value);
|
||||
@@ -57,7 +68,7 @@ void hicolor_process_image(image_data * p_decoded_image, const char * fname);
|
||||
RGBQUAD translate(uint8_t rgb[3]);
|
||||
unsigned int ImageRating(u8 *src, u8 *dest, int StartX, int StartY, int Width, int Height);
|
||||
void ConvertToHiColor(int ConvertType);
|
||||
int ConvertRegions(int StartX, int Width, int StartY, int Height, int StartJ, int FinishJ, int ConvertType);
|
||||
int ConvertRegions(unsigned int StartX, unsigned int Width, unsigned int StartY, unsigned int Height, unsigned int StartJ, unsigned int FinishJ, int ConvertType);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -116,7 +116,7 @@ void update_box_rgb(boxptr boxp)
|
||||
}
|
||||
}
|
||||
|
||||
have_Rmin:
|
||||
have_Rmin:
|
||||
|
||||
if (Rmax > Rmin)
|
||||
for (R = Rmax; R >= Rmin; R--)
|
||||
@@ -131,7 +131,7 @@ void update_box_rgb(boxptr boxp)
|
||||
}
|
||||
}
|
||||
|
||||
have_Rmax:
|
||||
have_Rmax:
|
||||
|
||||
if (Gmax > Gmin)
|
||||
for (G = Gmin; G <= Gmax; G++)
|
||||
@@ -146,7 +146,7 @@ void update_box_rgb(boxptr boxp)
|
||||
}
|
||||
}
|
||||
|
||||
have_Gmin:
|
||||
have_Gmin:
|
||||
|
||||
if (Gmax > Gmin)
|
||||
for (G = Gmax; G >= Gmin; G--)
|
||||
@@ -161,7 +161,7 @@ void update_box_rgb(boxptr boxp)
|
||||
}
|
||||
}
|
||||
|
||||
have_Gmax:
|
||||
have_Gmax:
|
||||
|
||||
if (Bmax > Bmin)
|
||||
for (B = Bmin; B <= Bmax; B++)
|
||||
@@ -176,7 +176,7 @@ void update_box_rgb(boxptr boxp)
|
||||
}
|
||||
}
|
||||
|
||||
have_Bmin:
|
||||
have_Bmin:
|
||||
|
||||
if (Bmax > Bmin)
|
||||
for (B = Bmax; B >= Bmin; B--)
|
||||
@@ -191,7 +191,7 @@ void update_box_rgb(boxptr boxp)
|
||||
}
|
||||
}
|
||||
|
||||
have_Bmax:
|
||||
have_Bmax:
|
||||
|
||||
// Update box volume.
|
||||
// We use 2-norm rather than real volume here; this biases the method
|
||||
@@ -390,7 +390,6 @@ s32 find_nearby_colors(s32 minR,s32 minG,s32 minB,s32 colorlist[])
|
||||
* the colors that need further consideration.
|
||||
*/
|
||||
{
|
||||
s32 numcolors = actual_number_of_colors;
|
||||
s32 maxR, maxG, maxB;
|
||||
s32 centerR, centerG, centerB;
|
||||
s32 i, x, ncolors;
|
||||
@@ -694,7 +693,7 @@ void fill_inverse_cmap_rgb(s32 R, s32 G, s32 B)
|
||||
|
||||
|
||||
/* This is pass 1 */
|
||||
void median_cut_pass1_rgb(u8 *src,u8 *dest,s32 width,s32 height)
|
||||
void median_cut_pass1_rgb(u8 *src,s32 width,s32 height)
|
||||
{
|
||||
s32 num_elems;
|
||||
ColorFreq *col;
|
||||
@@ -797,7 +796,7 @@ s32 *init_error_limit(void)
|
||||
|
||||
|
||||
|
||||
void to_indexed(u8 *input,s32 ncolors,s32 dither,s32 width,s32 height)
|
||||
void to_indexed(u8 *input,s32 dither,s32 width,s32 height)
|
||||
{
|
||||
s32 i, j;
|
||||
u8 *src;
|
||||
@@ -828,7 +827,7 @@ void to_indexed(u8 *input,s32 ncolors,s32 dither,s32 width,s32 height)
|
||||
|
||||
histogram = AHistorgram;
|
||||
|
||||
median_cut_pass1_rgb(input, Picture256, width, height);
|
||||
median_cut_pass1_rgb(input, width, height);
|
||||
|
||||
src=input;
|
||||
dest=Picture256;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef __median_h__
|
||||
#define __median_h__
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
|
||||
#define MAXNUMCOLORS 256
|
||||
|
||||
@@ -66,9 +68,9 @@ void compute_color_rgb(boxptr boxp,s32 icolor);
|
||||
s32 find_nearby_colors(s32 minR,s32 minG,s32 minB,s32 colorlist[]);
|
||||
void find_best_colors(s32 minR, s32 minG, s32 minB,s32 numcolors,s32 colorlist[],s32 bestcolor[]);
|
||||
void fill_inverse_cmap_rgb(s32 R, s32 G, s32 B);
|
||||
void median_cut_pass1_rgb(u8 *src,u8 *dest,s32 width,s32 height);
|
||||
void median_cut_pass1_rgb(u8 *src,s32 width,s32 height);
|
||||
s32 *init_error_limit(void);
|
||||
void to_indexed(u8 *input,s32 ncolors,s32 dither,s32 width,s32 height);
|
||||
void to_indexed(u8 *input,s32 dither,s32 width,s32 height);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
// image_info.h
|
||||
//
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef IMAGE_INFO_HEADER
|
||||
#define IMAGE_INFO_HEADER
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define RGBA_32SZ 4 // 4 bytes
|
||||
#define RGBA_RED 0
|
||||
#define RGBA_GREEN 1
|
||||
|
||||
@@ -26,7 +26,7 @@ static bool image_load_png(image_data *, const char *);
|
||||
static bool image_validate(image_data * p_decoded_image) {
|
||||
|
||||
if (p_decoded_image->width != VALIDATE_WIDTH) {
|
||||
log_error("Error: Image width is %d, must be %d\n", p_decoded_image->width, VALIDATE_WIDTH);
|
||||
ERR("Error: Image width is %d, must be %d\n", p_decoded_image->width, VALIDATE_WIDTH);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -36,17 +36,17 @@ static bool image_validate(image_data * p_decoded_image) {
|
||||
// Which is the highest possible within the 512 available on the CGB
|
||||
// without reloading the tiles and maps using an offset
|
||||
if ((p_decoded_image->height == 0) || (p_decoded_image->height > VALIDATE_HEIGHT)) {
|
||||
log_error("Error: Image height is %d, must be between 0 and %d\n", p_decoded_image->height, VALIDATE_HEIGHT);
|
||||
ERR("Error: Image height is %d, must be between 0 and %d\n", p_decoded_image->height, VALIDATE_HEIGHT);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((p_decoded_image->height % 8) != 0u) {
|
||||
log_verbose("Error: Image height must be a multiple of 8, %d is not\n", p_decoded_image->height);
|
||||
VERBOSE("Error: Image height must be a multiple of 8, %d is not\n", p_decoded_image->height);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((p_decoded_image->width % 8) != 0u) {
|
||||
log_verbose("Error: Image width must be a multiple of 8, %d is not\n", p_decoded_image->width);
|
||||
VERBOSE("Error: Image width must be a multiple of 8, %d is not\n", p_decoded_image->width);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ static bool image_load_png(image_data * p_decoded_image, const char * filename)
|
||||
|
||||
if (error) {
|
||||
status = false;
|
||||
log_error("Error: PNG load: %u: %s\n", error, lodepng_error_text(error));
|
||||
ERR("Error: PNG load: %u: %s\n", error, lodepng_error_text(error));
|
||||
} else {
|
||||
p_decoded_image->bytes_per_pixel = RGB_24SZ;
|
||||
p_decoded_image->size = p_decoded_image->width * p_decoded_image->height * p_decoded_image->bytes_per_pixel;
|
||||
@@ -86,7 +86,7 @@ bool image_load(image_data * p_decoded_image, const char * filename, const uint8
|
||||
|
||||
bool status = true;
|
||||
|
||||
log_verbose("Loading image from file: %s, type: %d\n", filename, image_type);
|
||||
VERBOSE("Loading image from file: %s, type: %d\n", filename, image_type);
|
||||
|
||||
switch (image_type) {
|
||||
case IMG_TYPE_PNG:
|
||||
@@ -95,7 +95,7 @@ bool image_load(image_data * p_decoded_image, const char * filename, const uint8
|
||||
|
||||
default:
|
||||
status = false;
|
||||
log_error("Invalid image format. No image will be loaded\n");
|
||||
ERR("Invalid image format. No image will be loaded\n");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -103,10 +103,10 @@ bool image_load(image_data * p_decoded_image, const char * filename, const uint8
|
||||
status = image_validate(p_decoded_image);
|
||||
|
||||
if (status) {
|
||||
log_verbose("Decoded image.width: %d\n", p_decoded_image->width);
|
||||
log_verbose("Decoded image.height: %d\n", p_decoded_image->height);
|
||||
log_verbose("Decoded image.size: %d\n", p_decoded_image->size);
|
||||
log_verbose("Decoded image.bytes_per_pixel: %d\n", p_decoded_image->bytes_per_pixel);
|
||||
VERBOSE("Decoded image.width: %d\n", p_decoded_image->width);
|
||||
VERBOSE("Decoded image.height: %d\n", p_decoded_image->height);
|
||||
VERBOSE("Decoded image.size: %d\n", p_decoded_image->size);
|
||||
VERBOSE("Decoded image.bytes_per_pixel: %d\n", p_decoded_image->bytes_per_pixel);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#ifndef _IMAGE_LOAD_C
|
||||
#define _IMAGE_LOAD_C
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "image_info.h"
|
||||
|
||||
bool image_load(image_data * p_src_image, const char * filename, const uint8_t img_type);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "logging.h"
|
||||
|
||||
int output_level = OUTPUT_LEVEL_DEFAULT;
|
||||
static enum output_level output_level = OUTPUT_LEVEL_DEFAULT;
|
||||
|
||||
|
||||
#define VA_LIST_PRINT() \
|
||||
@@ -16,33 +16,18 @@ int output_level = OUTPUT_LEVEL_DEFAULT;
|
||||
fflush(stdout); // If logging a lot of output to a file turn off the excessive flushing
|
||||
|
||||
|
||||
void log_set_level(int new_output_level) {
|
||||
void set_log_level(enum output_level new_output_level) {
|
||||
output_level = new_output_level;
|
||||
}
|
||||
|
||||
void log_debug(const char * format, ...){
|
||||
int log_(enum output_level level, const char *fmt, ...) {
|
||||
if (output_level > level) {
|
||||
return 0; // Pretend everything went smoothly. (It did, kind of!)
|
||||
}
|
||||
|
||||
if (output_level > OUTPUT_LEVEL_DEBUG) return;
|
||||
VA_LIST_PRINT();
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
int ret = vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void log_verbose(const char * format, ...){
|
||||
|
||||
if (output_level > OUTPUT_LEVEL_VERBOSE) return;
|
||||
VA_LIST_PRINT();
|
||||
}
|
||||
|
||||
void log_standard(const char * format, ...){
|
||||
|
||||
// Only print if quiet mode and error_only are NOT enabled
|
||||
if ((output_level == OUTPUT_LEVEL_QUIET) ||
|
||||
(output_level == OUTPUT_LEVEL_ONLY_ERRORS)) return;
|
||||
VA_LIST_PRINT();
|
||||
}
|
||||
|
||||
void log_error(const char * format, ...){
|
||||
|
||||
// Only print if quiet mode is NOT enabled
|
||||
if (output_level == OUTPUT_LEVEL_QUIET) return;
|
||||
VA_LIST_PRINT();
|
||||
}
|
||||
@@ -3,20 +3,20 @@
|
||||
#ifndef _LOGGING_H
|
||||
#define _LOGGING_H
|
||||
|
||||
enum output_levels {
|
||||
#include "common.h"
|
||||
|
||||
enum output_level {
|
||||
OUTPUT_LEVEL_DEBUG,
|
||||
OUTPUT_LEVEL_VERBOSE,
|
||||
OUTPUT_LEVEL_DEFAULT,
|
||||
OUTPUT_LEVEL_ONLY_ERRORS,
|
||||
OUTPUT_LEVEL_QUIET
|
||||
};
|
||||
|
||||
#define log_progress log_verbose
|
||||
void set_log_level(enum output_level new_output_level);
|
||||
int log_(enum output_level level, char const *fmt, ...) FMT(printf, 2, 3);
|
||||
#define DBG(...) log_(OUTPUT_LEVEL_DEBUG, __VA_ARGS__)
|
||||
#define VERBOSE(...) log_(OUTPUT_LEVEL_VERBOSE, __VA_ARGS__)
|
||||
#define LOG(...) log_(OUTPUT_LEVEL_DEFAULT, __VA_ARGS__)
|
||||
#define ERR(...) log_(OUTPUT_LEVEL_ONLY_ERRORS, __VA_ARGS__)
|
||||
|
||||
void log_set_level(int new_output_level);
|
||||
void log_debug(const char * format, ...);
|
||||
void log_verbose(const char * format, ...);
|
||||
void log_standard(const char * format, ...);
|
||||
void log_error(const char * format, ...);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -17,20 +17,36 @@
|
||||
#include <hicolour.h>
|
||||
|
||||
|
||||
#define VERSION "version 1.4.1"
|
||||
#define VERSION "version 1.4.2"
|
||||
|
||||
#define HELP_HISTORICAL_CREDITS_STR \
|
||||
"Historical credits and info:\n" \
|
||||
" Original Concept : Icarus Productions\n" \
|
||||
" Original Code : Jeff Frohwein\n" \
|
||||
" Full Screen Modification : Anon\n" \
|
||||
" Adaptive Code : Glen Cook\n" \
|
||||
" Windows Interface : Glen Cook\n" \
|
||||
" Additional Windows Programming : Rob Jones\n" \
|
||||
" Original Quantiser Code : Benny\n" \
|
||||
" Quantiser Conversion : Glen Cook\n" \
|
||||
"\n"
|
||||
|
||||
static void init(void);
|
||||
static void cleanup(void);
|
||||
static void display_help(void);
|
||||
static int handle_args(int argc, char * argv[]);
|
||||
static void set_drag_and_drop_mode_defaults(void);
|
||||
static bool handle_args_L_R_patterns(const char * str_opt_side, const char * str_value);
|
||||
#ifdef DRAG_AND_DROP_MODE
|
||||
static void set_drag_and_drop_mode_defaults(void);
|
||||
#endif
|
||||
|
||||
image_data src_image;
|
||||
char filename_in[MAX_STR_LEN] = {'\0'};
|
||||
char opt_filename_out[MAX_STR_LEN] = "";
|
||||
// bool opt_strip_output_filename_ext = true;
|
||||
|
||||
int show_help_and_exit = false;
|
||||
bool show_help_and_exit = false;
|
||||
bool show_full_credits = false;
|
||||
|
||||
|
||||
static void init(void) {
|
||||
@@ -97,7 +113,7 @@ int main( int argc, char *argv[] ) {
|
||||
|
||||
#ifdef DRAG_AND_DROP_MODE
|
||||
// Wait for input to keep the console window open after processing
|
||||
log_standard("\n\nPress Any Key to Continue\n");
|
||||
LOG("\n\nPress Any Key to Continue\n");
|
||||
getchar();
|
||||
#endif
|
||||
|
||||
@@ -106,7 +122,7 @@ int main( int argc, char *argv[] ) {
|
||||
|
||||
|
||||
static void display_help(void) {
|
||||
log_standard(
|
||||
LOG(
|
||||
"\n"
|
||||
"png2hicolorgb input_image.png [options]\n"
|
||||
VERSION": bbbbbr. Based on Glen Cook's Windows GUI \"hicolour.exe\" 1.2\n"
|
||||
@@ -122,36 +138,38 @@ static void display_help(void) {
|
||||
"--type=N : Set conversion type where N is one of below \n"
|
||||
" 1: Median Cut - No Dither (*Default*)\n"
|
||||
" 2: Median Cut - With Dither\n"
|
||||
" 3: Wu Quantiser\n"
|
||||
" 3: Wu Quantiser (best quality)\n"
|
||||
"-p : Show screen attribute pattern options (no processing)\n"
|
||||
"-L=N : Set Left screen attribute pattern where N is decimal entry (-p to show patterns)\n"
|
||||
"-R=N : Set Right screen attribute pattern where N is decimal entry (-p to show patterns)\n"
|
||||
"-L=N : Set Left side of screen palette arrangement where N is name listed below or decimal entry\n"
|
||||
"-R=N : Set Right side of screen palette arrangement where N is name listed below or decimal entry\n"
|
||||
" Named options for N: \"adaptive-fast\", \"adaptive-medium\", \"adaptive-best\" (-p for full options) \n"
|
||||
"--best : Use highest quality conversion settings (--type=3 -L=adaptive-best -R=adaptive-best)\n"
|
||||
"--vaddrid : Map uses vram id (128->255->0->127) instead of (*Default*) sequential tile order (0->255)\n"
|
||||
"--nodedupe : Turn off tile pattern deduplication\n"
|
||||
"--precompiled : Export Palette data as pre-compiled executable loading code\n"
|
||||
"--palendbit : Set unused bit .15 = 1 for last u16 entry in palette data indicating end (not in precompiled)\n"
|
||||
"--addendcolor=N : Append 32 x color N (hex BGR555) in pal data to clear BG for shorter images (64 bytes) (not in precompiled)\n"
|
||||
"\n"
|
||||
"Example 1: \"png2hicolorgb myimage.png\"\n"
|
||||
"Example 2: \"png2hicolorgb myimage.png --csource -o=my_output_filename\"\n"
|
||||
"* Default settings provide good results. Better quality but slower: \"--type=3 -L=2 -R=2\"\n"
|
||||
"\n"
|
||||
"Historical credits and info:\n"
|
||||
" Original Concept : Icarus Productions\n"
|
||||
" Original Code : Jeff Frohwein\n"
|
||||
" Full Screen Modification : Anon\n"
|
||||
" Adaptive Code : Glen Cook\n"
|
||||
" Windows Interface : Glen Cook\n"
|
||||
" Additional Windows Programming : Rob Jones\n"
|
||||
" Original Quantiser Code : Benny\n"
|
||||
" Quantiser Conversion : Glen Cook\n"
|
||||
"Example 2: \"png2hicolorgb myimage.png --palendbit --addendcolor=0x7FFF -o=my_output_filename\"\n"
|
||||
"* Default settings provide good results. Better quality but slower: \"--type=3 -L=adaptive-best -R=adaptive-best\"\n"
|
||||
"\n"
|
||||
);
|
||||
|
||||
if (show_full_credits)
|
||||
LOG(HELP_HISTORICAL_CREDITS_STR);
|
||||
}
|
||||
|
||||
|
||||
#ifdef DRAG_AND_DROP_MODE
|
||||
// Default options for Windows Drag and Drop recipient mode
|
||||
static void set_drag_and_drop_mode_defaults(void) {
|
||||
|
||||
// Set some options here
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static int handle_args(int argc, char * argv[]) {
|
||||
@@ -171,27 +189,28 @@ static int handle_args(int argc, char * argv[]) {
|
||||
for (i = 1; i <= (argc -1); i++ ) {
|
||||
|
||||
if ((strstr(argv[i], "-h") == argv[i]) || (strstr(argv[i], "-?") == argv[i])) {
|
||||
show_full_credits = true;
|
||||
display_help();
|
||||
show_help_and_exit = true;
|
||||
return true; // Don't parse further input when -h is used
|
||||
} else if (strstr(argv[i], "-p") == argv[i]) {
|
||||
log_standard(HELP_CONV_PATTERN_STR);
|
||||
LOG(HELP_CONV_PATTERN_STR);
|
||||
show_help_and_exit = true;
|
||||
return true; // Don't parse further input when -h is used
|
||||
|
||||
} else if (strstr(argv[i], "-vD") == argv[i]) {
|
||||
log_set_level(OUTPUT_LEVEL_DEBUG);
|
||||
set_log_level(OUTPUT_LEVEL_DEBUG);
|
||||
} else if (strstr(argv[i], "-vE") == argv[i]) {
|
||||
log_set_level(OUTPUT_LEVEL_ONLY_ERRORS);
|
||||
set_log_level(OUTPUT_LEVEL_ONLY_ERRORS);
|
||||
} else if (strstr(argv[i], "-vQ") == argv[i]) {
|
||||
log_set_level(OUTPUT_LEVEL_QUIET);
|
||||
set_log_level(OUTPUT_LEVEL_ONLY_ERRORS);
|
||||
} else if (strstr(argv[i], "-v") == argv[i]) {
|
||||
log_set_level(OUTPUT_LEVEL_VERBOSE);
|
||||
set_log_level(OUTPUT_LEVEL_VERBOSE);
|
||||
|
||||
} else if (strstr(argv[i], "--type=") == argv[i]) {
|
||||
uint8_t new_type = strtol(argv[i] + strlen("--type="), NULL, 10);
|
||||
if ((new_type < CONV_TYPE_MIN) || (new_type > CONV_TYPE_MAX)) {
|
||||
log_standard("Error: --type specified with invalid conversion setting: %d\n", new_type);
|
||||
LOG("Error: --type specified with invalid conversion setting: %d\n", new_type);
|
||||
display_help();
|
||||
show_help_and_exit = true;
|
||||
return false; // Abort
|
||||
@@ -199,22 +218,35 @@ static int handle_args(int argc, char * argv[]) {
|
||||
else
|
||||
hicolor_set_type(new_type);
|
||||
} else if (strstr(argv[i], "-L=") == argv[i]) {
|
||||
hicolor_set_convert_left_pattern( strtol(argv[i] + strlen("-L="), NULL, 10));
|
||||
if (!handle_args_L_R_patterns((const char *)"-L=", argv[i] + strlen("-L="))) {
|
||||
show_help_and_exit = true;
|
||||
return false; // Abort
|
||||
}
|
||||
|
||||
} else if (strstr(argv[i], "-R=") == argv[i]) {
|
||||
hicolor_set_convert_right_pattern( strtol(argv[i] + strlen("-R="), NULL, 10));
|
||||
if (!handle_args_L_R_patterns((const char *)"-R=", argv[i] + strlen("-R="))) {
|
||||
show_help_and_exit = true;
|
||||
return false; // Abort
|
||||
}
|
||||
|
||||
} else if (strstr(argv[i], "--best") == argv[i]) {
|
||||
hicolor_set_type(CONV_TYPE_WU);
|
||||
hicolor_set_convert_left_pattern(HICOLOR_PATTERN_ADAPTIVE_BEST);
|
||||
hicolor_set_convert_right_pattern(HICOLOR_PATTERN_ADAPTIVE_BEST);
|
||||
|
||||
|
||||
} else if (strstr(argv[i], "-o") == argv[i]) {
|
||||
if (i < (argc -1))
|
||||
i++; // Move to next argument if one is available
|
||||
else {
|
||||
log_standard("Error: -o specified but filename is missing\n");
|
||||
LOG("Error: -o specified but filename is missing\n");
|
||||
show_help_and_exit = true;
|
||||
return false; // Abort
|
||||
}
|
||||
|
||||
// Require colon and filename to be present
|
||||
if (*argv[i] == '-')
|
||||
log_standard("Warning: -o specified but filename has dash and looks like an option argument. Usage: -o my_base_output_filename\n");
|
||||
if (*argv[i] == '-')
|
||||
LOG("Warning: -o specified but filename has dash and looks like an option argument. Usage: -o my_base_output_filename\n");
|
||||
snprintf(opt_filename_out, sizeof(opt_filename_out), "%s", argv[i]);
|
||||
|
||||
// } else if (strstr(argv[i], "--keepext") == argv[i]) {
|
||||
@@ -226,7 +258,7 @@ static int handle_args(int argc, char * argv[]) {
|
||||
} else if (strstr(argv[i], "--bank=") == argv[i]) {
|
||||
opt_set_bank_num( strtol(argv[i] + strlen("--bank="), NULL, 10) );
|
||||
if ((opt_get_bank_num() < BANK_NUM_MIN) || (opt_get_bank_num() > BANK_NUM_MAX)) {
|
||||
log_standard("Error: Invalid bank number specified with --bank=%d\n", opt_get_bank_num());
|
||||
LOG("Error: Invalid bank number specified with --bank=%d\n", opt_get_bank_num());
|
||||
display_help();
|
||||
show_help_and_exit = true;
|
||||
return false; // Abort
|
||||
@@ -238,14 +270,66 @@ static int handle_args(int argc, char * argv[]) {
|
||||
} else if (strstr(argv[i], "--nodedupe") == argv[i]) {
|
||||
opt_set_tile_dedupe(false);
|
||||
|
||||
} else if (strstr(argv[i], "--precompiled") == argv[i]) {
|
||||
opt_set_precompiled_palette(true);
|
||||
|
||||
} else if (strstr(argv[i], "--palendbit") == argv[i]) {
|
||||
opt_set_pal_end_bit(true);
|
||||
|
||||
} else if (strstr(argv[i], "--addendcolor=") == argv[i]) {
|
||||
// Color should be in BGR555 hex format, so white: 0x7FFFF, max red 0x7C00, max green 0x3E00, etc
|
||||
opt_set_enable_pal_end_color( strtol(argv[i] + strlen("--addendcolor="), NULL, 16) );
|
||||
|
||||
} else if (argv[i][0] == '-') {
|
||||
log_error("Unknown argument: %s\n\n", argv[i]);
|
||||
ERR("Unknown argument: %s\n\n", argv[i]);
|
||||
display_help();
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Check and warn about option compatibility
|
||||
if (opt_get_pal_end_bit() && opt_get_precompiled_palette()) {
|
||||
LOG("Warning: --palendbit ignored when --precompiled is enabled\n");
|
||||
}
|
||||
|
||||
if (opt_get_enable_pal_end_color() && opt_get_precompiled_palette()) {
|
||||
LOG("Warning: --addendcolor ignored when --precompiled is enabled\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool handle_args_L_R_patterns(const char * str_opt_side, const char * str_value) {
|
||||
|
||||
if (*str_value == '\0') {
|
||||
ERR("Missing value for %s argument\n", str_opt_side);
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int pattern_num = hicolor_get_pattern_by_name(str_value);
|
||||
|
||||
if (pattern_num == HICOLOR_PATTERN_NOT_FOUND_HAS_CHARS) {
|
||||
ERR("Invalid value for %s argument: %s\n", str_opt_side, str_value);
|
||||
return false;
|
||||
}
|
||||
else if (pattern_num == HICOLOR_PATTERN_NOT_FOUND) {
|
||||
// Try numeric conversion on option instead named conversion
|
||||
pattern_num = (unsigned int)strtoul(str_value, NULL, 10);
|
||||
}
|
||||
|
||||
if (pattern_num > HICOLOR_PATTERN_OPT_MAX) {
|
||||
ERR("Invalid value for %s argument: %s\n", str_opt_side, str_value);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Got a valid option value, now apply it
|
||||
if (strstr(str_opt_side, "-L=") == str_opt_side)
|
||||
hicolor_set_convert_left_pattern(pattern_num);
|
||||
else
|
||||
hicolor_set_convert_right_pattern(pattern_num);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,11 @@
|
||||
bool opt_map_use_sequential_tile_index = true;
|
||||
bool opt_tile_dedupe = true;
|
||||
bool opt_c_file_output = false;
|
||||
bool opt_c_precompiled = false;
|
||||
int opt_bank_num = BANK_NUM_UNSET;
|
||||
bool opt_pal_end_bit = false;
|
||||
bool opt_enable_pal_end_col = false;
|
||||
uint16_t pal_end_color = 0x0000u; // Black in BGR555
|
||||
|
||||
void opt_set_map_tile_order(bool newval) { opt_map_use_sequential_tile_index = newval; }
|
||||
bool opt_get_map_tile_order(void) { return opt_map_use_sequential_tile_index; }
|
||||
@@ -26,3 +30,31 @@ bool opt_get_c_file_output(void) { return opt_c_file_output; }
|
||||
void opt_set_bank_num(int newval) { opt_bank_num = newval; }
|
||||
int opt_get_bank_num(void) { return opt_bank_num; }
|
||||
|
||||
void opt_set_precompiled_palette(bool newval) { opt_c_precompiled = newval; }
|
||||
bool opt_get_precompiled_palette(void) { return opt_c_precompiled; }
|
||||
|
||||
void opt_set_pal_end_bit(bool newval) { opt_pal_end_bit = newval; }
|
||||
bool opt_get_pal_end_bit(void) { return opt_pal_end_bit; }
|
||||
|
||||
void opt_set_enable_pal_end_color(uint16_t end_color_bgr555) {
|
||||
|
||||
opt_enable_pal_end_col = true;
|
||||
// Make sure unused high bit is not set for compat with pal_end_bit
|
||||
pal_end_color = (end_color_bgr555 & BGR555_MASK);
|
||||
}
|
||||
|
||||
bool opt_get_enable_pal_end_color(void) {
|
||||
|
||||
return opt_enable_pal_end_col;
|
||||
}
|
||||
|
||||
void opt_load_pal_end_color(uint16_t * p_end_color, int * pal_end_color_count) {
|
||||
|
||||
*p_end_color = pal_end_color;
|
||||
|
||||
if (opt_enable_pal_end_col) {
|
||||
*pal_end_color_count = APPEND_END_COLOR_COUNT; // Add 8 Palettes x 4 Colors to palette data (2 bytes each)
|
||||
} else {
|
||||
*pal_end_color_count = 0; // Not enabled, so add zero bytes to pal size
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#ifndef OPTIONS_H
|
||||
#define OPTIONS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define BANK_NUM_UNSET 0
|
||||
#define BANK_NUM_MIN 1
|
||||
@@ -12,6 +12,9 @@
|
||||
|
||||
#define OPTION_UNSET 0xFFFF
|
||||
|
||||
#define BGR555_MASK 0x7FFFu
|
||||
#define APPEND_END_COLOR_COUNT (8 * 4); // Add 8 Palettes x 4 Colors each x 2 bytes per color to pal size
|
||||
|
||||
#define OPT_MAP_TILE_ORDER_BY_VRAM_ID false
|
||||
#define OPT_MAP_TILE_SEQUENTIAL_ORDER true
|
||||
|
||||
@@ -24,6 +27,16 @@ bool opt_get_tile_dedupe(void);
|
||||
void opt_set_c_file_output(bool newval);
|
||||
bool opt_get_c_file_output(void);
|
||||
|
||||
void opt_set_precompiled_palette(bool newval);
|
||||
bool opt_get_precompiled_palette(void);
|
||||
|
||||
void opt_set_pal_end_bit(bool newval);
|
||||
bool opt_get_pal_end_bit(void);
|
||||
|
||||
void opt_set_enable_pal_end_color(uint16_t end_color_bgr555);
|
||||
bool opt_get_enable_pal_end_color(void);
|
||||
void opt_load_pal_end_color(uint16_t * p_end_color, int * pal_end_color_count);
|
||||
|
||||
void opt_set_bank_num(int newval);
|
||||
int opt_get_bank_num(void);
|
||||
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "path_ops.h"
|
||||
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
#ifndef _PATH_OPS_H
|
||||
#define _PATH_OPS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void filename_replace_extension(char * filename, char * new_ext, size_t maxlen);
|
||||
void filename_replace_path(char * filename, char * new_path, size_t maxlen);
|
||||
@@ -15,4 +16,4 @@ void filename_remove_extension(char * path);
|
||||
bool get_path_without_filename(const char * path, char * path_only, uint32_t str_max);
|
||||
bool matches_extension(char *, char *);
|
||||
|
||||
#endif // _PATH_OPS_H
|
||||
#endif // _PATH_OPS_H
|
||||
|
||||
@@ -92,7 +92,7 @@ bool tileset_find_matching_tile(const uint8_t * src_tile, const uint8_t * tile_s
|
||||
|
||||
for (unsigned int index_dedupe = 0; index_dedupe < tile_count_deduped; index_dedupe++) {
|
||||
|
||||
for (int f = 0; f < ARRAY_LEN(tile_flip_flags); f++) {
|
||||
for (size_t f = 0; f < ARRAY_LEN(tile_flip_flags); f++) {
|
||||
if (memcmp(&tile_set_deduped[index_dedupe * TILE_SZ], &tile_permutations[f * TILE_SZ], TILE_SZ) == 0) {
|
||||
|
||||
// Match Found
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#ifndef TILE_DEDUPE_H
|
||||
#define TILE_DEDUPE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
bool tileset_find_matching_tile(const uint8_t * src_tile, const uint8_t * tile_set_deduped, unsigned int tile_count_deduped, uint8_t * new_tile_id, uint8_t * new_attribs);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user