1 // license:BSD-3-Clause
2 // copyright-holders:Wilbert Pol, tim lindner
3 /*********************************************************************
4
5 formats/sdf_dsk.h
6
7 SDF disk images. Format created by Darren Atkinson for use with
8 his CoCoSDC floppy disk emulator.
9
10 http://cocosdc.blogspot.com/p/sd-card-socket-sd-card-socket-is-push.html
11
12 *********************************************************************/
13
14 #include "sdf_dsk.h"
15 #include <cassert>
16
sdf_format()17 sdf_format::sdf_format()
18 {
19 }
20
21
name() const22 const char *sdf_format::name() const
23 {
24 return "sdf";
25 }
26
27
description() const28 const char *sdf_format::description() const
29 {
30 return "SDF disk image";
31 }
32
33
extensions() const34 const char *sdf_format::extensions() const
35 {
36 return "sdf";
37 }
38
39
identify(io_generic * io,uint32_t form_factor)40 int sdf_format::identify(io_generic *io, uint32_t form_factor)
41 {
42 uint8_t header[HEADER_SIZE];
43
44 uint64_t size = io_generic_size(io);
45
46 if (size < HEADER_SIZE)
47 {
48 return 0;
49 }
50
51 io_generic_read(io, header, 0, HEADER_SIZE);
52
53 int tracks = header[4];
54 int heads = header[5];
55
56 // Check magic bytes
57 if (header[0] != 'S' || header[1] != 'D' || header[2] != 'F' || header[3] != '1')
58 {
59 return 0;
60 }
61
62 // Check heads
63 if (heads != 1 && heads != 2)
64 {
65 return 0;
66 }
67
68 if (size == HEADER_SIZE + heads * tracks * TOTAL_TRACK_SIZE)
69 {
70 return 100;
71 }
72
73 return 0;
74 }
75
76
load(io_generic * io,uint32_t form_factor,floppy_image * image)77 bool sdf_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
78 {
79 uint8_t header[HEADER_SIZE];
80 std::vector<uint8_t> track_data(TOTAL_TRACK_SIZE);
81 std::vector<uint32_t> raw_track_data;
82
83 io_generic_read(io, header, 0, HEADER_SIZE);
84
85 const int tracks = header[4];
86 const int heads = header[5];
87
88 if (heads == 2)
89 {
90 image->set_variant(floppy_image::DSDD);
91 }
92 else
93 {
94 image->set_variant(floppy_image::SSDD);
95 }
96
97 for (int track = 0; track < tracks; track++)
98 {
99 for (int head = 0; head < heads; head++)
100 {
101 int iam_location = -1;
102 int idam_location[SECTOR_SLOT_COUNT+1];
103 int dam_location[SECTOR_SLOT_COUNT+1];
104 raw_track_data.clear();
105
106 // Read track
107 io_generic_read(io, &track_data[0], HEADER_SIZE + ( heads * track + head ) * TOTAL_TRACK_SIZE, TOTAL_TRACK_SIZE);
108
109 int sector_count = track_data[0];
110
111 if (sector_count > SECTOR_SLOT_COUNT) return false;
112
113 // Transfer IDAM and DAM locations to table
114 for (int i = 0; i < SECTOR_SLOT_COUNT+1; i++)
115 {
116 if (i < sector_count )
117 {
118 idam_location[i] = ((track_data[ 8 * (i+1) + 1] << 8 | track_data[ 8 * (i+1)]) & 0x3FFF) - 4;
119 dam_location[i] = ((track_data[ 8 * (i+1) + 1 + 2] << 8 | track_data[ 8 * (i+1) + 2]) & 0x3FFF) - 4;
120
121 if (idam_location[i] > TOTAL_TRACK_SIZE) return false;
122 if (dam_location[i] > TOTAL_TRACK_SIZE) return false;
123 }
124 else
125 {
126 idam_location[i] = -1;
127 dam_location[i] = -1;
128 }
129 }
130
131 // Find IAM location
132 for (int i = idam_location[0] - 1; i >= TRACK_HEADER_SIZE + 3; i--)
133 {
134 // It's usually 3 bytes but several dumped tracks seem to contain only 2 bytes
135 if (track_data[i] == 0xfc && track_data[i-1] == 0xc2 && track_data[i-2] == 0xc2)
136 {
137 iam_location = i - 3;
138 break;
139 }
140 }
141
142 int idam_index = 0;
143 int dam_index = 0;
144 for (int offset = TRACK_HEADER_SIZE; offset < TRACK_HEADER_SIZE + TRACK_SIZE; offset++)
145 {
146 if (offset == iam_location)
147 {
148 // Write IAM
149 raw_w(raw_track_data, 16, 0x5224);
150 raw_w(raw_track_data, 16, 0x5224);
151 raw_w(raw_track_data, 16, 0x5224);
152 offset += 3;
153 }
154
155 if (offset == idam_location[idam_index])
156 {
157 raw_w(raw_track_data, 16, 0x4489);
158 raw_w(raw_track_data, 16, 0x4489);
159 raw_w(raw_track_data, 16, 0x4489);
160 idam_index += 1;
161 offset += 3;
162 }
163
164 if (offset == dam_location[dam_index])
165 {
166 raw_w(raw_track_data, 16, 0x4489);
167 raw_w(raw_track_data, 16, 0x4489);
168 raw_w(raw_track_data, 16, 0x4489);
169 dam_index += 1;
170 offset += 3;
171 }
172
173 mfm_w(raw_track_data, 8, track_data[offset]);
174 }
175
176 generate_track_from_levels(track, head, raw_track_data, 0, image);
177 }
178 }
179
180 return true;
181 }
182
183
save(io_generic * io,floppy_image * image)184 bool sdf_format::save(io_generic *io, floppy_image *image)
185 {
186 return false;
187 }
188
189
supports_save() const190 bool sdf_format::supports_save() const
191 {
192 return false;
193 }
194
195
196 const floppy_format_type FLOPPY_SDF_FORMAT = &floppy_image_format_creator<sdf_format>;
197