1 /*
2 Copyright (C) 2007,2008,2009 Luigi Auriemma
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 http://www.gnu.org/licenses/gpl-2.0.txt
15 */
16
17 #define _LARGE_FILES // if it's not supported the tool will work
18 #define __USE_LARGEFILE64 // without support for large files
19 #define __USE_FILE_OFFSET64
20 #define _LARGEFILE_SOURCE
21 #define _LARGEFILE64_SOURCE
22 #define _FILE_OFFSET_BITS 64
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdint.h>
28 #include <ctype.h>
29 #include <zlib.h>
30 #include "des.h"
31 #include "LzmaDec.h"
32 #include "Bra.h"
33
34 #ifdef __DJGPP__ // thanx to Robert Riebisch http://www.bttr-software.de
35 #define NOLFS
__crt0_glob_function(char * arg)36 char **__crt0_glob_function (char *arg) { return 0; }
__crt0_load_environment_file(char * progname)37 void __crt0_load_environment_file (char *progname) { }
38 #endif
39
40 #ifdef WIN32
41 #include <windows.h>
42 HWND mywnd;
43 char *get_file(void);
44 char *put_file(char *suggested);
45 #else
46 #define stricmp strcasecmp
47 #endif
48
49 typedef uint8_t u8;
50 typedef uint16_t u16;
51 typedef int32_t i32;
52 typedef uint32_t u32;
53 typedef int64_t i64;
54 typedef uint64_t u64;
55
56
57
58 #define VER "0.1.7c"
59 #define BBIS_SIGN 0x73696262
60 #define BLHR_SIGN 0x72686c62
61 #define BSDR_SIGN 0x72647362
62 #define BLMS_SIGN 0x736d6c62
63 #define BLSS_SIGN 0x73736c62
64 #define OUT_ISO 0
65 #define OUT_CUE 1
66 #define OUT_MDS 2
67 #define OUT_CCD 3
68 #define OUT_NRG 4
69
70 #define CREATECUE // creates an additional and "experimental" CUE file which can be used also on systems where are not available programs for the other formats
71 #define NRGFIX // calls nrg_truncate at the end of the process
72
73 #define PRINTF64(x) (u32)(((x) >> 32) & 0xffffffff), (u32)((x) & 0xffffffff) // I64x, llx? blah
74 #if defined(_LARGE_FILES)
75 #if defined(__APPLE__)
76 #define fseek fseeko
77 #define ftell ftello
78 #elif defined(__FreeBSD__) || defined(__DragonFly__)
79 #elif !defined(NOLFS) // use -DNOLFS if this tool can't be compiled on your OS!
80 #define off_t off64_t
81 #define fopen fopen64
82 #define fseek fseeko64
83 #define ftell ftello64
84 #endif
85 #endif
86
87
88
89 #pragma pack(1)
90
91 typedef struct {
92 u8 id[4];
93 u32 size;
94 } nrg_chunk_t;
95
96 typedef struct {
97 u32 sign; // blhr
98 u32 size; // size of the data plus ver and num
99 u32 compressed; // compressed data
100 u32 num; // number of blhr_data structures
101 } blhr_t;
102
103 typedef struct {
104 u64 offset; // input offset
105 u32 zsize; // block size
106 u32 sector; // where to place the output
107 u32 size; // size in sectors!
108 u32 type; // type
109 } blhr_data_t;
110
111 typedef struct {
112 u32 sign; // bbis
113 u32 bbis_size; // ignored, probably the size of the structure
114 u16 ver; // version, 1
115 u16 image_type; // 8 for ISO, 9 for mixed
116 u16 unknown1; // ???
117 u16 padding; // ignored
118 u32 sectors; // number of sectors of the ISO
119 u32 sectorsz; // CD use sectors and this is the size of them (chunks)
120 u32 lastdiff; // almost ignored
121 u64 blhr; // where is located the blhr header
122 u32 blhrbbissz; // total size of the blhr and bbis headers
123 u8 hash[16]; // hash, used with passwords
124 u8 key1;
125 u8 key2;
126 u8 key3;
127 u8 key4;
128 u32 unknown4; // ignored
129 } bbis_t;
130
131 #pragma pack()
132
133
134
135 int endian;
136
137
138
139 void myfree(u8 **mem);
140 u8 *path2fname(u8 *path);
141 u8 *frames2time(u64 num);
142 void nrg2cue(FILE *fd, u64 nrgoff, u8 *fileo);
143 void magiciso_is_invalid(FILE *fd, u64 nrgoff, u8 *fileo);
144 void nrg_truncate(u8 *fileo, int secsz);
145 u8 *blhr_unzip(FILE *fd, z_stream *z, CLzmaDec *lzma, des_context *des_ctx, u32 zsize, u32 unzsize, int compressed);
146 u8 *change_ext(u8 *fname, u8 *ext);
147 FILE *open_file(u8 *fname, int write);
148 int blms2cue(FILE *fd, u8 *fname, u8 *blms, int blms_len);
149 void uif_crypt_key(des_context **des_ctx, u8 *key, u8 *pwd);
150 void uif_crypt(des_context *des_ctx, u8 *data, int size);
151 u8 *show_hash(u8 *hash);
152 void myalloc(u8 **data, unsigned wantsize, unsigned *currsize);
153 void myfr(FILE *fd, void *data, unsigned size);
154 void myfw(FILE *fd, void *data, unsigned size);
155 u32 unlzma(CLzmaDec *lzma, u8 *in, u32 insz, u8 *out, u32 outsz);
156 u32 unzip(z_stream *z, u8 *in, u32 insz, u8 *out, u32 outsz);
157 void l2n_blhr(blhr_t *p);
158 void l2n_blhr_data(blhr_data_t *p);
159 void l2n_bbis(bbis_t *p);
160 void l2n_16(u16 *num); // from little endian to number
161 void l2n_32(u32 *num);
162 void l2n_64(u64 *num);
163 void b2n_16(u16 *num); // from big endian to number
164 void b2n_32(u32 *num);
165 void b2n_64(u64 *num);
166 int getxx(u8 *data, u64 *ret, int bits, int intnet);
167 int putxx(u8 *data, u64 num, int bits, int intnet);
168 void std_err(void);
169 int fgetz(u8 *data, int size, FILE *fd);
170 void myexit(void);
171 #include "magiciso_is_shit.h"
172
SzAlloc(void * p,size_t size)173 static void *SzAlloc(void *p, size_t size) { return(malloc(size)); }
SzFree(void * p,void * address)174 static void SzFree(void *p, void *address) { free(address); }
175 static ISzAlloc g_Alloc = { SzAlloc, SzFree };
176
177
178
179 magiciso_is_shit_ctx_t *shit_key_blhr = NULL,
180 *shit_key_data = NULL;
181 static const u8 *fixedkeys[] = {
182 "FAngS)snOt32", "AglEy29TarsI;", "bum87OrYx*THeCa", "ARMy67sabot&",
183 "FoOTs:blaZe70", "panIc+elD%self79", "Usnea*hest98", "apex(TUft!BLOKE70",
184 "sword18rEpP}", "ARb10naVY=Rouse", "PAIR18gAG:swAYs", "gums}Box73yANg",
185 "naVal45drain]", "Cams42hEt83faiLs)", "rIaNt$Notch5", "ExaCT&art*MEteS47",
186 NULL
187 };
188
189
190
main(int argc,char * argv[])191 int main(int argc, char *argv[]) {
192 des_context *des_ctx = NULL;
193 CLzmaDec *lzma = NULL;
194 z_stream *z = NULL;
195 blhr_data_t *blhr_data;
196 blhr_t blhr,
197 blms, // both blms and blss have a structure very similar to blhr so I have decided
198 blss; // to use the same type for avoiding to create other functions
199 bbis_t bbis;
200 FILE *fdi = NULL,
201 *fdo = NULL,
202 *fdx = NULL;
203 u64 file_size,
204 tmp,
205 tot;
206 u32 i,
207 insz,
208 outsz,
209 lastdiff = 0;
210 int outtype = OUT_ISO;
211 u8 ans[130], // password is max 31 chars
212 pwdkey[32], // password is max 31 chars
213 tmphash[16],
214 *blms_data = NULL,
215 *blss_data = NULL,
216 *outext = NULL,
217 *filei = NULL,
218 *fileo = NULL,
219 *filec = NULL,
220 *in = NULL,
221 *out = NULL,
222 *p;
223
224 setbuf(stdout, NULL);
225
226 fputs("\n"
227 "UIF2ISO "VER"\n"
228 "by Luigi Auriemma\n"
229 "e-mail: aluigi@autistici.org\n"
230 "web: aluigi.org\n"
231 "\n", stdout);
232
233 endian = 1; // big endian
234 if(*(char *)&endian) endian = 0; // little endian
235
236 #ifdef WIN32
237 mywnd = GetForegroundWindow();
238 if(GetWindowLong(mywnd, GWL_WNDPROC)) {
239 p = argv[1];
240 argv = malloc(sizeof(char *) * 3);
241 if(argc < 2) {
242 argv[1] = get_file();
243 } else {
244 argv[1] = p;
245 }
246 argv[2] = put_file(argv[1]);
247 argc = 3;
248 }
249 #endif
250
251 if(argc < 3) {
252 printf("\n"
253 "Usage: %s <input.UIF> <output>\n"
254 "\n"
255 "The output ISO,CUE/BIN,MDS/MDS,CCD,NRG extension is selected by this tool\n"
256 "\n", argv[0]);
257 myexit();
258 }
259
260 filei = argv[1];
261 fileo = argv[2];
262
263 fdi = open_file(filei, 0);
264
265 fseek(fdi, 0, SEEK_END);
266 file_size = ftell(fdi);
267 if(fseek(fdi, file_size - sizeof(bbis), SEEK_SET)) {
268 if(((file_size - sizeof(bbis)) > 0x7fffffff) && ((file_size - sizeof(bbis)) < file_size)) printf(" an error here means that your exe has no full LARGE_FILES 64 bit support!\n");
269 std_err();
270 }
271 myfr(fdi, &bbis, sizeof(bbis));
272 redo_bbis:
273 l2n_bbis(&bbis);
274 if(bbis.sign != BBIS_SIGN) {
275 printf("\nError: wrong bbis signature (%08x)\n", bbis.sign);
276 myexit();
277 }
278 if(des_ctx) bbis.blhr += sizeof(bbis) + 8;
279
280 printf("\n"
281 " file size %08x%08x\n"
282 " version %hu\n"
283 " image type %hu\n"
284 " padding %hu\n"
285 " sectors %u\n"
286 " sectors size %u\n"
287 " blhr offset %08x%08x\n"
288 " blhr size %u\n"
289 " hash %s\n"
290 " others %08x %08x %02x %02x %02x %02x %08x\n"
291 "\n",
292 PRINTF64(file_size),
293 bbis.ver,
294 bbis.image_type,
295 bbis.padding,
296 bbis.sectors,
297 bbis.sectorsz,
298 PRINTF64(bbis.blhr),
299 bbis.blhrbbissz,
300 show_hash(bbis.hash),
301 bbis.bbis_size, bbis.lastdiff, bbis.key1, bbis.key2, bbis.key3, bbis.key4, bbis.unknown4);
302
303 if((bbis.ver < 2) || ((bbis.key2 != 2) && (bbis.key1 > 0x10))) {
304 printf("- disable any encryption\n");
305 bbis.key1 = 0;
306 }
307 if(bbis.key2 == 2) {
308 printf("- enable magiciso_is_shit encryption\n");
309 shit_key_blhr = calloc(1, sizeof(magiciso_is_shit_ctx_t));
310 shit_key_data = calloc(1, sizeof(magiciso_is_shit_ctx_t));
311 if(!shit_key_blhr || !shit_key_data) std_err();
312
313 shit_key_blhr->flag = (bbis.key3 != 1) ? 0xff : bbis.key1;
314 magiciso_is_shit_key(shit_key_blhr, bbis.key3);
315
316 shit_key_data->flag = (bbis.key3 != 0x0f) ? bbis.key1 : 0;
317 magiciso_is_shit_key(shit_key_data, bbis.key3);
318 } else if(bbis.key1) {
319 printf("- enable fixedkey encryption\n");
320 uif_crypt_key(&des_ctx, pwdkey, (u8 *)fixedkeys[(bbis.key1 - 1) & 0x0f]);
321 des_setkey_dec(des_ctx, pwdkey);
322 }
323
324 if(fseek(fdi, bbis.blhr, SEEK_SET)) std_err();
325 myfr(fdi, &blhr, sizeof(blhr));
326 l2n_blhr(&blhr);
327 if(blhr.sign != BLHR_SIGN) {
328 if(blhr.sign == BSDR_SIGN) {
329 printf("- the input file is protected by password, insert it: ");
330 fgetz(ans, sizeof(ans), stdin);
331 if(strlen(ans) > 31) ans[31] = 0;
332
333 uif_crypt_key(&des_ctx, pwdkey, ans);
334 des_setkey_dec(des_ctx, pwdkey);
335
336 if(blhr.size != sizeof(bbis)) {
337 printf("- Alert: the size of the bbis struct and the one specified by bsdr don't match\n");
338 }
339 fseek(fdi, -8, SEEK_CUR);
340 memcpy(tmphash, bbis.hash, sizeof(bbis.hash));
341 myfr(fdi, &bbis, sizeof(bbis));
342 uif_crypt(des_ctx, (u8 *)&bbis, sizeof(bbis));
343 memcpy(bbis.hash, tmphash, sizeof(bbis.hash));
344 goto redo_bbis;
345 } else {
346 printf("\nError: wrong blhr signature (%08x)\n", blhr.sign);
347 }
348 myexit();
349 }
350
351 if(bbis.ver < 3) {
352 z = malloc(sizeof(z_stream));
353 if(!z) std_err();
354 z->zalloc = (alloc_func)0;
355 z->zfree = (free_func)0;
356 z->opaque = (voidpf)0;
357 if(inflateInit2(z, 15)) {
358 printf("\nError: zlib initialization error\n");
359 myexit();
360 }
361 } else {
362 lzma = malloc(sizeof(CLzmaDec));
363 if(!lzma) std_err();
364 }
365 blhr_data = (blhr_data_t *)blhr_unzip(fdi, z, lzma, des_ctx, blhr.size - 8, sizeof(blhr_data_t) * blhr.num, blhr.compressed);
366
367 if(bbis.image_type == 8) {
368 // nothing to do
369 } else if(bbis.image_type == 9) {
370 printf("- raw or mixed type image\n");
371
372 myfr(fdi, &blms, sizeof(blms));
373 l2n_blhr(&blms);
374 if(blms.sign != BLMS_SIGN) {
375 printf("- Alert: wrong blms signature (%08x)\n", blms.sign);
376 } else {
377 blms_data = blhr_unzip(fdi, z, lzma, des_ctx, blms.size - 8, blms.num, blms.compressed);
378
379 myfr(fdi, &blss, sizeof(blss));
380 myfr(fdi, &outtype, 4);
381 l2n_blhr(&blss);
382 l2n_32(&outtype);
383 if(blss.sign != BLSS_SIGN) {
384 printf("- Alert: wrong blss signature (%08x)\n", blss.sign);
385 } else {
386 if(blss.num) {
387 blss_data = blhr_unzip(fdi, z, lzma, des_ctx, blss.size - 12, blss.num, blss.compressed);
388 }
389 }
390 }
391 } else {
392 printf("- Alert: this type of image (%hu) is not supported by this tool, I try as ISO\n", bbis.image_type);
393 }
394
395 in = out = NULL;
396 insz = outsz = 0;
397 tot = 0;
398
399 switch(outtype) {
400 case OUT_ISO: {
401 printf("- ISO output image format\n");
402 outext = ".iso";
403 break;
404 }
405 case OUT_CUE: {
406 printf("- BIN/CUE output image format\n");
407 outext = ".bin";
408 break;
409 }
410 case OUT_MDS: {
411 printf("- MDS output image format\n");
412 outext = ".mdf";
413 break;
414 }
415 case OUT_CCD: {
416 printf("- CCD (CloneCD) output image format\n");
417 outext = ".img";
418 break;
419 }
420 case OUT_NRG: {
421 printf("- NRG (Nero v2) output image format\n");
422 outext = ".nrg";
423 break;
424 }
425 default: {
426 printf("\nError: the output image %u is not supported by this tool, contact me\n", outtype);
427 myexit();
428 break;
429 }
430 }
431 fileo = change_ext(fileo, outext);
432 fdo = open_file(fileo, 1);
433
434 #ifdef CREATECUE
435 if(outtype != OUT_ISO) { // I generate a CUE file in ANY case for maximum compatibility
436 printf("- generate an \"experimental\" CUE file for more compatibility on various systems\n");
437 filec = change_ext(fileo, "_uif2iso.cue");
438 fdx = open_file(filec, 1);
439 blms2cue(fdx, path2fname(fileo), blms_data, blms.num);
440 fclose(fdx);
441 myfree(&filec);
442 }
443 #endif
444
445 if(blss_data) {
446 switch(outtype) {
447 case OUT_ISO: {
448 break;
449 }
450 case OUT_CUE: {
451 filec = change_ext(fileo, ".cue");
452 fdx = open_file(filec, 1);
453 myfw(fdx, blss_data, blss.num);
454 fclose(fdx);
455 myfree(&filec);
456 break;
457 }
458 case OUT_MDS: {
459 filec = change_ext(fileo, ".mds");
460 fdx = open_file(filec, 1);
461 myfw(fdx, blss_data, blss.num);
462 fclose(fdx);
463 myfree(&filec);
464 break;
465 }
466 case OUT_CCD: {
467 p = blss_data + 8;
468 getxx(blss_data, &tmp, 32, 0);
469
470 filec = change_ext(fileo, ".ccd");
471 fdx = open_file(filec, 1);
472 myfw(fdx, p, tmp);
473 fclose(fdx);
474 myfree(&filec);
475
476 p += tmp;
477 getxx(blss_data + 4, &tmp, 32, 0);
478
479 filec = change_ext(fileo, ".sub");
480 fdx = open_file(filec, 1);
481 myfw(fdx, p, tmp);
482 fclose(fdx);
483 myfree(&filec);
484 break;
485 }
486 case OUT_NRG: {
487 break;
488 }
489 default: break; // handled previously
490 }
491 }
492
493 printf("- start unpacking:\n");
494 for(i = 0; i < blhr.num; i++) {
495 l2n_blhr_data(&blhr_data[i]);
496
497 printf(" %03d%%\r", (i * 100) / blhr.num);
498
499 #ifdef VERBOSE
500 printf("\n"
501 "offset %08x%08x\n"
502 "input size %08x\n"
503 "output sector %08x\n"
504 "sectors %08x\n"
505 "type %08x\n",
506 PRINTF64(blhr_data[i].offset),
507 blhr_data[i].zsize,
508 blhr_data[i].sector,
509 blhr_data[i].size,
510 blhr_data[i].type);
511 #endif
512
513 myalloc(&in, blhr_data[i].zsize, &insz);
514
515 if(blhr_data[i].zsize) {
516 if(fseek(fdi, blhr_data[i].offset, SEEK_SET)) std_err();
517 myfr(fdi, in, blhr_data[i].zsize);
518 magiciso_is_shit_dec(shit_key_data, in, blhr_data[i].zsize);
519 uif_crypt(des_ctx, in, blhr_data[i].zsize);
520 }
521
522 if(bbis.lastdiff && ((blhr_data[i].sector + blhr_data[i].size) >= bbis.sectors)) {
523 lastdiff = bbis.sectorsz - bbis.lastdiff;
524 }
525
526 blhr_data[i].size *= bbis.sectorsz;
527 myalloc(&out, blhr_data[i].size, &outsz);
528
529 switch(blhr_data[i].type) {
530 case 1: { // non compressed
531 if(blhr_data[i].zsize > blhr_data[i].size) {
532 printf("\nError: input size is bigger than output\n");
533 myexit();
534 }
535 memcpy(out, in, blhr_data[i].zsize);
536 if(blhr_data[i].zsize < blhr_data[i].size) {
537 memset(out + blhr_data[i].zsize, 0, blhr_data[i].size - blhr_data[i].zsize); // needed?
538 }
539 break;
540 }
541 case 3: { // multi byte
542 memset(out, 0, blhr_data[i].size);
543 break;
544 }
545 case 5: { // compressed
546 unlzma(lzma, in, blhr_data[i].zsize, out, blhr_data[i].size);
547 unzip(z, in, blhr_data[i].zsize, out, blhr_data[i].size);
548 break;
549 }
550 default: {
551 printf("\nError: unknown type (%d)\n", blhr_data[i].type);
552 myexit();
553 }
554 }
555
556 if(fseek(fdo, (u64)blhr_data[i].sector * (u64)bbis.sectorsz, SEEK_SET)) std_err();
557 if(lastdiff) {
558 blhr_data[i].size -= lastdiff; // remove the superflous bytes at the end
559 lastdiff = 0;
560 }
561 myfw(fdo, out, blhr_data[i].size);
562 tot += blhr_data[i].size;
563 }
564
565 printf(" 100%%\n"
566 "- 0x%08x%08x bytes written\n", PRINTF64(tot));
567
568 fclose(fdi);
569 fclose(fdo);
570 if(z) {
571 inflateEnd(z);
572 myfree((void *)&z);
573 }
574 if(lzma) {
575 myfree((void *)&lzma);
576 }
577 magiciso_is_shit_free(shit_key_blhr);
578 magiciso_is_shit_free(shit_key_data);
579 if(des_ctx) myfree((void *)&des_ctx);
580
581 if(outtype == OUT_NRG) {
582 printf(
583 "\n"
584 " Please keep in mind that MagicISO creates INVALID NRG files which not only\n"
585 " are unreadable by the various burners/mounters/converters for this type of\n"
586 " image but also by the same Nero which owns the original NRG format, so if the\n"
587 " output NRG file doesn't work is enough \"normal\".\n"
588 "\n");
589 #ifdef NRGFIX
590 printf(
591 " This is the reason why this tool will create an additional CUE file which can\n"
592 " be used in case the NRG one doesn't work. If you are trying to mount the CUE\n"
593 " file but it gives errors or you see no data try to enable all the emulation\n"
594 " options of your mounting program and it will work perfectly.\n"
595 "\n");
596 nrg_truncate(fileo, bbis.sectorsz * 2); // max 1 sector plus another one if NER5 is not in the last one
597 #endif
598 }
599
600 printf("- finished\n");
601 myexit();
602 return(0);
603 }
604
605
606
607 #ifdef WIN32
get_file(void)608 char *get_file(void) {
609 OPENFILENAME ofn;
610 static char filename[4096];
611 static const char filter[] =
612 "UIF file\0" "*.uif\0"
613 "(*.*)\0" "*.*\0"
614 "\0" "\0";
615
616 filename[0] = 0;
617 memset(&ofn, 0, sizeof(ofn));
618 ofn.lStructSize = sizeof(ofn);
619 ofn.lpstrFilter = filter;
620 ofn.nFilterIndex = 1;
621 ofn.lpstrFile = filename;
622 ofn.nMaxFile = sizeof(filename);
623 ofn.lpstrTitle = "select the input UIF file to convert";
624 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_LONGNAMES | OFN_EXPLORER | OFN_HIDEREADONLY;
625
626 printf("- %s\n", ofn.lpstrTitle);
627 if(!GetOpenFileName(&ofn)) exit(0);
628 return(filename);
629 }
630
put_file(char * suggested)631 char *put_file(char *suggested) {
632 OPENFILENAME ofn;
633 char *p;
634 static char filename[4096 + 10];
635 static const char filter[] =
636 "image file\0" "*.iso;*.cue;*.bin;*.mds;*.mdf;*.ccd;*.img;*.sub;*.nrg\0"
637 "(*.*)\0" "*.*\0"
638 "\0" "\0";
639
640 if(!suggested) {
641 filename[0] = 0;
642 } else {
643 p = strrchr(suggested, '.');
644 if(!p) p = suggested + strlen(suggested);
645 if((p - suggested) >= 4096) p = suggested + 4096 - 1;
646 memcpy(filename, suggested, p - suggested);
647 filename[p - suggested] = 0;
648 }
649 memset(&ofn, 0, sizeof(ofn));
650 ofn.lStructSize = sizeof(ofn);
651 ofn.lpstrFilter = filter;
652 ofn.nFilterIndex = 1;
653 ofn.lpstrFile = filename;
654 ofn.nMaxFile = sizeof(filename);
655 ofn.lpstrTitle = "choose the name of the output file to create (the extension is automatic)";
656 ofn.Flags = OFN_PATHMUSTEXIST | OFN_LONGNAMES | OFN_EXPLORER | OFN_HIDEREADONLY;
657
658 printf("- %s\n", ofn.lpstrTitle);
659 if(!GetSaveFileName(&ofn)) exit(0);
660 return(filename);
661 }
662 #endif
663
664
665
myfree(u8 ** mem)666 void myfree(u8 **mem) {
667 if(*mem) {
668 free(*mem);
669 *mem = NULL;
670 }
671 }
672
673
674
path2fname(u8 * path)675 u8 *path2fname(u8 *path) {
676 u8 *p;
677
678 p = strrchr(path, '\\');
679 if(!p) p = strrchr(path, '/');
680 if(p) return(p + 1);
681 return(path);
682 }
683
684
685
frames2time(u64 num)686 u8 *frames2time(u64 num) {
687 int mm,
688 ss,
689 ff;
690 static u8 ret_time[32];
691
692 num /= 2352; // default sector size
693 ff = num % 75;
694 ss = (num / 75) % 60;
695 mm = (num / 75) / 60;
696 sprintf(ret_time, "%02d:%02d:%02d", mm, ss, ff);
697 return(ret_time);
698 }
699
700
701
nrg2cue(FILE * fd,u64 nrgoff,u8 * fileo)702 void nrg2cue(FILE *fd, u64 nrgoff, u8 *fileo) {
703 nrg_chunk_t chunk;
704 FILE *fdcue = NULL,
705 *fdcdt = NULL;
706 u64 index0,
707 index1,
708 index2;
709 u32 sectsz,
710 mode;
711 int i,
712 numsz,
713 track,
714 firstindex = 1;
715 u8 *filec = NULL,
716 *filecdt = NULL,
717 *buff = NULL,
718 *p,
719 *l;
720
721 if(fseek(fd, nrgoff, SEEK_SET)) {
722 printf("- Alert: wrong NRG header offset\n");
723 return;
724 }
725
726 printf("- generate a new CUE file derived from the NRG one\n");
727 filec = change_ext(fileo, "_nrg.cue");
728 fdcue = open_file(filec, 1);
729 fprintf(fdcue, "FILE \"%s\" BINARY\r\n", path2fname(fileo));
730
731 track = 1;
732 for(;;) { // get tracks and do more things
733 myfr(fd, &chunk, sizeof(chunk));
734 b2n_32(&chunk.size);
735 if(!memcmp(chunk.id, "NER5", 4) || !memcmp(chunk.id, "NERO", 4)) break;
736 if(!memcmp(chunk.id, "DAOX", 4) || !memcmp(chunk.id, "DAOI", 4)) {
737 if(chunk.size >= 22) {
738 buff = malloc(chunk.size);
739 if(!buff) std_err();
740 myfr(fd, buff, chunk.size);
741
742 numsz = (!memcmp(chunk.id, "DAOX", 4)) ? 8 : 4;
743
744 p = buff + 22;
745 l = buff + chunk.size - (4 + 4 + (numsz * 3));
746 for(i = 0; p <= l; i++) {
747 p += 10;
748 sectsz = *(u32 *)p; p += 4;
749 b2n_32(§sz);
750 mode = p[0]; p += 4;
751 p += getxx(p, &index0, numsz << 3, 1);
752 p += getxx(p, &index1, numsz << 3, 1);
753 p += getxx(p, &index2, numsz << 3, 1);
754 #ifdef VERBOSE
755 printf(" %08x %02x %08x%08x %08x%08x %08x%08x\n", sectsz, mode, PRINTF64(index0), PRINTF64(index1), PRINTF64(index2));
756 #endif
757 switch(mode) {
758 // case 2: yes, this is data mode 2 BUT the CUE will give an error if you use this mode!
759 case 3: fprintf(fdcue, " TRACK %02d MODE2/%u\r\n", track, sectsz); break;
760 case 7: fprintf(fdcue, " TRACK %02d AUDIO\r\n", track); break;
761 case 0:
762 default:fprintf(fdcue, " TRACK %02d MODE1/%u\r\n", track, sectsz); break;
763 }
764 if(firstindex) {
765 fprintf(fdcue, " INDEX 00 00:00:00\r\n");
766 firstindex = 0;
767 } else if(index1 > index0) {
768 fprintf(fdcue, " INDEX 00 %s\r\n", frames2time(index0));
769 }
770 fprintf(fdcue, " INDEX 01 %s\r\n", frames2time(index1));
771 track++;
772 }
773
774 myfree(&buff);
775 continue;
776 }
777 }
778 if(!memcmp(chunk.id, "ETN2", 4) || !memcmp(chunk.id, "ETNF", 4)) {
779 if(chunk.size >= 22) {
780 buff = malloc(chunk.size);
781 if(!buff) std_err();
782 myfr(fd, buff, chunk.size);
783
784 numsz = (!memcmp(chunk.id, "ETN2", 4)) ? 8 : 4;
785
786 sectsz = 2352; // right???
787 p = buff;
788 l = buff + chunk.size - ((numsz * 2) + 4 + 4 + 4);
789 for(i = 0; p <= l; i++) {
790 p += getxx(p, &index1, numsz << 3, 1);
791 p += getxx(p, &index2, numsz << 3, 1);
792 mode = p[0]; p += 4;
793 p += 4 + 4;
794 #ifdef VERBOSE
795 printf(" %02x %08x%08x %08x%08x\n", mode, PRINTF64(index1), PRINTF64(index2));
796 #endif
797 switch(mode) {
798 case 3: fprintf(fdcue, " TRACK %02d MODE2/%u\r\n", track, sectsz); break;
799 case 7: fprintf(fdcue, " TRACK %02d AUDIO\r\n", track); break;
800 case 0:
801 default:fprintf(fdcue, " TRACK %02d MODE1/%u\r\n", track, sectsz); break;
802 }
803 if(!i) fprintf(fdcue, " INDEX 00 00:00:00\r\n");
804 fprintf(fdcue, " INDEX 01 %s\r\n", frames2time(index1));
805 track++;
806 }
807
808 myfree(&buff);
809 continue;
810 }
811 }
812 if(!memcmp(chunk.id, "CDTX", 4)) {
813 buff = malloc(chunk.size);
814 if(!buff) std_err();
815 myfr(fd, buff, chunk.size);
816
817 filecdt = change_ext(fileo, ".cdt");
818 fdcdt = open_file(filecdt, 1);
819 myfw(fdcdt, buff, chunk.size);
820 fclose(fdcdt);
821
822 fprintf(fdcue, "CDTEXTFILE \"%s\"\r\n", path2fname(filecdt));
823 myfree(&buff);
824 continue;
825 }
826 if(fseek(fd, chunk.size, SEEK_CUR)) break;
827 }
828 fclose(fdcue);
829 }
830
831
832
magiciso_is_invalid(FILE * fd,u64 nrgoff,u8 * fileo)833 void magiciso_is_invalid(FILE *fd, u64 nrgoff, u8 *fileo) {
834 nrg_chunk_t chunk;
835 u64 index2;
836 int numsz,
837 track;
838 u8 tracks, // can't be more than 8bit
839 *buff = NULL;
840
841 if(fseek(fd, nrgoff, SEEK_SET)) {
842 printf("- Alert: wrong NRG header offset\n");
843 return;
844 }
845
846 track = 1;
847 tracks = 1;
848 for(;;) { // get tracks and do more things
849 myfr(fd, &chunk, sizeof(chunk));
850 b2n_32(&chunk.size);
851 if(!memcmp(chunk.id, "NER5", 4) || !memcmp(chunk.id, "NERO", 4)) break;
852 if(!memcmp(chunk.id, "DAOX", 4) || !memcmp(chunk.id, "DAOI", 4)) {
853 if(chunk.size >= 22) {
854 buff = malloc(chunk.size);
855 if(!buff) std_err();
856 myfr(fd, buff, chunk.size);
857
858 tracks = (buff[21] - buff[20]) + 1;
859 numsz = (!memcmp(chunk.id, "DAOX", 4)) ? 8 : 4;
860 getxx(buff + chunk.size - numsz, &index2, numsz << 3, 1);
861 if(index2 > nrgoff) {
862 putxx(buff + chunk.size - numsz, nrgoff, numsz << 3, 1);
863 printf("- correcting last DAO index2\n");
864 fseek(fd, -numsz, SEEK_CUR);
865 myfw(fd, buff + chunk.size - numsz, numsz);
866 fflush(fd); // you can't imagine how much required is this fflush...
867 }
868
869 myfree(&buff);
870 continue; // skip the fseek chunk.size stuff made at each cycle
871 }
872 }
873 if(!memcmp(chunk.id, "SINF", 4)) { // usually located after DAO
874 if(chunk.size >= 4) {
875 if(fseek(fd, 3, SEEK_CUR)) break;
876 printf("- correcting SINF to %u tracks\n", tracks);
877 myfw(fd, &tracks, 1);
878 fflush(fd); // you can't imagine how much required is this fflush...
879 fseek(fd, -4, SEEK_CUR); // restore
880 }
881 }
882 if(fseek(fd, chunk.size, SEEK_CUR)) break;
883 }
884 }
885
886
887
nrg_truncate(u8 * fileo,int secsz)888 void nrg_truncate(u8 *fileo, int secsz) {
889 FILE *fd = NULL;
890 u64 truncsize,
891 realsize,
892 nrgoff;
893 int truncseek;
894 u8 *buff = NULL,
895 *p;
896
897 fd = fopen(fileo, "r+b");
898 if(!fd) return;
899
900 fflush(fd);
901 fseek(fd, 0, SEEK_END);
902 realsize = ftell(fd);
903
904 if(!fseek(fd, -secsz, SEEK_END)) {
905 buff = malloc(secsz);
906 if(!buff) std_err();
907 myfr(fd, buff, secsz);
908 for(p = buff + secsz - 12; p >= buff; p--) {
909 if(!memcmp(p, "NER5", 4)) {
910 nrgoff = *(u64 *)(p + 4);
911 p += 12;
912 break;
913 }
914 if(!memcmp(p, "NERO", 4)) {
915 nrgoff = *(u32 *)(p + 4);
916 p += 8;
917 break;
918 }
919 }
920 if(p >= buff) {
921 truncseek = -(secsz - (p - buff));
922
923 b2n_64(&nrgoff);
924 magiciso_is_invalid(fd, nrgoff, fileo);
925 nrg2cue(fd, nrgoff, fileo);
926
927 fseek(fd, truncseek, SEEK_END);
928 fflush(fd);
929 truncsize = ftell(fd);
930 if(realsize != truncsize) {
931 printf("- found NRG end of file at offset 0x%08x%08x\n", PRINTF64(truncsize));
932 ftruncate(fileno(fd), truncsize); // trick to spawn errors or warnings if there is no large file support
933 fflush(fd);
934 fclose(fd);
935
936 fd = fopen(fileo, "rb"); // verify if the truncation was correct
937 if(!fd) return;
938 fseek(fd, 0, SEEK_END);
939 realsize = ftell(fd);
940 if(realsize < truncsize) {
941 printf("\n"
942 "Error: the truncated file is smaller than how much I requested\n"
943 " is possible that ftruncate() doesn't support large files\n"
944 " Please contact me reporting also the sizeo of the UIF and your platform\n");
945 } else if(realsize != truncsize) {
946 printf("- Alert: seems that the file has not been truncated to the correct NRG size\n");
947 }
948 }
949 }
950 myfree(&buff);
951 }
952 fclose(fd);
953 }
954
955
956
blhr_unzip(FILE * fd,z_stream * z,CLzmaDec * lzma,des_context * des_ctx,u32 zsize,u32 unzsize,int compressed)957 u8 *blhr_unzip(FILE *fd, z_stream *z, CLzmaDec *lzma, des_context *des_ctx, u32 zsize, u32 unzsize, int compressed) {
958 static int insz = 0;
959 static u8 *in = NULL;
960 u8 *data;
961
962 if(compressed) {
963 myalloc(&in, zsize, &insz);
964 myfr(fd, in, zsize);
965 magiciso_is_shit_dec(shit_key_blhr, in, zsize);
966 if(des_ctx) uif_crypt(des_ctx, in, zsize);
967 data = malloc(unzsize);
968 if(!data) std_err();
969 unlzma(lzma, in, zsize, (u8 *)data, unzsize);
970 unzip(z, in, zsize, (u8 *)data, unzsize);
971 } else {
972 data = malloc(unzsize);
973 if(!data) std_err();
974 myfr(fd, data, unzsize);
975 magiciso_is_shit_dec(shit_key_blhr, data, unzsize);
976 }
977 return(data);
978 }
979
980
981
change_ext(u8 * fname,u8 * ext)982 u8 *change_ext(u8 *fname, u8 *ext) {
983 u8 *p;
984
985 p = malloc(strlen(fname) + strlen(ext) + 1);
986 if(!p) std_err();
987 strcpy(p, fname);
988 fname = p;
989 p = strrchr(fname, '.');
990 if(!p || (p && (strlen(p) != 4))) p = fname + strlen(fname);
991 strcpy(p, ext);
992 return(fname);
993 }
994
995
996
open_file(u8 * fname,int write)997 FILE *open_file(u8 *fname, int write) {
998 FILE *fd = NULL;
999 u8 ans[16];
1000
1001 if(write) {
1002 printf("- create %s\n", fname);
1003 fd = fopen(fname, "rb");
1004 if(fd) {
1005 fclose(fd);
1006 printf("- the output file already exists, do you want to overwrite it (y/N)? ");
1007 fgetz(ans, sizeof(ans), stdin);
1008 if((ans[0] != 'y') && (ans[0] != 'Y')) myexit();
1009 }
1010 fd = fopen(fname, "wb");
1011 if(!fd) std_err();
1012 } else {
1013 printf("- open %s\n", fname);
1014 fd = fopen(fname, "rb");
1015 if(!fd) std_err();
1016 }
1017 return(fd);
1018 }
1019
1020
1021
blms2cue(FILE * fd,u8 * fname,u8 * blms,int blms_len)1022 int blms2cue(FILE *fd, u8 *fname, u8 *blms, int blms_len) {
1023 u32 bin,
1024 cue,
1025 type;
1026 int track,
1027 mode,
1028 tot;
1029 u8 mm,
1030 ss,
1031 ff,
1032 *p;
1033
1034 if(blms_len < 0x40) return(-1);
1035
1036 bin = *(u32 *)(blms + 0x04);
1037 l2n_32(&bin);
1038 if(bin > blms_len) return(-1);
1039
1040 cue = *(u32 *)(blms + 0x10);
1041 l2n_32(&cue);
1042 if(cue > blms_len) return(-1);
1043
1044 p = blms + 0x40;
1045 if(bin) {
1046 p = blms + bin;
1047 printf("- BIN name stored in the UIF file: %s\n", p);
1048 p += strlen(p) + 1;
1049 }
1050 if(cue) {
1051 p = blms + cue;
1052 printf("- CUE name stored in the UIF file: %s\n", p);
1053 p += strlen(p) + 1;
1054 }
1055
1056 fprintf(fd, "FILE \"%s\" BINARY\r\n", fname);
1057
1058 for(tot = 0; (p - blms) < blms_len; p += 68) {
1059 if(p[3] & 0xa0) continue;
1060 track = p[3];
1061 mode = p[11];
1062 mm = p[8];
1063 ss = p[9] - 2; // these are the 2 seconds located at the beginning of the NRG file
1064 ff = p[10];
1065 type = *(u32 *)(p + 24);
1066 l2n_32(&type);
1067 switch(p[1]) {
1068 case 0x10:
1069 case 0x12: {
1070 fprintf(fd, " TRACK %02d AUDIO\r\n", track);
1071 } break;
1072 case 0x14:
1073 default: {
1074 fprintf(fd, " TRACK %02d MODE%d/%d\r\n", track, mode, type);
1075 } break;
1076 }
1077 fprintf(fd, " INDEX %02d %02d:%02d:%02d\r\n", 1, mm, ss, ff);
1078 tot++;
1079 }
1080
1081 return(tot);
1082 }
1083
1084
1085
uif_crypt_key(des_context ** des_ctx,u8 * key,u8 * pwd)1086 void uif_crypt_key(des_context **des_ctx, u8 *key, u8 *pwd) {
1087 i64 *k,
1088 a,
1089 b;
1090 int i;
1091
1092 if(!des_ctx) return;
1093 if(!*des_ctx) {
1094 *des_ctx = malloc(sizeof(des_context));
1095 if(!*des_ctx) std_err();
1096 }
1097
1098 strncpy(key, pwd, 32);
1099 k = (i64 *)key;
1100
1101 printf("- set DES encryption key: %.32s\n", key);
1102
1103 for(i = 1; i < 4; i++) {
1104 if(!endian) { // this solution is required for little/big endian compatibility and speed
1105 k[0] += k[i];
1106 continue;
1107 }
1108 a = k[0];
1109 b = k[i];
1110 l2n_64(&a);
1111 l2n_64(&b);
1112 a += b;
1113 l2n_64(&a);
1114 k[0] = a;
1115 }
1116
1117 printf("- DES password: %02x %02x %02x %02x %02x %02x %02x %02x\n",
1118 key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7]);
1119 }
1120
1121
1122
uif_crypt(des_context * des_ctx,u8 * data,int size)1123 void uif_crypt(des_context *des_ctx, u8 *data, int size) {
1124 u8 *p,
1125 *l;
1126
1127 if(!des_ctx) return;
1128 l = data + size - (size & 7);
1129 for(p = data; p < l; p += 8) {
1130 des_crypt_ecb(des_ctx, p, p);
1131 }
1132 }
1133
1134
1135
show_hash(u8 * hash)1136 u8 *show_hash(u8 *hash) {
1137 int i;
1138 static u8 vis[33];
1139 static const char hex[16] = "0123456789abcdef";
1140 u8 *p;
1141
1142 p = vis;
1143 for(i = 0; i < 16; i++) {
1144 *p++ = hex[hash[i] >> 4];
1145 *p++ = hex[hash[i] & 15];
1146 }
1147 *p = 0;
1148
1149 return(vis);
1150 }
1151
1152
1153
myalloc(u8 ** data,unsigned wantsize,unsigned * currsize)1154 void myalloc(u8 **data, unsigned wantsize, unsigned *currsize) {
1155 if(wantsize <= *currsize) return;
1156 *data = realloc(*data, wantsize);
1157 if(!*data) std_err();
1158 *currsize = wantsize;
1159 }
1160
1161
1162
myfr(FILE * fd,void * data,unsigned size)1163 void myfr(FILE *fd, void *data, unsigned size) {
1164 if(fread(data, 1, size, fd) == size) return;
1165 printf("\nError: incomplete input file, can't read %u bytes\n", size);
1166 myexit();
1167 }
1168
1169
1170
myfw(FILE * fd,void * data,unsigned size)1171 void myfw(FILE *fd, void *data, unsigned size) {
1172 if(fwrite(data, 1, size, fd) == size) return;
1173 printf("\nError: problems during the writing of the output file\n");
1174 myexit();
1175 }
1176
1177
1178
unlzma(CLzmaDec * lzma,u8 * in,u32 insz,u8 * out,u32 outsz)1179 u32 unlzma(CLzmaDec *lzma, u8 *in, u32 insz, u8 *out, u32 outsz) {
1180 ELzmaStatus status;
1181 SizeT inlen,
1182 outlen;
1183 UInt32 x86State;
1184 int filter;
1185
1186 if(!lzma) return(0);
1187 if(insz < (1 + LZMA_PROPS_SIZE + 8)) {
1188 printf("\nError: the input lzma block is too short (%u)\n", insz);
1189 myexit();
1190 }
1191
1192 filter = in[0];
1193 in++;
1194 insz--;
1195
1196 LzmaDec_Construct(lzma);
1197 LzmaDec_Allocate(lzma, in, LZMA_PROPS_SIZE, &g_Alloc);
1198 LzmaDec_Init(lzma);
1199
1200 in += (LZMA_PROPS_SIZE + 8); // the uncompressed size is already known so it must be not read from this 64 bit field
1201 inlen = insz - (LZMA_PROPS_SIZE + 8);
1202 outlen = outsz;
1203
1204 if(
1205 (LzmaDec_DecodeToBuf(lzma, out, &outlen, in, &inlen, LZMA_FINISH_END, &status) != SZ_OK)
1206 || ((status != LZMA_STATUS_FINISHED_WITH_MARK) && (status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))) {
1207 printf("\nError: the compressed LZMA input is wrong or incomplete (%d)\n", status);
1208 myexit();
1209 }
1210 if(filter) {
1211 x86_Convert_Init(x86State);
1212 x86_Convert(out, outlen, 0, &x86State, 0);
1213 }
1214 LzmaDec_Free(lzma, &g_Alloc);
1215 return(outlen);
1216 }
1217
1218
1219
unzip(z_stream * z,u8 * in,u32 insz,u8 * out,u32 outsz)1220 u32 unzip(z_stream *z, u8 *in, u32 insz, u8 *out, u32 outsz) {
1221 if(!z) return(0);
1222 inflateReset(z);
1223
1224 z->next_in = in;
1225 z->avail_in = insz;
1226 z->next_out = out;
1227 z->avail_out = outsz;
1228 if(inflate(z, Z_SYNC_FLUSH) != Z_STREAM_END) {
1229 printf("\nError: the compressed input is wrong or incomplete\n");
1230 myexit();
1231 }
1232 return(z->total_out);
1233 }
1234
1235
1236
l2n_blhr(blhr_t * p)1237 void l2n_blhr(blhr_t *p) {
1238 if(!endian) return;
1239 l2n_32(&p->sign);
1240 l2n_32(&p->size);
1241 l2n_32(&p->compressed);
1242 l2n_32(&p->num);
1243 }
1244
1245
1246
l2n_blhr_data(blhr_data_t * p)1247 void l2n_blhr_data(blhr_data_t *p) {
1248 if(!endian) return;
1249 l2n_64(&p->offset);
1250 l2n_32(&p->zsize);
1251 l2n_32(&p->sector);
1252 l2n_32(&p->size);
1253 l2n_32(&p->type);
1254 }
1255
1256
1257
l2n_bbis(bbis_t * p)1258 void l2n_bbis(bbis_t *p) {
1259 if(!endian) return;
1260 l2n_32(&p->sign);
1261 l2n_32(&p->bbis_size);
1262 l2n_16(&p->ver);
1263 l2n_16(&p->image_type);
1264 l2n_16(&p->unknown1);
1265 l2n_16(&p->padding);
1266 l2n_32(&p->sectors);
1267 l2n_32(&p->sectorsz);
1268 l2n_32(&p->lastdiff);
1269 l2n_64(&p->blhr);
1270 l2n_32(&p->blhrbbissz);
1271 l2n_32(&p->unknown4);
1272 }
1273
1274
1275
l2n_16(u16 * num)1276 void l2n_16(u16 *num) {
1277 u16 tmp;
1278
1279 if(!endian) return;
1280
1281 tmp = *num;
1282 *num = ((tmp & 0xff00) >> 8) |
1283 ((tmp & 0x00ff) << 8);
1284 }
1285
1286
1287
l2n_32(u32 * num)1288 void l2n_32(u32 *num) {
1289 u32 tmp;
1290
1291 if(!endian) return;
1292
1293 tmp = *num;
1294 *num = ((tmp & 0xff000000) >> 24) |
1295 ((tmp & 0x00ff0000) >> 8) |
1296 ((tmp & 0x0000ff00) << 8) |
1297 ((tmp & 0x000000ff) << 24);
1298 }
1299
1300
1301
l2n_64(u64 * num)1302 void l2n_64(u64 *num) {
1303 u64 tmp;
1304
1305 if(!endian) return;
1306
1307 tmp = *num;
1308 *num = (u64)((u64)(tmp & (u64)0xff00000000000000ULL) >> (u64)56) |
1309 (u64)((u64)(tmp & (u64)0x00ff000000000000ULL) >> (u64)40) |
1310 (u64)((u64)(tmp & (u64)0x0000ff0000000000ULL) >> (u64)24) |
1311 (u64)((u64)(tmp & (u64)0x000000ff00000000ULL) >> (u64)8) |
1312 (u64)((u64)(tmp & (u64)0x00000000ff000000ULL) << (u64)8) |
1313 (u64)((u64)(tmp & (u64)0x0000000000ff0000ULL) << (u64)24) |
1314 (u64)((u64)(tmp & (u64)0x000000000000ff00ULL) << (u64)40) |
1315 (u64)((u64)(tmp & (u64)0x00000000000000ffULL) << (u64)56);
1316 }
1317
1318
1319
b2n_16(u16 * num)1320 void b2n_16(u16 *num) {
1321 u16 tmp;
1322
1323 if(endian) return;
1324
1325 tmp = *num;
1326 *num = ((tmp & 0xff00) >> 8) |
1327 ((tmp & 0x00ff) << 8);
1328 }
1329
1330
1331
b2n_32(u32 * num)1332 void b2n_32(u32 *num) {
1333 u32 tmp;
1334
1335 if(endian) return;
1336
1337 tmp = *num;
1338 *num = ((tmp & 0xff000000) >> 24) |
1339 ((tmp & 0x00ff0000) >> 8) |
1340 ((tmp & 0x0000ff00) << 8) |
1341 ((tmp & 0x000000ff) << 24);
1342 }
1343
1344
1345
b2n_64(u64 * num)1346 void b2n_64(u64 *num) {
1347 u64 tmp;
1348
1349 if(endian) return;
1350
1351 tmp = *num;
1352 *num = (u64)((u64)(tmp & (u64)0xff00000000000000ULL) >> (u64)56) |
1353 (u64)((u64)(tmp & (u64)0x00ff000000000000ULL) >> (u64)40) |
1354 (u64)((u64)(tmp & (u64)0x0000ff0000000000ULL) >> (u64)24) |
1355 (u64)((u64)(tmp & (u64)0x000000ff00000000ULL) >> (u64)8) |
1356 (u64)((u64)(tmp & (u64)0x00000000ff000000ULL) << (u64)8) |
1357 (u64)((u64)(tmp & (u64)0x0000000000ff0000ULL) << (u64)24) |
1358 (u64)((u64)(tmp & (u64)0x000000000000ff00ULL) << (u64)40) |
1359 (u64)((u64)(tmp & (u64)0x00000000000000ffULL) << (u64)56);
1360 }
1361
1362
1363
getxx(u8 * data,u64 * ret,int bits,int intnet)1364 int getxx(u8 *data, u64 *ret, int bits, int intnet) {
1365 u64 num;
1366 int i,
1367 bytes;
1368
1369 num = 0;
1370 bytes = bits >> 3;
1371 for(i = 0; i < bytes; i++) {
1372 if(!intnet) { // intel/little endian
1373 num |= (data[i] << (i << 3));
1374 } else { // network/big endian
1375 num |= (data[i] << ((bytes - 1 - i) << 3));
1376 }
1377 }
1378 *ret = num;
1379 return(bytes);
1380 }
1381
1382
1383
putxx(u8 * data,u64 num,int bits,int intnet)1384 int putxx(u8 *data, u64 num, int bits, int intnet) {
1385 int i,
1386 bytes;
1387
1388 bytes = bits >> 3;
1389 for(i = 0; i < bytes; i++) {
1390 if(!intnet) {
1391 data[i] = (num >> (i << 3)) & 0xff;
1392 } else {
1393 data[i] = (num >> ((bytes - 1 - i) << 3)) & 0xff;
1394 }
1395 }
1396 return(bytes);
1397 }
1398
1399
1400
std_err(void)1401 void std_err(void) {
1402 perror("\nError");
1403 myexit();
1404 }
1405
1406
1407
fgetz(u8 * data,int size,FILE * fd)1408 int fgetz(u8 *data, int size, FILE *fd) {
1409 u8 *p;
1410
1411 fflush(fd);
1412 if(!fgets(data, size, fd)) {
1413 data[0] = 0;
1414 return(0);
1415 }
1416 for(p = data; *p && (*p != '\n') && (*p != '\r'); p++);
1417 *p = 0;
1418 return(p - data);
1419 }
1420
1421
1422
myexit(void)1423 void myexit(void) {
1424 #ifdef WIN32
1425 u8 ans[8];
1426
1427 if(GetWindowLong(mywnd, GWL_WNDPROC)) {
1428 printf("\nPress RETURN to quit");
1429 fgetz(ans, sizeof(ans), stdin);
1430 }
1431 #endif
1432 exit(0);
1433 }
1434
1435
1436