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>
33 #include "device_locale.h"
34 #include <SDI_compiler.h>
35 #include "rev/diskimage.device_rev.h"
39 extern struct DiskImagePlugin cpc_plugin
;
41 PLUGIN_TABLE(&cpc_plugin
)
43 BOOL
CPC_Init (struct DiskImagePlugin
*Self
, const struct PluginData
*data
);
44 BOOL
CPC_CheckImage (struct DiskImagePlugin
*Self
, BPTR file
, CONST_STRPTR name
, QUAD file_size
,
45 const UBYTE
*test
, LONG testsize
);
46 APTR
CPC_OpenImage (struct DiskImagePlugin
*Self
, APTR unit
, BPTR file
, CONST_STRPTR name
);
47 void CPC_CloseImage (struct DiskImagePlugin
*Self
, APTR image_ptr
);
48 LONG
CPC_Geometry (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct DriveGeometry
*dg
);
49 LONG
CPC_Read (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct IOStdReq
*io
);
50 LONG
CPC_Write (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct IOStdReq
*io
);
52 struct DiskImagePlugin cpc_plugin
= {
53 PLUGIN_NODE(0, "CPC"),
72 struct Library
*SysBase
;
73 struct Library
*DOSBase
;
74 static struct DIPluginIFace
*IPlugin
;
76 BOOL
CPC_Init (struct DiskImagePlugin
*Self
, const struct PluginData
*data
) {
77 SysBase
= data
->SysBase
;
78 DOSBase
= data
->DOSBase
;
79 IPlugin
= data
->IPlugin
;
83 BOOL
CPC_CheckImage (struct DiskImagePlugin
*Self
, BPTR file
, CONST_STRPTR name
, QUAD file_size
,
84 const UBYTE
*test
, LONG testsize
)
86 return testsize
>= 8 && (!memcmp(test
, "MV - CPC", 8) || !memcmp(test
, "EXTENDED", 8));
100 APTR
CPC_OpenImage (struct DiskImagePlugin
*Self
, APTR unit
, BPTR file
,
104 LONG error
= NO_ERROR
;
105 LONG error_string
= NO_ERROR_STRING
;
106 IPTR error_args
[4] = {0};
107 struct CPC
*image
= NULL
;
110 UWORD tracks
, *tracksize_ptr
= (UWORD
*)&buf
[2];
111 ULONG track_offs
, track_size
;
113 if (Read(file
, buf
, 8) != 8) {
117 if (!memcmp(buf
, "EXTENDED", 8)) {
118 error
= ERROR_NOT_IMPLEMENTED
;
122 image
= AllocVec(sizeof(*image
), MEMF_CLEAR
);
124 error
= ERROR_NO_FREE_STORE
;
129 if (!ChangeFilePosition(file
, 40, OFFSET_CURRENT
) ||
130 Read(file
, buf
, 4) != 4)
135 image
->cylinders
= buf
[0];
136 image
->heads
= buf
[1];
137 image
->tracks
= image
->cylinders
* image
->heads
;
138 image
->track_size
= track_size
= rle16(tracksize_ptr
);
140 if (!image
->tracks
|| !image
->heads
|| image
->track_size
< 256) {
141 error
= ERROR_BAD_NUMBER
;
144 image
->track_size
-= 256;
146 image
->track_offsets
= AllocVec(image
->tracks
<< 2, MEMF_ANY
);
147 if (!image
->track_offsets
) {
148 error
= ERROR_NO_FREE_STORE
;
152 if (!ChangeFilePosition(file
, 204, OFFSET_CURRENT
)) {
157 tracks
= image
->tracks
;
158 ptr
= image
->track_offsets
;
162 track_offs
+= track_size
;
164 if (Read(file
, buf
, 22) != 22) {
168 if (memcmp(buf
, "Track-Info\r\n", 12)) {
169 error
= ERROR_OBJECT_WRONG_TYPE
;
172 if (!image
->sectors
) {
173 image
->sectors
= buf
[21];
174 image
->sector_size
= 128 << buf
[20];
177 if (!ChangeFilePosition(file
, track_size
-22, OFFSET_CURRENT
)) {
188 Plugin_CloseImage(Self
, image
);
193 if (error
== NO_ERROR
) {
194 error
= ERROR_OBJECT_WRONG_TYPE
;
195 error_string
= MSG_EOF
;
197 IPlugin_SetDiskImageErrorA(unit
, error
, error_string
, error_args
);
202 void CPC_CloseImage (struct DiskImagePlugin
*Self
, APTR image_ptr
) {
203 struct CPC
*image
= image_ptr
;
205 FreeVec(image
->track_offsets
);
211 LONG
CPC_Geometry (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct DriveGeometry
*dg
) {
212 struct CPC
*image
= image_ptr
;
213 dg
->dg_SectorSize
= image
->sector_size
;
214 dg
->dg_Cylinders
= image
->cylinders
;
215 dg
->dg_Heads
= image
->heads
;
216 dg
->dg_TrackSectors
= image
->track_size
/ image
->sector_size
;
217 dg
->dg_CylSectors
= dg
->dg_TrackSectors
* dg
->dg_Heads
;
218 dg
->dg_TotalSectors
= dg
->dg_CylSectors
* dg
->dg_Cylinders
;
219 return IOERR_SUCCESS
;
222 LONG
CPC_Read (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct IOStdReq
*io
) {
223 struct CPC
*image
= image_ptr
;
224 BPTR file
= image
->file
;
228 ULONG track
, track_size
;
229 ULONG to_skip
, to_read
;
233 buffer
= io
->io_Data
;
234 offset
= io
->io_Offset
;
235 size
= io
->io_Length
;
238 track_size
= image
->track_size
;
239 track
= offset
/ track_size
;
240 to_skip
= offset
% track_size
;
241 if (track
>= image
->tracks
) return IOERR_BADADDRESS
;
243 ptr
= image
->track_offsets
+ track
;
244 io
->io_Actual
= size
;
246 if (track
>= image
->tracks
) {
247 io
->io_Actual
-= size
;
248 return IOERR_BADLENGTH
;
251 if (!ChangeFilePosition(file
, (*ptr
++) + to_skip
, OFFSET_BEGINNING
)) {
252 io
->io_Actual
-= size
;
253 return TDERR_SeekError
;
256 to_read
= min(size
, track_size
- to_skip
);
257 status
= Read(file
, buffer
, to_read
);
259 io
->io_Actual
-= size
;
260 return IPlugin_DOS2IOErr(IoErr());
262 if (status
!= to_read
) {
263 io
->io_Actual
-= size
;
264 return IOERR_BADLENGTH
;
270 return IOERR_SUCCESS
;
273 LONG
CPC_Write (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct IOStdReq
*io
) {
274 struct CPC
*image
= image_ptr
;
275 BPTR file
= image
->file
;
279 ULONG track
, track_size
;
280 ULONG to_skip
, to_write
;
284 buffer
= io
->io_Data
;
285 offset
= io
->io_Offset
;
286 size
= io
->io_Length
;
289 track_size
= image
->track_size
;
290 track
= offset
/ track_size
;
291 to_skip
= offset
% track_size
;
292 if (track
>= image
->tracks
) return IOERR_BADADDRESS
;
294 ptr
= image
->track_offsets
+ track
;
295 io
->io_Actual
= size
;
297 if (track
>= image
->tracks
) {
298 io
->io_Actual
-= size
;
299 return IOERR_BADLENGTH
;
302 if (!ChangeFilePosition(file
, (*ptr
++) + to_skip
, OFFSET_BEGINNING
)) {
303 io
->io_Actual
-= size
;
304 return TDERR_SeekError
;
307 to_write
= min(size
, track_size
- to_skip
);
308 status
= Write(file
, buffer
, to_write
);
309 if (status
!= to_write
) {
310 io
->io_Actual
-= size
;
311 return IPlugin_DOS2IOErr(IoErr());
317 return IOERR_SUCCESS
;