do not use libspectrum to detect disk image format
[zymosis.git] / src / libfusefdc / disk.h
blobfed3ef59a94c558d1a9f1808be104da2ad91af25
1 /* disk.h: Routines for handling disk images
2 Copyright (c) 2007-2015 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
23 #ifndef FUSE_DISK_H
24 #define FUSE_DISK_H
26 #include <stddef.h>
27 #include <stdint.h>
30 static const unsigned int DISK_FLAG_NONE = 0x00;
31 static const unsigned int DISK_FLAG_PLUS3_CPC = 0x01; /* try to fix some CPC issue */
32 static const unsigned int DISK_FLAG_OPEN_DS = 0x02; /* try to open the other side too */
35 typedef enum disk_error_t {
36 DISK_OK = 0,
37 DISK_IMPL,
38 DISK_MEM,
39 DISK_GEOM,
40 DISK_OPEN,
41 DISK_UNSUP,
42 DISK_RDONLY,
43 DISK_CLOSE,
44 DISK_WRFILE,
45 DISK_WRPART,
47 // for sector reading API
48 DISK_INVALID_HEAD,
49 DISK_NO_CYLINDER,
50 DISK_NO_SECTOR,
51 DISK_BAD_SECTOR,
52 DISK_SECTOR_TOO_BIG,
53 DISK_WRITE_ERROR,
55 DISK_LAST_ERROR,
56 } disk_error_t;
59 typedef enum disk_type_t {
60 DISK_TYPE_NONE = 0,
61 DISK_UDI, /* raw track disk image (our format :-) */
62 DISK_FDI, /* Full Disk Image ALT */
63 DISK_TD0,
65 /* DISCiPLE / +D / SAM Coupe */
66 DISK_MGT, /* ALT */
67 DISK_IMG, /* OUT-OUT */
68 DISK_SAD, /* OUT-OUT with geometry header */
70 DISK_CPC,
71 DISK_ECPC,
73 /* Beta disk interface (TR-DOS) */
74 DISK_TRD,
75 DISK_SCL,
77 /* Opus Discovery */
78 DISK_OPD,
80 /* Didaktik 40/80 */
81 DISK_D40,
82 DISK_D80,
84 /* Log disk structure (.log) */
85 DISK_LOG,
87 DISK_TYPE_LAST,
88 } disk_type_t;
91 typedef enum disk_dens_t {
92 DISK_DENS_AUTO = 0,
93 DISK_8_SD, /* 8" SD floppy 5208 MF */
94 DISK_8_DD, /* 8" DD floppy 10416 */
95 DISK_SD, /* 3125 bpt MF */
96 DISK_DD, /* 6250 bpt */
97 DISK_DD_PLUS, /* 6500 bpt e.g. Coin Op Hits */
98 DISK_HD, /* 12500 bpt*/
99 } disk_dens_t;
102 typedef struct disk_t {
103 char *filename; /* original filename */
104 int sides; /* 1 or 2 */
105 int cylinders; /* tracks per side */
106 int bpt; /* bytes per track */
107 int wrprot; /* disk write protect */
108 int dirty; /* disk changed */
109 int have_weak; /* disk contain weak sectors */
110 unsigned int flag;
111 disk_error_t status; /* last error code */
112 uint8_t *data; /* disk data */
113 /* private part */
114 int tlen; /* length of a track with clock and other marks (bpt + 3/8bpt) */
115 uint8_t *track; /* current track data bytes */
116 uint8_t *clocks; /* clock marks bits */
117 uint8_t *fm; /* FM/MFM marks bits */
118 uint8_t *weak; /* weak marks bits/weak data */
119 int i; /* index for track and clocks */
120 disk_type_t type; /* DISK_UDI, ... */
121 disk_dens_t density; /* DISK_SD DISK_DD, or DISK_HD */
122 } disk_t;
125 /* every track data:
126 TRACK_LEN TYPE TRACK......DATA CLOCK..MARKS MF..MARKS WEAK..MARKS
127 ^ ^ ^ ^
128 |__ track |__ clocks |__ mf |__ weak
129 so, track[-1] = TYPE
130 TLEN = track[-3] + tarck 256 * track[-2]
131 TYPE is Track type as in UDI spec (0x00, 0x01, 0x02, 0x80, 0x81, 0x82) after update_tracks_mode() !!!
134 #define DISK_CLEN(bpt) ((bpt)/8+((bpt)%8 ? 1 : 0))
136 #define DISK_SET_TRACK_IDX(d, idx) do { \
137 d->track = d->data+3+(idx)*d->tlen; \
138 d->clocks = d->track+d->bpt; \
139 d->fm = d->clocks+DISK_CLEN(d->bpt); \
140 d->weak = d->fm+DISK_CLEN(d->bpt); \
141 } while (0)
143 #define DISK_SET_TRACK(d, head, cyl) do { \
144 DISK_SET_TRACK_IDX((d), (d)->sides*cyl+head); \
145 } while (0)
148 // you need to save and restore disk position when manipulating disk data
149 // this is because FDC is using the position too, and if you will break it,
150 // disk i/o operations will read/write invalid data
151 typedef struct {
152 uint8_t *track; /* current track data bytes */
153 uint8_t *clocks; /* clock marks bits */
154 uint8_t *fm; /* FM/MFM marks bits */
155 uint8_t *weak; /* weak marks bits/weak data */
156 int i; /* index for track and clocks */
157 } disk_position_t;
160 static inline __attribute__((unused))
161 void disk_position_save (const disk_t *d, disk_position_t *c) {
162 c->track = d->track;
163 c->clocks = d->clocks;
164 c->fm = d->fm;
165 c->weak = d->weak;
166 c->i = d->i;
169 static inline __attribute__((unused))
170 void disk_position_restore (disk_t *d, const disk_position_t *c) {
171 d->track = c->track;
172 d->clocks = c->clocks;
173 d->fm = c->fm;
174 d->weak = c->weak;
175 d->i = c->i;
179 /* insert simple TR-DOS autoloader? */
180 extern int opt_beta_autoload; /* default is 1 */
183 const char *disk_strerror (int error);
185 /* create an unformatted disk sides -> (1/2) cylinders -> track/side,
186 dens -> 'density' related to unformatted length of a track (SD = 3125,
187 DD = 6250, HD = 12500, type -> if write this disk we want to convert
188 into this type of image file
190 int disk_new (disk_t *d, int sides, int cylinders, disk_dens_t dens, disk_type_t type);
192 /* detects some common disk image formats */
193 disk_type_t disk_detect_format (const void *data, int size);
195 /* open a disk image file. if preindex = 1 and the image file not UDI then
196 pre-index gap generated with index mark (0xfc)
197 this time only .mgt(.dsk)/.img/.udi and CPC/extended CPC file format
198 supported
200 int disk_open (disk_t *d, const char *filename, int preindex);
202 // returns error code
203 int disk_open_buf_udi (disk_t *d, const void *data, int size);
204 int disk_open_buf_fdi (disk_t *d, const void *data, int size);
205 int disk_open_buf_trd (disk_t *d, const void *data, int size);
206 int disk_open_buf_scl (disk_t *d, const void *data, int size);
207 int disk_open_buf_td0 (disk_t *d, const void *data, int size);
208 int disk_open_buf_dsk (disk_t *d, const void *data, int size);
211 /* merge two one sided disk (d1, d2) to a two sided one (d),
212 after merge closes d1 and d2
214 int disk_merge_sides (disk_t *d, disk_t *d1, disk_t *d2, int autofill);
216 /* write a disk image file (from the disk buffer). the d->type
217 gives the format of file. if it DISK_TYPE_AUTO, disk_write
218 try to guess from the file name (extension). if fail save as
219 UDI.
221 int disk_write (disk_t *d, const char *filename);
223 /* format disk to plus3 accept for formatting
225 int disk_preformat (disk_t *d);
227 /* close a disk and free buffers
229 void disk_close (disk_t *d);
232 // read disk sector
233 // returns error code (DISK_xxx)
234 // automatically saves and restores disk position
235 // doesn't change `d->status`
236 int disk_read_sector (disk_t *d, int head, int cylinder, int sector,
237 void *buf, size_t bufsize, int *sectorsize);
239 enum {
240 DISK_WR_BETA,
241 DISK_WR_PLUS3,
244 // write disk sector
245 // returns error code (DISK_xxx)
246 // automatically saves and restores disk position
247 // doesn't change `d->status`
248 int disk_write_sector (disk_t *d, int head, int cylinder, int sector,
249 const void *buf, size_t bufsize, int type/*DISK_WR_xxx*/);
251 // frees old disk data, creates new, sets `d->status`
252 // doesn't write TR-DOS directory, the disk is filled with zeroes
253 int disk_format_beta (disk_t *d, int cylinders, int interleave);
256 #endif