Keybindings UI is displayed based on the option used (--debugger, -- alpine)
[clinton/Virtual-Jaguar-Rx.git] / src / unzip.cpp
1 //
2 // ZIP file support
3 // This is here to simplify interfacing to zlib, as zlib does NO zip file handling
4 //
5 // by James Hammons
6 // (C) 2012 Underground Software
7 //
8 // JLH = James Hammons <jlhamm@acm.org>
9 //
10 // Who When What
11 // --- ---------- -------------------------------------------------------------
12 // JLH 01/16/2010 Created this log ;-)
13 // JLH 02/28/2010 Removed unnecessary cruft
14 // JLH 05/31/2012 Rewrote everything and removed all MAME code
15 //
16
17 #include "unzip.h"
18
19 #include <stdlib.h>
20 #include <string.h>
21 #include <zlib.h>
22 #include "log.h"
23
24
25 uint32_t GetLong(FILE * fp)
26 {
27 uint32_t n = ((uint32_t)fgetc(fp));
28 n |= ((uint32_t)fgetc(fp)) << 8;
29 n |= ((uint32_t)fgetc(fp)) << 16;
30 n |= ((uint32_t)fgetc(fp)) << 24;
31
32 return n;
33 }
34
35
36 uint16_t GetWord(FILE * fp)
37 {
38 uint16_t n = ((uint16_t)fgetc(fp));
39 n |= ((uint16_t)fgetc(fp)) << 8;
40
41 return n;
42 }
43
44
45 bool GetZIPHeader(FILE * fp, ZipFileEntry & ze)
46 {
47 ze.signature = GetLong(fp);
48 ze.version = GetWord(fp);
49 ze.flags = GetWord(fp);
50 ze.method = GetWord(fp);
51 ze.modifiedTime = GetWord(fp);
52 ze.modifiedDate = GetWord(fp);
53 ze.crc32 = GetLong(fp);
54 ze.compressedSize = GetLong(fp);
55 ze.uncompressedSize = GetLong(fp);
56 ze.filenameLength = GetWord(fp);
57 ze.extraLength = GetWord(fp);
58
59 // This handling is really ungraceful; but if someone is going to feed us
60 // shit, then why eat it? :-)
61 if (ze.filenameLength < 512)
62 {
63 fread(ze.filename, 1, ze.filenameLength, fp);
64 ze.filename[ze.filenameLength] = 0;
65 }
66 else
67 {
68 fseek(fp, ze.filenameLength, SEEK_CUR);
69 ze.filename[0] = 0;
70 }
71
72 // Skip the "extra" header
73 fseek(fp, ze.extraLength, SEEK_CUR);
74
75 return (ze.signature == 0x04034B50 ? true : false);
76 }
77
78
79 //
80 // Uncompress a file from a ZIP file filestream
81 // NOTE: The passed in buffer *must* be fully allocated before calling this!
82 //
83 #define CHUNKSIZE 16384
84 int UncompressFileFromZIP(FILE * fp, ZipFileEntry ze, uint8_t * buffer)
85 {
86 z_stream zip;
87 unsigned char inBuffer[CHUNKSIZE];
88 uint32_t remaining = ze.compressedSize;
89
90 // Set up z_stream for inflating
91 zip.zalloc = Z_NULL;
92 zip.zfree = Z_NULL;
93 zip.opaque = Z_NULL;
94 zip.avail_in = 0;
95 zip.next_in = Z_NULL;
96
97 int ret = inflateInit2(&zip, -MAX_WBITS); // -MAX_WBITS tells it there's no header
98
99 // Bail if can't initialize the z_stream...
100 if (ret != Z_OK)
101 return ret;
102
103 zip.avail_out = ze.uncompressedSize;
104 zip.next_out = buffer;
105
106 // Decompress until deflate stream ends or we hit end of file
107 do
108 {
109 zip.avail_in = fread(inBuffer, 1, (remaining < CHUNKSIZE ? remaining : CHUNKSIZE), fp);
110 zip.next_in = inBuffer;
111 remaining -= CHUNKSIZE;
112
113 if (ferror(fp))
114 {
115 inflateEnd(&zip);
116 return Z_ERRNO;
117 }
118
119 if (zip.avail_in == 0)
120 break;
121
122 ret = inflate(&zip, Z_NO_FLUSH);
123
124 if ((ret == Z_NEED_DICT) || (ret == Z_DATA_ERROR) || (ret == Z_MEM_ERROR))
125 {
126 inflateEnd(&zip);
127 return ret;
128 }
129
130 }
131 while (ret != Z_STREAM_END);
132
133 inflateEnd(&zip);
134
135 return (ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR);
136 }