Compressed ROM images now work.
This commit is contained in:
parent
37fa9a8706
commit
048bbeeebc
|
@ -90,6 +90,7 @@ MKCONFIG ?= $(PERL) ./util/mkconfig.pl
|
||||||
SYMCHECK ?= $(PERL) ./util/symcheck.pl
|
SYMCHECK ?= $(PERL) ./util/symcheck.pl
|
||||||
SORTOBJDUMP ?= $(PERL) ./util/sortobjdump.pl
|
SORTOBJDUMP ?= $(PERL) ./util/sortobjdump.pl
|
||||||
NRV2B ?= ./util/nrv2b
|
NRV2B ?= ./util/nrv2b
|
||||||
|
ZBIN ?= ./util/zbin
|
||||||
DOXYGEN ?= doxygen
|
DOXYGEN ?= doxygen
|
||||||
|
|
||||||
# Location to place generated files
|
# Location to place generated files
|
||||||
|
|
|
@ -307,11 +307,23 @@ $(BIN)/%.tmp : $(BLIB) $(MAKEDEPS) $(LDSCRIPT)
|
||||||
$(BIN)/%.map : $(BIN)/%.tmp
|
$(BIN)/%.map : $(BIN)/%.tmp
|
||||||
@less $(BIN)/$*.tmp.map
|
@less $(BIN)/$*.tmp.map
|
||||||
|
|
||||||
|
# Extract compression information from intermediate object file
|
||||||
|
#
|
||||||
|
$(BIN)/%.zinfo : $(BIN)/%.tmp
|
||||||
|
$(QM)echo " [ZINFO] $@"
|
||||||
|
$(Q)$(OBJCOPY) -O binary -j .zinfo $< $@
|
||||||
|
|
||||||
# Build raw binary file from intermediate object file
|
# Build raw binary file from intermediate object file
|
||||||
#
|
#
|
||||||
$(BIN)/%.bin : $(BIN)/%.tmp
|
$(BIN)/%.bin : $(BIN)/%.tmp
|
||||||
$(QM)echo " [BIN] $@"
|
$(QM)echo " [BIN] $@"
|
||||||
$(Q)$(OBJCOPY) -O binary $< $@
|
$(Q)$(OBJCOPY) -O binary -R .zinfo $< $@
|
||||||
|
|
||||||
|
# Compress raw binary file
|
||||||
|
#
|
||||||
|
$(BIN)/%.zbin : $(BIN)/%.bin $(BIN)/%.zinfo $(ZBIN)
|
||||||
|
$(QM)echo " [ZBIN] $@"
|
||||||
|
$(Q)$(ZBIN) $(BIN)/$*.bin $(BIN)/$*.zinfo > $@
|
||||||
|
|
||||||
# Build bochs symbol table
|
# Build bochs symbol table
|
||||||
$(BIN)/%.bxs : $(BIN)/%.tmp
|
$(BIN)/%.bxs : $(BIN)/%.tmp
|
||||||
|
@ -356,7 +368,7 @@ define media_template
|
||||||
@$(MKDIR) -p $(dir $(2))
|
@$(MKDIR) -p $(dir $(2))
|
||||||
@$(RM) $(2)
|
@$(RM) $(2)
|
||||||
@$(TOUCH) $(2)
|
@$(TOUCH) $(2)
|
||||||
@echo -e '$$(BIN)/%$(1) : $$(BIN)/%$(1).bin' \
|
@echo -e '$$(BIN)/%$(1) : $$(BIN)/%$(1).zbin' \
|
||||||
'\n\t$$(QM)echo " [FINISH] $$@"' \
|
'\n\t$$(QM)echo " [FINISH] $$@"' \
|
||||||
'\n\t$$(Q)$$(CP) $$< $$@' \
|
'\n\t$$(Q)$$(CP) $$< $$@' \
|
||||||
'\n\t$$(Q)$$(FINALISE_$(1))' \
|
'\n\t$$(Q)$$(FINALISE_$(1))' \
|
||||||
|
@ -383,13 +395,19 @@ include $(MEDIA_DEPS)
|
||||||
allroms allzroms : all%s : $(foreach ROM,$(ROMS),$(BIN)/$(ROM).%)
|
allroms allzroms : all%s : $(foreach ROM,$(ROMS),$(BIN)/$(ROM).%)
|
||||||
all%s : $(foreach DRIVER,$(DRIVERS),$(BIN)/$(DRIVER).%)
|
all%s : $(foreach DRIVER,$(DRIVERS),$(BIN)/$(DRIVER).%)
|
||||||
|
|
||||||
# The compressor utility
|
# The compression utilities
|
||||||
#
|
#
|
||||||
$(NRV2B) : util/nrv2b.c $(MAKEDEPS)
|
$(NRV2B) : util/nrv2b.c $(MAKEDEPS)
|
||||||
$(HOST_CC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -DNDEBUG \
|
$(QM)echo " [HOSTCC] $@"
|
||||||
|
$(Q)$(HOST_CC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -DNDEBUG \
|
||||||
-DBITSIZE=32 -DENDIAN=0 -o $@ $<
|
-DBITSIZE=32 -DENDIAN=0 -o $@ $<
|
||||||
CLEANUP += $(NRV2B)
|
CLEANUP += $(NRV2B)
|
||||||
|
|
||||||
|
$(ZBIN) : util/zbin.c util/nrv2b.c $(MAKEDEPS)
|
||||||
|
$(QM)echo " [HOSTCC] $@"
|
||||||
|
$(Q)$(HOST_CC) -O2 -o $@ $<
|
||||||
|
CLEANUP += $(ZBIN)
|
||||||
|
|
||||||
# Auto-incrementing build serial number. Append "bs" to your list of
|
# Auto-incrementing build serial number. Append "bs" to your list of
|
||||||
# build targets to get a serial number printed at the end of the
|
# build targets to get a serial number printed at the end of the
|
||||||
# build. Enable -DBUILD_SERIAL in order to see it when the code runs.
|
# build. Enable -DBUILD_SERIAL in order to see it when the code runs.
|
||||||
|
|
|
@ -37,6 +37,9 @@
|
||||||
*/
|
*/
|
||||||
#define HIGHMEM_LOADPOINT ( 4 << 20 )
|
#define HIGHMEM_LOADPOINT ( 4 << 20 )
|
||||||
|
|
||||||
|
/* Image compression enabled */
|
||||||
|
#define COMPRESS 1
|
||||||
|
|
||||||
#define CR0_PE 1
|
#define CR0_PE 1
|
||||||
|
|
||||||
.arch i386
|
.arch i386
|
||||||
|
@ -81,7 +84,11 @@ install_block:
|
||||||
|
|
||||||
/* Do the copy */
|
/* Do the copy */
|
||||||
cld
|
cld
|
||||||
rep addr32 movsb /* or "call decompress16" */
|
#if COMPRESS
|
||||||
|
call decompress16
|
||||||
|
#else
|
||||||
|
call nodecompress16
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Zero remaining space */
|
/* Zero remaining space */
|
||||||
movl %eax, %edi
|
movl %eax, %edi
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
/* Placeholder for decompress16 in non-compressed images */
|
||||||
|
|
||||||
|
.text
|
||||||
|
.arch i386
|
||||||
|
.section ".prefix.lib", "ax", @progbits
|
||||||
|
|
||||||
|
.code16
|
||||||
|
.globl nodecompress16
|
||||||
|
nodecompress16:
|
||||||
|
rep addr32 movsb
|
||||||
|
ret
|
||||||
|
|
||||||
|
/* File split information for the compressor */
|
||||||
|
.section ".zinfo", "a"
|
||||||
|
.ascii "COPY"
|
||||||
|
.long _prefix_load_offset
|
||||||
|
.long _load_size
|
||||||
|
.long _max_align
|
|
@ -14,7 +14,7 @@
|
||||||
.org 0x00
|
.org 0x00
|
||||||
romheader:
|
romheader:
|
||||||
.word 0xAA55 /* BIOS extension signature */
|
.word 0xAA55 /* BIOS extension signature */
|
||||||
.byte _rom_size /* Size in 512-byte blocks */
|
romheader_size: .byte _rom_size /* Size in 512-byte blocks */
|
||||||
jmp init_vector /* Initialisation vector */
|
jmp init_vector /* Initialisation vector */
|
||||||
.org 0x16
|
.org 0x16
|
||||||
.word undiheader
|
.word undiheader
|
||||||
|
@ -34,7 +34,7 @@ pciheader:
|
||||||
.byte 0x02 /* Device Base Type code */
|
.byte 0x02 /* Device Base Type code */
|
||||||
.byte 0x00 /* Device Sub-Type code */
|
.byte 0x00 /* Device Sub-Type code */
|
||||||
.byte 0x00 /* Device Interface Type code */
|
.byte 0x00 /* Device Interface Type code */
|
||||||
.word _rom_size /* Image length same as offset 02h */
|
pciheader_size: .word _rom_size /* Image length same as offset 02h */
|
||||||
.word 0x0001 /* revision level of code/data */
|
.word 0x0001 /* revision level of code/data */
|
||||||
.byte 0x00 /* code type */
|
.byte 0x00 /* code type */
|
||||||
.byte 0x80 /* Flags (last PCI data structure) */
|
.byte 0x80 /* Flags (last PCI data structure) */
|
||||||
|
@ -215,3 +215,15 @@ print_message:
|
||||||
popw %ax
|
popw %ax
|
||||||
ret
|
ret
|
||||||
.size print_message, . - print_message
|
.size print_message, . - print_message
|
||||||
|
|
||||||
|
|
||||||
|
/* Data update information for the compressor */
|
||||||
|
.section ".zinfo.fixup", "a"
|
||||||
|
.ascii "SUBB"
|
||||||
|
.long romheader_size
|
||||||
|
.long 512
|
||||||
|
.long 0
|
||||||
|
.ascii "SUBW"
|
||||||
|
.long pciheader_size
|
||||||
|
.long 512
|
||||||
|
.long 0
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
.text
|
.text
|
||||||
.arch i386
|
.arch i386
|
||||||
.section ".prefix", "ax", @progbits
|
.section ".prefix.lib", "ax", @progbits
|
||||||
|
|
||||||
#ifdef CODE16
|
#ifdef CODE16
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -54,6 +54,7 @@
|
||||||
* NOTE: It would be possible to build a smaller version of the
|
* NOTE: It would be possible to build a smaller version of the
|
||||||
* decompression code for -DKEEP_IT_REAL by using
|
* decompression code for -DKEEP_IT_REAL by using
|
||||||
* #define REG(x) x
|
* #define REG(x) x
|
||||||
|
* #define MOVSB movsb
|
||||||
* to use 16-bit registers where possible. This would impose limits
|
* to use 16-bit registers where possible. This would impose limits
|
||||||
* that the compressed data size must be in the range [1,65533-%si]
|
* that the compressed data size must be in the range [1,65533-%si]
|
||||||
* and the uncompressed data size must be in the range [1,65536-%di]
|
* and the uncompressed data size must be in the range [1,65536-%di]
|
||||||
|
@ -66,6 +67,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define REG(x) e ## x
|
#define REG(x) e ## x
|
||||||
|
#define MOVSB addr32 movsb
|
||||||
|
|
||||||
.code16
|
.code16
|
||||||
.globl decompress16
|
.globl decompress16
|
||||||
|
@ -109,11 +111,10 @@ decompress:
|
||||||
cld
|
cld
|
||||||
xor %xBP, %xBP
|
xor %xBP, %xBP
|
||||||
dec %xBP /* last_m_off = -1 */
|
dec %xBP /* last_m_off = -1 */
|
||||||
add $4, %xSI /* Skip "file length" field */
|
|
||||||
jmp dcl1_n2b
|
jmp dcl1_n2b
|
||||||
|
|
||||||
decompr_literals_n2b:
|
decompr_literals_n2b:
|
||||||
movsb
|
MOVSB
|
||||||
decompr_loop_n2b:
|
decompr_loop_n2b:
|
||||||
addl %ebx, %ebx
|
addl %ebx, %ebx
|
||||||
jnz dcl2_n2b
|
jnz dcl2_n2b
|
||||||
|
@ -157,7 +158,7 @@ decompr_got_mlen_n2b:
|
||||||
push %xSI
|
push %xSI
|
||||||
lea (%xBP,%xDI), %xSI /* m_pos = dst + olen + -m_off */
|
lea (%xBP,%xDI), %xSI /* m_pos = dst + olen + -m_off */
|
||||||
rep
|
rep
|
||||||
es movsb /* dst[olen++] = *m_pos++ while(m_len > 0) */
|
es MOVSB /* dst[olen++] = *m_pos++ while(m_len > 0) */
|
||||||
pop %xSI
|
pop %xSI
|
||||||
jmp decompr_loop_n2b
|
jmp decompr_loop_n2b
|
||||||
|
|
||||||
|
@ -179,3 +180,23 @@ decompr_end_n2b:
|
||||||
popl %ebx
|
popl %ebx
|
||||||
pop %xAX
|
pop %xAX
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
/* File split information for the compressor */
|
||||||
|
.section ".zinfo", "a"
|
||||||
|
.ascii "COPY"
|
||||||
|
.long _prefix_load_offset
|
||||||
|
.long _prefix_progbits_size
|
||||||
|
.long _max_align
|
||||||
|
.ascii "PACK"
|
||||||
|
.long _text16_load_offset
|
||||||
|
.long _text16_progbits_size
|
||||||
|
.long _max_align
|
||||||
|
.ascii "PACK"
|
||||||
|
.long _data16_load_offset
|
||||||
|
.long _data16_progbits_size
|
||||||
|
.long _max_align
|
||||||
|
.ascii "PACK"
|
||||||
|
.long _textdata_load_offset
|
||||||
|
.long _textdata_progbits_size
|
||||||
|
.long _max_align
|
||||||
|
|
|
@ -164,6 +164,24 @@ SECTIONS {
|
||||||
|
|
||||||
_end = .;
|
_end = .;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compressor information block
|
||||||
|
*/
|
||||||
|
|
||||||
|
_zinfo_link_addr = 0;
|
||||||
|
. = _zinfo_link_addr;
|
||||||
|
_zinfo = .;
|
||||||
|
|
||||||
|
.zinfo : AT ( _zinfo_load_offset + __zinfo ) {
|
||||||
|
__zinfo = .;
|
||||||
|
_entry = .;
|
||||||
|
*(.zinfo)
|
||||||
|
*(.zinfo.*)
|
||||||
|
_ezinfo_progbits = .;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ezinfo = .;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dispose of the comment and note sections to make the link map
|
* Dispose of the comment and note sections to make the link map
|
||||||
* easier to read
|
* easier to read
|
||||||
|
@ -215,6 +233,13 @@ SECTIONS {
|
||||||
|
|
||||||
_load_size = . - _load_addr;
|
_load_size = . - _load_addr;
|
||||||
|
|
||||||
|
. -= _zinfo_link_addr;
|
||||||
|
_zinfo_load_offset = ALIGN ( _max_align );
|
||||||
|
_zinfo_load_addr = _zinfo_link_addr + _zinfo_load_offset;
|
||||||
|
_zinfo_size = _ezinfo - _zinfo;
|
||||||
|
_zinfo_progbits_size = _ezinfo_progbits - _zinfo;
|
||||||
|
. = _zinfo_load_addr + _zinfo_progbits_size;
|
||||||
|
|
||||||
_payload_offset = _text16_load_offset;
|
_payload_offset = _text16_load_offset;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
nrv2b
|
nrv2b
|
||||||
|
zbin
|
||||||
hijack
|
hijack
|
||||||
prototester
|
prototester
|
||||||
|
|
|
@ -0,0 +1,325 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#define ENCODE
|
||||||
|
#define VERBOSE
|
||||||
|
#include "nrv2b.c"
|
||||||
|
FILE *infile, *outfile;
|
||||||
|
|
||||||
|
struct input_file {
|
||||||
|
void *buf;
|
||||||
|
size_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct output_file {
|
||||||
|
void *buf;
|
||||||
|
size_t len;
|
||||||
|
size_t max_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zinfo_common {
|
||||||
|
char type[4];
|
||||||
|
char pad[12];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zinfo_copy {
|
||||||
|
char type[4];
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t len;
|
||||||
|
uint32_t align;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zinfo_pack {
|
||||||
|
char type[4];
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t len;
|
||||||
|
uint32_t align;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zinfo_subtract {
|
||||||
|
char type[4];
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t divisor;
|
||||||
|
uint32_t pad;
|
||||||
|
};
|
||||||
|
|
||||||
|
union zinfo_record {
|
||||||
|
struct zinfo_common common;
|
||||||
|
struct zinfo_copy copy;
|
||||||
|
struct zinfo_pack pack;
|
||||||
|
struct zinfo_subtract subtract;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zinfo_file {
|
||||||
|
union zinfo_record *zinfo;
|
||||||
|
unsigned int num_entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int read_file ( const char *filename, void **buf, size_t *len ) {
|
||||||
|
FILE *file;
|
||||||
|
struct stat stat;
|
||||||
|
|
||||||
|
file = fopen ( filename, "r" );
|
||||||
|
if ( ! file ) {
|
||||||
|
fprintf ( stderr, "Could not open %s: %s\n", filename,
|
||||||
|
strerror ( errno ) );
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fstat ( fileno ( file ), &stat ) < 0 ) {
|
||||||
|
fprintf ( stderr, "Could not stat %s: %s\n", filename,
|
||||||
|
strerror ( errno ) );
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
*len = stat.st_size;
|
||||||
|
*buf = malloc ( *len );
|
||||||
|
if ( ! *buf ) {
|
||||||
|
fprintf ( stderr, "Could not malloc() %d bytes for %s: %s\n",
|
||||||
|
*len, filename, strerror ( errno ) );
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fread ( *buf, 1, *len, file ) != *len ) {
|
||||||
|
fprintf ( stderr, "Could not read %d bytes from %s: %s\n",
|
||||||
|
*len, filename, strerror ( errno ) );
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose ( file );
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
fclose ( file );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_input_file ( const char *filename,
|
||||||
|
struct input_file *input ) {
|
||||||
|
return read_file ( filename, &input->buf, &input->len );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_zinfo_file ( const char *filename,
|
||||||
|
struct zinfo_file *zinfo ) {
|
||||||
|
void *buf;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if ( read_file ( filename, &buf, &len ) < 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if ( ( len % sizeof ( *(zinfo->zinfo) ) ) != 0 ) {
|
||||||
|
fprintf ( stderr, ".zinfo file %s has invalid length %d\n",
|
||||||
|
filename, len );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
zinfo->zinfo = buf;
|
||||||
|
zinfo->num_entries = ( len / sizeof ( *(zinfo->zinfo) ) );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int alloc_output_file ( size_t max_len, struct output_file *output ) {
|
||||||
|
output->len = 0;
|
||||||
|
output->max_len = ( max_len );
|
||||||
|
output->buf = malloc ( max_len );
|
||||||
|
if ( ! output->buf ) {
|
||||||
|
fprintf ( stderr, "Could not allocate %d bytes for output\n",
|
||||||
|
max_len );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memset ( output->buf, 0xff, sizeof ( output->buf ) );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int process_zinfo_copy ( struct input_file *input,
|
||||||
|
struct output_file *output,
|
||||||
|
union zinfo_record *zinfo ) {
|
||||||
|
struct zinfo_copy *copy = &zinfo->copy;
|
||||||
|
size_t offset = copy->offset;
|
||||||
|
size_t len = copy->len;
|
||||||
|
unsigned int align = copy->align;
|
||||||
|
|
||||||
|
if ( ( offset + len ) > input->len ) {
|
||||||
|
fprintf ( stderr, "Input buffer overrun on copy\n" );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
output->len = ( ( output->len + align - 1 ) & ~( align - 1 ) );
|
||||||
|
if ( ( output->len + len ) > output->max_len ) {
|
||||||
|
fprintf ( stderr, "Output buffer overrun on copy\n" );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy ( ( output->buf + output->len ),
|
||||||
|
( input->buf + offset ), len );
|
||||||
|
output->len += len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int process_zinfo_pack ( struct input_file *input,
|
||||||
|
struct output_file *output,
|
||||||
|
union zinfo_record *zinfo ) {
|
||||||
|
struct zinfo_pack *pack = &zinfo->pack;
|
||||||
|
size_t offset = pack->offset;
|
||||||
|
size_t len = pack->len;
|
||||||
|
unsigned int align = pack->align;
|
||||||
|
unsigned long packed_len;
|
||||||
|
|
||||||
|
if ( ( offset + len ) > input->len ) {
|
||||||
|
fprintf ( stderr, "Input buffer overrun on pack\n" );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
output->len = ( ( output->len + align - 1 ) & ~( align - 1 ) );
|
||||||
|
if ( output->len > output->max_len ) {
|
||||||
|
fprintf ( stderr, "Output buffer overrun on pack\n" );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ucl_nrv2b_99_compress ( ( input->buf + offset ), len,
|
||||||
|
( output->buf + output->len ),
|
||||||
|
&packed_len, 0 ) != UCL_E_OK ) {
|
||||||
|
fprintf ( stderr, "Compression failure\n" );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
output->len += packed_len;
|
||||||
|
if ( output->len > output->max_len ) {
|
||||||
|
fprintf ( stderr, "Output buffer overrun on pack\n" );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int process_zinfo_subtract ( struct input_file *input,
|
||||||
|
struct output_file *output,
|
||||||
|
struct zinfo_subtract *subtract,
|
||||||
|
size_t datasize ) {
|
||||||
|
size_t offset = subtract->offset;
|
||||||
|
void *target;
|
||||||
|
long delta;
|
||||||
|
|
||||||
|
if ( ( offset + datasize ) > output->len ) {
|
||||||
|
fprintf ( stderr, "Subtract at %#zx outside output buffer\n",
|
||||||
|
offset );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
target = ( output->buf + offset );
|
||||||
|
delta = ( ( output->len / subtract->divisor ) -
|
||||||
|
( input->len / subtract->divisor ) );
|
||||||
|
|
||||||
|
switch ( datasize ) {
|
||||||
|
case 1: {
|
||||||
|
uint8_t *byte = target;
|
||||||
|
*byte += delta;
|
||||||
|
break; }
|
||||||
|
case 2: {
|
||||||
|
uint16_t *word = target;
|
||||||
|
*word += delta;
|
||||||
|
break; }
|
||||||
|
case 4: {
|
||||||
|
uint32_t *dword = target;
|
||||||
|
*dword += delta;
|
||||||
|
break; }
|
||||||
|
default:
|
||||||
|
fprintf ( stderr, "Unsupported subtract datasize %d\n",
|
||||||
|
datasize );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int process_zinfo_subb ( struct input_file *input,
|
||||||
|
struct output_file *output,
|
||||||
|
union zinfo_record *zinfo ) {
|
||||||
|
return process_zinfo_subtract ( input, output, &zinfo->subtract, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int process_zinfo_subw ( struct input_file *input,
|
||||||
|
struct output_file *output,
|
||||||
|
union zinfo_record *zinfo ) {
|
||||||
|
return process_zinfo_subtract ( input, output, &zinfo->subtract, 2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int process_zinfo_subl ( struct input_file *input,
|
||||||
|
struct output_file *output,
|
||||||
|
union zinfo_record *zinfo ) {
|
||||||
|
return process_zinfo_subtract ( input, output, &zinfo->subtract, 4 );
|
||||||
|
}
|
||||||
|
|
||||||
|
struct zinfo_processor {
|
||||||
|
char *type;
|
||||||
|
int ( * process ) ( struct input_file *input,
|
||||||
|
struct output_file *output,
|
||||||
|
union zinfo_record *zinfo );
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct zinfo_processor zinfo_processors[] = {
|
||||||
|
{ "COPY", process_zinfo_copy },
|
||||||
|
{ "PACK", process_zinfo_pack },
|
||||||
|
{ "SUBB", process_zinfo_subb },
|
||||||
|
{ "SUBW", process_zinfo_subw },
|
||||||
|
{ "SUBL", process_zinfo_subl },
|
||||||
|
};
|
||||||
|
|
||||||
|
static int process_zinfo ( struct input_file *input,
|
||||||
|
struct output_file *output,
|
||||||
|
union zinfo_record *zinfo ) {
|
||||||
|
struct zinfo_common *common = &zinfo->common;
|
||||||
|
struct zinfo_processor *processor;
|
||||||
|
char type[ sizeof ( common->type ) + 1 ] = "";
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
strncat ( type, common->type, sizeof ( type ) - 1 );
|
||||||
|
for ( i = 0 ; i < ( sizeof ( zinfo_processors ) /
|
||||||
|
sizeof ( zinfo_processors[0] ) ) ; i++ ) {
|
||||||
|
processor = &zinfo_processors[i];
|
||||||
|
if ( strcmp ( processor->type, type ) == 0 )
|
||||||
|
return processor->process ( input, output, zinfo );
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf ( stderr, "Unknown zinfo record type \"%s\"\n", &type[0] );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_output_file ( struct output_file *output ) {
|
||||||
|
if ( fwrite ( output->buf, 1, output->len, stdout ) != output->len ) {
|
||||||
|
fprintf ( stderr, "Could not write %d bytes of output: %s\n",
|
||||||
|
output->len, strerror ( errno ) );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main ( int argc, char **argv ) {
|
||||||
|
struct input_file input;
|
||||||
|
struct output_file output;
|
||||||
|
struct zinfo_file zinfo;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if ( argc != 3 ) {
|
||||||
|
fprintf ( stderr, "Syntax: %s file.bin file.zinfo "
|
||||||
|
"> file.zbin\n", argv[0] );
|
||||||
|
exit ( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( read_input_file ( argv[1], &input ) < 0 )
|
||||||
|
exit ( 1 );
|
||||||
|
if ( read_zinfo_file ( argv[2], &zinfo ) < 0 )
|
||||||
|
exit ( 1 );
|
||||||
|
if ( alloc_output_file ( ( input.len * 4 ), &output ) < 0 )
|
||||||
|
exit ( 1 );
|
||||||
|
|
||||||
|
for ( i = 0 ; i < zinfo.num_entries ; i++ ) {
|
||||||
|
if ( process_zinfo ( &input, &output,
|
||||||
|
&zinfo.zinfo[i] ) < 0 )
|
||||||
|
exit ( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( write_output_file ( &output ) < 0 )
|
||||||
|
exit ( 1 );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Reference in New Issue