1 /* Copyright 2007-2012 Fredrik Wikstrom. All rights reserved.
3 ** Redistribution and use in source and binary forms, with or without
4 ** modification, are permitted provided that the following conditions
7 ** 1. Redistributions of source code must retain the above copyright
8 ** notice, this list of conditions and the following disclaimer.
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>
35 # define InflateInit2 inflateInit2
36 # define Inflate inflate
37 # define InflateEnd inflateEnd
38 # define InflateReset inflateReset
40 # include <libraries/z.h>
44 #include <SDI_compiler.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
)
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"),
94 struct Library
*SysBase
;
95 struct Library
*DOSBase
;
96 static struct DIPluginIFace
*IPlugin
;
98 #define ZBase image->zbase
100 struct Library
*Z1Base
;
103 BOOL
CISO_Init (struct DiskImagePlugin
*Self
, const struct PluginData
*data
) {
104 SysBase
= data
->SysBase
;
105 DOSBase
= data
->DOSBase
;
106 IPlugin
= data
->IPlugin
;
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
;
132 APTR
CISO_OpenImage (struct DiskImagePlugin
*Self
, APTR unit
, BPTR file
, CONST_STRPTR name
) {
134 LONG error
= NO_ERROR
;
135 LONG error_string
= NO_ERROR_STRING
;
136 IPTR error_args
[4] = {0};
137 struct CISOImage
*image
= NULL
;
144 if (Read(file
, &ciso
, sizeof(ciso
)) != sizeof(ciso
)) {
148 if (ciso
.block_size
== 0 || ciso
.total_bytes
== 0) {
149 error
= ERROR_BAD_NUMBER
;
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
);
159 error
= ERROR_NO_FREE_STORE
;
164 image
->block_size
= block_size
;
165 image
->total_blocks
= total_blocks
;
166 image
->align
= ciso
.align
;
169 image
->zbase
= OpenLibrary("z1.library", 1);
170 Z1Base
= image
->zbase
;
172 image
->zbase
= OpenLibrary("z.library", 1);
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";
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
;
190 if (InflateInit2(&image
->zs
, -15) != Z_OK
) {
191 error
= ERROR_OBJECT_WRONG_TYPE
;
192 error_string
= MSG_ZLIBERR
;
196 if (Read(file
, image
->index_buf
, index_size
) != index_size
) {
201 for (i
= 0; i
<= total_blocks
; i
++) {
202 image
->index_buf
[i
] = rle32(&image
->index_buf
[i
]);
210 Plugin_CloseImage(Self
, image
);
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
);
224 void CISO_CloseImage (struct DiskImagePlugin
*Self
, APTR image_ptr
) {
225 struct CISOImage
*image
= image_ptr
;
228 if (CheckLib(image
->zbase
, 1, 6)) InflateEnd(&image
->zs
);
229 CloseLibrary(image
->zbase
);
231 FreeVec(image
->block_buf
);
232 FreeVec(image
->index_buf
);
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
;
242 dg
->dg_TrackSectors
=
243 dg
->dg_CylSectors
= 1;
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
;
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
;
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
;
268 if (offset
% block_size
) return IOERR_BADADDRESS
;
269 if (size
% block_size
) return IOERR_BADLENGTH
;
271 offset
/= 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
;
283 index
= *index_buf
++;
284 plain
= index
& 0x80000000;
286 read_pos
= index
<< align
;
288 read_size
= block_size
;
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());
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
;