z_au.library -> z1.library
[AROS.git] / workbench / devs / diskimage / plugins / ciso.c
blob78c8d967aa74db2f7dbc7f375d64f98a22ea162b
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/diskimage.h>
30 #include <proto/exec.h>
31 #include <proto/dos.h>
33 #ifdef __AROS__
34 # include <zlib.h>
35 # define InflateInit2 inflateInit2
36 # define Inflate inflate
37 # define InflateEnd inflateEnd
38 # define InflateReset inflateReset
39 #else
40 # include <libraries/z.h>
41 # include <proto/z.h>
42 #endif
44 #include <SDI_compiler.h>
45 #include "endian.h"
46 #include "device_locale.h"
47 #include "rev/diskimage.device_rev.h"
49 PLUGIN_VERSTAG("CISO")
51 extern struct DiskImagePlugin ciso_plugin;
53 PLUGIN_TABLE(&ciso_plugin)
55 struct CISOImage {
56 BPTR file;
57 ULONG block_size;
58 ULONG total_blocks;
59 UBYTE align;
60 UBYTE *block_buf;
61 z_stream zs;
62 ULONG *index_buf;
63 struct Library *zbase;
66 BOOL CISO_Init (struct DiskImagePlugin *Self, const struct PluginData *data);
67 BOOL CISO_CheckImage (struct DiskImagePlugin *Self, BPTR file, CONST_STRPTR name, QUAD file_size,
68 const UBYTE *test, LONG testsize);
69 APTR CISO_OpenImage (struct DiskImagePlugin *Self, APTR unit, BPTR file, CONST_STRPTR name);
70 void CISO_CloseImage (struct DiskImagePlugin *Self, APTR image_ptr);
71 LONG CISO_Geometry (struct DiskImagePlugin *Self, APTR image_ptr, struct DriveGeometry *dg);
72 LONG CISO_Read (struct DiskImagePlugin *Self, APTR image_ptr, struct IOStdReq *io);
74 struct DiskImagePlugin ciso_plugin = {
75 PLUGIN_NODE(0, "CISO"),
76 PLUGIN_FLAG_M68K,
78 ZERO,
79 NULL,
80 CISO_Init,
81 NULL,
82 CISO_CheckImage,
83 CISO_OpenImage,
84 CISO_CloseImage,
85 CISO_Geometry,
86 CISO_Read,
87 NULL,
88 NULL,
89 NULL,
90 NULL,
91 NULL
94 struct Library *SysBase;
95 struct Library *DOSBase;
96 static struct DIPluginIFace *IPlugin;
97 #ifndef __AROS__
98 #define ZBase image->zbase
99 #else
100 struct Library *Z1Base;
101 #endif
103 BOOL CISO_Init (struct DiskImagePlugin *Self, const struct PluginData *data) {
104 SysBase = data->SysBase;
105 DOSBase = data->DOSBase;
106 IPlugin = data->IPlugin;
107 return TRUE;
110 #define CISO_MAGIC MAKE_ID('C','I','S','O')
112 BOOL CISO_CheckImage (struct DiskImagePlugin *Self, BPTR file, CONST_STRPTR name, QUAD file_size,
113 const UBYTE *test, LONG testsize)
115 return testsize >= sizeof(ULONG) && rbe32(test) == CISO_MAGIC;
118 #pragma pack(1)
120 typedef struct {
121 ULONG magic;
122 ULONG header_size;
123 UQUAD total_bytes;
124 ULONG block_size;
125 UBYTE version;
126 UBYTE align;
127 UBYTE reserved[2];
128 } ciso_t;
130 #pragma pack()
132 APTR CISO_OpenImage (struct DiskImagePlugin *Self, APTR unit, BPTR file, CONST_STRPTR name) {
133 LONG done = FALSE;
134 LONG error = NO_ERROR;
135 LONG error_string = NO_ERROR_STRING;
136 IPTR error_args[4] = {0};
137 struct CISOImage *image = NULL;
138 ciso_t ciso;
139 ULONG block_size;
140 ULONG total_blocks;
141 ULONG index_size;
142 ULONG i;
144 if (Read(file, &ciso, sizeof(ciso)) != sizeof(ciso)) {
145 error = IoErr();
146 goto error;
148 if (ciso.block_size == 0 || ciso.total_bytes == 0) {
149 error = ERROR_BAD_NUMBER;
150 goto error;
153 block_size = rle32(&ciso.block_size);
154 total_blocks = rle64(&ciso.total_bytes) / block_size;
155 index_size = (total_blocks + 1) << 2;
157 image = AllocVec(sizeof(*image), MEMF_CLEAR);
158 if (!image) {
159 error = ERROR_NO_FREE_STORE;
160 goto error;
163 image->file = file;
164 image->block_size = block_size;
165 image->total_blocks = total_blocks;
166 image->align = ciso.align;
168 #ifdef __AROS__
169 image->zbase = OpenLibrary("z1.library", 1);
170 Z1Base = image->zbase;
171 #else
172 image->zbase = OpenLibrary("z.library", 1);
173 #endif
174 if (!image->zbase || !CheckLib(image->zbase, 1, 6)) {
175 error = ERROR_OBJECT_NOT_FOUND;
176 error_string = MSG_REQVER;
177 error_args[0] = (IPTR)"z.library";
178 error_args[1] = 1;
179 error_args[2] = 6;
180 goto error;
183 image->index_buf = AllocVec(index_size, MEMF_ANY);
184 image->block_buf = AllocVec(block_size << 1, MEMF_ANY);
185 if (!image->index_buf || !image->block_buf) {
186 error = ERROR_NO_FREE_STORE;
187 goto error;
190 if (InflateInit2(&image->zs, -15) != Z_OK) {
191 error = ERROR_OBJECT_WRONG_TYPE;
192 error_string = MSG_ZLIBERR;
193 goto error;
196 if (Read(file, image->index_buf, index_size) != index_size) {
197 error = IoErr();
198 goto error;
201 for (i = 0; i <= total_blocks; i++) {
202 image->index_buf[i] = rle32(&image->index_buf[i]);
205 done = TRUE;
207 error:
208 if (!done) {
209 if (image) {
210 Plugin_CloseImage(Self, image);
211 image = NULL;
212 } else {
213 Close(file);
215 if (error == NO_ERROR) {
216 error = ERROR_OBJECT_WRONG_TYPE;
217 error_string = MSG_EOF;
219 IPlugin_SetDiskImageErrorA(unit, error, error_string, error_args);
221 return image;
224 void CISO_CloseImage (struct DiskImagePlugin *Self, APTR image_ptr) {
225 struct CISOImage *image = image_ptr;
226 if (image) {
227 if (image->zbase) {
228 if (CheckLib(image->zbase, 1, 6)) InflateEnd(&image->zs);
229 CloseLibrary(image->zbase);
231 FreeVec(image->block_buf);
232 FreeVec(image->index_buf);
233 Close(image->file);
234 FreeVec(image);
238 LONG CISO_Geometry (struct DiskImagePlugin *Self, APTR image_ptr, struct DriveGeometry *dg) {
239 struct CISOImage *image = image_ptr;
240 dg->dg_SectorSize = image->block_size;
241 dg->dg_Heads =
242 dg->dg_TrackSectors =
243 dg->dg_CylSectors = 1;
244 dg->dg_Cylinders =
245 dg->dg_TotalSectors = image->total_blocks;
246 return IOERR_SUCCESS;
249 LONG CISO_Read (struct DiskImagePlugin *Self, APTR image_ptr, struct IOStdReq *io) {
250 struct CISOImage *image = image_ptr;
251 UBYTE *buffer;
252 UQUAD offset;
253 ULONG size;
254 ULONG block_size = image->block_size;
255 UBYTE align = image->align;
256 UBYTE *block_buf = image->block_buf;
257 ULONG *index_buf, index, index2, plain;
258 UBYTE *read_buf;
259 ULONG read_pos, read_size;
260 LONG error = IOERR_SUCCESS;
261 BPTR file = image->file;
263 buffer = io->io_Data;
264 offset = ((UQUAD)io->io_Offset)|((UQUAD)io->io_Actual << 32);
265 size = io->io_Length;
266 io->io_Actual = 0;
268 if (offset % block_size) return IOERR_BADADDRESS;
269 if (size % block_size) return IOERR_BADLENGTH;
271 offset /= block_size;
272 size /= block_size;
273 if (offset >= image->total_blocks) {
274 return IOERR_BADADDRESS;
276 if (offset + size > image->total_blocks) {
277 size = image->total_blocks - offset;
278 error = IOERR_BADLENGTH;
281 index_buf = image->index_buf + offset;
282 while (size--) {
283 index = *index_buf++;
284 plain = index & 0x80000000;
285 index -= plain;
286 read_pos = index << align;
287 if (plain) {
288 read_size = block_size;
289 read_buf = buffer;
290 } else {
291 index2 = *index_buf & 0x7fffffff;
292 read_size = (index2 - index) << align;
293 read_buf = block_buf;
295 if (!ChangeFilePosition(file, read_pos, OFFSET_BEGINNING) ||
296 Read(file, read_buf, read_size) != read_size)
298 return IPlugin_DOS2IOErr(IoErr());
300 if (!plain) {
301 InflateReset(&image->zs);
302 image->zs.next_in = read_buf;
303 image->zs.avail_in = read_size;
304 image->zs.next_out = buffer;
305 image->zs.avail_out = block_size;
306 if (Inflate(&image->zs, Z_SYNC_FLUSH) != Z_STREAM_END) {
307 return TDERR_NotSpecified;
310 buffer += block_size;
311 io->io_Actual += block_size;
313 return error;