123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- #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;
- }
|