Were did that svn:executable come from?
[AROS.git] / workbench / devs / diskimage / plugins / cpc.c
blob849c1428c5a72d2ce6005c0b16342540549223ed
1 /* Copyright 2007-2012 Fredrik Wikstrom. All rights reserved.
2 **
3 ** Redistribution and use in source and binary forms, with or without
4 ** modification, are permitted provided that the following conditions
5 ** are met:
6 **
7 ** 1. Redistributions of source code must retain the above copyright
8 ** notice, this list of conditions and the following disclaimer.
9 **
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 <string.h>
32 #include "endian.h"
33 #include "device_locale.h"
34 #include <SDI_compiler.h>
35 #include "rev/diskimage.device_rev.h"
37 PLUGIN_VERSTAG("CPC")
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"),
54 PLUGIN_FLAG_M68K,
56 ZERO,
57 NULL,
58 CPC_Init,
59 NULL,
60 CPC_CheckImage,
61 CPC_OpenImage,
62 CPC_CloseImage,
63 CPC_Geometry,
64 CPC_Read,
65 CPC_Write,
66 NULL,
67 NULL,
68 NULL,
69 NULL
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;
80 return TRUE;
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));
89 struct CPC {
90 BPTR file;
91 ULONG *track_offsets;
92 UWORD track_size;
93 UWORD sector_size;
94 UBYTE tracks;
95 UBYTE cylinders;
96 UBYTE heads;
97 UBYTE sectors;
100 APTR CPC_OpenImage (struct DiskImagePlugin *Self, APTR unit, BPTR file,
101 CONST_STRPTR name)
103 LONG done = FALSE;
104 LONG error = NO_ERROR;
105 LONG error_string = NO_ERROR_STRING;
106 IPTR error_args[4] = {0};
107 struct CPC *image = NULL;
108 UBYTE buf[22];
109 ULONG *ptr;
110 UWORD tracks;
111 ULONG track_offs, track_size;
113 if (Read(file, buf, 8) != 8) {
114 error = IoErr();
115 goto error;
117 if (!memcmp(buf, "EXTENDED", 8)) {
118 error = ERROR_NOT_IMPLEMENTED;
119 goto error;
122 image = AllocVec(sizeof(*image), MEMF_CLEAR);
123 if (!image) {
124 error = ERROR_NO_FREE_STORE;
125 goto error;
127 image->file = file;
129 if (!ChangeFilePosition(file, 40, OFFSET_CURRENT) ||
130 Read(file, buf, 4) != 4)
132 error = IoErr();
133 goto error;
135 image->cylinders = buf[0];
136 image->heads = buf[1];
137 image->tracks = image->cylinders * image->heads;
138 image->track_size = track_size = rle16(&buf[2]);
140 if (!image->tracks || !image->heads || image->track_size < 256) {
141 error = ERROR_BAD_NUMBER;
142 goto error;
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;
149 goto error;
152 if (!ChangeFilePosition(file, 204, OFFSET_CURRENT)) {
153 error = IoErr();
154 goto error;
157 tracks = image->tracks;
158 ptr = image->track_offsets;
159 track_offs = 512;
160 while (tracks--) {
161 *ptr++ = track_offs;
162 track_offs += track_size;
164 if (Read(file, buf, 22) != 22) {
165 error = IoErr();
166 goto error;
168 if (memcmp(buf, "Track-Info\r\n", 12)) {
169 error = ERROR_OBJECT_WRONG_TYPE;
170 goto error;
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)) {
178 error = IoErr();
179 goto error;
183 done = TRUE;
185 error:
186 if (!done) {
187 if (image) {
188 Plugin_CloseImage(Self, image);
189 image = NULL;
190 } else {
191 Close(file);
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);
199 return image;
202 void CPC_CloseImage (struct DiskImagePlugin *Self, APTR image_ptr) {
203 struct CPC *image = image_ptr;
204 if (image) {
205 FreeVec(image->track_offsets);
206 Close(image->file);
207 FreeVec(image);
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;
225 UBYTE *buffer;
226 ULONG offset;
227 ULONG size;
228 ULONG track, track_size;
229 ULONG to_skip, to_read;
230 ULONG *ptr;
231 LONG status;
233 buffer = io->io_Data;
234 offset = io->io_Offset;
235 size = io->io_Length;
236 io->io_Actual = 0;
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;
245 while (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);
258 if (status == -1) {
259 io->io_Actual -= size;
260 return IPlugin_DOS2IOErr(IoErr());
261 } else
262 if (status != to_read) {
263 io->io_Actual -= size;
264 return IOERR_BADLENGTH;
267 buffer += to_read;
268 size -= to_read;
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;
276 UBYTE *buffer;
277 ULONG offset;
278 ULONG size;
279 ULONG track, track_size;
280 ULONG to_skip, to_write;
281 ULONG *ptr;
282 LONG status;
284 buffer = io->io_Data;
285 offset = io->io_Offset;
286 size = io->io_Length;
287 io->io_Actual = 0;
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;
296 while (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());
314 buffer += to_write;
315 size -= to_write;
317 return IOERR_SUCCESS;