diff options
author | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-15 21:04:28 +0100 |
---|---|---|
committer | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-24 18:05:53 +0100 |
commit | c876d3bbefe0dc00c27ca0c12d29da5874946962 (patch) | |
tree | 69f468a185a369b01998314bc3ecc19b70f4fcaa /utils/rbutilqt/mspack/szddd.c | |
parent | 6c6f0757d7a902feb293be165d1490c42bc8e7ad (diff) | |
download | rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.tar.gz rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.zip |
rbutil: Merge rbutil with utils folder.
rbutil uses several components from the utils folder, and can be
considered part of utils too. Having it in a separate folder is an
arbitrary split that doesn't help anymore these days, so merge them.
This also allows other utils to easily use libtools.make without the
need to navigate to a different folder.
Change-Id: I3fc2f4de19e3e776553efb5dea5f779dfec0dc21
Diffstat (limited to 'utils/rbutilqt/mspack/szddd.c')
-rw-r--r-- | utils/rbutilqt/mspack/szddd.c | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/utils/rbutilqt/mspack/szddd.c b/utils/rbutilqt/mspack/szddd.c new file mode 100644 index 0000000000..1d6d05f844 --- /dev/null +++ b/utils/rbutilqt/mspack/szddd.c | |||
@@ -0,0 +1,247 @@ | |||
1 | /* This file is part of libmspack. | ||
2 | * (C) 2003-2010 Stuart Caie. | ||
3 | * | ||
4 | * SZDD is a format used in the MS-DOS commands COMPRESS.EXE and | ||
5 | * EXPAND.EXE. The compression method is attributed to Steven Zeck, | ||
6 | * however it's pretty much identical to LZSS. | ||
7 | * | ||
8 | * libmspack is free software; you can redistribute it and/or modify it under | ||
9 | * the terms of the GNU Lesser General Public License (LGPL) version 2.1 | ||
10 | * | ||
11 | * For further details, see the file COPYING.LIB distributed with libmspack | ||
12 | */ | ||
13 | |||
14 | /* SZDD decompression implementation */ | ||
15 | |||
16 | #include "system-mspack.h" | ||
17 | #include "szdd.h" | ||
18 | |||
19 | /* prototypes */ | ||
20 | static struct msszddd_header *szddd_open( | ||
21 | struct msszdd_decompressor *base, const char *filename); | ||
22 | static void szddd_close( | ||
23 | struct msszdd_decompressor *base, struct msszddd_header *hdr); | ||
24 | static int szddd_read_headers( | ||
25 | struct mspack_system *sys, struct mspack_file *fh, | ||
26 | struct msszddd_header *hdr); | ||
27 | static int szddd_extract( | ||
28 | struct msszdd_decompressor *base, struct msszddd_header *hdr, | ||
29 | const char *filename); | ||
30 | static int szddd_decompress( | ||
31 | struct msszdd_decompressor *base, const char *input, const char *output); | ||
32 | static int szddd_error( | ||
33 | struct msszdd_decompressor *base); | ||
34 | |||
35 | /*************************************** | ||
36 | * MSPACK_CREATE_SZDD_DECOMPRESSOR | ||
37 | *************************************** | ||
38 | * constructor | ||
39 | */ | ||
40 | struct msszdd_decompressor * | ||
41 | mspack_create_szdd_decompressor(struct mspack_system *sys) | ||
42 | { | ||
43 | struct msszdd_decompressor_p *self = NULL; | ||
44 | |||
45 | if (!sys) sys = mspack_default_system; | ||
46 | if (!mspack_valid_system(sys)) return NULL; | ||
47 | |||
48 | if ((self = (struct msszdd_decompressor_p *) sys->alloc(sys, sizeof(struct msszdd_decompressor_p)))) { | ||
49 | self->base.open = &szddd_open; | ||
50 | self->base.close = &szddd_close; | ||
51 | self->base.extract = &szddd_extract; | ||
52 | self->base.decompress = &szddd_decompress; | ||
53 | self->base.last_error = &szddd_error; | ||
54 | self->system = sys; | ||
55 | self->error = MSPACK_ERR_OK; | ||
56 | } | ||
57 | return (struct msszdd_decompressor *) self; | ||
58 | } | ||
59 | |||
60 | /*************************************** | ||
61 | * MSPACK_DESTROY_SZDD_DECOMPRESSOR | ||
62 | *************************************** | ||
63 | * destructor | ||
64 | */ | ||
65 | void mspack_destroy_szdd_decompressor(struct msszdd_decompressor *base) | ||
66 | { | ||
67 | struct msszdd_decompressor_p *self = (struct msszdd_decompressor_p *) base; | ||
68 | if (self) { | ||
69 | struct mspack_system *sys = self->system; | ||
70 | sys->free(self); | ||
71 | } | ||
72 | } | ||
73 | |||
74 | /*************************************** | ||
75 | * SZDDD_OPEN | ||
76 | *************************************** | ||
77 | * opens an SZDD file without decompressing, reads header | ||
78 | */ | ||
79 | static struct msszddd_header *szddd_open(struct msszdd_decompressor *base, | ||
80 | const char *filename) | ||
81 | { | ||
82 | struct msszdd_decompressor_p *self = (struct msszdd_decompressor_p *) base; | ||
83 | struct msszddd_header *hdr; | ||
84 | struct mspack_system *sys; | ||
85 | struct mspack_file *fh; | ||
86 | |||
87 | if (!self) return NULL; | ||
88 | sys = self->system; | ||
89 | |||
90 | fh = sys->open(sys, filename, MSPACK_SYS_OPEN_READ); | ||
91 | hdr = (struct msszddd_header *) sys->alloc(sys, sizeof(struct msszddd_header_p)); | ||
92 | if (fh && hdr) { | ||
93 | ((struct msszddd_header_p *) hdr)->fh = fh; | ||
94 | self->error = szddd_read_headers(sys, fh, hdr); | ||
95 | } | ||
96 | else { | ||
97 | if (!fh) self->error = MSPACK_ERR_OPEN; | ||
98 | if (!hdr) self->error = MSPACK_ERR_NOMEMORY; | ||
99 | } | ||
100 | |||
101 | if (self->error) { | ||
102 | if (fh) sys->close(fh); | ||
103 | sys->free(hdr); | ||
104 | hdr = NULL; | ||
105 | } | ||
106 | |||
107 | return hdr; | ||
108 | } | ||
109 | |||
110 | /*************************************** | ||
111 | * SZDDD_CLOSE | ||
112 | *************************************** | ||
113 | * closes an SZDD file | ||
114 | */ | ||
115 | static void szddd_close(struct msszdd_decompressor *base, | ||
116 | struct msszddd_header *hdr) | ||
117 | { | ||
118 | struct msszdd_decompressor_p *self = (struct msszdd_decompressor_p *) base; | ||
119 | struct msszddd_header_p *hdr_p = (struct msszddd_header_p *) hdr; | ||
120 | |||
121 | if (!self || !self->system) return; | ||
122 | |||
123 | /* close the file handle associated */ | ||
124 | self->system->close(hdr_p->fh); | ||
125 | |||
126 | /* free the memory associated */ | ||
127 | self->system->free(hdr); | ||
128 | |||
129 | self->error = MSPACK_ERR_OK; | ||
130 | } | ||
131 | |||
132 | /*************************************** | ||
133 | * SZDDD_READ_HEADERS | ||
134 | *************************************** | ||
135 | * reads the headers of an SZDD format file | ||
136 | */ | ||
137 | static unsigned char szdd_signature_expand[8] = { | ||
138 | 0x53, 0x5A, 0x44, 0x44, 0x88, 0xF0, 0x27, 0x33 | ||
139 | }; | ||
140 | static unsigned char szdd_signature_qbasic[8] = { | ||
141 | 0x53, 0x5A, 0x20, 0x88, 0xF0, 0x27, 0x33, 0xD1 | ||
142 | }; | ||
143 | |||
144 | static int szddd_read_headers(struct mspack_system *sys, | ||
145 | struct mspack_file *fh, | ||
146 | struct msszddd_header *hdr) | ||
147 | { | ||
148 | unsigned char buf[8]; | ||
149 | |||
150 | /* read and check signature */ | ||
151 | if (sys->read(fh, buf, 8) != 8) return MSPACK_ERR_READ; | ||
152 | |||
153 | if ((memcmp(buf, szdd_signature_expand, 8) == 0)) { | ||
154 | /* common SZDD */ | ||
155 | hdr->format = MSSZDD_FMT_NORMAL; | ||
156 | |||
157 | /* read the rest of the header */ | ||
158 | if (sys->read(fh, buf, 6) != 6) return MSPACK_ERR_READ; | ||
159 | if (buf[0] != 0x41) return MSPACK_ERR_DATAFORMAT; | ||
160 | hdr->missing_char = buf[1]; | ||
161 | hdr->length = EndGetI32(&buf[2]); | ||
162 | } | ||
163 | else if ((memcmp(buf, szdd_signature_qbasic, 8) == 0)) { | ||
164 | /* special QBasic SZDD */ | ||
165 | hdr->format = MSSZDD_FMT_QBASIC; | ||
166 | if (sys->read(fh, buf, 4) != 4) return MSPACK_ERR_READ; | ||
167 | hdr->missing_char = '\0'; | ||
168 | hdr->length = EndGetI32(buf); | ||
169 | } | ||
170 | else { | ||
171 | return MSPACK_ERR_SIGNATURE; | ||
172 | } | ||
173 | return MSPACK_ERR_OK; | ||
174 | } | ||
175 | |||
176 | /*************************************** | ||
177 | * SZDDD_EXTRACT | ||
178 | *************************************** | ||
179 | * decompresses an SZDD file | ||
180 | */ | ||
181 | static int szddd_extract(struct msszdd_decompressor *base, | ||
182 | struct msszddd_header *hdr, const char *filename) | ||
183 | { | ||
184 | struct msszdd_decompressor_p *self = (struct msszdd_decompressor_p *) base; | ||
185 | struct mspack_file *fh, *outfh; | ||
186 | struct mspack_system *sys; | ||
187 | off_t data_offset; | ||
188 | |||
189 | if (!self) return MSPACK_ERR_ARGS; | ||
190 | if (!hdr) return self->error = MSPACK_ERR_ARGS; | ||
191 | sys = self->system; | ||
192 | |||
193 | fh = ((struct msszddd_header_p *) hdr)->fh; | ||
194 | |||
195 | /* seek to the compressed data */ | ||
196 | data_offset = (hdr->format == MSSZDD_FMT_NORMAL) ? 14 : 12; | ||
197 | if (sys->seek(fh, data_offset, MSPACK_SYS_SEEK_START)) { | ||
198 | return self->error = MSPACK_ERR_SEEK; | ||
199 | } | ||
200 | |||
201 | /* open file for output */ | ||
202 | if (!(outfh = sys->open(sys, filename, MSPACK_SYS_OPEN_WRITE))) { | ||
203 | return self->error = MSPACK_ERR_OPEN; | ||
204 | } | ||
205 | |||
206 | /* decompress the data */ | ||
207 | self->error = lzss_decompress(sys, fh, outfh, SZDD_INPUT_SIZE, | ||
208 | hdr->format == MSSZDD_FMT_NORMAL | ||
209 | ? LZSS_MODE_EXPAND | ||
210 | : LZSS_MODE_QBASIC); | ||
211 | |||
212 | /* close output file */ | ||
213 | sys->close(outfh); | ||
214 | |||
215 | return self->error; | ||
216 | } | ||
217 | |||
218 | /*************************************** | ||
219 | * SZDDD_DECOMPRESS | ||
220 | *************************************** | ||
221 | * unpacks directly from input to output | ||
222 | */ | ||
223 | static int szddd_decompress(struct msszdd_decompressor *base, | ||
224 | const char *input, const char *output) | ||
225 | { | ||
226 | struct msszdd_decompressor_p *self = (struct msszdd_decompressor_p *) base; | ||
227 | struct msszddd_header *hdr; | ||
228 | int error; | ||
229 | |||
230 | if (!self) return MSPACK_ERR_ARGS; | ||
231 | |||
232 | if (!(hdr = szddd_open(base, input))) return self->error; | ||
233 | error = szddd_extract(base, hdr, output); | ||
234 | szddd_close(base, hdr); | ||
235 | return self->error = error; | ||
236 | } | ||
237 | |||
238 | /*************************************** | ||
239 | * SZDDD_ERROR | ||
240 | *************************************** | ||
241 | * returns the last error that occurred | ||
242 | */ | ||
243 | static int szddd_error(struct msszdd_decompressor *base) | ||
244 | { | ||
245 | struct msszdd_decompressor_p *self = (struct msszdd_decompressor_p *) base; | ||
246 | return (self) ? self->error : MSPACK_ERR_ARGS; | ||
247 | } | ||