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"
35 #include <SDI_compiler.h>
36 #include "rev/diskimage.device_rev.h"
40 extern struct DiskImagePlugin dms_plugin
;
42 PLUGIN_TABLE(&dms_plugin
)
44 BOOL
DMS_Init (struct DiskImagePlugin
*Self
, const struct PluginData
*data
);
45 BOOL
DMS_CheckImage (struct DiskImagePlugin
*Self
, BPTR file
, CONST_STRPTR name
, QUAD file_size
,
46 const UBYTE
*test
, LONG testsize
);
47 APTR
DMS_OpenImage (struct DiskImagePlugin
*Self
, APTR unit
, BPTR file
, CONST_STRPTR name
);
49 struct DiskImagePlugin dms_plugin
= {
50 PLUGIN_NODE(0, "DMS"),
69 static struct Library
*SysBase
;
70 static struct Library
*DOSBase
;
71 static struct DIPluginIFace
*IPlugin
;
73 BOOL
DMS_Init (struct DiskImagePlugin
*Self
, const struct PluginData
*data
) {
74 SysBase
= data
->SysBase
;
75 DOSBase
= data
->DOSBase
;
76 IPlugin
= data
->IPlugin
;
80 #define DMS_MAGIC MAKE_ID('D','M','S','!')
82 BOOL
DMS_CheckImage (struct DiskImagePlugin
*Self
, BPTR file
, CONST_STRPTR name
, QUAD file_size
,
83 const UBYTE
*test
, LONG testsize
)
85 return testsize
>= sizeof(ULONG
) && rbe32(test
) == DMS_MAGIC
;
88 #define TRACK_BUFFER_SIZE (32*1024)
89 #define TEMP_BUFFER_SIZE (32*1024)
95 #define ERR_UNKNMODE 2
97 static LONG
process_track (struct xdms_data
*xdms
, BPTR in
, BPTR out
, UBYTE
*b1
, UBYTE
*b2
, UWORD pwd
,
98 UBYTE
*eof
, LONG
*error_string
);
99 static UWORD
unpack_track (struct xdms_data
*xdms
, UBYTE
*b1
, UBYTE
*b2
, UWORD pklen2
, UWORD unpklen
,
100 UWORD cmode
, UBYTE flags
);
101 static void dms_decrypt (struct xdms_data
*xdms
, UBYTE
*p
, UWORD len
);
103 APTR
DMS_OpenImage (struct DiskImagePlugin
*Self
, APTR unit
, BPTR file
,
107 LONG error
= NO_ERROR
;
108 LONG error_string
= NO_ERROR_STRING
;
109 IPTR error_args
[4] = {0};
112 UWORD geninfo
, hcrc
, disktype
;
117 CONST_STRPTR tmpname
;
118 struct xdms_data
*xdms
;
121 b1
= AllocVec(TRACK_BUFFER_SIZE
, MEMF_ANY
);
122 b2
= AllocVec(TRACK_BUFFER_SIZE
, MEMF_ANY
);
123 xdms
= AllocVec(sizeof(struct xdms_data
), MEMF_CLEAR
);
124 text
= AllocVec(TEMP_BUFFER_SIZE
, MEMF_ANY
);
125 if (!b1
|| !b2
|| !xdms
|| !text
) {
126 error
= ERROR_NO_FREE_STORE
;
131 if (FRead(file
, b1
, 1, HEADLEN
) != HEADLEN
) {
135 hcrc
= rbe16(&b1
[HEADLEN
-2]);
136 if (hcrc
!= CreateCRC(b1
+4, HEADLEN
-6)) {
137 error
= ERROR_BAD_NUMBER
;
138 error_string
= MSG_BADCRC
;
142 geninfo
= rbe16(&b1
[10]);
143 disktype
= rbe16(&b1
[50]);
146 error
= ERROR_OBJECT_WRONG_TYPE
;
152 passwd
= IPlugin_RequestPassword(unit
);
154 error
= ERROR_NO_FREE_STORE
;
158 xdms
->PWDCRC
= CreateCRC(passwd
, strlen(passwd
));
162 error
= ERROR_REQUIRED_ARG_MISSING
;
163 error_string
= MSG_NOPASSWD
;
168 error
= IPlugin_CreateTempFile(unit
, "adf", &tmpdir
, &tmpname
);
172 outfile
= IPlugin_OpenTempFile(unit
, MODE_NEWFILE
);
178 Init_Decrunchers(xdms
);
181 while (error
== NO_ERROR
&& !eof
)
182 error
= process_track(xdms
, file
, outfile
, b1
, b2
, pwd
, &eof
, &error_string
);
183 if (error
!= NO_ERROR
) goto error
;
188 outfile
= IPlugin_OpenTempFile(unit
, MODE_OLDFILE
);
195 tmpdir
= CurrentDir(tmpdir
);
196 image
= IPlugin_OpenImage(unit
, outfile
, tmpname
);
208 if (error
== NO_ERROR
) {
209 error
= ERROR_OBJECT_WRONG_TYPE
;
210 error_string
= MSG_EOF
;
212 IPlugin_SetDiskImageErrorA(unit
, error
, error_string
, error_args
);
217 static LONG
process_track (struct xdms_data
*xdms
, BPTR in
, BPTR out
, UBYTE
*b1
, UBYTE
*b2
, UWORD pwd
,
218 UBYTE
*eof
, LONG
*error_string
)
221 UWORD l
, hcrc
, dcrc
, number
, pklen1
, pklen2
, unpklen
, usum
;
224 l
= FRead(in
, b1
, 1, THLEN
);
232 error
= ERROR_OBJECT_WRONG_TYPE
;
233 *error_string
= MSG_EOF
;
238 if (b1
[0] != 'T' || b1
[1] != 'R') {
243 hcrc
= rbe16(&b1
[THLEN
-2]);
244 if (hcrc
!= CreateCRC(b1
, THLEN
-2)) {
245 error
= ERROR_BAD_NUMBER
;
246 *error_string
= MSG_BADCRC
;
250 number
= rbe16(&b1
[2]);
251 pklen1
= rbe16(&b1
[6]);
252 pklen2
= rbe16(&b1
[8]);
253 unpklen
= rbe16(&b1
[10]);
256 usum
= rbe16(&b1
[14]);
257 dcrc
= rbe16(&b1
[16]);
259 if (pklen1
> TRACK_BUFFER_SIZE
|| pklen2
> TRACK_BUFFER_SIZE
||
260 unpklen
> TRACK_BUFFER_SIZE
)
262 return ERROR_BUFFER_OVERFLOW
;
265 if (FRead(in
, b1
, 1, pklen1
) != pklen1
) {
269 error
= ERROR_OBJECT_WRONG_TYPE
;
270 *error_string
= MSG_EOF
;
275 if (dcrc
!= CreateCRC(b1
, pklen1
)) {
276 error
= ERROR_BAD_NUMBER
;
277 *error_string
= MSG_BADCRC
;
281 if (pwd
&& number
!= 80) dms_decrypt(xdms
, b1
, pklen1
);
283 if (number
< 80 && unpklen
> 2048) {
284 error
= unpack_track(xdms
, b1
, b2
, pklen2
, unpklen
, cmode
, flags
);
287 error
= ERROR_BAD_NUMBER
;
288 *error_string
= MSG_BADDATA
;
291 error
= ERROR_BAD_NUMBER
;
292 *error_string
= MSG_UNKNCOMPMETHOD
;
296 if (usum
!= Calc_CheckSum(b2
, unpklen
)) {
297 error
= ERROR_BAD_NUMBER
;
298 *error_string
= MSG_BADCHECKSUM
;
302 if (Write(out
, b2
, unpklen
) != unpklen
) {
310 static UWORD
unpack_track (struct xdms_data
*xdms
, UBYTE
*b1
, UBYTE
*b2
, UWORD pklen2
, UWORD unpklen
, UWORD cmode
,
315 if (Unpack_RLE(xdms
, b1
, b2
, unpklen
)) return ERR_BADDECR
;
318 if (Unpack_QUICK(xdms
, b1
, b2
, pklen2
)) return ERR_BADDECR
;
319 if (Unpack_RLE(xdms
, b2
, b1
, unpklen
)) return ERR_BADDECR
;
321 memcpy(b2
, b1
, unpklen
);
324 if (Unpack_MEDIUM(xdms
, b1
, b2
, pklen2
)) return ERR_BADDECR
;
325 if (Unpack_RLE(xdms
, b2
, b1
, unpklen
)) return ERR_BADDECR
;
326 memcpy(b2
, b1
, unpklen
);
329 if (Unpack_DEEP(xdms
, b1
, b2
, pklen2
)) return ERR_BADDECR
;
330 if (Unpack_RLE(xdms
, b2
, b1
, unpklen
)) return ERR_BADDECR
;
331 memcpy(b2
, b1
, unpklen
);
335 if (Unpack_HEAVY(xdms
, b1
, b2
, (cmode
== 5) ? (flags
& 7) : (flags
| 8), pklen2
))
338 if (Unpack_RLE(xdms
, b2
, b1
, unpklen
)) return ERR_BADDECR
;
339 memcpy(b2
, b1
, unpklen
);
346 if (!(flags
& 1)) Init_Decrunchers(xdms
);
351 static void dms_decrypt (struct xdms_data
*xdms
, UBYTE
*p
, UWORD len
) {
355 *p
++ ^= (UBYTE
)xdms
->PWDCRC
;
356 xdms
->PWDCRC
= (UWORD
)((xdms
->PWDCRC
>> 1) + t
);