You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

zbin.c 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. #include <stdio.h>
  2. #include <sys/stat.h>
  3. #define ENCODE
  4. #define VERBOSE
  5. #include "nrv2b.c"
  6. FILE *infile, *outfile;
  7. #define DEBUG 0
  8. struct input_file {
  9. void *buf;
  10. size_t len;
  11. };
  12. struct output_file {
  13. void *buf;
  14. size_t len;
  15. size_t max_len;
  16. };
  17. struct zinfo_common {
  18. char type[4];
  19. char pad[12];
  20. };
  21. struct zinfo_copy {
  22. char type[4];
  23. uint32_t offset;
  24. uint32_t len;
  25. uint32_t align;
  26. };
  27. struct zinfo_pack {
  28. char type[4];
  29. uint32_t offset;
  30. uint32_t len;
  31. uint32_t align;
  32. };
  33. struct zinfo_add {
  34. char type[4];
  35. uint32_t offset;
  36. uint32_t divisor;
  37. uint32_t pad;
  38. };
  39. union zinfo_record {
  40. struct zinfo_common common;
  41. struct zinfo_copy copy;
  42. struct zinfo_pack pack;
  43. struct zinfo_add add;
  44. };
  45. struct zinfo_file {
  46. union zinfo_record *zinfo;
  47. unsigned int num_entries;
  48. };
  49. static unsigned long align ( unsigned long value, unsigned long align ) {
  50. return ( ( value + align - 1 ) & ~( align - 1 ) );
  51. }
  52. static int read_file ( const char *filename, void **buf, size_t *len ) {
  53. FILE *file;
  54. struct stat stat;
  55. file = fopen ( filename, "r" );
  56. if ( ! file ) {
  57. fprintf ( stderr, "Could not open %s: %s\n", filename,
  58. strerror ( errno ) );
  59. goto err;
  60. }
  61. if ( fstat ( fileno ( file ), &stat ) < 0 ) {
  62. fprintf ( stderr, "Could not stat %s: %s\n", filename,
  63. strerror ( errno ) );
  64. goto err;
  65. }
  66. *len = stat.st_size;
  67. *buf = malloc ( *len );
  68. if ( ! *buf ) {
  69. fprintf ( stderr, "Could not malloc() %d bytes for %s: %s\n",
  70. *len, filename, strerror ( errno ) );
  71. goto err;
  72. }
  73. if ( fread ( *buf, 1, *len, file ) != *len ) {
  74. fprintf ( stderr, "Could not read %d bytes from %s: %s\n",
  75. *len, filename, strerror ( errno ) );
  76. goto err;
  77. }
  78. fclose ( file );
  79. return 0;
  80. err:
  81. if ( file )
  82. fclose ( file );
  83. return -1;
  84. }
  85. static int read_input_file ( const char *filename,
  86. struct input_file *input ) {
  87. return read_file ( filename, &input->buf, &input->len );
  88. }
  89. static int read_zinfo_file ( const char *filename,
  90. struct zinfo_file *zinfo ) {
  91. void *buf;
  92. size_t len;
  93. if ( read_file ( filename, &buf, &len ) < 0 )
  94. return -1;
  95. if ( ( len % sizeof ( *(zinfo->zinfo) ) ) != 0 ) {
  96. fprintf ( stderr, ".zinfo file %s has invalid length %d\n",
  97. filename, len );
  98. return -1;
  99. }
  100. zinfo->zinfo = buf;
  101. zinfo->num_entries = ( len / sizeof ( *(zinfo->zinfo) ) );
  102. return 0;
  103. }
  104. static int alloc_output_file ( size_t max_len, struct output_file *output ) {
  105. output->len = 0;
  106. output->max_len = ( max_len );
  107. output->buf = malloc ( max_len );
  108. if ( ! output->buf ) {
  109. fprintf ( stderr, "Could not allocate %d bytes for output\n",
  110. max_len );
  111. return -1;
  112. }
  113. memset ( output->buf, 0xff, sizeof ( output->buf ) );
  114. return 0;
  115. }
  116. static int process_zinfo_copy ( struct input_file *input,
  117. struct output_file *output,
  118. union zinfo_record *zinfo ) {
  119. struct zinfo_copy *copy = &zinfo->copy;
  120. size_t offset = copy->offset;
  121. size_t len = copy->len;
  122. if ( ( offset + len ) > input->len ) {
  123. fprintf ( stderr, "Input buffer overrun on copy\n" );
  124. return -1;
  125. }
  126. output->len = align ( output->len, copy->align );
  127. if ( ( output->len + len ) > output->max_len ) {
  128. fprintf ( stderr, "Output buffer overrun on copy\n" );
  129. return -1;
  130. }
  131. if ( DEBUG ) {
  132. fprintf ( stderr, "COPY [%#zx,%#zx) to [%#zx,%#zx)\n",
  133. offset, ( offset + len ), output->len,
  134. ( output->len + len ) );
  135. }
  136. memcpy ( ( output->buf + output->len ),
  137. ( input->buf + offset ), len );
  138. output->len += len;
  139. return 0;
  140. }
  141. static int process_zinfo_pack ( struct input_file *input,
  142. struct output_file *output,
  143. union zinfo_record *zinfo ) {
  144. struct zinfo_pack *pack = &zinfo->pack;
  145. size_t offset = pack->offset;
  146. size_t len = pack->len;
  147. unsigned long packed_len;
  148. if ( ( offset + len ) > input->len ) {
  149. fprintf ( stderr, "Input buffer overrun on pack\n" );
  150. return -1;
  151. }
  152. output->len = align ( output->len, pack->align );
  153. if ( output->len > output->max_len ) {
  154. fprintf ( stderr, "Output buffer overrun on pack\n" );
  155. return -1;
  156. }
  157. if ( ucl_nrv2b_99_compress ( ( input->buf + offset ), len,
  158. ( output->buf + output->len ),
  159. &packed_len, 0 ) != UCL_E_OK ) {
  160. fprintf ( stderr, "Compression failure\n" );
  161. return -1;
  162. }
  163. if ( DEBUG ) {
  164. fprintf ( stderr, "PACK [%#zx,%#zx) to [%#zx,%#zx)\n",
  165. offset, ( offset + len ), output->len,
  166. ( output->len + packed_len ) );
  167. }
  168. output->len += packed_len;
  169. if ( output->len > output->max_len ) {
  170. fprintf ( stderr, "Output buffer overrun on pack\n" );
  171. return -1;
  172. }
  173. return 0;
  174. }
  175. static int process_zinfo_add ( struct input_file *input,
  176. struct output_file *output,
  177. struct zinfo_add *add,
  178. size_t datasize ) {
  179. size_t offset = add->offset;
  180. void *target;
  181. signed long addend;
  182. unsigned long size;
  183. signed long val;
  184. unsigned long mask;
  185. if ( ( offset + datasize ) > output->len ) {
  186. fprintf ( stderr, "Add at %#zx outside output buffer\n",
  187. offset );
  188. return -1;
  189. }
  190. target = ( output->buf + offset );
  191. size = ( align ( output->len, add->divisor ) / add->divisor );
  192. switch ( datasize ) {
  193. case 1:
  194. addend = *( ( int8_t * ) target );
  195. break;
  196. case 2:
  197. addend = *( ( int16_t * ) target );
  198. break;
  199. case 4:
  200. addend = *( ( int32_t * ) target );
  201. break;
  202. default:
  203. fprintf ( stderr, "Unsupported add datasize %d\n",
  204. datasize );
  205. return -1;
  206. }
  207. val = size + addend;
  208. /* The result of 1UL << ( 8 * sizeof(unsigned long) ) is undefined */
  209. mask = ( ( datasize < sizeof ( mask ) ) ?
  210. ( ( 1UL << ( 8 * datasize ) ) - 1 ) : ~0UL );
  211. if ( val < 0 ) {
  212. fprintf ( stderr, "Add %s%#lx+%#lx at %#zx %sflows field\n",
  213. ( ( addend < 0 ) ? "-" : "" ), abs ( addend ), size,
  214. offset, ( ( addend < 0 ) ? "under" : "over" ) );
  215. return -1;
  216. }
  217. if ( val & ~mask ) {
  218. fprintf ( stderr, "Add %s%#lx+%#lx at %#zx overflows %d-byte "
  219. "field (%d bytes too big)\n",
  220. ( ( addend < 0 ) ? "-" : "" ), abs ( addend ), size,
  221. offset, datasize,
  222. ( ( val - mask - 1 ) * add->divisor ) );
  223. return -1;
  224. }
  225. switch ( datasize ) {
  226. case 1:
  227. *( ( uint8_t * ) target ) = val;
  228. break;
  229. case 2:
  230. *( ( uint16_t * ) target ) = val;
  231. break;
  232. case 4:
  233. *( ( uint32_t * ) target ) = val;
  234. break;
  235. }
  236. if ( DEBUG ) {
  237. fprintf ( stderr, "ADDx [%#zx,%#zx) (%s%#lx+(%#lx/%#x)) = "
  238. "%#lx\n", offset, ( offset + datasize ),
  239. ( ( addend < 0 ) ? "-" : "" ), abs ( addend ),
  240. output->len, add->divisor, val );
  241. }
  242. return 0;
  243. }
  244. static int process_zinfo_addb ( struct input_file *input,
  245. struct output_file *output,
  246. union zinfo_record *zinfo ) {
  247. return process_zinfo_add ( input, output, &zinfo->add, 1 );
  248. }
  249. static int process_zinfo_addw ( struct input_file *input,
  250. struct output_file *output,
  251. union zinfo_record *zinfo ) {
  252. return process_zinfo_add ( input, output, &zinfo->add, 2 );
  253. }
  254. static int process_zinfo_addl ( struct input_file *input,
  255. struct output_file *output,
  256. union zinfo_record *zinfo ) {
  257. return process_zinfo_add ( input, output, &zinfo->add, 4 );
  258. }
  259. struct zinfo_processor {
  260. char *type;
  261. int ( * process ) ( struct input_file *input,
  262. struct output_file *output,
  263. union zinfo_record *zinfo );
  264. };
  265. static struct zinfo_processor zinfo_processors[] = {
  266. { "COPY", process_zinfo_copy },
  267. { "PACK", process_zinfo_pack },
  268. { "ADDB", process_zinfo_addb },
  269. { "ADDW", process_zinfo_addw },
  270. { "ADDL", process_zinfo_addl },
  271. };
  272. static int process_zinfo ( struct input_file *input,
  273. struct output_file *output,
  274. union zinfo_record *zinfo ) {
  275. struct zinfo_common *common = &zinfo->common;
  276. struct zinfo_processor *processor;
  277. char type[ sizeof ( common->type ) + 1 ] = "";
  278. unsigned int i;
  279. strncat ( type, common->type, sizeof ( type ) - 1 );
  280. for ( i = 0 ; i < ( sizeof ( zinfo_processors ) /
  281. sizeof ( zinfo_processors[0] ) ) ; i++ ) {
  282. processor = &zinfo_processors[i];
  283. if ( strcmp ( processor->type, type ) == 0 )
  284. return processor->process ( input, output, zinfo );
  285. }
  286. fprintf ( stderr, "Unknown zinfo record type \"%s\"\n", &type[0] );
  287. return -1;
  288. }
  289. static int write_output_file ( struct output_file *output ) {
  290. if ( fwrite ( output->buf, 1, output->len, stdout ) != output->len ) {
  291. fprintf ( stderr, "Could not write %d bytes of output: %s\n",
  292. output->len, strerror ( errno ) );
  293. return -1;
  294. }
  295. return 0;
  296. }
  297. int main ( int argc, char **argv ) {
  298. struct input_file input;
  299. struct output_file output;
  300. struct zinfo_file zinfo;
  301. unsigned int i;
  302. if ( argc != 3 ) {
  303. fprintf ( stderr, "Syntax: %s file.bin file.zinfo "
  304. "> file.zbin\n", argv[0] );
  305. exit ( 1 );
  306. }
  307. if ( read_input_file ( argv[1], &input ) < 0 )
  308. exit ( 1 );
  309. if ( read_zinfo_file ( argv[2], &zinfo ) < 0 )
  310. exit ( 1 );
  311. if ( alloc_output_file ( ( input.len * 4 ), &output ) < 0 )
  312. exit ( 1 );
  313. for ( i = 0 ; i < zinfo.num_entries ; i++ ) {
  314. if ( process_zinfo ( &input, &output,
  315. &zinfo.zinfo[i] ) < 0 )
  316. exit ( 1 );
  317. }
  318. if ( write_output_file ( &output ) < 0 )
  319. exit ( 1 );
  320. return 0;
  321. }