emu: deactivate debugger/memview when the other one is activated
[zymosis.git] / src / libfusefdc / disk_fdi.c
blob00081c5586b21fcc8a4b39c2688308be3178c1cb
1 /* disk.c: Routines for handling disk images
2 Copyright (c) 2007-2017 Gergely Szasz
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 Author contact information:
20 Philip: philip-fuse@shadowmagic.org.uk
24 //==========================================================================
26 // open_fdi
28 //==========================================================================
29 static int open_fdi (buffer_t *buffer, disk_t *d, int preindex) {
30 int i, j, h, gap;
31 int bpt, bpt_fm, max_bpt = 0, max_bpt_fm = 0;
32 int data_offset, track_offset, head_offset, sector_offset;
33 uint8_t head[256];
35 d->wrprot = (buff[0x03] == 1 ? 1 : 0);
36 d->sides = buff[0x06]+256*buff[0x07];
37 d->cylinders = buff[0x04]+256*buff[0x05];
38 GEOM_CHECK;
39 data_offset = buff[0x0a]+256*buff[0x0b];
40 h = (0x0e)+buff[0x0c]+256*buff[0x0d]; /* save head start */
41 head_offset = h;
43 /* first determine the longest track */
44 d->bpt = 0;
45 for (i = 0; i < d->cylinders*d->sides; ++i) {
46 /* ALT */
47 buffer->index = head_offset;
48 if (buffread(head, 7, buffer) != 1) return (d->status = DISK_OPEN); /* 7 := track head */
49 bpt = postindex_len(d, GAP_MINIMAL_MFM)+
50 (preindex ? preindex_len(d, GAP_MINIMAL_MFM) : 0)+6; /* +gap4 */
51 bpt_fm = postindex_len(d, GAP_MINIMAL_FM)+
52 (preindex ? preindex_len(d, GAP_MINIMAL_FM) : 0)+3; /* +gap4 */
53 /* calculate track len */
54 for (j = 0; j < head[0x06]; ++j) {
55 if (j%35 == 0) {
56 /* 35-sector header */
57 if (buffread(head+7, 245, buffer) != 1) {
58 /* 7*35 := max 35 sector head */
59 return d->status = DISK_OPEN;
62 if ((head[0x0b+7*(j%35)]&0x3f) != 0) {
63 bpt += calc_sectorlen(1, 0x80<<head[0x0a+7*(j%35)], GAP_MINIMAL_MFM);
64 bpt_fm += calc_sectorlen(0, 0x80<<head[0x0a+7*(j%35)], GAP_MINIMAL_FM);
67 if (bpt > max_bpt) max_bpt = bpt;
68 if (bpt_fm > max_bpt_fm) max_bpt_fm = bpt_fm;
69 head_offset += 7+7*head[0x06];
72 if (max_bpt == 0 || max_bpt_fm == 0) return (d->status = DISK_GEOM);
74 d->density = DISK_DENS_AUTO; /* disk_alloc use d->bpt */
75 if (max_bpt_fm < 3000) {
76 /* we choose an SD disk with FM */
77 d->bpt = max_bpt_fm;
78 gap = GAP_MINIMAL_FM;
79 } else {
80 d->bpt = max_bpt;
81 gap = GAP_MINIMAL_MFM;
83 if (disk_alloc(d) != DISK_OK) return d->status;
85 /* start reading the tracks */
86 head_offset = h; /* restore head start */
87 for (i = 0; i < d->cylinders*d->sides; ++i) {
88 /* ALT */
89 buffer->index = head_offset;
90 buffread(head, 7, buffer); /* 7 = track head */
91 track_offset = head[0x00]+256*head[0x01]+65536*head[0x02]+16777216*head[0x03];
92 DISK_SET_TRACK_IDX(d, i);
93 d->pos.i = 0;
95 if (preindex) preindex_add(d, gap);
96 postindex_add(d, gap);
98 for (j = 0; j < head[0x06]; ++j) {
99 if (j%35 == 0) {
100 /* if we have more than 35 sector in a track,
101 we have to seek back to the next sector
102 headers and read it (max 35 sector header) */
103 buffer->index = head_offset+7*(j+1);
104 buffread(head+7, 245, buffer); /* 7*35 := max 35 sector head */
106 id_add(d, head[0x08+7*(j%35)], head[0x07+7*(j%35)],
107 head[0x09+7*(j%35)], head[0x0a+7*(j%35)], gap,
108 (head[0x0b+7*(j%35)]&0x3f ? CRC_OK : CRC_ERROR));
109 sector_offset = head[0x0c+7*(j%35)]+256*head[0x0d+7*(j%35)];
110 buffer->index = data_offset+track_offset+sector_offset;
111 data_add(d, buffer, NULL,
112 ((head[0x0b+7*(j%35)]&0x3f) == 0 ? -1 : 0x80<<head[0x0a+7*(j%35)]),
113 (head[0x0b+7*(j%35)]&0x80 ? DDAM : NO_DDAM),
114 gap, CRC_OK, NO_AUTOFILL, NULL);
116 head_offset += 7+7*head[0x06];
117 gap4_add(d, gap);
120 return (d->status = DISK_OK);
124 //==========================================================================
126 // write_fdi
128 //==========================================================================
129 static int write_fdi (FILE *file, disk_t *d) {
130 int i, j, k, sbase, sectors, seclen, mfm, del;
131 int h, t, s, b;
132 int toff, soff;
133 uint8_t head[256];
135 memset(head, 0, 14);
136 memcpy(head, "FDI", 3);
137 head[0x03] = d->wrprot = 1;
138 head[0x04] = d->cylinders&0xff;
139 head[0x05] = d->cylinders>>8;
140 head[0x06] = d->sides&0xff;
141 head[0x07] = d->sides>>8;
142 sectors = 0;
143 /* count sectors */
144 for (j = 0; j < d->cylinders; ++j) {
145 for (i = 0; i < d->sides; ++i) {
146 guess_track_geom(d, i, j, &sbase, &s, &seclen, &mfm);
147 sectors += s;
150 h = (sectors+d->cylinders*d->sides)*7; /* track header len */
151 head[0x08] = (h+0x0e)&0xff; /* description offset */
152 head[0x09] = (h+0x0e)>>8; /* "http://fuse-emulator.sourceforge.net" */
153 head[0x0a] = (h+0x33)&0xff; /* data offset */
154 head[0x0b] = (h+0x33)>>8;
155 /* FDI head */
156 if (fwrite(head, 14, 1, file) != 1) return (d->status = DISK_WRPART);
158 /* write track headers */
159 toff = 0; /* offset of track data */
160 for (i = 0; i < d->cylinders; ++i) {
161 for (j = 0; j < d->sides; ++j) {
162 DISK_SET_TRACK(d, j, i);
163 d->pos.i = 0;
164 head[0x00] = toff&0xff;
165 head[0x01] = (toff>>8)&0xff; /* track offset */
166 head[0x02] = (toff>>16)&0xff;
167 head[0x03] = (toff>>24)&0xff;
168 head[0x04] = 0;
169 head[0x05] = 0;
170 guess_track_geom(d, j, i, &sbase, &sectors, &seclen, &mfm);
171 head[0x06] = sectors;
172 /* track header */
173 if (fwrite(head, 7, 1, file) != 1) return (d->status = DISK_WRPART);
175 DISK_SET_TRACK(d, j, i);
176 d->pos.i = 0;
177 k = 0;
178 soff = 0;
179 while (sectors > 0) {
180 while (k < 35 && id_read(d, &h, &t, &s, &b)) {
181 head[0x00+k*7] = t;
182 head[0x01+k*7] = h;
183 head[0x02+k*7] = s;
184 head[0x03+k*7] = b;
185 head[0x05+k*7] = soff&0xff;
186 head[0x06+k*7] = (soff>>8)&0xff;
187 if (!datamark_read(d, &del)) {
188 head[0x04+k*7] = 0; /* corrupt sector data */
189 } else {
190 head[0x04+k*7] = 1<<b|(del ? 0x80 : 0x00);
191 soff += 0x80<<b;
193 ++k;
195 /* Sector header */
196 if (fwrite(head, 7*k, 1, file) != 1) return (d->status = DISK_WRPART);
197 sectors -= k;
198 k = 0;
200 toff += soff;
204 if (fwrite("http://fuse-emulator.sourceforge.net", 37, 1, file) != 1) {
205 return (d->status = DISK_WRPART);
208 /* write data */
209 for (i = 0; i < d->cylinders; ++i) {
210 for (j = 0; j < d->sides; ++j) {
211 if (saverawtrack(d, file, j, i)) return (d->status = DISK_WRPART);
215 return (d->status = DISK_OK);