~ubuntu-branches/ubuntu/trusty/vice/trusty

« back to all changes in this revision

Viewing changes to src/diskimage/fsimage-gcr.c

  • Committer: Package Import Robot
  • Author(s): Laszlo Boszormenyi (GCS)
  • Date: 2013-07-28 20:38:23 UTC
  • mfrom: (1.2.5)
  • mto: This revision was merged to the branch mainline in revision 27.
  • Revision ID: package-import@ubuntu.com-20130728203823-w495rps5wuykespp
Tags: upstream-2.4.dfsg
ImportĀ upstreamĀ versionĀ 2.4.dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
#include "fsimage-gcr.h"
35
35
#include "fsimage.h"
36
36
#include "gcr.h"
 
37
#include "cbmdos.h"
37
38
#include "log.h"
 
39
#include "lib.h"
38
40
#include "types.h"
39
41
#include "util.h"
40
42
 
41
43
 
42
44
static log_t fsimage_gcr_log = LOG_ERR;
43
45
static const BYTE gcr_image_header_expected[] =
44
 
    { 0x47, 0x43, 0x52, 0x2D, 0x31, 0x35, 0x34, 0x31 };
45
 
/* Hardcoded/expected values VICE works with:
46
 
 * 0x1EF8 - 7928: Maximum container size for a raw GCR track
47
 
 * 0x54   -   84: Maximum container size for (half) track pointers
48
 
 * 0x00   -    0: GCR image file version number
49
 
 */
50
 
static const DWORD gcr_container_sizes_expected = 0x1EF85400;
 
46
    { 0x47, 0x43, 0x52, 0x2D, 0x31, 0x35, 0x34, 0x31, 0x00 };
51
47
 
52
48
/*-----------------------------------------------------------------------*/
53
49
/* Intial GCR buffer setup.  */
54
50
 
55
 
int fsimage_read_gcr_image(disk_image_t *image)
 
51
int fsimage_read_gcr_image(const disk_image_t *image)
56
52
{
57
 
    unsigned int track, num_tracks;
58
 
    DWORD gcr_track_p[MAX_TRACKS_1541 * 2];
59
 
    DWORD gcr_speed_p[MAX_TRACKS_1541 * 2];
60
 
    BYTE gcr_image_header[ sizeof( gcr_image_header_expected ) ];
61
 
    DWORD gcr_container_sizes;
62
 
    fsimage_t *fsimage;
63
 
 
64
 
    fsimage = image->media.fsimage;
65
 
 
66
 
    num_tracks = image->tracks;
67
 
 
68
 
    /* Do G64 image file sanity checks, current VICE implementation
69
 
     * does only support image file version 0 with a fixed track map
70
 
     * container size of 84 and maximum track container size of 7928
71
 
     */
72
 
    fseek(fsimage->fd, 0, SEEK_SET);
73
 
    if (fread(gcr_image_header, 1, sizeof( gcr_image_header_expected ), fsimage->fd) < 1) {
74
 
        log_error(fsimage_gcr_log, "Could not read GCR disk image.");
75
 
        return -1;
76
 
    }
77
 
    if (memcmp( gcr_image_header_expected, gcr_image_header,
78
 
                sizeof( gcr_image_header_expected ) ) != 0) {
79
 
        log_error(fsimage_gcr_log,
80
 
                  "Unexpected GCR header found." );
81
 
        return -1;
82
 
    }
83
 
    if (util_dword_read(fsimage->fd, &gcr_container_sizes, 1) < 0) {
84
 
        log_error(fsimage_gcr_log, "Could not read GCR disk image.");
85
 
        return -1;
86
 
    }
87
 
    if (gcr_container_sizes != gcr_container_sizes_expected) {
88
 
        log_error(fsimage_gcr_log,
89
 
                  "Unexpected GCR image file constants found, VICE is unable to work with." );
90
 
        return -1;
91
 
    }
92
 
 
93
 
    fseek(fsimage->fd, 12, SEEK_SET);
94
 
    if (util_dword_read(fsimage->fd, gcr_track_p, num_tracks * 2) < 0) {
95
 
        log_error(fsimage_gcr_log, "Could not read GCR disk image.");
96
 
        return -1;
97
 
    }
98
 
 
99
 
    fseek(fsimage->fd, 12 + num_tracks * 8, SEEK_SET);
100
 
    if (util_dword_read(fsimage->fd, gcr_speed_p, num_tracks * 2) < 0) {
101
 
        log_error(fsimage_gcr_log, "Could not read GCR disk image.");
102
 
        return -1;
103
 
    }
104
 
 
105
 
    for (track = 0; track < MAX_TRACKS_1541; track++) {
106
 
        BYTE *track_data, *zone_data;
107
 
 
108
 
        track_data = image->gcr->data + track * NUM_MAX_BYTES_TRACK;
109
 
        zone_data = image->gcr->speed_zone + track * NUM_MAX_BYTES_TRACK;
110
 
        memset(track_data, 0xff, NUM_MAX_BYTES_TRACK);
111
 
        memset(zone_data, 0x00, NUM_MAX_BYTES_TRACK / 4);
112
 
        image->gcr->track_size[track] = 6250;
113
 
 
114
 
        if (track <= num_tracks && gcr_track_p[track * 2] != 0) {
115
 
            BYTE len[2];
116
 
            long offset;
117
 
            size_t track_len;
118
 
            unsigned int zone_len;
119
 
 
120
 
            offset = gcr_track_p[track * 2];
121
 
 
122
 
            fseek(fsimage->fd, offset, SEEK_SET);
123
 
            if (fread(len, 2, 1, fsimage->fd) < 1) {
124
 
                log_error(fsimage_gcr_log, "Could not read GCR disk image.");
125
 
                return -1;
126
 
            }
127
 
 
128
 
            track_len = len[0] + len[1] * 256;
129
 
 
130
 
            if (track_len < 5000 || track_len > 7928) {
131
 
                log_error(fsimage_gcr_log,
132
 
                          "Track field length %i is not supported.",
133
 
                          (int)track_len);
134
 
                return -1;
135
 
            }
136
 
 
137
 
            image->gcr->track_size[track] = (unsigned int)track_len;
138
 
 
139
 
            fseek(fsimage->fd, offset + 2, SEEK_SET);
140
 
            if (fread(track_data, track_len, 1, fsimage->fd) < 1) {
141
 
                log_error(fsimage_gcr_log, "Could not read GCR disk image.");
142
 
                return -1;
143
 
            }
144
 
 
145
 
            zone_len = (unsigned int)((track_len + 3) / 4);
146
 
 
147
 
            if (gcr_speed_p[track * 2] > 3) {
148
 
                unsigned int i;
149
 
                BYTE comp_speed[NUM_MAX_BYTES_TRACK / 4];
150
 
 
151
 
                offset = gcr_speed_p[track * 2];
152
 
 
153
 
                fseek(fsimage->fd, offset, SEEK_SET);
154
 
                if (fread(comp_speed, zone_len, 1, fsimage->fd) < 1) {
155
 
                    log_error(fsimage_gcr_log,
156
 
                              "Could not read GCR disk image.");
157
 
                    return -1;
158
 
                }
159
 
                for (i = 0; i < zone_len; i++) {
160
 
                    zone_data[i * 4 + 3] = comp_speed[i] & 3;
161
 
                    zone_data[i * 4 + 2] = (comp_speed[i] >> 2) & 3;
162
 
                    zone_data[i * 4 + 1] = (comp_speed[i] >> 4) & 3;
163
 
                    zone_data[i * 4 ] = (comp_speed[i] >> 6) & 3;
164
 
                }
165
 
            } else {
166
 
                memset(zone_data, gcr_speed_p[track * 2], NUM_MAX_BYTES_TRACK);
167
 
            }
 
53
    unsigned int half_track;
 
54
 
 
55
    for (half_track = 0; half_track < MAX_GCR_TRACKS; half_track++) {
 
56
        if (image->gcr->tracks[half_track].data) {
 
57
            lib_free(image->gcr->tracks[half_track].data);
 
58
            image->gcr->tracks[half_track].data = NULL;
 
59
            image->gcr->tracks[half_track].size = 0;
 
60
        }
 
61
        if (half_track < image->max_half_tracks) {
 
62
            fsimage_gcr_read_half_track(image, half_track + 2, &image->gcr->tracks[half_track]);
168
63
        }
169
64
    }
170
65
    return 0;
171
66
}
 
67
/*-----------------------------------------------------------------------*/
 
68
/* Seek to half track */
 
69
 
 
70
static long fsimage_gcr_seek_half_track(fsimage_t *fsimage, unsigned int half_track,
 
71
        WORD *max_track_length, BYTE *num_half_tracks)
 
72
{
 
73
    BYTE buf[12];
 
74
 
 
75
    if (fsimage->fd == NULL) {
 
76
        log_error(fsimage_gcr_log, "Attempt to read without disk image.");
 
77
        return -1;
 
78
    }
 
79
    if (util_fpread(fsimage->fd, buf, 12, 0) < 0) {
 
80
        log_error(fsimage_gcr_log, "Could not read GCR disk image.");
 
81
        return -1;
 
82
    }
 
83
    if (memcmp(gcr_image_header_expected, buf, sizeof(gcr_image_header_expected)) != 0) {
 
84
        log_error(fsimage_gcr_log, "Unexpected GCR header found." );
 
85
        return -1;
 
86
    }
 
87
 
 
88
    *num_half_tracks = buf[9];
 
89
    if (*num_half_tracks > MAX_GCR_TRACKS) {
 
90
        log_error(fsimage_gcr_log, "Too many half tracks." );
 
91
        return -1;
 
92
    }
 
93
 
 
94
    *max_track_length = util_le_buf_to_word(&buf[10]);
 
95
    if (*max_track_length > NUM_MAX_MEM_BYTES_TRACK) {
 
96
        log_error(fsimage_gcr_log, "Too large max track length.");
 
97
        return -1;
 
98
    }
 
99
 
 
100
    if (util_fpread(fsimage->fd, buf, 4, 12 + (half_track - 2) * 4) < 0) {
 
101
        log_error(fsimage_gcr_log, "Could not read GCR disk image.");
 
102
        return -1;
 
103
    }
 
104
    return util_le_buf_to_dword(buf);
 
105
}
172
106
 
173
107
/*-----------------------------------------------------------------------*/
174
108
/* Read an entire GCR track from the disk image.  */
175
109
 
176
 
int fsimage_gcr_read_track(disk_image_t *image, unsigned int track,
177
 
                           BYTE *gcr_data, int *gcr_track_size)
 
110
int fsimage_gcr_read_half_track(const disk_image_t *image, unsigned int half_track,
 
111
                                  disk_track_t *raw)
178
112
{
179
 
    int track_len;
180
 
    BYTE len[2];
181
 
    DWORD gcr_track_p;
 
113
    WORD track_len;
 
114
    BYTE buf[4];
182
115
    long offset;
183
116
    fsimage_t *fsimage;
 
117
    WORD max_track_length;
 
118
    BYTE num_half_tracks;
184
119
 
185
120
    fsimage = image->media.fsimage;
186
121
 
187
 
    if (fsimage->fd == NULL) {
188
 
        log_error(fsimage_gcr_log, "Attempt to read without disk image.");
189
 
        return -1;
190
 
    }
191
 
 
192
 
    fseek(fsimage->fd, 12 + (track - 1) * 8, SEEK_SET);
193
 
    if (util_dword_read(fsimage->fd, &gcr_track_p, 1) < 0) {
194
 
        log_error(fsimage_gcr_log, "Could not read GCR disk image.");
195
 
        return -1;
196
 
    }
197
 
 
198
 
    memset(gcr_data, 0xff, NUM_MAX_BYTES_TRACK);
199
 
    *gcr_track_size = 6250;
200
 
 
201
 
    if (gcr_track_p != 0) {
202
 
 
203
 
        offset = gcr_track_p;
204
 
 
205
 
        fseek(fsimage->fd, offset, SEEK_SET);
206
 
        if (fread(len, 2, 1, fsimage->fd) < 1) {
 
122
    raw->data = NULL;
 
123
    raw->size = 0;
 
124
 
 
125
    offset = fsimage_gcr_seek_half_track(fsimage, half_track, &max_track_length, &num_half_tracks);
 
126
 
 
127
    if (offset < 0) {
 
128
        return -1;
 
129
    }
 
130
 
 
131
    if (offset != 0) {
 
132
        if (util_fpread(fsimage->fd, buf, 2, offset) < 0) {
207
133
            log_error(fsimage_gcr_log, "Could not read GCR disk image.");
208
134
            return -1;
209
135
        }
210
136
 
211
 
        track_len = len[0] + len[1] * 256;
 
137
        track_len = util_le_buf_to_word(buf);
212
138
 
213
 
        if (track_len < 5000 || track_len > 7928) {
 
139
        if ((track_len < 1) || (track_len > max_track_length)) {
214
140
            log_error(fsimage_gcr_log,
215
 
                      "Track field length %i is not supported.",
 
141
                      "Track field length %u is not supported.",
216
142
                      track_len);
217
143
            return -1;
218
144
        }
219
145
 
220
 
        *gcr_track_size = track_len;
 
146
        raw->data = lib_calloc(1, track_len);
 
147
        raw->size = track_len;
221
148
 
222
 
        fseek(fsimage->fd, offset + 2, SEEK_SET);
223
 
        if (fread(gcr_data, track_len, 1, fsimage->fd) < 1) {
 
149
        if (fread(raw->data, track_len, 1, fsimage->fd) < 1) {
224
150
            log_error(fsimage_gcr_log, "Could not read GCR disk image.");
225
151
            return -1;
226
152
        }
 
153
    } else {
 
154
        raw->size = disk_image_raw_track_size(image->type, half_track / 2);
 
155
        raw->data = lib_malloc(raw->size);
 
156
        memset(raw->data, 0x55, raw->size);
227
157
    }
228
158
    return 0;
229
159
}
230
160
 
 
161
static int fsimage_gcr_read_track(const disk_image_t *image, unsigned int track,
 
162
                           disk_track_t *raw)
 
163
{
 
164
    return fsimage_gcr_read_half_track(image, track << 1, raw);
 
165
}
 
166
 
231
167
/*-----------------------------------------------------------------------*/
232
168
/* Write an entire GCR track to the disk image.  */
233
169
 
234
 
int fsimage_gcr_write_track(disk_image_t *image, unsigned int track,
235
 
                            int gcr_track_size, BYTE *gcr_speed_zone,
236
 
                            BYTE *gcr_track_start_ptr)
 
170
int fsimage_gcr_write_half_track(disk_image_t *image, unsigned int half_track,
 
171
                                 const disk_track_t *raw)
237
172
{
238
 
    int gap, i;
239
 
    unsigned int num_tracks;
240
 
    BYTE len[2];
241
 
    DWORD gcr_track_p[MAX_TRACKS_1541 * 2];
242
 
    DWORD gcr_speed_p[MAX_TRACKS_1541 * 2];
243
 
    int offset;
 
173
    int gap, extend = 0;
 
174
    WORD max_track_length;
 
175
    BYTE buf[4];
 
176
    long offset;
244
177
    fsimage_t *fsimage;
 
178
    BYTE num_half_tracks;
245
179
 
246
180
    fsimage = image->media.fsimage;
247
181
 
248
 
    if (fsimage->fd == NULL) {
249
 
        log_error(fsimage_gcr_log, "Attempt to write without disk image.");
 
182
    offset = fsimage_gcr_seek_half_track(fsimage, half_track, &max_track_length, &num_half_tracks);
 
183
    if (offset < 0) {
250
184
        return -1;
251
185
    }
252
 
 
253
186
    if (image->read_only != 0) {
254
187
        log_error(fsimage_gcr_log,
255
188
                  "Attempt to write to read-only disk image.");
256
189
        return -1;
257
190
    }
258
191
 
259
 
    num_tracks = image->tracks;
260
 
 
261
 
    fseek(fsimage->fd, 12, SEEK_SET);
262
 
    if (util_dword_read(fsimage->fd, gcr_track_p, num_tracks * 2) < 0) {
263
 
        log_error(fsimage_gcr_log, "Could not read GCR disk image header.");
264
 
        return -1;
265
 
    }
266
 
 
267
 
    fseek(fsimage->fd, 12 + num_tracks * 8, SEEK_SET);
268
 
    if (util_dword_read(fsimage->fd, gcr_speed_p, num_tracks * 2) < 0) {
269
 
        log_error(fsimage_gcr_log, "Could not read GCR disk image header.");
270
 
        return -1;
271
 
    }
272
 
 
273
 
    if (gcr_track_p[(track - 1) * 2] == 0) {
 
192
    if (raw->size > max_track_length) {
 
193
        log_error(fsimage_gcr_log,
 
194
                  "Track too long for image.");
 
195
        return -1;
 
196
    }
 
197
 
 
198
    if (offset == 0) {
274
199
        offset = fseek(fsimage->fd, 0, SEEK_END);
 
200
        if (offset == 0) {
 
201
            offset = ftell(fsimage->fd);
 
202
        }
275
203
        if (offset < 0) {
276
204
            log_error(fsimage_gcr_log, "Could not extend GCR disk image.");
277
205
            return -1;
278
206
        }
279
 
        gcr_track_p[(track - 1) * 2] = offset;
280
 
    }
281
 
 
282
 
    offset = gcr_track_p[(track - 1) * 2];
283
 
 
284
 
    len[0] = gcr_track_size % 256;
285
 
    len[1] = gcr_track_size / 256;
286
 
 
287
 
    if (fseek(fsimage->fd, offset, SEEK_SET) < 0
288
 
        || fwrite(len, 2, 1, fsimage->fd) < 1) {
289
 
        log_error(fsimage_gcr_log, "Could not write GCR disk image.");
290
 
        return -1;
291
 
    }
292
 
 
293
 
    /* Clear gap between the end of the actual track and the start of
294
 
       the next track.  */
295
 
    gap = NUM_MAX_BYTES_TRACK - gcr_track_size;
296
 
    if (gap > 0)
297
 
        memset(gcr_track_start_ptr + gcr_track_size, 0, gap);
298
 
 
299
 
    if (fseek(fsimage->fd, offset + 2, SEEK_SET) < 0
300
 
        || fwrite(gcr_track_start_ptr, NUM_MAX_BYTES_TRACK, 1,
301
 
        fsimage->fd) < 1) {
302
 
        log_error(fsimage_gcr_log, "Could not write GCR disk image.");
303
 
        return -1;
304
 
    }
305
 
 
306
 
    if (gcr_speed_zone != NULL) {
307
 
        for (i = 0; (gcr_speed_zone[(track - 1) * NUM_MAX_BYTES_TRACK]
308
 
            == gcr_speed_zone[(track - 1) * NUM_MAX_BYTES_TRACK + i])
309
 
            && i < NUM_MAX_BYTES_TRACK; i++);
310
 
 
311
 
        if (i < gcr_track_size) {
312
 
            /* This will change soon.  */
313
 
            log_error(fsimage_gcr_log,
314
 
                      "Saving different speed zones is not supported yet.");
315
 
            return -1;
316
 
        }
317
 
 
318
 
        if (gcr_speed_p[(track - 1) * 2] >= 4) {
319
 
            /* This will change soon.  */
320
 
            log_error(fsimage_gcr_log,
321
 
                      "Adding new speed zones is not supported yet.");
322
 
            return -1;
323
 
        }
324
 
 
325
 
        offset = 12 + num_tracks * 8 + (track - 1) * 8;
326
 
        if (fseek(fsimage->fd, offset, SEEK_SET) < 0
327
 
            || util_dword_write(fsimage->fd, &gcr_speed_p[(track - 1) * 2], 1)
328
 
            < 0) {
329
 
            log_error(fsimage_gcr_log, "Could not write GCR disk image.");
330
 
            return -1;
331
 
        }
332
 
    }
333
 
 
334
 
#if 0  /* We do not support writing different speeds yet.  */
335
 
    for (i = 0; i < (NUM_MAX_BYTES_TRACK / 4); i++)
336
 
        zone_len = (gcr_track_size + 3) / 4;
337
 
    zone_data = gcr_speed_zone + (track - 1) * NUM_MAX_BYTES_TRACK;
338
 
 
339
 
    if (gap > 0)
340
 
        memset(zone_data + gcr_track_size, 0, gap);
341
 
 
342
 
    for (i = 0; i < (NUM_MAX_BYTES_TRACK / 4); i++)
343
 
        comp_speed[i] = (zone_data[i * 4]
344
 
                         | (zone_data[i * 4 + 1] << 2)
345
 
                         | (zone_data[i * 4 + 2] << 4)
346
 
                         | (zone_data[i * 4 + 3] << 6));
347
 
 
348
 
    if (fseek(fsimage->fd, offset, SEEK_SET) < 0
349
 
        || fwrite((char *)comp_speed, NUM_MAX_BYTES_TRACK / 4, 1
350
 
        fsimage->fd) < 1) {
351
 
        log_error(fsimage_gcr_log, "Could not write GCR disk image");
352
 
        return;
353
 
    }
354
 
#endif
 
207
        extend = 1;
 
208
    }
 
209
 
 
210
    if (raw->data != NULL) {
 
211
        util_word_to_le_buf(buf, raw->size);
 
212
 
 
213
        if (util_fpwrite(fsimage->fd, buf, 2, offset) < 0) {
 
214
            log_error(fsimage_gcr_log, "Could not write GCR disk image.");
 
215
            return -1;
 
216
        }
 
217
 
 
218
        /* Clear gap between the end of the actual track and the start of
 
219
           the next track.  */
 
220
        if (fwrite(raw->data, raw->size, 1, fsimage->fd) < 1) {
 
221
            log_error(fsimage_gcr_log, "Could not write GCR disk image.");
 
222
            return -1;
 
223
        }
 
224
        gap = max_track_length - raw->size;
 
225
 
 
226
        if (gap > 0) {
 
227
            BYTE *padding = lib_calloc(1, gap);
 
228
            fwrite(padding, gap, 1, fsimage->fd);
 
229
            lib_free(padding);
 
230
        }
 
231
 
 
232
        if (extend) {
 
233
            util_dword_to_le_buf(buf, offset);
 
234
            if (util_fpwrite(fsimage->fd, buf, 4, 12 + (half_track - 2) * 4) < 0) {
 
235
                log_error(fsimage_gcr_log, "Could not write GCR disk image.");
 
236
                return -1;
 
237
            }
 
238
 
 
239
            util_dword_to_le_buf(buf, disk_image_speed_map(image->type, half_track / 2));
 
240
            if (util_fpwrite(fsimage->fd, buf, 4, 12 + (half_track - 2 + num_half_tracks) * 4) < 0) {
 
241
                log_error(fsimage_gcr_log, "Could not write GCR disk image.");
 
242
                return -1;
 
243
            }
 
244
        }
 
245
    }
355
246
 
356
247
    /* Make sure the stream is visible to other readers.  */
357
248
    fflush(fsimage->fd);
359
250
    return 0;
360
251
}
361
252
 
 
253
static int fsimage_gcr_write_track(disk_image_t *image, unsigned int track,
 
254
                            const disk_track_t *raw)
 
255
{
 
256
  return fsimage_gcr_write_half_track(image, track << 1, raw);
 
257
}
 
258
 
362
259
/*-----------------------------------------------------------------------*/
363
260
/* Read a sector from the GCR disk image.  */
364
261
 
365
 
int fsimage_gcr_read_sector(disk_image_t *image, BYTE *buf,
366
 
                               unsigned int track, unsigned int sector)
 
262
int fsimage_gcr_read_sector(const disk_image_t *image, BYTE *buf, const disk_addr_t *dadr)
367
263
{
368
 
    BYTE gcr_data[NUM_MAX_BYTES_TRACK], *gcr_track_start_ptr;
369
 
    int gcr_track_size, gcr_current_track_size;
 
264
    fdc_err_t rf;
370
265
 
371
 
    if (track > image->tracks) {
 
266
    if (dadr->track > image->tracks) {
372
267
        log_error(fsimage_gcr_log,
373
268
                  "Track %i out of bounds.  Cannot read GCR track.",
374
 
                  track);
 
269
                  dadr->track);
375
270
        return -1;
376
271
    }
 
272
 
377
273
    if (image->gcr == NULL) {
378
 
        if (fsimage_gcr_read_track(image, track, gcr_data,
379
 
            &gcr_track_size) < 0) {
380
 
            log_error(fsimage_gcr_log,
381
 
                      "Cannot read track %i from GCR image.", track);
 
274
        disk_track_t raw;
 
275
        if (fsimage_gcr_read_track(image, dadr->track, &raw) < 0) {
382
276
            return -1;
 
277
        } 
 
278
        if (raw.data == NULL) {
 
279
            return CBMDOS_IPE_NOT_READY;
383
280
        }
384
 
        gcr_track_start_ptr = gcr_data;
385
 
        gcr_current_track_size = gcr_track_size;
 
281
        rf = gcr_read_sector(&raw, buf, dadr->sector);
 
282
        lib_free(raw.data);
386
283
    } else {
387
 
        gcr_track_start_ptr = image->gcr->data
388
 
                              + ((track - 1) * NUM_MAX_BYTES_TRACK);
389
 
        gcr_current_track_size = image->gcr->track_size[track - 1];
 
284
        rf = gcr_read_sector(&image->gcr->tracks[(dadr->track * 2) - 2], buf, dadr->sector);
390
285
    }
391
 
    if (gcr_read_sector(gcr_track_start_ptr, gcr_current_track_size,
392
 
        buf, track, sector) < 0) {
 
286
    if (rf != CBMDOS_FDC_ERR_OK) {
393
287
        log_error(fsimage_gcr_log,
394
288
                  "Cannot find track: %i sector: %i within GCR image.",
395
 
                  track, sector);
396
 
        return -1;
 
289
                  dadr->track, dadr->sector);
 
290
        switch (rf) {
 
291
        case CBMDOS_FDC_ERR_HEADER:
 
292
            return CBMDOS_IPE_READ_ERROR_BNF;   /* 20 */
 
293
        case CBMDOS_FDC_ERR_SYNC:
 
294
            return CBMDOS_IPE_READ_ERROR_SYNC;  /* 21 */
 
295
        case CBMDOS_FDC_ERR_NOBLOCK:
 
296
            return CBMDOS_IPE_READ_ERROR_DATA;  /* 22 */
 
297
        case CBMDOS_FDC_ERR_DCHECK:
 
298
            return CBMDOS_IPE_READ_ERROR_CHK;   /* 23 */ 
 
299
        case CBMDOS_FDC_ERR_VERIFY:
 
300
            return CBMDOS_IPE_WRITE_ERROR_VER;  /* 25 */
 
301
        case CBMDOS_FDC_ERR_WPROT:
 
302
            return CBMDOS_IPE_WRITE_PROTECT_ON; /* 26 */
 
303
        case CBMDOS_FDC_ERR_HCHECK:
 
304
            return CBMDOS_IPE_READ_ERROR_BCHK;  /* 27 */
 
305
        case CBMDOS_FDC_ERR_BLENGTH:
 
306
            return CBMDOS_IPE_WRITE_ERROR_BIG;  /* 28 */
 
307
        case CBMDOS_FDC_ERR_ID:
 
308
            return CBMDOS_IPE_DISK_ID_MISMATCH; /* 29 */
 
309
        case CBMDOS_FDC_ERR_DRIVE:
 
310
            return CBMDOS_IPE_NOT_READY;        /* 74 */
 
311
        case CBMDOS_FDC_ERR_DECODE:
 
312
            return CBMDOS_IPE_READ_ERROR_GCR;   /* 24 */
 
313
        default:
 
314
            return CBMDOS_IPE_NOT_READY;
 
315
        }
397
316
    }
398
 
 
399
 
    return 0;
 
317
    return CBMDOS_IPE_OK;
400
318
}
401
319
 
402
320
 
403
321
/*-----------------------------------------------------------------------*/
404
322
/* Write a sector to the GCR disk image.  */
405
323
 
406
 
int fsimage_gcr_write_sector(disk_image_t *image, BYTE *buf,
407
 
                                unsigned int track, unsigned int sector)
 
324
int fsimage_gcr_write_sector(disk_image_t *image, const BYTE *buf,
 
325
                                const disk_addr_t *dadr)
408
326
{
409
 
    BYTE gcr_data[NUM_MAX_BYTES_TRACK];
410
 
    BYTE *gcr_track_start_ptr, *speed_zone;
411
 
    int gcr_track_size, gcr_current_track_size;
412
 
 
413
 
    if (track > image->tracks) {
 
327
    if (dadr->track > image->tracks) {
414
328
        log_error(fsimage_gcr_log,
415
329
                  "Track %i out of bounds.  Cannot write GCR sector",
416
 
                  track);
 
330
                  dadr->track);
417
331
        return -1;
418
332
    }
 
333
 
419
334
    if (image->gcr == NULL) {
420
 
        if (fsimage_gcr_read_track(image, track, gcr_data,
421
 
            &gcr_track_size) < 0) {
 
335
        disk_track_t raw;
 
336
        if (fsimage_gcr_read_track(image, dadr->track, &raw) < 0
 
337
                || raw.data == NULL) {
 
338
            return -1;
 
339
        }
 
340
        if (gcr_write_sector(&raw, buf, dadr->sector) != CBMDOS_FDC_ERR_OK) {
422
341
            log_error(fsimage_gcr_log,
423
 
                      "Cannot read track %i from GCR image.", track);
424
 
            return -1;
425
 
        }
426
 
        gcr_track_start_ptr = gcr_data;
427
 
        gcr_current_track_size = gcr_track_size;
428
 
        speed_zone = NULL;
 
342
                    "Could not find track %i sector %i in disk image",
 
343
                    dadr->track, dadr->sector);
 
344
            lib_free(raw.data);
 
345
            return -1;
 
346
        }
 
347
        if (fsimage_gcr_write_track(image, dadr->track, &raw) < 0) {
 
348
            lib_free(raw.data);
 
349
            return -1;
 
350
        }
 
351
        lib_free(raw.data);
429
352
    } else {
430
 
        gcr_track_start_ptr = image->gcr->data
431
 
                              + ((track - 1) * NUM_MAX_BYTES_TRACK);
432
 
        gcr_current_track_size = image->gcr->track_size[track - 1];
433
 
        speed_zone = image->gcr->speed_zone;
434
 
    }
435
 
    if (gcr_write_sector(gcr_track_start_ptr,
436
 
        gcr_current_track_size, buf, track, sector) < 0) {
437
 
        log_error(fsimage_gcr_log,
438
 
                  "Could not find track %i sector %i in disk image",
439
 
                  track, sector);
440
 
        return -1;
441
 
    }
442
 
    if (disk_image_write_track(image, track, gcr_current_track_size,
443
 
        speed_zone, gcr_track_start_ptr) < 0) {
444
 
        log_error(fsimage_gcr_log,
445
 
                  "Failed writing track %i to disk image.", track);
446
 
        return -1;
 
353
        if (gcr_write_sector(&image->gcr->tracks[(dadr->track * 2) - 2], buf, dadr->sector) != CBMDOS_FDC_ERR_OK) {
 
354
            log_error(fsimage_gcr_log,
 
355
                    "Could not find track %i sector %i in disk image",
 
356
                    dadr->track, dadr->sector);
 
357
            return -1;
 
358
        }
 
359
        if (fsimage_gcr_write_track(image, dadr->track, &image->gcr->tracks[(dadr->track * 2) - 2]) < 0) {
 
360
            log_error(fsimage_gcr_log,
 
361
                    "Failed writing track %i to disk image.", dadr->track);
 
362
            return -1;
 
363
        }
447
364
    }
448
365
 
449
366
    return 0;
455
372
{
456
373
    fsimage_gcr_log = log_open("Filesystem Image GCR");
457
374
}
458