z_au.library -> z1.library
[AROS.git] / workbench / devs / diskimage / plugins / dax.c
blobb4fb377b25266b5fb7b9bbfbefb2c3ccde08e3e7
1 /* Copyright 2007-2012 Fredrik Wikstrom. All rights reserved.
2 **
3 ** Redistribution and use in source and binary forms, with or without
4 ** modification, are permitted provided that the following conditions
5 ** are met:
6 **
7 ** 1. Redistributions of source code must retain the above copyright
8 ** notice, this list of conditions and the following disclaimer.
9 **
10 ** 2. Redistributions in binary form must reproduce the above copyright
11 ** notice, this list of conditions and the following disclaimer in the
12 ** documentation and/or other materials provided with the distribution.
14 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
15 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 ** POSSIBILITY OF SUCH DAMAGE.
27 #define USED_PLUGIN_API_VERSION 8
28 #include <devices/diskimage.h>
29 #include <proto/exec.h>
30 #include <proto/dos.h>
32 #ifdef __AROS__
33 # include <zlib.h>
34 # define Uncompress uncompress
35 #else
36 # include <libraries/z.h>
37 # include <proto/z.h>
38 #endif
40 #include "endian.h"
41 #include "device_locale.h"
42 #include <SDI_compiler.h>
43 #include "rev/diskimage.device_rev.h"
45 PLUGIN_VERSTAG("DAX")
47 extern struct DiskImagePlugin dax_plugin;
49 PLUGIN_TABLE(&dax_plugin)
51 typedef struct {
52 ULONG offset;
53 UWORD size;
54 UWORD comp;
55 } frame_t;
57 struct DAXImage {
58 BPTR file;
59 UBYTE *in_buf, *out_buf;
60 ULONG nframes;
61 frame_t *frames;
62 frame_t *frame_in_buf;
63 ULONG total_bytes;
64 ULONG block_size;
65 ULONG total_blocks;
66 struct Library *zbase;
69 BOOL DAX_Init (struct DiskImagePlugin *Self, const struct PluginData *data);
70 BOOL DAX_CheckImage (struct DiskImagePlugin *Self, BPTR file, CONST_STRPTR name, QUAD file_size,
71 const UBYTE *test, LONG testsize);
72 APTR DAX_OpenImage (struct DiskImagePlugin *Self, APTR unit, BPTR file, CONST_STRPTR name);
73 void DAX_CloseImage (struct DiskImagePlugin *Self, APTR image_ptr);
74 LONG DAX_Geometry (struct DiskImagePlugin *Self, APTR image_ptr, struct DriveGeometry *dg);
75 LONG DAX_Read (struct DiskImagePlugin *Self, APTR image_ptr, struct IOStdReq *io);
77 struct DiskImagePlugin dax_plugin = {
78 PLUGIN_NODE(0, "DAX"),
79 PLUGIN_FLAG_M68K,
81 ZERO,
82 NULL,
83 DAX_Init,
84 NULL,
85 DAX_CheckImage,
86 DAX_OpenImage,
87 DAX_CloseImage,
88 DAX_Geometry,
89 DAX_Read,
90 NULL,
91 NULL,
92 NULL,
93 NULL,
94 NULL
97 struct Library *SysBase;
98 struct Library *DOSBase;
99 static struct DIPluginIFace *IPlugin;
100 #ifndef __AROS__
101 #define ZBase image->zbase
102 #else
103 struct Library *Z1Base;
104 #endif
106 BOOL DAX_Init (struct DiskImagePlugin *Self, const struct PluginData *data) {
107 SysBase = data->SysBase;
108 DOSBase = data->DOSBase;
109 IPlugin = data->IPlugin;
110 return TRUE;
113 #define DAX_MAGIC MAKE_ID('D','A','X',0)
115 BOOL DAX_CheckImage (struct DiskImagePlugin *Self, BPTR file, CONST_STRPTR name, QUAD file_size,
116 const UBYTE *test, LONG testsize)
118 return testsize >= sizeof(ULONG) && rbe32(test) == DAX_MAGIC;
121 #pragma pack(1)
123 #define DAX_FRAME_SIZE 8192
124 #define MAX_NCAREAS 192
126 typedef struct {
127 ULONG magic;
128 ULONG isosize;
129 ULONG version;
130 ULONG ncareas;
131 UBYTE reserved[16];
132 } dax_t;
134 typedef struct {
135 ULONG frame;
136 ULONG size;
137 } ncarea_t;
139 #pragma pack()
141 static inline BOOL IsNCArea (ncarea_t *ncareas, ULONG frame, ULONG count) {
142 ULONG i;
143 for (i = 0; i < count; i++) {
144 if (frame >= ncareas->frame &&
145 (frame - ncareas->frame) < ncareas->size)
147 return TRUE;
150 return FALSE;
153 APTR DAX_OpenImage (struct DiskImagePlugin *Self, APTR unit, BPTR file,
154 CONST_STRPTR name)
156 LONG done = FALSE;
157 LONG error = NO_ERROR;
158 LONG error_string = NO_ERROR_STRING;
159 IPTR error_args[4] = {0};
160 struct DAXImage *image = NULL;
161 dax_t dax;
162 ULONG nframes;
163 ULONG *offsets = NULL;
164 UWORD *lengths = NULL;
165 ncarea_t *ncareas = NULL;
166 ULONG i;
168 if (FRead(file, &dax, 1, sizeof(dax)) != sizeof(dax)) {
169 error = IoErr();
170 goto error;
173 if (rle32(&dax.version) > 1) {
174 error = ERROR_OBJECT_WRONG_TYPE;
175 goto error;
178 image = AllocVec(sizeof(*image), MEMF_CLEAR);
179 if (!image) {
180 error = ERROR_NO_FREE_STORE;
181 goto error;
184 image->file = file;
185 image->total_bytes = rle32(&dax.isosize);
186 image->block_size = 2048;
187 image->total_blocks = image->total_bytes >> 11;
189 #ifdef __AROS__
190 image->zbase = OpenLibrary("z1.library", 1);
191 Z1Base = image->zbase;
192 #else
193 image->zbase = OpenLibrary("z.library", 1);
194 #endif
195 if (!image->zbase || !CheckLib(image->zbase, 1, 6)) {
196 error = ERROR_OBJECT_NOT_FOUND;
197 error_string = MSG_REQVER;
198 error_args[0] = (IPTR)"z.library";
199 error_args[1] = 1;
200 error_args[2] = 6;
201 goto error;
204 nframes = image->total_bytes / DAX_FRAME_SIZE;
205 if (image->total_bytes % DAX_FRAME_SIZE) nframes++;
206 image->nframes = nframes;
208 offsets = AllocVec(nframes << 2, MEMF_ANY);
209 lengths = AllocVec(nframes << 1, MEMF_ANY);
210 image->frames = AllocVec(nframes << 3, MEMF_ANY);
211 if (!offsets || !lengths || !image->frames) {
212 error = ERROR_NO_FREE_STORE;
213 goto error;
216 if (FRead(file, offsets, 4, nframes) != nframes ||
217 FRead(file, lengths, 2, nframes) != nframes)
219 error = IoErr();
220 goto error;
223 for (i = 0; i < nframes; i++) {
224 image->frames[i].offset = rle32(&offsets[i]);
225 image->frames[i].size = rle16(&lengths[i]);
226 image->frames[i].comp = 1;
229 FreeVec(offsets);
230 FreeVec(lengths);
231 offsets = NULL;
232 lengths = NULL;
234 if (dax.ncareas) {
235 ULONG nncareas;
236 nncareas = rle32(&dax.ncareas);
237 ncareas = AllocVec(MAX_NCAREAS*sizeof(*ncareas), MEMF_ANY);
238 if (!ncareas) {
239 error = ERROR_NO_FREE_STORE;
240 goto error;
242 if (FRead(file, ncareas, sizeof(*ncareas), MAX_NCAREAS) != MAX_NCAREAS) {
243 error = IoErr();
244 goto error;
246 for (i = 0; i < MAX_NCAREAS; i++) {
247 ncareas[i].frame = rle32(&ncareas[i].frame);
248 ncareas[i].size = rle32(&ncareas[i].size);
250 for (i = 0; i < nframes; i++) {
251 if (IsNCArea(ncareas, i, nncareas)) {
252 image->frames[i].comp = 0;
255 FreeVec(ncareas);
256 ncareas = NULL;
259 image->in_buf = AllocVec(DAX_FRAME_SIZE+1024, MEMF_ANY);
260 image->out_buf = AllocVec(DAX_FRAME_SIZE, MEMF_ANY);
261 if (!image->in_buf || !image->out_buf) {
262 error = ERROR_NO_FREE_STORE;
263 goto error;
266 done = TRUE;
268 error:
269 FreeVec(ncareas);
270 FreeVec(offsets);
271 FreeVec(lengths);
272 if (!done) {
273 if (image) {
274 Plugin_CloseImage(Self, image);
275 image = NULL;
276 } else {
277 Close(file);
279 if (error == NO_ERROR) {
280 error = ERROR_OBJECT_WRONG_TYPE;
281 error_string = MSG_EOF;
283 IPlugin_SetDiskImageErrorA(unit, error, error_string, error_args);
285 return image;
288 void DAX_CloseImage (struct DiskImagePlugin *Self, APTR image_ptr) {
289 struct DAXImage *image = image_ptr;
290 if (image) {
291 if (image->zbase) CloseLibrary(image->zbase);
292 FreeVec(image->in_buf);
293 FreeVec(image->out_buf);
294 FreeVec(image->frames);
295 Close(image->file);
296 FreeVec(image);
300 LONG DAX_Geometry (struct DiskImagePlugin *Self, APTR image_ptr, struct DriveGeometry *dg) {
301 struct DAXImage *image = image_ptr;
302 dg->dg_SectorSize = image->block_size;
303 dg->dg_Heads =
304 dg->dg_TrackSectors =
305 dg->dg_CylSectors = 1;
306 dg->dg_Cylinders =
307 dg->dg_TotalSectors = image->total_blocks;
308 return IOERR_SUCCESS;
311 LONG DAX_Read (struct DiskImagePlugin *Self, APTR image_ptr, struct IOStdReq *io) {
312 struct DAXImage *image = image_ptr;
313 BPTR file = image->file;
314 ULONG offset;
315 UBYTE *buffer;
316 ULONG size;
317 ULONG i;
318 ULONG to_skip, to_read;
319 frame_t *frame;
321 offset = io->io_Offset;
322 buffer = io->io_Data;
323 size = io->io_Length;
324 io->io_Actual = 0;
326 i = offset / DAX_FRAME_SIZE;
327 to_skip = offset % DAX_FRAME_SIZE;
328 if (i >= image->nframes) return IOERR_BADADDRESS;
330 frame = &image->frames[i];
331 io->io_Actual = size;
332 while (size) {
333 if (i >= image->nframes) {
334 io->io_Actual -= size;
335 return IOERR_BADLENGTH;
338 to_read = min(size, DAX_FRAME_SIZE - to_skip);
339 if (frame->comp) {
340 if (image->frame_in_buf != frame) {
341 uLongf bytes;
342 image->frame_in_buf = NULL;
343 if (!ChangeFilePosition(file, frame->offset, OFFSET_BEGINNING) ||
344 Read(file, image->in_buf, frame->size) != frame->size)
346 io->io_Actual -= size;
347 return IPlugin_DOS2IOErr(IoErr());
349 bytes = DAX_FRAME_SIZE;
350 if (Uncompress(image->out_buf, &bytes, image->in_buf, frame->size) != Z_OK) {
351 io->io_Actual -= size;
352 return TDERR_NotSpecified;
354 image->frame_in_buf = frame;
356 CopyMem(image->out_buf + to_skip, buffer, to_read);
357 } else {
358 if (!ChangeFilePosition(file, frame->offset + to_skip, OFFSET_BEGINNING) ||
359 Read(file, buffer, to_read) != to_read)
361 io->io_Actual -= size;
362 return IPlugin_DOS2IOErr(IoErr());
366 buffer += to_read;
367 size -= to_read;
368 to_skip = 0;
369 frame++;
370 i++;
372 return IOERR_SUCCESS;