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>
36 # define InflateInit2 inflateInit2
37 # define Inflate inflate
38 # define InflateEnd inflateEnd
39 # define InflateReset inflateReset
41 # include <libraries/z.h>
46 #include "device_locale.h"
48 #include <SDI_compiler.h>
49 #include "rev/diskimage.device_rev.h"
53 extern struct DiskImagePlugin daa_plugin
;
55 PLUGIN_TABLE(&daa_plugin
)
57 typedef struct daa_file_s
{
58 struct daa_file_s
*next
;
74 UBYTE
*in_buf
, *out_buf
;
75 ULONG in_size
, out_size
;
76 daa_data_t
*data_in_buf
;
80 struct Library
*zbase
;
83 BOOL
DAA_Init (struct DiskImagePlugin
*Self
, const struct PluginData
*data
);
84 BOOL
DAA_CheckImage (struct DiskImagePlugin
*Self
, BPTR file
, CONST_STRPTR name
, QUAD file_size
,
85 const UBYTE
*test
, LONG testsize
);
86 APTR
DAA_OpenImage (struct DiskImagePlugin
*Self
, APTR unit
, BPTR file
, CONST_STRPTR name
);
87 void DAA_CloseImage (struct DiskImagePlugin
*Self
, APTR image_ptr
);
88 LONG
DAA_Geometry (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct DriveGeometry
*dg
);
89 LONG
DAA_Read (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct IOStdReq
*io
);
91 struct DiskImagePlugin daa_plugin
= {
92 PLUGIN_NODE(0, "DAA"),
111 struct Library
*SysBase
;
112 struct Library
*DOSBase
;
113 static struct Library
*UtilityBase
;
114 static struct DIPluginIFace
*IPlugin
;
116 #define ZBase image->zbase
118 struct Library
*Z1Base
;
121 BOOL
DAA_Init (struct DiskImagePlugin
*Self
, const struct PluginData
*data
) {
122 SysBase
= data
->SysBase
;
123 DOSBase
= data
->DOSBase
;
124 UtilityBase
= data
->UtilityBase
;
125 IPlugin
= data
->IPlugin
;
129 BOOL
DAA_CheckImage (struct DiskImagePlugin
*Self
, BPTR file
, CONST_STRPTR name
, QUAD file_size
,
130 const UBYTE
*test
, LONG testsize
)
132 return testsize
>= 8 && (!strcmp(test
, "DAA") || !strcmp(test
, "DAA VOL"));
138 UBYTE sign
[16]; // 00: DAA
139 ULONG size_offset
; // 10: where starts the list of sizes of the zipped chunks
140 ULONG b100
; // 14: must be 0x100
141 ULONG data_offset
; // 18: where starts the zipped chunks
142 ULONG b1
; // 1C: must be 1
143 ULONG b0
; // 20: ever 0
144 ULONG chunksize
; // 24: size of each output chunk
145 UQUAD isosize
; // 28: total size of the output ISO
146 UQUAD filesize
; // 30: total size of the DAA file
147 UBYTE zero
[16]; // 38: it's ever zero
148 ULONG crc
; // 48: checksum calculated on the first 0x48 bytes
153 static CONST_STRPTR
find_ext (CONST_STRPTR fname
, CONST_STRPTR ext
) {
157 extlen
= strlen(ext
);
158 ret
= fname
+len
-extlen
;
159 if (len
>= extlen
&& !Stricmp(ret
, ext
)) {
165 APTR
DAA_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 DAAImage
*image
= NULL
;
175 LONG multi
= FALSE
, multinum
= 0;
177 STRPTR namebuf
= NULL
, extbuf
= NULL
;
178 CONST_STRPTR fmt
= NULL
;
179 ULONG daa_size
, daas
, i
;
180 UBYTE
*daa_data
= NULL
, *src
;
183 if (FRead(file
, &daa
, 1, sizeof(daa
)) != sizeof(daa
)) {
187 if (!strcmp(daa
.sign
, "DAA VOL")) {
188 error
= ERROR_OBJECT_WRONG_TYPE
;
189 error_string
= MSG_WRONGDAA
;
192 if (strcmp(daa
.sign
, "DAA") ||
193 rle32(&daa
.b100
) != 0x100 ||
196 error
= ERROR_OBJECT_WRONG_TYPE
;
200 offset
= sizeof(daa
);
201 size_offset
= rle32(&daa
.size_offset
);
202 while (offset
< size_offset
) {
203 if (FRead(file
, &type
, 1, 4) != 4 ||
204 FRead(file
, &len
, 1, 4) != 4)
215 error
= ERROR_OBJECT_WRONG_TYPE
;
219 if (!ChangeFilePosition(file
, len
-8, OFFSET_CURRENT
)) {
226 image
= AllocVec(sizeof(*image
), MEMF_CLEAR
);
228 error
= ERROR_NO_FREE_STORE
;
233 fn
= AllocVec(sizeof(*fn
), MEMF_CLEAR
);
235 error
= ERROR_NO_FREE_STORE
;
239 fn
->size
= GetFileSize(file
);
240 fn
->offset
= rle32(&daa
.data_offset
);
241 if (fn
->size
== (UQUAD
)-1) {
247 image
->zbase
= OpenLibrary("z1.library", 1);
248 Z1Base
= image
->zbase
;
250 image
->zbase
= OpenLibrary("z.library", 1);
252 if (!image
->zbase
|| !CheckLib(image
->zbase
, 1, 6)) {
253 error
= ERROR_OBJECT_NOT_FOUND
;
254 error_string
= MSG_REQVER
;
255 error_args
[0] = (IPTR
)"z.library";
261 if (multi
|| fn
->size
!= rle64(&daa
.filesize
)) {
263 if ((p
= find_ext(name
, "001.daa"))) {
267 if ((p
= find_ext(name
, "01.daa"))) {
273 p
= find_ext(name
, ".daa");
274 if (!p
) p
= strchr(p
, 0);
277 namebuf
= AllocVec(len
+ 16, MEMF_ANY
);
279 error
= ERROR_NO_FREE_STORE
;
282 memcpy(namebuf
, name
, len
);
283 extbuf
= namebuf
+ len
;
285 case 1: fmt
= "%03ld.daa"; break;
286 case 2: fmt
= "%02ld.daa"; break;
287 default: fmt
= ".d%02ld"; break;
291 daa_size
= rle32(&daa
.data_offset
) - size_offset
;
293 image
->out_size
= rle32(&daa
.chunksize
);
294 image
->block_size
= 2048;
295 image
->total_bytes
= daas
* image
->out_size
;
296 image
->total_blocks
= image
->total_bytes
>> 11;
298 daa_data
= AllocVec(daa_size
, MEMF_ANY
);
299 image
->data
= data
= AllocVec(daas
* sizeof(*image
->data
), MEMF_ANY
);
300 image
->out_buf
= AllocVec(image
->out_size
, MEMF_ANY
);
301 if (!daa_data
|| !data
|| !image
->out_buf
) {
302 error
= ERROR_NO_FREE_STORE
;
306 if (!ChangeFilePosition(file
, size_offset
- offset
, OFFSET_CURRENT
) ||
307 FRead(file
, daa_data
, 1, daa_size
) != daa_size
)
315 for (i
= 0; i
< daas
; i
++) {
316 while (offset
>= fn
->size
) {
320 error
= ERROR_OBJECT_WRONG_TYPE
;
324 fn
->next
= AllocVec(sizeof(*fn
), MEMF_CLEAR
);
325 if (!(fn
= fn
->next
)) {
326 error
= ERROR_NO_FREE_STORE
;
330 SNPrintf(extbuf
, 16, fmt
, multinum
++);
331 fn
->file
= file
= Open(namebuf
, MODE_OLDFILE
);
333 (fn
->size
= GetFileSize(file
)) == (UQUAD
)-1 ||
334 Read(file
, &daa
, sizeof(daa
)) != sizeof(daa
))
339 if (strcmp(daa
.sign
, "DAA VOL")) {
340 error
= ERROR_OBJECT_WRONG_TYPE
;
344 fn
->offset
= rle32(&daa
.size_offset
);
345 offset
+= fn
->offset
;
346 if (!ChangeFilePosition(file
, fn
->offset
, OFFSET_BEGINNING
)) {
352 len
= (src
[0] << 16)|(src
[2] << 8)|(src
[1]);
357 data
->offset
= offset
;
362 if (InflateInit2(&image
->zs
, -15) != Z_OK
) {
363 error
= ERROR_OBJECT_WRONG_TYPE
;
364 error_string
= MSG_ZLIBERR
;
375 Plugin_CloseImage(Self
, image
);
380 if (error
== NO_ERROR
) {
381 error
= ERROR_OBJECT_WRONG_TYPE
;
382 error_string
= MSG_EOF
;
384 IPlugin_SetDiskImageErrorA(unit
, error
, error_string
, error_args
);
389 void DAA_CloseImage (struct DiskImagePlugin
*Self
, APTR image_ptr
) {
390 struct DAAImage
*image
= image_ptr
;
393 daa_file_t
*fn
, *next
;
395 if (CheckLib(image
->zbase
, 1, 6)) InflateEnd(&image
->zs
);
396 CloseLibrary(image
->zbase
);
398 FreeVec(image
->in_buf
);
399 FreeVec(image
->out_buf
);
400 for (fn
= image
->files
; fn
; fn
= next
) {
405 FreeVec(image
->data
);
410 LONG
DAA_Geometry (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct DriveGeometry
*dg
) {
411 struct DAAImage
*image
= image_ptr
;
412 dg
->dg_SectorSize
= image
->block_size
;
414 dg
->dg_TrackSectors
=
415 dg
->dg_CylSectors
= 1;
417 dg
->dg_TotalSectors
= image
->total_blocks
;
418 return IOERR_SUCCESS
;
421 LONG
DAA_Read (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct IOStdReq
*io
) {
422 struct DAAImage
*image
= image_ptr
;
425 ULONG block
, to_read
, to_skip
;
427 ULONG out_size
= image
->out_size
;
430 LONG error
= IOERR_SUCCESS
;
432 buffer
= io
->io_Data
;
433 offset
= ((UQUAD
)io
->io_Offset
)|((UQUAD
)io
->io_Actual
<< 32);
434 size
= io
->io_Length
;
437 if (offset
>= image
->total_bytes
) return TDERR_SeekError
;
438 if (offset
+ size
> image
->total_bytes
) {
439 error
= IOERR_BADLENGTH
;
440 size
= image
->total_bytes
- offset
;
443 block
= offset
/ out_size
;
444 to_skip
= offset
% out_size
;
445 data
= image
->data
+ block
;
447 to_read
= min(size
, out_size
- to_skip
);
449 if (image
->data_in_buf
!= data
) {
452 ULONG bytes_left
, read_size
;
454 image
->data_in_buf
= NULL
;
456 image
->in_buf
= ReAllocBuf(image
->in_buf
, &image
->in_size
, data
->size
);
457 if (!image
->in_buf
) {
461 in_buf
= image
->in_buf
;
463 bytes_left
= data
->size
;
464 read_offs
= data
->offset
;
466 if (!ChangeFilePosition(fn
->file
, data
->offset
, OFFSET_BEGINNING
)) {
467 return TDERR_SeekError
;
469 read_size
= min(bytes_left
, fn
->size
- read_offs
);
470 if (Read(fn
->file
, in_buf
, read_size
) != read_size
) {
471 return IPlugin_DOS2IOErr(IoErr());
473 bytes_left
-= read_size
;
474 if (bytes_left
== 0) break;
479 InflateReset(&image
->zs
);
480 image
->zs
.next_in
= image
->in_buf
;
481 image
->zs
.next_out
= image
->out_buf
;
482 image
->zs
.avail_in
= data
->size
;
483 image
->zs
.avail_out
= out_size
;
484 if (Inflate(&image
->zs
, Z_SYNC_FLUSH
) != Z_STREAM_END
) {
485 return TDERR_NotSpecified
;
488 image
->data_in_buf
= data
;
490 CopyMem(image
->out_buf
+ to_skip
, buffer
, to_read
);
495 io
->io_Actual
+= to_read
;