~ubuntu-branches/debian/sid/mame/sid

« back to all changes in this revision

Viewing changes to mess/src/lib/formats/coco_dsk.c

  • Committer: Package Import Robot
  • Author(s): Jordi Mallach, Jordi Mallach, Emmanuel Kasper
  • Date: 2011-12-19 22:56:27 UTC
  • mfrom: (0.1.2)
  • Revision ID: package-import@ubuntu.com-20111219225627-ub5oga1oys4ogqzm
Tags: 0.144-1
[ Jordi Mallach ]
* Fix syntax errors in DEP5 copyright file (lintian).
* Use a versioned copyright Format specification field.
* Update Vcs-* URLs.
* Move transitional packages to the new metapackages section, and make
  them priority extra.
* Remove references to GNU/Linux and MESS sources from copyright.
* Add build variables for s390x.
* Use .xz tarballs as it cuts 4MB for the upstream sources.
* Add nplayers.ini as a patch. Update copyright file to add CC-BY-SA-3.0.

[ Emmanuel Kasper ]
* New upstream release. Closes: #651538.
* Add Free Desktop compliant png icons of various sizes taken from
  the hydroxygen iconset
* Mess is now built from a new source package, to avoid possible source
  incompatibilities between mame and the mess overlay.
* Mame-tools are not built from the mame source package anymore, but
  from the mess source package

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*********************************************************************
2
 
 
3
 
    formats/coco_dsk.c
4
 
 
5
 
    Tandy Color Computer / Dragon disk images
6
 
 
7
 
*********************************************************************/
8
 
 
9
 
#include <string.h>
10
 
#include <assert.h>
11
 
#include <time.h>
12
 
 
13
 
#include "formats/coco_dsk.h"
14
 
#include "formats/basicdsk.h"
15
 
#include "imageutl.h"
16
 
 
17
 
/* -----------------------------------------------------------------------
18
 
 * JVC (Jeff Vavasour CoCo) format
19
 
 *
20
 
 * Used by Jeff Vavasour's CoCo Emulators
21
 
 *
22
 
 *  Documentation taken from Tim Linder's web site:
23
 
 *      http://home.netcom.com/~tlindner/JVC.html
24
 
 *
25
 
 *  A. Header length
26
 
 *      The header length is determined by the file length modulo 256:
27
 
 *          headerSize = fileLength % 256;
28
 
 *      This means that the header is variable length and the minimum size
29
 
 *      is zero bytes, and the maximum size of 255 bytes.
30
 
 *
31
 
 * B. Header
32
 
 *      Here is a description of the header bytes:
33
 
 *          Byte Offset     Description            Default
34
 
 *          -----------     -----------------      -------
35
 
 *                    0     Sectors per track      18
36
 
 *                    1     Side count              1
37
 
 *                    2     Sector size code        1
38
 
 *                    3     First sector ID         1
39
 
 *                    4     Sector attribute flag   0
40
 
 *
41
 
 *  If the sector attribute flag is zero then the track count is determined
42
 
 *  by the formula:
43
 
 *
44
 
 *      (fileLength - headerSize) / (sectorsPerTrack * (128 <<
45
 
 *          sectorSizeCode)) / sideCount
46
 
 *
47
 
 *  If the sector attribute flag is non zero then the track count is
48
 
 *  determined by the more complex formula:
49
 
 *
50
 
 *      (fileLength - headerSize) / (sectorsPerTrack * ((128 <<
51
 
 *          sectorSizeCode) + 1) ) / sideCount
52
 
 *
53
 
 *  If the length of the header is to short to contain the geometry desired,
54
 
 *  then the default values are assumed. If the header length is zero the all
55
 
 *  of the geometry is assumed. When creating disk images it is desirable to
56
 
 *  make the header length as short as possible. The header should only be
57
 
 *  used to deviate from the default values.
58
 
 *
59
 
 *  The sector data begins immediately after the header. If the header length
60
 
 *  is zero then the sector data is at the beginning file.
61
 
 *
62
 
 *  C. Sectors per track
63
 
 *      This is the number of sectors per track (ones based). A value of 18
64
 
 *      means there are 18 sectors per track
65
 
 *
66
 
 *  D. Side Count
67
 
 *      This is the number of sides in the disk image. Values of 1 or 2 are
68
 
 *      acceptable. If there are two sides then the tracks are interleaved.
69
 
 *      The first track in the image file is track zero side 1, the second
70
 
 *      track in the image file is track zero side 2.
71
 
 *
72
 
 *  E. Sector size
73
 
 *      The is the same value that is stored in the wd179x ID field to
74
 
 *      determine sector size:
75
 
 *
76
 
 *          0x00         128 bytes
77
 
 *          0x01         256 bytes
78
 
 *          0x02         512 bytes
79
 
 *          0x03        1024 bytes
80
 
 *
81
 
 *  Other values are undefined. Every sector in the disk image must be the
82
 
 *  same size.
83
 
 *
84
 
 *  F. First sector ID
85
 
 *      This determines the first sector ID for each track. Each successive
86
 
 *      sector adds one to the previous ID. If the first sector ID is 1, then
87
 
 *      the second sector has an ID of 2, and the third has an ID of 3.
88
 
 *
89
 
 *  G. Sector Attribute Flag
90
 
 *      If this byte is non zero, then each sector contains an additional
91
 
 *      byte prepended to the sector data. If the attribute flag is zero then
92
 
 *      there are no extra bytes in front of the sector data.
93
 
 *
94
 
 *  H. Sector attribute byte
95
 
 *      This byte is put at the begining of every sector if the header flag
96
 
 *      is turned on. The information this byte contains is the same as the
97
 
 *      status register (of the wd179x) would contain when a 'Read Sector'
98
 
 *      command was issued. The bit fields are defined as:
99
 
 *
100
 
 *      Bit position:
101
 
 *      ---------------
102
 
 *      7 6 5 4 3 2 1 0
103
 
 *      | | | | | | | |
104
 
 *      | | | | | | | +--- Not used. Set to zero.
105
 
 *      | | | | | | +----- Not used. Set to zero.
106
 
 *      | | | | | +------- Not used. Set to zero.
107
 
 *      | | | | +--------- Set on CRC error.
108
 
 *      | | | +----------- Set if sector not found.
109
 
 *      | | +------------- Record type: 1 - Deleted Data Mark, 0 - Data Mark.
110
 
 *      | +--------------- Not Used. Set to zero.
111
 
 *      +----------------- Not Used. Set to zero.
112
 
 *
113
 
 * ----------------------------------------------------------------------- */
114
 
 
115
 
static int coco_jvc_decode_header(floppy_image *floppy, UINT64 size,
116
 
        struct basicdsk_geometry *geometry)
117
 
{
118
 
        UINT8 header[256];
119
 
        UINT8 sector_attribute_flag;
120
 
        UINT16 physical_bytes_per_sector;
121
 
        UINT32 header_size, file_size;
122
 
        struct basicdsk_geometry dummy_geometry;
123
 
 
124
 
        if (geometry)
125
 
                memset(geometry, 0, sizeof(*geometry));
126
 
        else
127
 
                geometry = &dummy_geometry;
128
 
 
129
 
        if (size > 0xFFFFFFFF)
130
 
                return -1;
131
 
        file_size = (UINT32) size;
132
 
 
133
 
        /* read the header */
134
 
        header_size = (UINT32) file_size % 0x100;
135
 
        floppy_image_read(floppy, header, 0, header_size);
136
 
        geometry->offset = header_size;
137
 
 
138
 
        /* byte offset 0 - sectors per track */
139
 
        geometry->sectors = (header_size > 0) ? header[0] : 18;
140
 
        if (geometry->sectors <= 0)
141
 
                return -1;
142
 
 
143
 
        /* byte offset 1 - side count */
144
 
        geometry->heads = (header_size > 1) ? header[1] : 1;
145
 
        if (geometry->heads <= 0)
146
 
                return -1;
147
 
 
148
 
        /* byte offset 2 - sector size code */
149
 
        geometry->sector_length = 128 << ((header_size > 2) ? header[2] : 1);
150
 
        if (geometry->sector_length <= 0)
151
 
                return -1;
152
 
 
153
 
        /* byte offset 3 - first sector ID */
154
 
        geometry->first_sector_id = (header_size > 3) ? header[3] : 1;
155
 
 
156
 
        /* byte offset 4 - sector attribute flag */
157
 
        sector_attribute_flag = (header_size > 4) ? header[4] : 0;
158
 
        if (sector_attribute_flag != 0)
159
 
                return -1;      /* we do not support sector attribute flags */
160
 
 
161
 
        physical_bytes_per_sector = geometry->sector_length;
162
 
        if (sector_attribute_flag)
163
 
                physical_bytes_per_sector++;
164
 
 
165
 
        geometry->tracks = (file_size - header_size) / geometry->sectors / geometry->heads / physical_bytes_per_sector;
166
 
 
167
 
        /* do we have an oddball size?  reject this file if not */
168
 
        if ((file_size - header_size) % physical_bytes_per_sector)
169
 
                return -1;
170
 
 
171
 
        /* minimum of 35 tracks; support degenerate JVC files */
172
 
        if (geometry->tracks < 35)
173
 
                geometry->tracks = 35;
174
 
 
175
 
        return 0;
176
 
}
177
 
 
178
 
 
179
 
 
180
 
static FLOPPY_IDENTIFY(coco_jvc_identify)
181
 
{
182
 
        UINT64 size;
183
 
        size = floppy_image_size(floppy);
184
 
        *vote = coco_jvc_decode_header(floppy, size, NULL) ? 0 : 100;
185
 
        return FLOPPY_ERROR_SUCCESS;
186
 
}
187
 
 
188
 
 
189
 
 
190
 
static FLOPPY_CONSTRUCT(coco_jvc_construct)
191
 
{
192
 
        struct basicdsk_geometry geometry;
193
 
        UINT8 header[5];
194
 
        size_t header_size;
195
 
 
196
 
        if (params)
197
 
        {
198
 
                /* create */
199
 
                memset(&geometry, 0, sizeof(geometry));
200
 
                geometry.heads                          = option_resolution_lookup_int(params, PARAM_HEADS);
201
 
                geometry.tracks                         = option_resolution_lookup_int(params, PARAM_TRACKS);
202
 
                geometry.sectors                        = option_resolution_lookup_int(params, PARAM_SECTORS);
203
 
                geometry.first_sector_id        = option_resolution_lookup_int(params, PARAM_FIRST_SECTOR_ID);
204
 
                geometry.sector_length          = option_resolution_lookup_int(params, PARAM_SECTOR_LENGTH);
205
 
 
206
 
                header[0] = (UINT8) geometry.sectors;
207
 
                header[1] = (UINT8) geometry.heads;
208
 
                header[2] = (UINT8) compute_log2(geometry.sector_length) - 7;
209
 
                header[3] = (UINT8) geometry.first_sector_id;
210
 
                header[4] = 0;
211
 
 
212
 
                /* now that we have the header computed, figure out the header size */
213
 
                header_size = 0;
214
 
                if (header[0] != 18)
215
 
                        header_size = 1;
216
 
                if (header[1] != 1)
217
 
                        header_size = 2;
218
 
                if (header[2] != 1)
219
 
                        header_size = 3;
220
 
                if (header[3] != 1)
221
 
                        header_size = 4;
222
 
                if (header[4] != 0)
223
 
                        header_size = 5;
224
 
 
225
 
                geometry.offset = header_size;
226
 
 
227
 
                floppy_image_write(floppy, header, 0, header_size);
228
 
        }
229
 
        else
230
 
        {
231
 
                /* load */
232
 
                if (coco_jvc_decode_header(floppy, floppy_image_size(floppy), &geometry))
233
 
                        return FLOPPY_ERROR_INVALIDIMAGE;
234
 
        }
235
 
        return basicdsk_construct(floppy, &geometry);
236
 
}
237
 
 
238
 
 
239
 
/* -----------------------------------------------------------------------
240
 
 * OS-9 file format
241
 
 *
242
 
 * This file format is largely a hack because there are a large amount of
243
 
 * disk images that do not have geometry image separate from the disk image
244
 
 * itself.  So we support OS-9 images with are simply basic disks whose
245
 
 * geometry is determined by the disk image.
246
 
 *
247
 
 * OS-9 images identified by an LSN; which are simply blocks of 256 bytes
248
 
 *
249
 
 * LSN0
250
 
 * Byte    size    use
251
 
 * $00     3       sectors on disk
252
 
 * $03     1       track size in sectors
253
 
 * $04     2       bytes in allocation bit map; typically 1bit/sector so for
254
 
 *                 35 tracks of 18 sectors each that's $4E (single sided disk)
255
 
 *                 40 tracks per side, 18 sectors each = $B4
256
 
 * $06     2       sectors per bit in allocation map; normally 1
257
 
 * $08     3       LSN of root directory; normally 2 but depends on size of
258
 
 *                 $04 value
259
 
 * $0B     2       owner's user number; normally 0
260
 
 * $0D     1       disk attributes; normally $FF
261
 
 * $0E     2       psuedo random number for identification
262
 
 * $10     1       disk format; typical is 3
263
 
 *                 %00000001 0=single side 1=double side
264
 
 *                 %00000010 0=single density (non Coco) 1=double density
265
 
 *                 %00000100 0=48tracks/inch 1=96tracks/inch
266
 
 * $11     2       sectors per track; normal is $12 skip several not needed
267
 
 *                 for Format
268
 
 * $1A     5       date of creation Y:M:D:H:M
269
 
 * $1F     32      ASCII name of disk, last letter has $80 added to it,
270
 
 *                 the full 32 bytes do not need to be used.
271
 
 *
272
 
 * Allocation bit map, fill with zeros and set bits from low to high as
273
 
 * sectors are used. So, for a fresh disk sectors LSN0,LSN1,LSN2, and LSN3
274
 
 * will be in use so the first byte will be $FF $C0 and all others
275
 
 * in the map are $00
276
 
 *
277
 
 * Root directory LSN2
278
 
 * Byte    size     use
279
 
 * $00      1       attributes will be $BF
280
 
 * $01      2       owners ID will be $0000
281
 
 * $03      5       date last modified will be creation date  Y:M:D:H:M
282
 
 * $08      1       link count; set to $02
283
 
 * $09      4       file size in bytes, set to $40
284
 
 * $0D      3       date created Y:M:D
285
 
 * $10      3       block LSN set to current sector number+1 ie $03 in this case
286
 
 * $13      2       size in sectors of directory block, set to $07
287
 
 * All other bytes in sector set to $00
288
 
 * LSN3 first sector of directory with names
289
 
 * Fill sector with all $00 and then set listed bytes
290
 
 * $00      2       value $2EAE   which is .. with last byte+$80
291
 
 * $1F      1       value $02     LSN for start of this directory as there is
292
 
 *                  none higher in tree
293
 
 * $20      1       value $AE     which is . with $80 added
294
 
 * $3F      1       value $02     LSN for start of this directory
295
 
 * ----------------------------------------------------------------------- */
296
 
 
297
 
static floperr_t coco_os9_readheader(floppy_image *floppy, struct basicdsk_geometry *geometry)
298
 
{
299
 
        UINT8 header[0x20];
300
 
        int total_sectors;
301
 
 
302
 
        floppy_image_read(floppy, header, 0, sizeof(header));
303
 
 
304
 
        total_sectors = (header[0x00] << 16) | (header[0x01] << 8) | header[0x02];
305
 
 
306
 
        memset(geometry, 0, sizeof(*geometry));
307
 
        geometry->first_sector_id = 1;
308
 
        geometry->sector_length = 256;
309
 
        geometry->sectors = (header[0x11] << 8) + header[0x12];
310
 
        geometry->heads = (header[0x10] & 0x01) ? 2 : 1;
311
 
 
312
 
        if (!geometry->sectors)
313
 
                return FLOPPY_ERROR_INVALIDIMAGE;
314
 
 
315
 
        geometry->tracks = total_sectors / geometry->sectors / geometry->heads;
316
 
 
317
 
        if (total_sectors != geometry->tracks * geometry->sectors * geometry->heads)
318
 
                return FLOPPY_ERROR_INVALIDIMAGE;
319
 
 
320
 
        return FLOPPY_ERROR_SUCCESS;
321
 
}
322
 
 
323
 
 
324
 
 
325
 
static floperr_t coco_os9_post_format(floppy_image *floppy, option_resolution *params)
326
 
{
327
 
        UINT8 header[0x0400];
328
 
        floperr_t err;
329
 
        time_t t;
330
 
        struct tm *ltime;
331
 
        int heads, tracks, sectors, total_sectors;
332
 
 
333
 
        heads   = option_resolution_lookup_int(params, PARAM_HEADS);
334
 
        tracks  = option_resolution_lookup_int(params, PARAM_TRACKS);
335
 
        sectors = option_resolution_lookup_int(params, PARAM_SECTORS);
336
 
        total_sectors = heads * tracks * sectors;
337
 
 
338
 
        /* write the initial header */
339
 
        time(&t);
340
 
        ltime = localtime(&t);
341
 
 
342
 
        memset(&header, 0, sizeof(header));
343
 
        header[0x0000] = (UINT8) (total_sectors >> 16);
344
 
        header[0x0001] = (UINT8) (total_sectors >>  8);
345
 
        header[0x0002] = (UINT8) (total_sectors >>  0);
346
 
        header[0x0003] = (UINT8) sectors;
347
 
        header[0x0004] = (UINT8) (((total_sectors + 7) / 8) >> 8);
348
 
        header[0x0005] = (UINT8) (((total_sectors + 7) / 8) >> 0);
349
 
        header[0x0006] = 0x00;
350
 
        header[0x0007] = 0x01;
351
 
        header[0x0008] = 0x00;
352
 
        header[0x0009] = 0x00;
353
 
        header[0x000a] = 0x02;
354
 
        header[0x000b] = 0x00;
355
 
        header[0x000c] = 0x00;
356
 
        header[0x000d] = 0xff;
357
 
        header[0x000e] = floppy_random_byte(floppy);
358
 
        header[0x000f] = floppy_random_byte(floppy);
359
 
        header[0x0010] = (heads == 2) ? 3 : 2;
360
 
        header[0x0011] = (UINT8) (sectors >> 8);
361
 
        header[0x0012] = (UINT8) (sectors >> 0);
362
 
        header[0x001A] = (UINT8) ltime->tm_year;
363
 
        header[0x001B] = (UINT8) ltime->tm_mon + 1;
364
 
        header[0x001C] = (UINT8) ltime->tm_mday;
365
 
        header[0x001D] = (UINT8) ltime->tm_hour;
366
 
        header[0x001E] = (UINT8) ltime->tm_min;
367
 
        header[0x001F] = 0xA0;
368
 
        header[0x0100] = 0xFF;
369
 
        header[0x0101] = 0xC0;
370
 
        header[0x0200] = 0xBF;
371
 
        header[0x0201] = 0x00;
372
 
        header[0x0202] = 0x00;
373
 
        header[0x0203] = (UINT8) ltime->tm_year;
374
 
        header[0x0204] = (UINT8) ltime->tm_mon + 1;
375
 
        header[0x0205] = (UINT8) ltime->tm_mday;
376
 
        header[0x0206] = (UINT8) ltime->tm_hour;
377
 
        header[0x0207] = (UINT8) ltime->tm_min;
378
 
        header[0x0208] = 0x02;
379
 
        header[0x0209] = 0x00;
380
 
        header[0x020A] = 0x00;
381
 
        header[0x020B] = 0x00;
382
 
        header[0x020C] = 0x40;
383
 
        header[0x020D] = (UINT8) (ltime->tm_year % 100);
384
 
        header[0x020E] = (UINT8) ltime->tm_mon;
385
 
        header[0x020F] = (UINT8) ltime->tm_mday;
386
 
        header[0x0210] = 0x00;
387
 
        header[0x0211] = 0x00;
388
 
        header[0x0212] = 0x03;
389
 
        header[0x0213] = 0x00;
390
 
        header[0x0214] = 0x07;
391
 
        header[0x0300] = 0x2E;
392
 
        header[0x0301] = 0xAE;
393
 
        header[0x031F] = 0x02;
394
 
        header[0x0320] = 0xAE;
395
 
        header[0x033F] = 0x02;
396
 
 
397
 
        if (total_sectors % 8)
398
 
                header[0x0100 + (total_sectors / 8)] = 0xFF >> (total_sectors % 8);
399
 
 
400
 
        err = floppy_write_sector(floppy, 0, 0, 1, 0, &header[0x0000], 256, 0);
401
 
        if (err)
402
 
                return err;
403
 
 
404
 
        err = floppy_write_sector(floppy, 0, 0, 2, 0, &header[0x0100], 256, 0);
405
 
        if (err)
406
 
                return err;
407
 
 
408
 
        err = floppy_write_sector(floppy, 0, 0, 3, 0, &header[0x0200], 256, 0);
409
 
        if (err)
410
 
                return err;
411
 
 
412
 
        err = floppy_write_sector(floppy, 0, 0, 4, 0, &header[0x0300], 256, 0);
413
 
        if (err)
414
 
                return err;
415
 
 
416
 
        return FLOPPY_ERROR_SUCCESS;
417
 
}
418
 
 
419
 
 
420
 
 
421
 
static FLOPPY_IDENTIFY(coco_os9_identify)
422
 
{
423
 
        struct basicdsk_geometry geometry;
424
 
        *vote = coco_os9_readheader(floppy, &geometry) ? 0 : 100;
425
 
        return FLOPPY_ERROR_SUCCESS;
426
 
}
427
 
 
428
 
 
429
 
 
430
 
static FLOPPY_CONSTRUCT(coco_os9_construct)
431
 
{
432
 
        floperr_t err;
433
 
        struct basicdsk_geometry geometry;
434
 
 
435
 
        if (params)
436
 
        {
437
 
                /* create */
438
 
                memset(&geometry, 0, sizeof(geometry));
439
 
                geometry.heads                          = option_resolution_lookup_int(params, PARAM_HEADS);
440
 
                geometry.tracks                         = option_resolution_lookup_int(params, PARAM_TRACKS);
441
 
                geometry.sectors                        = option_resolution_lookup_int(params, PARAM_SECTORS);
442
 
                geometry.first_sector_id        = option_resolution_lookup_int(params, PARAM_FIRST_SECTOR_ID);
443
 
                geometry.sector_length          = option_resolution_lookup_int(params, PARAM_SECTOR_LENGTH);
444
 
        }
445
 
        else
446
 
        {
447
 
                /* open */
448
 
                err = coco_os9_readheader(floppy, &geometry);
449
 
                if (err)
450
 
                        return err;
451
 
        }
452
 
 
453
 
        /* actually construct the image */
454
 
        err = basicdsk_construct(floppy, &geometry);
455
 
        floppy_callbacks(floppy)->post_format = coco_os9_post_format;
456
 
        return err;
457
 
}
458
 
 
459
 
 
460
 
 
461
 
/* -----------------------------------------------------------------------
462
 
 * VDK file format
463
 
 *
464
 
 * Used by Paul Burgin's PC-Dragon emulator
465
 
 *
466
 
 *  Offset  Bytes   Field           Description
467
 
 *  ------  -----   ------------    -----------
468
 
 *       0      1   magic1          Signature byte 1 ('d')
469
 
 *       1      1   magic2          Signature byte 2 ('k')
470
 
 *       2      2   header_len      Total header length (little endian)
471
 
 *       4      1   ver_actual      Version of the VDK format (0x10)
472
 
 *       5      1   ver_compat      Backwards compatibility version (0x10)
473
 
 *       6      1   source_id       Identify of the file source
474
 
 *       7      1   source_ver      Version of the file source
475
 
 *       8      1   tracks          Number of tracks
476
 
 *       9      1   sides           Number of sides (1-2)
477
 
 *      10      1   flags           Various flags
478
 
 *                                      bit 0: Write protect
479
 
 *                                      bit 1: A Lock
480
 
 *                                      bit 2: F Lock
481
 
 *                                      bit 3: Disk set
482
 
 *      11      1   compression     Compression flags (bits 0-2) and name length
483
 
 * ----------------------------------------------------------------------- */
484
 
 
485
 
 
486
 
 
487
 
static int coco_vdk_decode_header(floppy_image *floppy, struct basicdsk_geometry *geometry)
488
 
{
489
 
        UINT8 header[12];
490
 
        int heads, tracks, sectors, sector_length, offset;
491
 
        UINT64 size;
492
 
 
493
 
        size = floppy_image_size(floppy);
494
 
 
495
 
        floppy_image_read(floppy, header, 0, sizeof(header));
496
 
 
497
 
        if (header[0] != 'd')
498
 
                return -1;
499
 
        if (header[1] != 'k')
500
 
                return -1;
501
 
        if (header[5] != 0x10)
502
 
                return -1;
503
 
        if (header[11] & 0x07)
504
 
                return -1;
505
 
 
506
 
        heads = header[9];
507
 
        tracks = header[8];
508
 
        sectors = 18;
509
 
        sector_length = 0x100;
510
 
 
511
 
        offset = ((int) header[3]) * 0x100 + header[2];
512
 
 
513
 
        if (size != (heads * tracks * sectors * sector_length + offset))
514
 
                return -1;
515
 
 
516
 
        if (geometry)
517
 
        {
518
 
                memset(geometry, 0, sizeof(*geometry));
519
 
                geometry->heads = heads;
520
 
                geometry->tracks = tracks;
521
 
                geometry->sectors = sectors;
522
 
                geometry->first_sector_id = 1;
523
 
                geometry->sector_length = sector_length;
524
 
                geometry->offset = offset;
525
 
        }
526
 
        return 0;
527
 
}
528
 
 
529
 
 
530
 
 
531
 
static FLOPPY_IDENTIFY(coco_vdk_identify)
532
 
{
533
 
        *vote = coco_vdk_decode_header(floppy, NULL) ? 0 : 100;
534
 
        return FLOPPY_ERROR_SUCCESS;
535
 
}
536
 
 
537
 
 
538
 
 
539
 
static FLOPPY_CONSTRUCT(coco_vdk_construct)
540
 
{
541
 
        struct basicdsk_geometry geometry;
542
 
        UINT8 header[12];
543
 
 
544
 
        if (params)
545
 
        {
546
 
                /* create */
547
 
                memset(&geometry, 0, sizeof(geometry));
548
 
                geometry.heads = option_resolution_lookup_int(params, PARAM_HEADS);
549
 
                geometry.tracks = option_resolution_lookup_int(params, PARAM_TRACKS);
550
 
                geometry.sectors = 18;
551
 
                geometry.first_sector_id = 1;
552
 
                geometry.sector_length = 256;
553
 
                geometry.offset = sizeof(header);
554
 
 
555
 
                memset(&header, 0, sizeof(header));
556
 
                header[0] = 'd';
557
 
                header[1] = 'k';
558
 
                header[2] = (UINT8) (sizeof(header) >> 0);
559
 
                header[3] = (UINT8) (sizeof(header) >> 8);
560
 
                header[4] = 0x10;
561
 
                header[5] = 0x10;
562
 
                header[8] = (UINT8) geometry.tracks;
563
 
                header[9] = (UINT8) geometry.heads;
564
 
 
565
 
                floppy_image_write(floppy, header, 0, sizeof(header));
566
 
        }
567
 
        else
568
 
        {
569
 
                /* load */
570
 
                if (coco_vdk_decode_header(floppy, &geometry))
571
 
                        return FLOPPY_ERROR_INVALIDIMAGE;
572
 
        }
573
 
        return basicdsk_construct(floppy, &geometry);
574
 
}
575
 
 
576
 
 
577
 
 
578
 
/* -----------------------------------------------------------------------
579
 
 * DMK file format
580
 
 *
581
 
 * David M. Keil's disk image format is aptly called an 'on disk' image
582
 
 * format. This means that whatever written to the disk is enocded into
583
 
 * the image file. IDAMS, sector headers, traling CRCs, and intra sector
584
 
 * spacing.                                                         *
585
 
 *
586
 
 *  HEADER DESCRIPTION:
587
 
 *
588
 
 *  Offset  Bytes   Field           Description
589
 
 *  ------  -----   ------------    -----------
590
 
 *       0      1   write_prot      0xff = Writed Protected, 0x00 = R/W
591
 
 *       1      1   tracks          Number of tracks
592
 
 *       2      2   track_length    Bytes per track (little endian)
593
 
 *       4      1   disk_options    Miscellaneous flags
594
 
 *                                      bit 0-3:  Unused
595
 
 *                                      bit   4:  1=single sided 0=dbl
596
 
 *                                      bit   5:  Unused
597
 
 *                                      bit   6:  Single density?
598
 
 *                                      bit   6:  Ignore density flags?
599
 
 *       5      7   reserved        Reserved for future use
600
 
 *      12      4   real_disk_code  If this is 0x12345678 (little endian)
601
 
 *                                  then access a real disk drive
602
 
 *                                  (unsupported)
603
 
 *
604
 
 * Each track begins with a track TOC, consisting of 64 little endian 16-bit
605
 
 * integers.  Each integer has the following format:
606
 
 *      bit 0-13:   Offset from begining of track to 'FE' byte of IDAM
607
 
 *                  Note these are always sorted from first to last. All empty
608
 
 *                  entries are 0x00
609
 
 *      bit 14:     Undefined (reserved)
610
 
 *      bit 15:     Sector double density (0=SD 1=DD)
611
 
 * ----------------------------------------------------------------------- */
612
 
 
613
 
struct dmk_tag
614
 
{
615
 
        int heads;
616
 
        int tracks;
617
 
        UINT32 track_size;
618
 
};
619
 
 
620
 
#define DMK_HEADER_LEN                  16
621
 
#define DMK_TOC_LEN                             64
622
 
#define DMK_IDAM_LENGTH                 7
623
 
#define DMK_DATA_GAP                    80
624
 
#define DMK_LEAD_IN                             32
625
 
#define DMK_EXTRA_TRACK_LENGTH  156
626
 
 
627
 
#define dmk_idam_type(x)                        (x)[0]
628
 
#define dmk_idam_track(x)                       (x)[1]
629
 
#define dmk_idam_side(x)                        (x)[2]
630
 
#define dmk_idam_sector(x)                      (x)[3]
631
 
#define dmk_idam_sectorlength(x)        (x)[4]
632
 
#define dmk_idam_crc(x)                         (((x)[5] << 8) + (x)[6])
633
 
#define dmk_idam_set_crc(x, crc)        (x)[5] = ((crc) >> 8); (x)[6] = ((crc) >> 0);
634
 
 
635
 
 
636
 
static struct dmk_tag *get_dmk_tag(floppy_image *floppy)
637
 
{
638
 
        return (dmk_tag *)floppy_tag(floppy);
639
 
}
640
 
 
641
 
 
642
 
static floperr_t coco_dmk_get_offset(floppy_image *floppy, int head, int track, UINT64 *offset)
643
 
{
644
 
        struct dmk_tag *tag = get_dmk_tag(floppy);
645
 
 
646
 
        if ((head < 0) || (head >= tag->heads) || (track < 0) || (track >= tag->tracks))
647
 
                return FLOPPY_ERROR_SEEKERROR;
648
 
 
649
 
        *offset = track;
650
 
        *offset *= tag->heads;
651
 
        *offset += head;
652
 
        *offset *= tag->track_size;
653
 
        *offset += DMK_HEADER_LEN;
654
 
        return FLOPPY_ERROR_SUCCESS;
655
 
}
656
 
 
657
 
 
658
 
 
659
 
static UINT32 coco_dmk_min_track_size(int sectors, int sector_length)
660
 
{
661
 
        int sector_physical_length;
662
 
        sector_physical_length = 8 + 3 + DMK_IDAM_LENGTH + 22 + 12 + 3 + 1 + sector_length + 2 + 24;
663
 
        return DMK_TOC_LEN * 2 + DMK_LEAD_IN + (sectors * sector_physical_length);
664
 
}
665
 
 
666
 
 
667
 
 
668
 
static floperr_t coco_dmk_read_track(floppy_image *floppy, int head, int track, UINT64 offset, void *buffer, size_t buflen)
669
 
{
670
 
        floperr_t err;
671
 
        UINT64 track_offset;
672
 
 
673
 
        err = coco_dmk_get_offset(floppy, head, track, &track_offset);
674
 
        if (err)
675
 
                return err;
676
 
 
677
 
        floppy_image_read(floppy, buffer, offset + track_offset, buflen);
678
 
        return FLOPPY_ERROR_SUCCESS;
679
 
}
680
 
 
681
 
 
682
 
 
683
 
static floperr_t coco_dmk_write_track(floppy_image *floppy, int head, int track, UINT64 offset, const void *buffer, size_t buflen)
684
 
{
685
 
        floperr_t err;
686
 
        UINT64 track_offset;
687
 
 
688
 
        err = coco_dmk_get_offset(floppy, head, track, &track_offset);
689
 
        if (err)
690
 
                return err;
691
 
 
692
 
        floppy_image_write(floppy, buffer, offset + track_offset, buflen);
693
 
        return FLOPPY_ERROR_SUCCESS;
694
 
}
695
 
 
696
 
 
697
 
 
698
 
static floperr_t coco_dmk_get_track_data_offset(floppy_image *floppy, int head, int track, UINT64 *offset)
699
 
{
700
 
        *offset = DMK_TOC_LEN + 1;
701
 
        return FLOPPY_ERROR_SUCCESS;
702
 
}
703
 
 
704
 
 
705
 
 
706
 
static floperr_t coco_dmk_format_track(floppy_image *floppy, int head, int track, option_resolution *params)
707
 
{
708
 
        int sectors;
709
 
        int sector_length;
710
 
        int interleave;
711
 
        int first_sector_id;
712
 
        floperr_t err;
713
 
        int physical_sector;
714
 
        int logical_sector;
715
 
        int track_position;
716
 
        UINT16 idam_offset;
717
 
        UINT16 crc;
718
 
        UINT8 *track_data;
719
 
        void *track_data_v;
720
 
        UINT32 max_track_size;
721
 
        int *sector_map = NULL;
722
 
 
723
 
        sectors                 = option_resolution_lookup_int(params, PARAM_SECTORS);
724
 
        sector_length   = option_resolution_lookup_int(params, PARAM_SECTOR_LENGTH);
725
 
        interleave              = option_resolution_lookup_int(params, PARAM_INTERLEAVE);
726
 
        first_sector_id = option_resolution_lookup_int(params, PARAM_FIRST_SECTOR_ID);
727
 
 
728
 
        max_track_size = get_dmk_tag(floppy)->track_size;
729
 
 
730
 
        if (sectors > DMK_TOC_LEN)
731
 
        {
732
 
        err = FLOPPY_ERROR_INTERNAL;
733
 
                goto done;
734
 
        }
735
 
 
736
 
        if (max_track_size < coco_dmk_min_track_size(sectors, sector_length))
737
 
        {
738
 
                err = FLOPPY_ERROR_NOSPACE;
739
 
                goto done;
740
 
        }
741
 
 
742
 
        err = floppy_load_track(floppy, head, track, TRUE, &track_data_v, NULL);
743
 
        if (err)
744
 
                goto done;
745
 
        track_data = (UINT8 *) track_data_v;
746
 
 
747
 
        /* set up sector map */
748
 
        sector_map = (int*)malloc(sectors * sizeof(*sector_map));
749
 
        if (!sector_map)
750
 
        {
751
 
                err = FLOPPY_ERROR_OUTOFMEMORY;
752
 
                goto done;
753
 
        }
754
 
        memset(sector_map, 0xFF, sectors * sizeof(*sector_map));
755
 
 
756
 
        physical_sector = 0;
757
 
        for (logical_sector = 0; logical_sector < sectors; logical_sector++)
758
 
        {
759
 
                while(sector_map[physical_sector] >= 0)
760
 
                {
761
 
                        physical_sector++;
762
 
                        physical_sector %= sectors;
763
 
                }
764
 
 
765
 
                sector_map[physical_sector] = logical_sector + first_sector_id;
766
 
                physical_sector += interleave + 1;
767
 
                physical_sector %= sectors;
768
 
        }
769
 
 
770
 
        /* set up track table of contents */
771
 
        physical_sector = 0;
772
 
        track_position = DMK_TOC_LEN * 2 + DMK_LEAD_IN;
773
 
        while(physical_sector < DMK_TOC_LEN)
774
 
        {
775
 
                if (physical_sector >= sectors)
776
 
                {
777
 
                        /* no more sectors */
778
 
                        idam_offset = 0;
779
 
                }
780
 
                else
781
 
                {
782
 
                        /* this is a sector */
783
 
                        logical_sector = sector_map[physical_sector];
784
 
 
785
 
                        /* write the sector */
786
 
                        memset(&track_data[track_position], 0x00, 8);
787
 
                        track_position += 8;
788
 
 
789
 
                        memset(&track_data[track_position], 0xA1, 3);
790
 
                        track_position += 3;
791
 
 
792
 
                        idam_offset = track_position | 0x8000;
793
 
                        dmk_idam_type(                          &track_data[track_position]) = 0xFE;
794
 
                        dmk_idam_track(                         &track_data[track_position]) = track;
795
 
                        dmk_idam_side(                          &track_data[track_position]) = head;
796
 
                        dmk_idam_sector(                        &track_data[track_position]) = logical_sector;
797
 
                        dmk_idam_sectorlength(          &track_data[track_position]) = compute_log2(sector_length / 128);
798
 
                        crc = ccitt_crc16(0xcdb4,       &track_data[track_position], DMK_IDAM_LENGTH - 2);
799
 
                        dmk_idam_set_crc(                       &track_data[track_position], crc);
800
 
                        track_position += DMK_IDAM_LENGTH;
801
 
 
802
 
                        memset(&track_data[track_position], 0x4E, 22);
803
 
                        track_position += 22;
804
 
 
805
 
                        memset(&track_data[track_position], 0x00, 12);
806
 
                        track_position += 12;
807
 
 
808
 
                        memset(&track_data[track_position], 0xA1, 3);
809
 
                        track_position += 3;
810
 
 
811
 
                        /* write sector body */
812
 
                        track_data[track_position] = 0xFB;
813
 
                        memset(&track_data[track_position + 1], floppy_get_filler(floppy), sector_length);
814
 
                        crc = ccitt_crc16(0xcdb4, &track_data[track_position], sector_length + 1);
815
 
                        track_data[track_position + sector_length + 1] = (UINT8) (crc >> 8);
816
 
                        track_data[track_position + sector_length + 2] = (UINT8) (crc >> 0);
817
 
                        track_position += sector_length + 3;
818
 
 
819
 
                        /* write sector footer */
820
 
                        memset(&track_data[track_position], 0x4E, 24);
821
 
                        track_position += 24;
822
 
                }
823
 
 
824
 
                /* write the TOC entry */
825
 
                track_data[physical_sector * 2 + 0] = (UINT8) (idam_offset >> 0);
826
 
                track_data[physical_sector * 2 + 1] = (UINT8) (idam_offset >> 8);
827
 
 
828
 
                physical_sector++;
829
 
        }
830
 
 
831
 
        /* write track lead in */
832
 
        memset(&track_data[physical_sector * 2], 0x4e, DMK_LEAD_IN);
833
 
 
834
 
        /* write track footer */
835
 
        assert(max_track_size >= (UINT32)track_position);
836
 
        memset(&track_data[track_position], 0x4e, max_track_size - track_position);
837
 
 
838
 
done:
839
 
        if (sector_map)
840
 
                free(sector_map);
841
 
        return FLOPPY_ERROR_SUCCESS;
842
 
}
843
 
 
844
 
 
845
 
 
846
 
static int coco_dmk_get_heads_per_disk(floppy_image *floppy)
847
 
{
848
 
        return get_dmk_tag(floppy)->heads;
849
 
}
850
 
 
851
 
 
852
 
 
853
 
static int coco_dmk_get_tracks_per_disk(floppy_image *floppy)
854
 
{
855
 
        return get_dmk_tag(floppy)->tracks;
856
 
}
857
 
 
858
 
 
859
 
 
860
 
static UINT32 coco_dmk_get_track_size(floppy_image *floppy, int head, int track)
861
 
{
862
 
        return get_dmk_tag(floppy)->track_size;
863
 
}
864
 
 
865
 
 
866
 
 
867
 
static floperr_t coco_dmk_seek_sector_in_track(floppy_image *floppy, int head, int track, int sector, int sector_is_index, int dirtify, UINT8 **sector_data, UINT32 *sector_length)
868
 
{
869
 
        struct dmk_tag *tag = get_dmk_tag(floppy);
870
 
        floperr_t err;
871
 
        UINT32 idam_offset = 0;
872
 
        UINT16 calculated_crc;
873
 
        size_t i;
874
 
        size_t offs;
875
 
        int state;
876
 
        UINT8 *track_data;
877
 
        void *track_data_v;
878
 
        size_t track_length;
879
 
        size_t sec_len;
880
 
 
881
 
        err = floppy_load_track(floppy, head, track, dirtify, &track_data_v, &track_length);
882
 
        if (err)
883
 
                return err;
884
 
        track_data = (UINT8 *) track_data_v;
885
 
 
886
 
        /* search for matching IDAM */
887
 
        for (i = 0; i < DMK_TOC_LEN; i++)
888
 
        {
889
 
                idam_offset = track_data[i * 2 + 1];
890
 
                idam_offset <<= 8;
891
 
                idam_offset |= track_data[i * 2 + 0];
892
 
                idam_offset &= 0x3FFF;
893
 
 
894
 
                if (idam_offset == 0)
895
 
                {
896
 
                        /* we've reached the end of the road */
897
 
                        i = DMK_TOC_LEN;
898
 
                        break;
899
 
                }
900
 
 
901
 
                if ((idam_offset + DMK_IDAM_LENGTH) >= tag->track_size)
902
 
                        continue;
903
 
 
904
 
                calculated_crc = ccitt_crc16(0xCDB4, &track_data[idam_offset], DMK_IDAM_LENGTH - 2);
905
 
 
906
 
                if (calculated_crc == dmk_idam_crc(&track_data[idam_offset]))
907
 
                {
908
 
                        if (sector_is_index)
909
 
                        {
910
 
                                /* the sector is indexed; decrement the index and go */
911
 
                                if (sector-- == 0)
912
 
                                        break;
913
 
                        }
914
 
                        else
915
 
                        {
916
 
                                /* check IDAM integrity and check for matching sector */
917
 
                                if ((sector == dmk_idam_sector(&track_data[idam_offset]))
918
 
/*                  && (track == dmk_idam_track(&track_data[idam_offset]))  */
919
 
/*                  && (head == dmk_idam_side(&track_data[idam_offset]))    */
920
 
                                        )
921
 
                                        break;
922
 
                        }
923
 
                }
924
 
        }
925
 
 
926
 
        if (i >= DMK_TOC_LEN)
927
 
                return FLOPPY_ERROR_SEEKERROR;
928
 
 
929
 
        /* we found a matching sector ID */
930
 
        state = 0;
931
 
        offs = idam_offset + DMK_IDAM_LENGTH;
932
 
 
933
 
        /* find pattern 0xA1A1FB; this represents the start of a data sector */
934
 
        for (i = 0; i < DMK_DATA_GAP; i++)
935
 
        {
936
 
                /* overflowing the track? */
937
 
                if ((i + offs) >= tag->track_size)
938
 
                        return FLOPPY_ERROR_SEEKERROR;
939
 
 
940
 
                if (track_data[offs + i] == 0xA1)
941
 
                        state++;
942
 
                else if ((track_data[offs + i] == 0xFB) && state)
943
 
                        break;
944
 
                else
945
 
                        state = 0;
946
 
        }
947
 
        if (i >= DMK_DATA_GAP)
948
 
                return FLOPPY_ERROR_SEEKERROR;
949
 
 
950
 
        offs += i + 1;
951
 
        sec_len = 128 << dmk_idam_sectorlength(&track_data[idam_offset]);
952
 
 
953
 
        if ((offs + sec_len) > track_length)
954
 
                return FLOPPY_ERROR_INVALIDIMAGE;
955
 
 
956
 
        if (sector_data)
957
 
                *sector_data = track_data + offs;
958
 
        if (sector_length)
959
 
                *sector_length = sec_len;
960
 
        return FLOPPY_ERROR_SUCCESS;
961
 
}
962
 
 
963
 
 
964
 
 
965
 
static floperr_t coco_dmk_get_sector_length(floppy_image *floppy, int head, int track, int sector, UINT32 *sector_length)
966
 
{
967
 
        return coco_dmk_seek_sector_in_track(floppy, head, track, sector, FALSE, FALSE, NULL, sector_length);
968
 
}
969
 
 
970
 
 
971
 
 
972
 
static floperr_t coco_dmk_get_indexed_sector_info(floppy_image *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, UINT32 *sector_length, unsigned long *flags)
973
 
{
974
 
        floperr_t err;
975
 
        UINT32 idam_offset;
976
 
        const UINT8 *track_data;
977
 
        void *track_data_v;
978
 
 
979
 
        if (sector_index*2 >= DMK_TOC_LEN)
980
 
                return FLOPPY_ERROR_SEEKERROR;
981
 
 
982
 
        err = floppy_load_track(floppy, head, track, FALSE, &track_data_v, NULL);
983
 
        if (err)
984
 
                return err;
985
 
        track_data = (UINT8 *) track_data_v;
986
 
 
987
 
        idam_offset = track_data[sector_index * 2 + 1];
988
 
        idam_offset <<= 8;
989
 
        idam_offset |= track_data[sector_index * 2 + 0];
990
 
        idam_offset &= 0x3FFF;
991
 
 
992
 
        if (idam_offset == 0)
993
 
                return FLOPPY_ERROR_SEEKERROR;
994
 
 
995
 
        if (cylinder)
996
 
                *cylinder = dmk_idam_track(&track_data[idam_offset]);
997
 
        if (side)
998
 
                *side = dmk_idam_side(&track_data[idam_offset]);
999
 
        if (sector)
1000
 
                *sector = dmk_idam_sector(&track_data[idam_offset]);
1001
 
        if (sector_length)
1002
 
                *sector_length = 128 << dmk_idam_sectorlength(&track_data[idam_offset]);
1003
 
        if (flags)
1004
 
                /* TODO: read DAM or DDAM and determine flags */
1005
 
                *flags = 0;
1006
 
        return FLOPPY_ERROR_SUCCESS;
1007
 
}
1008
 
 
1009
 
 
1010
 
 
1011
 
static floperr_t internal_coco_dmk_read_sector(floppy_image *floppy, int head, int track, int sector, int sector_is_index, void *buffer, size_t buflen)
1012
 
{
1013
 
        floperr_t err;
1014
 
        UINT32 sector_length;
1015
 
        UINT16 crc_on_disk;
1016
 
        UINT16 calculated_crc;
1017
 
        UINT8 *sector_data;
1018
 
 
1019
 
        err = coco_dmk_seek_sector_in_track(floppy, head, track, sector, sector_is_index, FALSE, &sector_data, &sector_length);
1020
 
        if (err)
1021
 
                return err;
1022
 
 
1023
 
        crc_on_disk = sector_data[sector_length + 0];
1024
 
        crc_on_disk <<= 8;
1025
 
        crc_on_disk += sector_data[sector_length + 1];
1026
 
 
1027
 
        calculated_crc = ccitt_crc16(0xE295, sector_data, sector_length);
1028
 
        if (calculated_crc != crc_on_disk)
1029
 
                return FLOPPY_ERROR_INVALIDIMAGE;
1030
 
 
1031
 
        memcpy(buffer, sector_data, MIN(sector_length, buflen));
1032
 
 
1033
 
        return FLOPPY_ERROR_SUCCESS;
1034
 
}
1035
 
 
1036
 
 
1037
 
 
1038
 
static floperr_t internal_coco_dmk_write_sector(floppy_image *floppy, int head, int track, int sector, int sector_is_index, const void *buffer, size_t buflen, int ddam)
1039
 
{
1040
 
        floperr_t err;
1041
 
        UINT32 sector_length;
1042
 
        UINT8 *sector_data;
1043
 
        UINT16 crc;
1044
 
 
1045
 
        err = coco_dmk_seek_sector_in_track(floppy, head, track, sector, sector_is_index, TRUE, &sector_data, &sector_length);
1046
 
        if (err)
1047
 
                return err;
1048
 
 
1049
 
        if (buflen > sector_length)
1050
 
                return FLOPPY_ERROR_INTERNAL;
1051
 
 
1052
 
        memcpy(sector_data, buffer, buflen);
1053
 
 
1054
 
        crc = ccitt_crc16(0xE295, sector_data, sector_length);
1055
 
        sector_data[sector_length + 0] = crc >> 8;
1056
 
        sector_data[sector_length + 1] = crc >> 0;
1057
 
        return FLOPPY_ERROR_SUCCESS;
1058
 
}
1059
 
 
1060
 
 
1061
 
 
1062
 
static floperr_t coco_dmk_read_sector(floppy_image *floppy, int head, int track, int sector, void *buffer, size_t buflen)
1063
 
{
1064
 
        return internal_coco_dmk_read_sector(floppy, head, track, sector, FALSE, buffer, buflen);
1065
 
}
1066
 
 
1067
 
static floperr_t coco_dmk_write_sector(floppy_image *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam)
1068
 
{
1069
 
        return internal_coco_dmk_write_sector(floppy, head, track, sector, FALSE, buffer, buflen, ddam);
1070
 
}
1071
 
 
1072
 
static floperr_t coco_dmk_read_indexed_sector(floppy_image *floppy, int head, int track, int sector, void *buffer, size_t buflen)
1073
 
{
1074
 
        return internal_coco_dmk_read_sector(floppy, head, track, sector, TRUE, buffer, buflen);
1075
 
}
1076
 
 
1077
 
static floperr_t coco_dmk_write_indexed_sector(floppy_image *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam)
1078
 
{
1079
 
        return internal_coco_dmk_write_sector(floppy, head, track, sector, TRUE, buffer, buflen, ddam);
1080
 
}
1081
 
 
1082
 
 
1083
 
 
1084
 
static void coco_dmk_interpret_header(floppy_image *floppy, int *heads, int *tracks, int *track_size)
1085
 
{
1086
 
        UINT8 header[DMK_HEADER_LEN];
1087
 
 
1088
 
        floppy_image_read(floppy, header, 0, DMK_HEADER_LEN);
1089
 
 
1090
 
        if (tracks)
1091
 
                *tracks = header[1];
1092
 
        if (heads)
1093
 
                *heads = (header[4] & 0x10) ? 1 : 2;
1094
 
        if (track_size)
1095
 
                *track_size = ((int) header[3]) * 0x100 + header[2];
1096
 
}
1097
 
 
1098
 
 
1099
 
 
1100
 
FLOPPY_CONSTRUCT(coco_dmk_construct)
1101
 
{
1102
 
        struct FloppyCallbacks *callbacks;
1103
 
        struct dmk_tag *tag;
1104
 
        UINT8 header[DMK_HEADER_LEN];
1105
 
        int heads, tracks, track_size, sectors, sector_length;
1106
 
 
1107
 
        if (params)
1108
 
        {
1109
 
                heads                   = option_resolution_lookup_int(params, PARAM_HEADS);
1110
 
                tracks                  = option_resolution_lookup_int(params, PARAM_TRACKS);
1111
 
                sectors                 = option_resolution_lookup_int(params, PARAM_SECTORS);
1112
 
                sector_length   = option_resolution_lookup_int(params, PARAM_SECTOR_LENGTH);
1113
 
 
1114
 
                track_size = coco_dmk_min_track_size(sectors, sector_length) + DMK_EXTRA_TRACK_LENGTH;
1115
 
 
1116
 
                memset(header, 0, sizeof(header));
1117
 
                header[1] = tracks;
1118
 
                header[2] = track_size >> 0;
1119
 
                header[3] = track_size >> 8;
1120
 
                header[4] = (heads == 2) ? 0x00 : 0x10;
1121
 
 
1122
 
                floppy_image_write(floppy, header, 0, sizeof(header));
1123
 
        }
1124
 
        else
1125
 
        {
1126
 
                coco_dmk_interpret_header(floppy, &heads, &tracks, &track_size);
1127
 
        }
1128
 
 
1129
 
        tag = (dmk_tag *)floppy_create_tag(floppy, sizeof(struct dmk_tag));
1130
 
        if (!tag)
1131
 
                return FLOPPY_ERROR_OUTOFMEMORY;
1132
 
        tag->heads = heads;
1133
 
        tag->track_size = track_size;
1134
 
        tag->tracks = tracks;
1135
 
 
1136
 
        callbacks = floppy_callbacks(floppy);
1137
 
        callbacks->read_track = coco_dmk_read_track;
1138
 
        callbacks->write_track = coco_dmk_write_track;
1139
 
        callbacks->get_track_data_offset = coco_dmk_get_track_data_offset;
1140
 
        callbacks->format_track = coco_dmk_format_track;
1141
 
        callbacks->get_heads_per_disk = coco_dmk_get_heads_per_disk;
1142
 
        callbacks->get_tracks_per_disk = coco_dmk_get_tracks_per_disk;
1143
 
        callbacks->get_track_size = coco_dmk_get_track_size;
1144
 
        callbacks->get_sector_length = coco_dmk_get_sector_length;
1145
 
        callbacks->get_indexed_sector_info = coco_dmk_get_indexed_sector_info;
1146
 
        callbacks->read_sector = coco_dmk_read_sector;
1147
 
        callbacks->write_sector = coco_dmk_write_sector;
1148
 
        callbacks->read_indexed_sector = coco_dmk_read_indexed_sector;
1149
 
        callbacks->write_indexed_sector = coco_dmk_write_indexed_sector;
1150
 
 
1151
 
        return FLOPPY_ERROR_SUCCESS;
1152
 
}
1153
 
 
1154
 
 
1155
 
 
1156
 
FLOPPY_IDENTIFY(coco_dmk_identify)
1157
 
{
1158
 
        int heads, tracks, track_size;
1159
 
        UINT64 size, expected_size;
1160
 
 
1161
 
        size = floppy_image_size(floppy);
1162
 
        coco_dmk_interpret_header(floppy, &heads, &tracks, &track_size);
1163
 
        expected_size = DMK_HEADER_LEN + (heads * tracks * track_size);
1164
 
        *vote = (size == expected_size) ? 100 : 0;
1165
 
        return FLOPPY_ERROR_SUCCESS;
1166
 
}
1167
 
 
1168
 
 
1169
 
 
1170
 
/* ----------------------------------------------------------------------- */
1171
 
 
1172
 
FLOPPY_OPTIONS_START( coco )
1173
 
        FLOPPY_OPTION( coco_jvc, "dsk",                 "CoCo JVC disk image",  coco_jvc_identify,      coco_jvc_construct, NULL,
1174
 
                HEADS([1]-2)
1175
 
                TRACKS([35]-255)
1176
 
                SECTORS(1-[18]-255)
1177
 
                SECTOR_LENGTH(128/[256]/512/1024)
1178
 
                FIRST_SECTOR_ID(0-[1]))
1179
 
        FLOPPY_OPTION( coco_os9, "os9",                 "CoCo OS-9 disk image", coco_os9_identify,      coco_os9_construct, NULL,
1180
 
                HEADS([1]-2)
1181
 
                TRACKS([35]-255)
1182
 
                SECTORS(1-[18]-255)
1183
 
                SECTOR_LENGTH([256])
1184
 
                FIRST_SECTOR_ID([1]))
1185
 
        FLOPPY_OPTION( coco_vdk, "vdk",                 "CoCo VDK disk image",  coco_vdk_identify,      coco_vdk_construct, NULL,
1186
 
                HEADS([1]-2)
1187
 
                TRACKS([35]-255)
1188
 
                SECTORS([18])
1189
 
                SECTOR_LENGTH([256])
1190
 
                FIRST_SECTOR_ID([1]))
1191
 
        FLOPPY_OPTION( coco_dmk, "dsk,dmk",     "CoCo DMK disk image",  coco_dmk_identify,      coco_dmk_construct, NULL,
1192
 
                HEADS([1]-2)
1193
 
                TRACKS([35]-255)
1194
 
                SECTORS(1-[18])
1195
 
                SECTOR_LENGTH(128/[256]/512/1024/2048/4096/8192)
1196
 
                INTERLEAVE(0-[6]-17)
1197
 
                FIRST_SECTOR_ID(0-[1]))
1198
 
FLOPPY_OPTIONS_END