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>
32 #include "device_locale.h"
35 #include <SDI_compiler.h>
36 #include "rev/diskimage.device_rev.h"
40 extern struct DiskImagePlugin gi_plugin
;
42 PLUGIN_TABLE(&gi_plugin
)
44 BOOL
GI_Init (struct DiskImagePlugin
*Self
, const struct PluginData
*data
);
45 BOOL
GI_CheckImage (struct DiskImagePlugin
*Self
, BPTR file
, CONST_STRPTR name
, QUAD file_size
,
46 const UBYTE
*test
, LONG testsize
);
47 APTR
GI_OpenImage (struct DiskImagePlugin
*Self
, APTR unit
, BPTR file
, CONST_STRPTR name
);
48 void GI_CloseImage (struct DiskImagePlugin
*Self
, APTR image_ptr
);
49 LONG
GI_Geometry (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct DriveGeometry
*dg
);
50 LONG
GI_Read (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct IOStdReq
*io
);
52 struct DiskImagePlugin gi_plugin
= {
72 struct Library
*SysBase
;
73 struct Library
*DOSBase
;
74 static struct Library
*UtilityBase
;
75 static struct DIPluginIFace
*IPlugin
;
77 BOOL
GI_Init (struct DiskImagePlugin
*Self
, const struct PluginData
*data
) {
78 SysBase
= data
->SysBase
;
79 DOSBase
= data
->DOSBase
;
80 UtilityBase
= data
->UtilityBase
;
81 IPlugin
= data
->IPlugin
;
85 BOOL
GI_CheckImage (struct DiskImagePlugin
*Self
, BPTR file
, CONST_STRPTR name
, QUAD file_size
,
86 const UBYTE
*test
, LONG testsize
)
92 return !Stricmp(name
, ".gi");
98 struct FileNode
*next
;
105 struct FileNode
*files
;
111 APTR
GI_OpenImage (struct DiskImagePlugin
*Self
, APTR unit
, BPTR file
,
115 LONG error
= NO_ERROR
;
116 LONG error_string
= NO_ERROR_STRING
;
117 IPTR error_args
[4] = {0};
118 struct GIImage
*image
= NULL
;
121 STRPTR namebuf
= NULL
, extbuf
;
122 CONST_STRPTR fmt
= "%ld.gi";
125 image
= AllocVec(sizeof(*image
), MEMF_CLEAR
);
127 error
= ERROR_NO_FREE_STORE
;
131 ext
= strrchr(name
, '.');
134 namebuf
= AllocVec(len
+ 8, MEMF_ANY
);
135 image
->files
= fn
= AllocVec(sizeof(*fn
), MEMF_CLEAR
);
136 if (!namebuf
|| !fn
) {
137 error
= ERROR_NO_FREE_STORE
;
142 CopyMem(name
, namebuf
, len
);
143 extbuf
= namebuf
+ len
;
148 fn
->offset
= image
->total_bytes
;
149 fn
->size
= GetFileSize(file
);
150 if (fn
->size
== -1) {
154 image
->total_bytes
+= fn
->size
;
156 SNPrintf(extbuf
, 8, fmt
, i
++);
157 file
= Open(namebuf
, MODE_OLDFILE
);
160 if (error
!= ERROR_OBJECT_NOT_FOUND
) {
166 fn
->next
= AllocVec(sizeof(*fn
), MEMF_CLEAR
);
167 if (!(fn
= fn
->next
)) {
168 error
= ERROR_NO_FREE_STORE
;
174 image
->block_size
= 2048;
175 image
->total_blocks
= image
->total_bytes
>> 11;
183 Plugin_CloseImage(Self
, image
);
188 if (error
== NO_ERROR
) {
189 error
= ERROR_OBJECT_WRONG_TYPE
;
190 error_string
= MSG_EOF
;
192 IPlugin_SetDiskImageErrorA(unit
, error
, error_string
, error_args
);
197 void GI_CloseImage (struct DiskImagePlugin
*Self
, APTR image_ptr
) {
198 struct GIImage
*image
= image_ptr
;
200 struct FileNode
*fn
, *next
;
212 LONG
GI_Geometry (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct DriveGeometry
*dg
) {
213 struct GIImage
*image
= image_ptr
;
214 dg
->dg_SectorSize
= image
->block_size
;
216 dg
->dg_TrackSectors
=
217 dg
->dg_CylSectors
= 1;
219 dg
->dg_TotalSectors
= image
->total_blocks
;
220 return IOERR_SUCCESS
;
223 LONG
GI_Read (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct IOStdReq
*io
) {
224 struct GIImage
*image
= image_ptr
;
226 UQUAD offset
, in_offs
;
231 buffer
= io
->io_Data
;
232 offset
= ((UQUAD
)io
->io_Offset
)|((UQUAD
)io
->io_Actual
<< 32);
233 size
= io
->io_Length
;
236 if (offset
>= image
->total_bytes
) return TDERR_SeekError
;
239 while (fn
&& fn
->offset
+ fn
->size
<= offset
) fn
= fn
->next
;
240 if (!fn
) return TDERR_SeekError
;
242 in_offs
= offset
- fn
->offset
;
243 if (in_offs
&& !ChangeFilePosition(fn
->file
, in_offs
, OFFSET_BEGINNING
)) {
244 return TDERR_SeekError
;
248 if (!fn
) return IOERR_BADLENGTH
;
250 to_read
= min(size
, fn
->size
- in_offs
);
251 status
= Read(fn
->file
, buffer
, to_read
);
253 return IPlugin_DOS2IOErr(IoErr());
255 if (status
!= to_read
) {
256 return IOERR_BADLENGTH
;
262 io
->io_Actual
+= to_read
;
265 return IOERR_SUCCESS
;