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(&sectsz);
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