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/exec.h>
30 #include <proto/dos.h>
31 #include <proto/utility.h>
35 # define InflateInit2 inflateInit2
36 # define Inflate inflate
37 # define InflateEnd inflateEnd
38 # define InflateReset inflateReset
40 # include <libraries/z.h>
46 #include "device_locale.h"
47 #include <SDI_compiler.h>
48 #include "rev/diskimage.device_rev.h"
52 extern struct DiskImagePlugin uif_plugin
;
54 PLUGIN_TABLE(&uif_plugin
)
58 BOOL
UIF_Init (struct DiskImagePlugin
*Self
, const struct PluginData
*data
);
59 BOOL
UIF_CheckImage (struct DiskImagePlugin
*Self
, BPTR file
, CONST_STRPTR name
, QUAD file_size
,
60 const UBYTE
*test
, LONG testsize
);
61 APTR
UIF_OpenImage (struct DiskImagePlugin
*Self
, APTR unit
, BPTR file
, CONST_STRPTR name
);
62 void UIF_CloseImage (struct DiskImagePlugin
*Self
, APTR image_ptr
);
63 LONG
UIF_Geometry (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct DriveGeometry
*dg
);
64 LONG
UIF_Read (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct IOStdReq
*io
);
66 struct DiskImagePlugin uif_plugin
= {
67 PLUGIN_NODE(0, "UIF"),
68 PLUGIN_FLAG_FOOTER
|PLUGIN_FLAG_M68K
,
86 struct Library
*SysBase
;
87 struct Library
*DOSBase
;
88 static struct DIPluginIFace
*IPlugin
;
90 #define ZBase image->zbase
92 struct Library
*Z1Base
;
95 BOOL
UIF_Init (struct DiskImagePlugin
*Self
, const struct PluginData
*data
) {
96 SysBase
= data
->SysBase
;
97 DOSBase
= data
->DOSBase
;
98 IPlugin
= data
->IPlugin
;
102 #define BBIS_MAGIC MAKE_ID('b','b','i','s')
103 #define BLHR_MAGIC MAKE_ID('b','l','h','r')
104 #define BSDR_MAGIC MAKE_ID('b','s','d','r')
106 BOOL
UIF_CheckImage (struct DiskImagePlugin
*Self
, BPTR file
, CONST_STRPTR name
, QUAD file_size
,
107 const UBYTE
*test
, LONG testsize
)
109 return testsize
>= 64 && rbe32(&test
[testsize
-64]) == BBIS_MAGIC
;
139 ULONG blhr_bbis_size
;
154 UBYTE
*in_buf
, *out_buf
;
155 ULONG in_size
, out_size
;
157 blhr_data_t
*data
, *data_in_buf
;
158 struct UIFHash
*hash
;
162 struct Library
*zbase
;
165 APTR
UIF_OpenImage (struct DiskImagePlugin
*Self
, APTR unit
, BPTR file
, CONST_STRPTR name
) {
167 LONG error
= NO_ERROR
;
168 LONG error_string
= NO_ERROR_STRING
;
169 IPTR error_args
[4] = {0};
170 struct UIFImage
*image
= NULL
;
173 blhr_data_t
*data
= NULL
;
177 struct UIFHash
*hash
;
178 UQUAD offset
, next_offset
;
181 if (!ChangeFilePosition(file
, -(int)sizeof(bbis
), OFFSET_END
) ||
182 Read(file
, &bbis
, sizeof(bbis
)) != sizeof(bbis
))
187 if (rbe32(&bbis
.magic
) != BBIS_MAGIC
) {
188 error
= ERROR_OBJECT_WRONG_TYPE
;
192 if (!ChangeFilePosition(file
, rle64(&bbis
.blhr
), OFFSET_BEGINNING
) ||
193 Read(file
, &blhr
, sizeof(blhr
)) != sizeof(blhr
))
198 if (rbe32(&blhr
.magic
) != BLHR_MAGIC
) {
199 error
= ERROR_OBJECT_WRONG_TYPE
;
203 image
= AllocVec(sizeof(*image
), MEMF_CLEAR
);
205 error
= ERROR_NO_FREE_STORE
;
210 image
->num
= rle32(&blhr
.num
);
211 image
->block_size
= rle32(&bbis
.sector_size
);
214 image
->zbase
= OpenLibrary("z1.library", 1);
215 Z1Base
= image
->zbase
;
217 image
->zbase
= OpenLibrary("z.library", 1);
219 if (!image
->zbase
|| !CheckLib(image
->zbase
, 1, 6)) {
220 error
= ERROR_OBJECT_NOT_FOUND
;
221 error_string
= MSG_REQVER
;
222 error_args
[0] = (IPTR
)"z.library";
228 image
->in_size
= rle32(&blhr
.size
);
229 image
->out_size
= sizeof(*data
) * image
->num
;
231 image
->in_buf
= AllocVec(image
->in_size
, MEMF_ANY
);
232 image
->data
= AllocVec(image
->out_size
, MEMF_ANY
);
233 if (!image
->in_buf
|| !image
->data
) {
234 error
= ERROR_NO_FREE_STORE
;
238 if (Read(file
, image
->in_buf
, image
->in_size
) != image
->in_size
) {
243 if (InflateInit2(&image
->zs
, 15) != Z_OK
) {
244 error
= ERROR_OBJECT_WRONG_TYPE
;
245 error_string
= MSG_ZLIBERR
;
249 image
->zs
.next_in
= image
->in_buf
;
250 image
->zs
.next_out
= (UBYTE
*)image
->data
;
251 image
->zs
.avail_in
= image
->in_size
;
252 image
->zs
.avail_out
= image
->out_size
;
253 if (Inflate(&image
->zs
, Z_SYNC_FLUSH
) != Z_STREAM_END
) {
254 error
= ERROR_OBJECT_WRONG_TYPE
;
255 error_string
= MSG_ZLIBERR
;
261 for (i
= 0; i
< image
->num
; i
++, data
++) {
262 data
->offset
= rle64(&data
->offset
);
263 data
->in_size
= rle32(&data
->in_size
);
264 data
->sector
= rle32(&data
->sector
);
265 data
->out_size
= rle32(&data
->out_size
);
266 data
->type
= rle32(&data
->type
);
268 image
->total_blocks
+= data
->out_size
;
269 data
->out_size
*= image
->block_size
;
271 switch (data
->type
) {
277 error
= ERROR_BAD_NUMBER
;
282 image
->total_bytes
= image
->total_blocks
* image
->block_size
;
284 hash_size
= ((image
->total_bytes
>> HASH_FUNC
) + 1) << 3;
285 image
->hash
= hash
= AllocVec(hash_size
, MEMF_ANY
);
287 error
= ERROR_NO_FREE_STORE
;
295 for (i
= 0; i
< image
->num
; i
++, data
++) {
296 next_offset
+= data
->out_size
;
297 while (next_offset
> hash_offset
) {
299 hash
->offset
= offset
/ image
->block_size
;
301 hash_offset
+= (1 << HASH_FUNC
);
303 offset
= next_offset
;
311 Plugin_CloseImage(Self
, image
);
316 if (error
== NO_ERROR
) {
317 error
= ERROR_OBJECT_WRONG_TYPE
;
318 error_string
= MSG_EOF
;
320 IPlugin_SetDiskImageErrorA(unit
, error
, error_string
, error_args
);
325 void UIF_CloseImage (struct DiskImagePlugin
*Self
, APTR image_ptr
) {
326 struct UIFImage
*image
= image_ptr
;
329 if (CheckLib(image
->zbase
, 1, 6)) InflateEnd(&image
->zs
);
330 CloseLibrary(image
->zbase
);
332 FreeVec(image
->hash
);
333 FreeVec(image
->data
);
334 FreeVec(image
->in_buf
);
335 FreeVec(image
->out_buf
);
341 LONG
UIF_Geometry (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct DriveGeometry
*dg
) {
342 struct UIFImage
*image
= image_ptr
;
343 dg
->dg_SectorSize
= image
->block_size
;
345 dg
->dg_TrackSectors
=
346 dg
->dg_CylSectors
= 1;
348 dg
->dg_TotalSectors
= image
->total_blocks
;
349 return IOERR_SUCCESS
;
352 LONG
UIF_Read (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct IOStdReq
*io
) {
353 struct UIFImage
*image
= image_ptr
;
354 BPTR file
= image
->file
;
358 struct UIFHash
*hash
;
360 UQUAD read_offs
, next_offs
;
361 ULONG to_skip
, to_read
;
363 buffer
= io
->io_Data
;
364 offset
= ((UQUAD
)io
->io_Offset
)|((UQUAD
)io
->io_Actual
<< 32);
365 size
= io
->io_Length
;
368 if (offset
>= image
->total_bytes
) return TDERR_SeekError
;
370 hash
= &image
->hash
[offset
>> HASH_FUNC
];
373 read_offs
= next_offs
= hash
->offset
* image
->block_size
;
375 next_offs
+= data
->out_size
;
376 if (next_offs
> offset
) break;
377 read_offs
= next_offs
;
381 to_skip
= offset
- read_offs
;
383 if (read_offs
== image
->total_bytes
) return IOERR_BADLENGTH
;
385 if (data
->in_size
> image
->in_size
) {
386 FreeVec(image
->in_buf
);
387 image
->in_buf
= AllocVec(image
->in_size
= data
->in_size
, MEMF_ANY
);
388 if (!image
->in_buf
) {
393 if (data
->out_size
> image
->out_size
) {
394 FreeVec(image
->out_buf
);
395 image
->out_buf
= AllocVec(image
->out_size
= data
->out_size
, MEMF_ANY
);
396 if (!image
->out_buf
) {
402 if (image
->data_in_buf
!= data
) {
403 image
->data_in_buf
= NULL
;
404 if (!ChangeFilePosition(file
, data
->offset
, OFFSET_BEGINNING
) ||
405 Read(file
, image
->in_buf
, data
->in_size
) != data
->in_size
)
407 return IPlugin_DOS2IOErr(IoErr());
411 to_read
= min(data
->out_size
- to_skip
, size
);
412 switch (data
->type
) {
414 if (data
->in_size
!= data
->out_size
) {
415 return TDERR_NotSpecified
;
417 CopyMem(image
->in_buf
+ to_skip
, buffer
, to_read
);
418 image
->data_in_buf
= data
;
421 memset(buffer
, 0, to_read
);
424 if (image
->data_in_buf
!= data
) {
425 InflateReset(&image
->zs
);
426 image
->zs
.next_in
= image
->in_buf
;
427 image
->zs
.next_out
= image
->out_buf
;
428 image
->zs
.avail_in
= data
->in_size
;
429 image
->zs
.avail_out
= data
->out_size
;
430 if (Inflate(&image
->zs
, Z_SYNC_FLUSH
) != Z_STREAM_END
) {
431 return TDERR_NotSpecified
;
433 image
->data_in_buf
= data
;
435 CopyMem(image
->out_buf
+ to_skip
, buffer
, to_read
);
442 io
->io_Actual
+= to_read
;
444 read_offs
+= data
->out_size
;
447 return IOERR_SUCCESS
;