ys2-intro/loader/tools/dali/dali.c
2025-11-13 19:07:39 +03:00

732 lines
26 KiB
C

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sfx_small.h"
#include "sfx_fast.h"
#define BUFFER_SIZE 65536 /* must be > MAX_OFFSET */
#define INITIAL_OFFSET 1
#define FALSE 0
#define TRUE 1
#define DALI_BITS_LEFT 0
#define DALI_ELIAS_LE 1
typedef struct ctx {
unsigned char *packed_data;
unsigned char *reencoded_data;
unsigned char *unpacked_data;
size_t packed_index;
size_t packed_size;
int packed_bit_mask;
int packed_bit_value;
size_t reencoded_index;
int reencoded_bit_mask;
int reencoded_bit_value;
int reencoded_bit_index;
size_t unpacked_index;
size_t unpacked_size;
int inplace;
char *output_name;
char *input_name;
char *prefix_name;
char *clamped_name;
int cbm;
int cbm_orig_addr;
int cbm_packed_addr;
int cbm_range_from;
int cbm_range_to;
int cbm_relocate_packed_addr;
int cbm_relocate_origin_addr;
int cbm_prefix_from;
int sfx;
int sfx_addr;
int sfx_01;
int sfx_cli;
int sfx_small;
int sfx_size;
char *sfx_code;
int lz_bits;
} ctx;
void salvador_main();
static int read_number(char* arg, char* argname, int limit) {
int number;
if (arg != NULL && arg[0] == '$') number = strtoul(arg + 1, NULL, 16);
else if (arg != NULL && arg[0] == '0' && arg[1] == 'x') number = strtoul(arg + 2, NULL, 16);
else if (arg != NULL && arg[0] >= '0' && arg[0] <= '9') number = strtoul(arg, NULL, 10);
else {
fprintf(stderr, "Error: no valid number given for argument %s (given value is: '%s')\n", argname, arg);
exit(1);
}
if (number < 0 || number > limit) {
fprintf(stderr, "Error: Number '%s' out of range (0 - 65536)\n", arg);
exit(1);
}
return number;
}
static void file_write_byte(int byte, FILE *ofp) {
if (fputc(byte, ofp) != byte) {
fprintf(stderr, "Error: Cannot write output file\n");
perror("fputc");
exit(1);
}
return;
}
static inline unsigned bit_size(unsigned value) {
# ifdef __GNUC__
// enum { WORD_BITS = sizeof(unsigned) * CHAR_BIT };
return ((sizeof(unsigned) * 8 - 1) ^ __builtin_clz(value));
# else
signed bits = -1;
do
++bits;
while(value >>= 1);
return bits;
# endif
}
void write_reencoded_byte(ctx* ctx, int value) {
ctx->reencoded_data[ctx->reencoded_index++] = value;
}
void write_reencoded_bit(ctx* ctx, int value) {
if (!(ctx->reencoded_bit_mask & 255)) {
if (DALI_BITS_LEFT == 1) {
ctx->reencoded_bit_mask = 0x80;
} else {
ctx->reencoded_bit_mask = 0x1;
}
/* remember position of bit-buffer */
ctx->reencoded_bit_index = ctx->reencoded_index;
ctx->lz_bits++;
write_reencoded_byte(ctx, 0);
}
if (value)
ctx->reencoded_data[ctx->reencoded_bit_index] |= ctx->reencoded_bit_mask;
if (DALI_BITS_LEFT == 1) {
ctx->reencoded_bit_mask >>= 1;
} else {
ctx->reencoded_bit_mask <<= 1;
}
}
void write_reencoded_interlaced_elias_gamma(ctx* ctx, int value, int skip) {
int bits = bit_size(value);
int i;
for (i = 2; i <= value; i <<= 1);
i >>= 1;
if (DALI_ELIAS_LE) {
if (bits >= 8) {
/* change bit-order, send LSB first */
/* remove preceeding 1 first */
value = value & ((0xffff ^ i));
/* move LSB bits to the beginning */
value = (value >> 8) | ((value & 0xff) << (bits - 8));
}
}
while ((i >>= 1) > 0) {
if (!skip) write_reencoded_bit(ctx, 0);
skip = 0;
write_reencoded_bit(ctx, ((value & i) > 0));
}
if (!skip) write_reencoded_bit(ctx, 1);
}
int read_byte(ctx* ctx) {
return ctx->packed_data[ctx->packed_index++];
}
int read_bit(ctx* ctx) {
if ((ctx->packed_bit_mask >>= 1) == 0) {
ctx->packed_bit_mask = 0x80;
ctx->packed_bit_value = read_byte(ctx);
}
return (ctx->packed_bit_value & ctx->packed_bit_mask) != 0;
}
int read_interlaced_elias_gamma(ctx* ctx, int inverted, int skip) {
int value = 1;
/* skip first read bit if skip != 0 */
while (skip || !read_bit(ctx)) {
skip = 0;
value = (value << 1) | (read_bit(ctx) ^ inverted);
}
return value;
}
void save_reencoded_stream(ctx* ctx) {
}
void copy_inplace_literal(ctx* ctx) {
int i;
for (i = ctx->unpacked_index; i < ctx->unpacked_size; i++) {
ctx->reencoded_data[ctx->packed_index] = ctx->unpacked_data[i];
ctx->packed_index++;
}
}
void encode_literal(ctx* ctx, int length, int first) {
int i;
if (!first) write_reencoded_bit(ctx, 0);
write_reencoded_interlaced_elias_gamma(ctx, length, 0);
for (i = 0; i < length; i++) {
write_reencoded_byte(ctx, ctx->unpacked_data[ctx->unpacked_index + i]);
}
}
void encode_rep(ctx* ctx, int length) {
write_reencoded_bit(ctx, 0);
write_reencoded_interlaced_elias_gamma(ctx, length, 0);
}
void encode_match(ctx* ctx, int length, int offset) {
write_reencoded_bit(ctx, 1);
write_reencoded_interlaced_elias_gamma(ctx, ((offset - 1) >> 7) + 1, 0);
write_reencoded_byte(ctx, (((offset - 1) & 0x7f) << 1) | (length == 2));
write_reencoded_interlaced_elias_gamma(ctx, length - 1, 1);
}
void reencode_packed_stream(ctx* ctx) {
int last_offset = INITIAL_OFFSET;
int length;
int overwrite;
int bit, byte;
int i;
int safe_input_index = 0;
int safe_output_index = 0;
int first = 1;
ctx->packed_index = 0;
ctx->packed_bit_mask = 0;
ctx->reencoded_index = 0;
ctx->reencoded_bit_mask = 0;
ctx->reencoded_bit_value = 0;
ctx->reencoded_bit_index = 0;
ctx->packed_index = 0;
ctx->unpacked_index = 0;
ctx->packed_bit_mask = 0;
ctx->lz_bits = 0;
while (1) {
/* literal */
length = read_interlaced_elias_gamma(ctx, FALSE, 0);
for (i = 0; i < length; i++) read_byte(ctx);
encode_literal(ctx, length, first);
first = 0;
ctx->unpacked_index += length;
overwrite = (ctx->unpacked_index) - (ctx->unpacked_size - ctx->packed_size + ctx->packed_index);
/* literal would overwrite packed src */
if (ctx->inplace && overwrite >= 0) {
/* go back to previous index */
ctx->unpacked_index = safe_input_index;
ctx->packed_index = safe_output_index;
copy_inplace_literal(ctx);
return;
}
/* do remember last safe position */
safe_input_index = ctx->unpacked_index;
safe_output_index = ctx->packed_index;
/* copy from new or last offset? */
bit = read_bit(ctx);
if (!bit) {
/* copy from last_offset */
length = read_interlaced_elias_gamma(ctx, FALSE, 0);
encode_rep(ctx, length);
ctx->unpacked_index += length;
overwrite = (ctx->unpacked_index) - (ctx->unpacked_size - ctx->packed_size + ctx->packed_index);
/* rep would overwrite packed src */
if (ctx->inplace && overwrite >= 0) {
copy_inplace_literal(ctx);
return;
}
safe_input_index = ctx->unpacked_index;
safe_output_index = ctx->packed_index;
bit = read_bit(ctx);
}
while (bit) {
/* copy from new_offset */
last_offset = read_interlaced_elias_gamma(ctx, TRUE, 0);
if (last_offset == 256) {
if (!ctx->inplace) {
write_reencoded_bit(ctx, 1);
write_reencoded_interlaced_elias_gamma(ctx, last_offset, 0);
}
return;
}
byte = read_byte(ctx);
if (byte & 1) length = 2;
else length = read_interlaced_elias_gamma(ctx, FALSE, 1) + 1;
last_offset = (last_offset << 7) - (byte >> 1);
encode_match(ctx, length, last_offset);
ctx->unpacked_index += length;
overwrite = (ctx->unpacked_index) - (ctx->unpacked_size - ctx->packed_size + ctx->packed_index);
/* rep would overwrite packed src */
if (ctx->inplace && overwrite >= 0) {
copy_inplace_literal(ctx);
return;
}
safe_input_index = ctx->unpacked_index;
safe_output_index = ctx->packed_index;
bit = read_bit(ctx);
}
}
}
void write_reencoded_stream(ctx* ctx) {
FILE *fp = NULL;
/* write reencoded output file */
fp = fopen(ctx->output_name, "wb");
if (!fp) {
fprintf(stderr, "Error: Cannot create reencoded file (%s)\n", ctx->output_name);
exit(1);
}
/* as sfx */
if (ctx->sfx) {
printf("Creating sfx with start-address $%04x\n", ctx->sfx_addr);
if (ctx->sfx_small) {
ctx->sfx_size = sizeof(decruncher_small);
/* copy over to change values in code */
ctx->sfx_code = (char *)malloc(ctx->sfx_size);
memcpy (ctx->sfx_code, decruncher_small, ctx->sfx_size);
/* setup jmp target after decompression */
ctx->sfx_code[DALI_SMALL_SFX_ADDR + 0] = ctx->sfx_addr & 0xff;
ctx->sfx_code[DALI_SMALL_SFX_ADDR + 1] = (ctx->sfx_addr >> 8) & 0xff;
/* setup decompression destination */
ctx->sfx_code[DALI_SMALL_DST + 0] = ctx->cbm_orig_addr & 0xff;
ctx->sfx_code[DALI_SMALL_DST + 1] = (ctx->cbm_orig_addr >> 8) & 0xff;
/* setup compressed data src */
ctx->sfx_code[DALI_SMALL_SRC + 0] = (0x10000 - ctx->reencoded_index) & 0xff;
ctx->sfx_code[DALI_SMALL_SRC + 1] = ((0x10000 - ctx->reencoded_index) >> 8) & 0xff;
/* setup compressed data end */
ctx->sfx_code[DALI_SMALL_DATA_END + 0] = (0x0801 + ctx->sfx_size - 2 + ctx->reencoded_index - 0x100) & 0xff;
ctx->sfx_code[DALI_SMALL_DATA_END + 1] = ((0x0801 + ctx->sfx_size - 2 + ctx->reencoded_index - 0x100) >> 8) & 0xff;
ctx->sfx_code[DALI_SMALL_DATA_SIZE_HI] = 0xff - (((ctx->reencoded_index + 0x100) >> 8) & 0xff);
} else {
ctx->sfx_size = sizeof(decruncher);
/* copy over to change values in code */
ctx->sfx_code = (char *)malloc(ctx->sfx_size);
memcpy (ctx->sfx_code, decruncher, ctx->sfx_size);
if (ctx->sfx_01 < 0) ctx->sfx_01 = 0x37;
/* setup jmp target after decompression */
ctx->sfx_code[DALI_FAST_SFX_ADDR + 0] = ctx->sfx_addr & 0xff;
ctx->sfx_code[DALI_FAST_SFX_ADDR + 1] = (ctx->sfx_addr >> 8) & 0xff;
/* setup decompression destination */
ctx->sfx_code[DALI_FAST_DST + 0] = ctx->cbm_orig_addr & 0xff;
ctx->sfx_code[DALI_FAST_DST + 1] = (ctx->cbm_orig_addr >> 8) & 0xff;
/* setup compressed data src */
ctx->sfx_code[DALI_FAST_SRC + 0] = (0x10000 - ctx->reencoded_index) & 0xff;
ctx->sfx_code[DALI_FAST_SRC + 1] = ((0x10000 - ctx->reencoded_index) >> 8) & 0xff;
/* setup compressed data end */
ctx->sfx_code[DALI_FAST_DATA_END + 0] = (0x0801 + ctx->sfx_size - 2 + ctx->reencoded_index - 0x100) & 0xff;
ctx->sfx_code[DALI_FAST_DATA_END + 1] = ((0x0801 + ctx->sfx_size - 2 + ctx->reencoded_index - 0x100) >> 8) & 0xff;
ctx->sfx_code[DALI_FAST_DATA_SIZE_HI] = 0xff - (((ctx->reencoded_index + 0x100) >> 8) & 0xff);
ctx->sfx_code[DALI_FAST_01] = ctx->sfx_01;
if (ctx->sfx_cli) ctx->sfx_code[DALI_FAST_CLI] = 0x58;
}
printf("original: $%04x-$%04lx ($%04lx) 100%%\n", ctx->cbm_orig_addr, ctx->cbm_orig_addr + ctx->unpacked_size, ctx->unpacked_size);
printf("packed: $%04x-$%04lx ($%04lx) %3.2f%%\n", 0x0801, 0x0801 + (int)ctx->sfx_size + ctx->packed_index, (int)ctx->sfx_size + ctx->packed_index, ((float)(ctx->packed_index + (int)ctx->sfx_size) / (float)(ctx->unpacked_size) * 100.0));
if (fwrite(ctx->sfx_code, sizeof(char), ctx->sfx_size, fp) != ctx->sfx_size) {
fprintf(stderr, "Error: Cannot write output file %s\n", ctx->output_name);
exit(1);
}
/* or standard compressed */
} else {
if (ctx->cbm_relocate_origin_addr >= 0) {
ctx->cbm_orig_addr = ctx->cbm_relocate_origin_addr;
ctx->cbm = TRUE;
}
if (ctx->inplace) {
ctx->cbm_packed_addr = ctx->cbm_range_to - ctx->packed_index - 2;
} else {
if (ctx->cbm_relocate_packed_addr >= 0) {
ctx->cbm_packed_addr = ctx->cbm_relocate_packed_addr;
} else {
ctx->cbm_packed_addr = ctx->cbm_orig_addr;
}
}
if (ctx->cbm) {
printf("original: $%04x-$%04lx ($%04lx) 100%%\n", ctx->cbm_orig_addr, ctx->cbm_orig_addr + ctx->unpacked_size, ctx->unpacked_size);
printf("packed: $%04x-$%04lx ($%04lx) %3.2f%%\n", ctx->cbm_packed_addr, ctx->cbm_packed_addr + ctx->packed_index + 2, ctx->packed_index + 2, ((float)(ctx->packed_index) / (float)(ctx->unpacked_size) * 100.0));
if ((ctx->cbm_packed_addr >= 0xd000 && ctx->cbm_packed_addr < 0xe000) || (ctx->cbm_packed_addr < 0xd000 && ctx->cbm_packed_addr + ctx->packed_index + 2 > 0xd000)) {
fprintf(stderr, "Warning: Packed file lies in I/O-range from $d000-$dfff\n");
}
/* little endian */
file_write_byte(ctx->cbm_packed_addr & 255, fp);
file_write_byte((ctx->cbm_packed_addr >> 8) & 255, fp);
/* big endian, as read backwards by depacker */
file_write_byte((ctx->cbm_orig_addr >> 8) & 255, fp);
file_write_byte(ctx->cbm_orig_addr & 255, fp);
} else {
printf("original: $%04x-$%04lx ($%04lx) 100%%\n", 0, ctx->unpacked_size, ctx->unpacked_size);
printf("packed: $%04x-$%04lx ($%04lx) %3.2f%%\n", 0, ctx->packed_index, ctx->packed_index, ((float)(ctx->packed_index) / (float)(ctx->unpacked_size) * 100.0));
}
}
if (fwrite(ctx->reencoded_data, sizeof(char), ctx->packed_index, fp) != ctx->packed_index) {
fprintf(stderr, "Error: Cannot write output file\n");
exit(1);
}
fclose(fp);
}
void do_reencode(ctx* ctx) {
char tmp_name[] = "dict-XXXXXX";
char src_name[] = "src-XXXXXX";
unsigned char *dict_data = NULL;
int dict_size = 0;
char *salvador_argv[5];
int salvador_argc = 0;
int dict_temp = FALSE;
FILE *dfp = NULL;
FILE *sfp = NULL;
FILE* ufp = NULL;
FILE* pfp = NULL;
/* determine output filename */
if (ctx->output_name == NULL) {
ctx->output_name = (char *)malloc(strlen(ctx->input_name) + 4);
strcpy(ctx->output_name, ctx->input_name);
strcat(ctx->output_name, ".lz");
printf("output name: %s\n", ctx->output_name);
}
/* allocate buffers */
ctx->packed_data = (unsigned char *)malloc(BUFFER_SIZE);
ctx->unpacked_data = (unsigned char *)malloc(BUFFER_SIZE + 2);
ctx->reencoded_data = (unsigned char *)malloc(BUFFER_SIZE);
if (!ctx->packed_data || !ctx->unpacked_data || !ctx->reencoded_data) {
fprintf(stderr, "Error: Insufficient memory\n");
exit(1);
}
/* load unpacked file */
ufp = fopen(ctx->input_name, "rb");
if (!ufp) {
fprintf(stderr, "Error: Cannot access input file\n");
exit(1);
}
ctx->unpacked_size = fread(ctx->unpacked_data, sizeof(char), BUFFER_SIZE + 2, ufp);
fclose(ufp);
/* cbm address handling */
if (ctx->cbm_relocate_origin_addr >= 0) {
ctx->cbm_orig_addr = ctx->cbm_relocate_origin_addr;
} else {
ctx->cbm_orig_addr = ctx->unpacked_data[0] + (ctx->unpacked_data[1] << 8);
}
if (ctx->cbm) {
ctx->unpacked_data += 2;
ctx->unpacked_size -= 2;
}
/* take care of range (--from --to) */
if (ctx->cbm_range_from < 0) ctx->cbm_range_from = ctx->cbm_orig_addr;
if (ctx->cbm_range_to < 0) ctx->cbm_range_to = ctx->cbm_orig_addr + ctx->unpacked_size;
if ((ctx->cbm_range_to - ctx->cbm_orig_addr) > ctx->unpacked_size) {
ctx->cbm_range_to = ctx->unpacked_size + ctx->cbm_orig_addr;
fprintf(stderr, "Warning: File ends at $%04x, adopting --to value\n", ctx->cbm_range_to);
}
ctx->unpacked_size = (ctx->cbm_range_to - ctx->cbm_orig_addr);
/* if range is below start_address, adopt range */
if (ctx->cbm_range_from < ctx->cbm_orig_addr) {
ctx->cbm_range_from = ctx->cbm_orig_addr;
fprintf(stderr, "Warning: File starts at $%04x, adopting --from value\n", ctx->cbm_range_from);
}
if (ctx->cbm_range_from > ctx->cbm_range_to) {
fprintf(stderr, "Error: --from beyond fileend ($%04x - $%04x)\n", ctx->cbm_range_from, ctx->cbm_range_to);
exit(1);
}
/* setup dict lengths and position */
if (ctx->cbm_prefix_from >= 0) {
if (ctx->cbm_range_from < 0) {
fprintf(stderr, "Error: Dict is zero size (use --from)\n");
exit(1);
}
else if (ctx->cbm_prefix_from >= ctx->cbm_range_from) {
fprintf(stderr, "Error: --from must be greater than --prefix-from\n");
exit(1);
}
if (ctx->cbm_range_from >= 0 && ctx->cbm_range_from - ctx->cbm_prefix_from > 32640) {
//ctx->cbm_prefix_from = ctx->cbm_range_from - 32640;
fprintf(stderr, "Info: --prefix-from exceeds max offset, not all bytes can be used\n");
}
/* if range is below start_address, adopt range */
if (ctx->cbm_prefix_from < ctx->cbm_orig_addr) {
ctx->cbm_prefix_from = ctx->cbm_orig_addr;
fprintf(stderr, "Warning: File starts at $%04x, adopting --prefix-from value\n", ctx->cbm_prefix_from);
}
dict_data = ctx->unpacked_data + ctx->cbm_prefix_from - ctx->cbm_orig_addr;
dict_size = ctx->cbm_range_from - ctx->cbm_prefix_from;
}
/* load file from start_pos on only, so skip bytes on input */
ctx->unpacked_data += (ctx->cbm_range_from - ctx->cbm_orig_addr);
/* also adopt ctx->unpacked_size */
ctx->unpacked_size -= (ctx->cbm_range_from - ctx->cbm_orig_addr);
/* and set up new load-address */
ctx->cbm_orig_addr = ctx->cbm_range_from;
if (ctx->unpacked_size <= 0) {
fprintf(stderr, "Error: Input too small\n");
exit(1);
}
printf("Compressing from $%04x to $%04x = $%04lx bytes\n", ctx->cbm_range_from, ctx->cbm_range_to, ctx->unpacked_size);
if (ctx->cbm_relocate_packed_addr >= 0 || ctx->sfx) {
ctx->inplace = FALSE;
}
/* write clamped raw data */
ctx->clamped_name = (char*)malloc(sizeof(src_name));
strcpy(ctx->clamped_name, src_name);
sfp = fdopen(mkstemp(ctx->clamped_name),"wb");
if (!sfp) {
fprintf(stderr, "Error: Cannot create clamped file %s\n", ctx->clamped_name);
exit(1);
}
if (ctx->unpacked_size != 0) {
if (fwrite(ctx->unpacked_data, sizeof(char), ctx->unpacked_size, sfp) != ctx->unpacked_size) {
fprintf(stderr, "Error: Cannot write clamped file\n");
perror("fwrite");
exit(1);
}
}
fclose(sfp);
/* ctreate temp file for dict */
if (ctx->cbm_prefix_from >= 0) {
if (ctx->prefix_name == NULL) {
ctx->prefix_name = (char*)malloc(sizeof(tmp_name));
strcpy(ctx->prefix_name, tmp_name);
dfp = fdopen(mkstemp(ctx->prefix_name),"wb");
printf("using prefix: $%04x - $%04x\n", ctx->cbm_prefix_from, ctx->cbm_prefix_from + dict_size);
if (!dfp) {
fprintf(stderr, "Error: Cannot create dict file %s\n", ctx->prefix_name);
exit(1);
}
if (!dict_data || fwrite(dict_data, sizeof(char), dict_size, dfp) != dict_size) {
fprintf(stderr, "Error: Cannot write dict file %s\n", ctx->prefix_name);
remove(ctx->prefix_name);
exit(1);
}
dict_temp = TRUE;
fclose(dfp);
}
}
/* compress data with salvador */
salvador_argv[salvador_argc++] = "salvador";
if (ctx->prefix_name) {
salvador_argv[salvador_argc++] = "-D";
salvador_argv[salvador_argc++] = ctx->prefix_name;
}
salvador_argv[salvador_argc++] = ctx->clamped_name;
salvador_argv[salvador_argc++] = ctx->output_name;
salvador_main(salvador_argc, salvador_argv);
/* delete dict */
if (dict_temp) remove(ctx->prefix_name);
/* remove clamped */
remove(ctx->clamped_name);
/* read packed data */
pfp = fopen(ctx->output_name, "rb");
if (!pfp) {
fprintf(stderr, "Error: Cannot access input file\n");
exit(1);
}
ctx->packed_size = fread(ctx->packed_data, sizeof(char), BUFFER_SIZE, pfp);
fclose(pfp);
/* determine size without eof-marker -> remove 18 bits, either 2 byte or three byte depending on position of last bitpair */
if (ctx->packed_data[ctx->packed_size - 1] & 0x80) ctx->packed_size -= 3;
else ctx->packed_size -= 2;
reencode_packed_stream(ctx);
if (ctx->packed_index + 2 > ctx->unpacked_size) {
fprintf(stderr, "Error: Packed file larger than original\n");
exit(1);
}
//printf("control-bytes: $%04x\n", ctx->lz_bits);
write_reencoded_stream(ctx);
return;
}
int main(int argc, char *argv[]) {
int i;
ctx ctx = { 0 };
ctx.output_name = NULL;
ctx.input_name = NULL;
ctx.prefix_name = NULL;
ctx.inplace = TRUE;
ctx.cbm = TRUE;
ctx.cbm_orig_addr = 0;
ctx.cbm_packed_addr = 0;
ctx.cbm_range_from = -1;
ctx.cbm_range_to = -1;
ctx.cbm_relocate_packed_addr = -1;
ctx.cbm_relocate_origin_addr = -1;
ctx.cbm_prefix_from = -1;
ctx.sfx = FALSE;
ctx.sfx_addr = -1;
ctx.sfx_01 = -1;
ctx.sfx_cli = FALSE;
ctx.sfx_small = FALSE;
ctx.sfx_code = NULL;
for (i = 1; i < argc; i++) {
if (!strncmp(argv[i], "-", 1) || !strncmp(argv[i], "--", 2)) {
if (!strcmp(argv[i], "--binfile")) {
ctx.cbm = FALSE;
} else if (!strcmp(argv[i], "--prefix-from")) {
ctx.cbm_prefix_from = read_number(argv[i + 1], argv[i], 65536);
i++;
} else if (!strcmp(argv[i], "--prefix-file")) {
i++;
ctx.prefix_name = argv[i];
} else if (!strcmp(argv[i], "--no-inplace")) {
ctx.inplace = FALSE;
} else if (!strcmp(argv[i], "--small")) {
ctx.sfx_small = TRUE;
} else if (!strcmp(argv[i], "--relocate-packed")) {
ctx.cbm_relocate_packed_addr = read_number(argv[i + 1], argv[i], 65536);
i++;
} else if (!strcmp(argv[i], "--relocate-origin")) {
ctx.cbm_relocate_origin_addr = read_number(argv[i + 1], argv[i], 65536);
i++;
} else if (!strcmp(argv[i], "--from")) {
ctx.cbm_range_from = read_number(argv[i + 1], argv[i], 65536);
i++;
} else if (!strcmp(argv[i], "--to")) {
ctx.cbm_range_to = read_number(argv[i + 1], argv[i], 65536);
i++;
} else if (!strcmp(argv[i], "--01")) {
ctx.sfx_01 = read_number(argv[i + 1], argv[i], 256);
i++;
} else if (!strcmp(argv[i], "--cli")) {
ctx.sfx_cli = TRUE;
} else if (!strcmp(argv[i], "--sfx")) {
ctx.sfx_addr = read_number(argv[i + 1], argv[i], 65536);
i++;
ctx.sfx = TRUE;
ctx.inplace = FALSE;
} else if (!strcmp(argv[i], "-o")) {
i++;
ctx.output_name = argv[i];
} else {
fprintf(stderr, "Error: Unknown option %s\n", argv[i]);
exit(1);
}
} else if (i == argc - 1) {
ctx.input_name = argv[i];
} else {
fprintf(stderr, "Error: Unknown option %s\n", argv[i]);
exit(1);
}
}
printf("dali v0.3 - a zx0-reencoder for bitfire by Tobias Bindhammer\n");
printf("underlying zx0-packer salvador by Emmanuel Marty\n");
if (argc == 1) {
fprintf(stderr, "Usage: %s [options] input\n"
" -o [filename] Set output filename.\n"
" --sfx [num] Create a c64 compatible sfx-executable.\n"
" --01 [num] Set 01 to [num] after sfx.\n"
" --cli [num] Do a CLI after sfx, default is SEI.\n"
" --small Use a very small depacker that fits into zeropage, but --01 and --cli are ignored and it trashes zeropage (!)\n"
" --no-inplace Disable inplace-decompression.\n"
" --binfile Input file is a raw binary without load-address.\n"
" --from [num] Compress file from [num] on.\n"
" --to [num] Compress file until position [num].\n"
" --prefix-from [num] Use preceeding data from [num] on as dictionary (in combination with --from).\n"
" --prefix-file [file] Use preceeding data from [file] as dictionary.\n"
" --relocate-packed [num] Relocate packed data to desired address [num] (resulting file can't de decompressed inplace!)\n"
" --relocate-origin [num] Set load-address of source file to [num] prior to compression. If used on bin-files, load-address and depack-target is prepended on output.\n"
,argv[0]);
exit(1);
}
if (!ctx.sfx && ctx.sfx_small) {
fprintf(stderr, "Info: No sfx, ignoring --small option\n");
}
if (!ctx.sfx && ctx.sfx_01 >= 0) {
fprintf(stderr, "Info: No sfx, ignoring --01 option\n");
}
if (!ctx.sfx && ctx.sfx_cli) {
fprintf(stderr, "Info: No sfx, ignoring --cli option\n");
}
if (ctx.input_name == NULL) {
fprintf(stderr, "Error: No input-filename given\n");
exit(1);
}
do_reencode(&ctx);
return 0;
}