1 /***************************************************************************
2  *                                                                         *
3  *    LIBDSK: General floppy and diskimage access library                  *
4  *    Copyright (C) 2001-2015 John Elliott <seasip.webmaster@gmail.com>    *
5  *                                                                         *
6  *    Modifications to add dsk_dirty()                                     *
7  *    (c) 2005 Philip Kendall <pak21-spectrum@srcf.ucam.org>               *
8  *                                                                         *
9  *    This library is free software; you can redistribute it and/or        *
10  *    modify it under the terms of the GNU Library General Public          *
11  *    License as published by the Free Software Foundation; either         *
12  *    version 2 of the License, or (at your option) any later version.     *
13  *                                                                         *
14  *    This library is distributed in the hope that it will be useful,      *
15  *    but WITHOUT ANY WARRANTY; without even the implied warranty of       *
16  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    *
17  *    Library General Public License for more details.                     *
18  *                                                                         *
19  *    You should have received a copy of the GNU Library General Public    *
20  *    License along with this library; if not, write to the Free           *
21  *    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,      *
22  *    MA 02111-1307, USA                                                   *
23  *                                                                         *
24  ***************************************************************************/
25 
26 #ifndef LIBDSK_H
27 #define LIBDSK_H 1
28 /*
29  * LIBDSK: Portable library for floppy / disk image access
30  *
31  */
32 
33 /* The Magic Incantations for exporting the functions from DLLs under
34  * Windows. */
35 #ifdef WIN16
36 # define LDPUBLIC16 __export __far __pascal
37 # define LDPUBLIC32
38 #else   /* def WIN16 */
39 # ifdef WIN32
40 #  ifdef NOTWINDLL
41 #   define LDPUBLIC16
42 #   define LDPUBLIC32
43 #  else /* def NOTDLL */
44 #   define LDPUBLIC16 __stdcall
45 #   ifdef LIBDSK_EXPORTS
46 #    define LDPUBLIC32 __declspec(dllexport)
47 #   else  /* def LIBDSK_EXPORTS */
48 #    define LDPUBLIC32 __declspec(dllimport)
49 #   endif /* def LIBDSK_EXPORTS */
50 #  endif  /* def NOTDLL */
51 # else    /* def WIN32 */
52 #  define LDPUBLIC32
53 #  define LDPUBLIC16
54 # endif /* def WIN32 */
55 #endif  /* def WIN16 */
56 
57 #ifdef __cplusplus
58 extern "C" {
59 #endif
60 
61 #define LIBDSK_VERSION "1.4.2"
62 
63 /************************* TYPES ********************************/
64 
65 typedef          int  dsk_err_t;	/* Error number */
66 typedef unsigned long dsk_lsect_t;	/* Logical sector */
67 typedef unsigned int  dsk_ltrack_t;	/* Logical track */
68 typedef unsigned int  dsk_psect_t;	/* Physical sector */
69 typedef unsigned int  dsk_pcyl_t;	/* Physical cylinder */
70 typedef unsigned int  dsk_phead_t;	/* Physical head */
71 typedef unsigned char dsk_gap_t;	/* Gap length */
72 typedef const char *  dsk_cchar_t;	/* Const char * */
73 #define DSK_ERR_OK	 (0)	/* No error */
74 #define DSK_ERR_BADPTR	 (-1)	/* Bad pointer */
75 #define DSK_ERR_DIVZERO  (-2)	/* Division by zero */
76 #define DSK_ERR_BADPARM  (-3)	/* Bad parameter */
77 #define DSK_ERR_NODRVR   (-4)	/* Driver not found */
78 #define DSK_ERR_NOTME    (-5)	/* Driver rejects disc */
79 #define DSK_ERR_SYSERR   (-6)	/* System error, use errno */
80 #define DSK_ERR_NOMEM  	 (-7)	/* Null return from malloc */
81 #define DSK_ERR_NOTIMPL  (-8)	/* Function not implemented */
82 #define DSK_ERR_MISMATCH (-9)	/* Check sectors: No match*/
83 #define DSK_ERR_NOTRDY   (-10)	/* Drive not ready */
84 #define DSK_ERR_RDONLY	 (-11)	/* Read-only disc */
85 #define DSK_ERR_SEEKFAIL (-12)	/* Seek fail */
86 #define DSK_ERR_DATAERR  (-13)	/* CRC data error */
87 #define DSK_ERR_NODATA   (-14)	/* No data */
88 #define DSK_ERR_NOADDR	 (-15)	/* Missing address mark */
89 #define DSK_ERR_BADFMT   (-16)	/* Bad format */
90 #define DSK_ERR_CHANGED  (-19)	/* Disc changed */
91 #define DSK_ERR_ECHECK	 (-20)	/* Equipment check */
92 #define DSK_ERR_OVERRUN  (-21)	/* Overrun */
93 #define DSK_ERR_ACCESS   (-22)	/* Access denied */
94 #define DSK_ERR_CTRLR 	 (-23)	/* Failed controller */
95 #define DSK_ERR_COMPRESS (-24)	/* Compressed file is corrupt */
96 #define DSK_ERR_RPC	 (-25)  /* Error encoding / decoding RPC */
97 #define DSK_ERR_BADOPT	 (-26)  /* Requested optional feature not present */
98 #define DSK_ERR_BADVAL	 (-27)  /* Bad value for requested option */
99 #define DSK_ERR_ABORT    (-28)  /* User abort requested */
100 #define DSK_ERR_TIMEOUT  (-29)  /* Communications timed out */
101 #define DSK_ERR_UNKRPC   (-30)  /* RPC server does not recognise function */
102 #define DSK_ERR_BADMEDIA (-31)	/* Unsuitable media for drive */
103 #define DSK_ERR_UNKNOWN  (-99)	/* Unknown error */
104 
105 /* Is this error a transient error, that may be cleared by a retry? */
106 /* 1.1.3: Get this the right way round; they're negative numbers! */
107 #define DSK_TRANSIENT_ERROR(e) ((e) > DSK_ERR_COMPRESS && (e) <= DSK_ERR_NOTRDY)
108 
109 /* Disc sidedness (logical/physical mapping). Use SIDES_ALT for single-sided floppies. */
110 typedef enum
111 {
112 	SIDES_ALT, 	/* Track n is cylinder (n/heads) head (n%heads) */
113 	SIDES_OUTBACK, 	/* Tracks go (head 0) 0,1,2,3,...37,38,39, then
114 			             (head 1) 39,38,37,...,2,1,0 */
115 	SIDES_OUTOUT,	/* Tracks go (head 0) 0,1,2,3,...37,38,39, then
116 			             (head 1) 0,1,2,3,...37,38,39 */
117 	SIDES_EXTSURFACE/* As SIDES_ALT, but sectors on head 1 identify
118 			 * as head 0, with numbers in sequence
119 			 * eg: Head 0 has sectors 1-9, head 1 has 10-18 */
120 } dsk_sides_t;
121 
122 typedef enum
123 {
124 	RATE_HD,	/* Data rate for 1.4Mb 3.5"  in 3.5"  drive */
125 	RATE_DD,	/* Data rate for 360k  5.25" in 1.2Mb drive */
126 	RATE_SD,	/* Data rate for 720k  3.5"  in 3.5"  drive */
127 	RATE_ED		/* Data rate for 2.8Mb 3.5"  in 3.5"  drive */
128 } dsk_rate_t;
129 
130 typedef enum
131 {
132 	FMT_180K,	/* 9 sectors, 1 side */
133 	FMT_CPCSYS,	/* CPC system 180K */
134 	FMT_CPCDATA,	/* CPC data 180K */
135 	FMT_720K,	/* 9 sectors, 80 tracks, 2 sides */
136 	FMT_1440K,	/* 1.4M */
137 	FMT_160K,	/* 8 sectors, 1 side */
138 	FMT_320K,	/* 8 sectors, 2 sides */
139 	FMT_360K,	/* 9 sectors, 2 sides */
140 	FMT_720F,	/* 9 sectors, 2 sides out-and-back */
141 	FMT_1200F,	/* 15 sectors, 2 sides out-and-back */
142 	FMT_1440F,	/* 18 sectors, 2 sides out-and-back */
143 	FMT_ACORN160,	/* 16 sectors,  256 bytes/sector, 1 side */
144 	FMT_ACORN320,	/* 16 sectors,  256 bytes/sector, 1 side */
145 	FMT_ACORN640,	/* 16 sectors,  256 bytes/sector, 2 sides */
146 	FMT_ACORN800,	/*  5 sectors, 1024 bytes/sector, 2 sides */
147 	FMT_ACORN1600,	/* 10 sectors, 1024 bytes/sector, 2 sides */
148 	FMT_800K,	/* 10 sectors, 80 tracks, 2 sides */
149 	FMT_200K,	/* 10 sectors, 40 tracks, 1 side */
150 	FMT_BBC100,	/* 10 sectors, 40 tracks, 1 side, FM */
151 	FMT_BBC200,	/* 10 sectors, 80 tracks, 1 side, FM */
152 	FMT_MBEE400,	/* 10 sectors, 80 tracks, 1 side */
153 	FMT_MGT800,     /* 10 sectors, 80 tracks, 2 sides out and out */
154 	FMT_TRDOS640,	/* 16 sectors,  256 bytes/sector, 2 sides */
155 	FMT_AMPRO200,	/* 10 sectors, 512 bytes/sector, 1 side */
156 	FMT_AMPRO400D,	/* 10 sectors, 512 bytes/sector, 2 sides */
157 	FMT_AMPRO400S,	/* 5 sectors, 1024 bytes/sector, 1 side */
158 	FMT_AMPRO800,	/* 5 sectors, 1024 bytes/sector, 2 sides */
159 	FMT_UNKNOWN = -1
160 } dsk_format_t;
161 
162 typedef enum
163 {
164 	/* Low byte of dg_fm: Recording mode */
165 	RECMODE_MASK     = 0x00FF,
166 	RECMODE_MFM      = 0x0000,
167 	RECMODE_FM       = 0x0001,
168 	/* High byte of dg_fm: Other data recording flags */
169 	RECMODE_FLAGMASK = 0xFF00,
170 	RECMODE_COMPLEMENT = 0x0100
171 
172 } dsk_recmode_t;
173 
174 /* DSK_GEOMETRY holds information used to convert physical to/from logical
175  * sectors and to access the disc */
176 typedef struct
177 {
178 	dsk_sides_t	dg_sidedness;	/* How to handle multisided discs? */
179 	dsk_pcyl_t  	dg_cylinders;	/* Number of cylinders */
180 	dsk_phead_t	dg_heads;	/* Number of heads */
181 	dsk_psect_t	dg_sectors;	/* Sectors per track */
182 	dsk_psect_t	dg_secbase;	/* First physical sector number */
183 	size_t		dg_secsize;	/* Sector size in bytes */
184 	dsk_rate_t	dg_datarate;	/* Data rate */
185 	dsk_gap_t	dg_rwgap;	/* Read/write gap length */
186 	dsk_gap_t	dg_fmtgap;	/* Format gap length */
187 	int		dg_fm;		/* Really a dsk_recmode_t, kept as
188 					 * int for backward compatibility  */
189 	int		dg_nomulti;	/* Disable multitrack? */
190 	int		dg_noskip;	/* Set to 0 to skip deleted data */
191 } DSK_GEOMETRY;
192 
193 
194 /* Used when formatting a sector or reading its ID */
195 typedef struct
196 {
197 	dsk_pcyl_t	fmt_cylinder;
198 	dsk_phead_t	fmt_head;
199 	dsk_psect_t	fmt_sector;
200 	size_t		fmt_secsize;
201 } DSK_FORMAT;
202 
203 /* Callbacks from LibDsk to program */
204 
205 typedef void (*DSK_REPORTFUNC)(const char *message);
206 typedef void (*DSK_REPORTEND)(void);
207 
208 /***************************** GLOBAL FUNCTIONS ******************************/
209 
210 /* Convert physical C/H/S to logical sector */
211 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dg_ps2ls(const DSK_GEOMETRY *self,
212 	/* in */	dsk_pcyl_t cyl, dsk_phead_t head, dsk_psect_t sec,
213 	/* out */	dsk_lsect_t *logical);
214 
215 /* Convert logical sector to physical C/H/S */
216 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dg_ls2ps(const DSK_GEOMETRY *self,
217 	/* in */	dsk_lsect_t logical,
218 	/* out */	dsk_pcyl_t *cyl, dsk_phead_t *head, dsk_psect_t *sec);
219 
220 /* Convert physical cylinder/head to logical track */
221 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dg_pt2lt(const DSK_GEOMETRY *self,
222 	/* in */	dsk_pcyl_t cyl, dsk_phead_t head,
223 	/* out */	dsk_ltrack_t *logical);
224 
225 /* Convert logical track to physical cylinder/head */
226 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dg_lt2pt(const DSK_GEOMETRY *self,
227 	/* in */	dsk_ltrack_t logical,
228 	/* out */	dsk_pcyl_t *cyl, dsk_phead_t *head);
229 /* Expand error message */
230 LDPUBLIC32 char * LDPUBLIC16 dsk_strerror(/* in */ dsk_err_t err);
231 
232 /* Initialise a DSK_GEOMETRY with one of the standard formats.
233  * If name / desc are not null, these are populated with the format's
234  * short name and a brief description. */
235 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dg_stdformat(DSK_GEOMETRY *self, dsk_format_t formatid,
236 			dsk_cchar_t *name, dsk_cchar_t *desc);
237 
238 /* Convert sector size to a physical sector shift as used by the controller.
239  * To go the other way, size = 128 << psh  */
240 LDPUBLIC32 unsigned char LDPUBLIC16 dsk_get_psh(size_t sector_size);
241 
242 /* Register callbacks for LibDsk functions to display information on the
243  * screen. */
244 LDPUBLIC32 void LDPUBLIC16 dsk_reportfunc_set(DSK_REPORTFUNC report,
245 					      DSK_REPORTEND  repend);
246 /* Retrieve the values of the callbacks */
247 LDPUBLIC32 void LDPUBLIC16 dsk_reportfunc_get(DSK_REPORTFUNC *report,
248 					      DSK_REPORTEND  *repend);
249 
250 /* Calls to these functions (or no-op, as appropriate) */
251 /* Report a work-in-progress message - LibDsk does this when starting a long
252  * operation such as decompression */
253 LDPUBLIC32 void LDPUBLIC16 dsk_report(const char *s);
254 /* Remove a work-in-progress message, if appropriate */
255 LDPUBLIC32 void LDPUBLIC16 dsk_report_end(void);
256 
257 /*****************************************************************************/
258 
259 /* Open a DSK file, POSIX image, drive or whatever.
260  * "type" is:
261  *   NULL    : Autodetect file type from name or magic number
262  *   "dsk"   : CPCEMU DSK or EDSK format
263  *   "raw"   : Raw dd if=foo of=bar file
264  *   "floppy": Host system's floppy drive
265  *   "myz80" : MYZ80 image file
266  *   "cfi"   : RLE-encoded raw file. Not done as a transparent compression
267  *            driver, because it has no magic number.
268  * "compress" is:
269  *  NULL     : Autodetect compression system.
270  *  "sq"     : Huffman (Squeezed)
271  *  "gz"     : Gzip
272  * Will allocate a DSK_DRIVER object.
273  */
274 
275 typedef struct dsk_driver *DSK_PDRIVER;
276 
277 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_open(DSK_PDRIVER *self, const char *filename,
278 			const char *type,
279 			const char *compress);
280 
281 /* As for "open", but creates a new image file. On a floppy drive
282  * this will act exactly as "open"; for an image this will attempt to
283  * create the file new or truncate it.
284  * Note that "type" cannot be NULL. "compress" can be (to create an
285  * uncompresed file). */
286 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_creat(DSK_PDRIVER *self, const char *filename,
287 			const char *type,
288 			const char *compress);
289 
290 /* Close a DSK file. Frees the pointer and sets it to null. */
291 
292 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_close(DSK_PDRIVER *self);
293 
294 /* Returns whether the disk has been modified since it was opened */
295 
296 LDPUBLIC32 int              LDPUBLIC16 dsk_dirty(DSK_PDRIVER self);
297 
298 /* Get drive status (Ready, Read-Only etc.). The actual status is
299  * based on the FDC's ST3 register. The following bits should be available: */
300 
301 #define DSK_ST3_FAULT	0x80	/* Drive fault */
302 #define DSK_ST3_RO	0x40	/* Read only */
303 #define DSK_ST3_READY	0x20	/* Drive ready */
304 #define DSK_ST3_TRACK0	0x10	/* Head is over track 0 (not all drivers) */
305 #define DSK_ST3_DSDRIVE	0x08	/* Drive is double-sided */
306 #define DSK_ST3_HEAD1	0x04	/* Current head is head 1, not head 0 */
307 
308 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_drive_status(DSK_PDRIVER self, const DSK_GEOMETRY *geom,
309 				dsk_phead_t head, unsigned char *status);
310 
311 /* Read a sector. There are three alternative versions:
312  *  One that uses physical sectors
313  *  One that uses logical sectors
314  *  One that uses physical sectors *which can have numbers not matching
315  *  their positions on disc* - this functionality is only exposed by
316  *  drivers which can manipulate the FDC directly. */
317 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_pread(DSK_PDRIVER self, const DSK_GEOMETRY *geom,
318                               void *buf, dsk_pcyl_t cylinder,
319                               dsk_phead_t head, dsk_psect_t sector);
320 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_lread(DSK_PDRIVER self, const DSK_GEOMETRY *geom,
321                               void *buf, dsk_lsect_t sector);
322 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_xread(DSK_PDRIVER self, const DSK_GEOMETRY *geom,
323                               void *buf,
324 			      dsk_pcyl_t cylinder, dsk_phead_t head,
325 			      dsk_pcyl_t cyl_expected, dsk_phead_t head_expected,
326 			      dsk_psect_t sector, size_t sector_len,
327 			      int *deleted);
328 /* Write a sector. There are three alternative versions:
329  *  One that uses physical sectors
330  *  One that uses logical sectors
331  *  One that uses physical sectors *which can have numbers not matching
332  *  their positions on disc* - this functionality is only exposed by
333  *  drivers which can manipulate the FDC directly. */
334 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_pwrite(DSK_PDRIVER self, const DSK_GEOMETRY *geom,
335                               const void *buf, dsk_pcyl_t cylinder,
336                               dsk_phead_t head, dsk_psect_t sector);
337 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_lwrite(DSK_PDRIVER self, const DSK_GEOMETRY *geom,
338                               const void *buf, dsk_lsect_t sector);
339 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_xwrite(DSK_PDRIVER self, const DSK_GEOMETRY *geom,
340                               const void *buf,
341 			      dsk_pcyl_t cylinder, dsk_phead_t head,
342 			      dsk_pcyl_t cyl_expected, dsk_phead_t head_expected,
343 			      dsk_psect_t sector, size_t sector_len,
344 			      int deleted);
345 
346 /* Verify sector against memory buffer. There are three alternative versions:
347  *  One that uses physical sectors
348  *  One that uses logical sectors
349  *  One that uses physical sectors *which can have numbers not matching
350  *  their positions on disc* - this functionality is only exposed by
351  *  drivers which can manipulate the FDC directly. */
352 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_pcheck(DSK_PDRIVER self, const DSK_GEOMETRY *geom,
353                               const void *buf, dsk_pcyl_t cylinder,
354                               dsk_phead_t head, dsk_psect_t sector);
355 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_lcheck(DSK_PDRIVER self, const DSK_GEOMETRY *geom,
356                               const void *buf, dsk_lsect_t sector);
357 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_xcheck(DSK_PDRIVER self, const DSK_GEOMETRY *geom,
358                               const void *buf,
359 			      dsk_pcyl_t cylinder, dsk_phead_t head,
360 			      dsk_pcyl_t cyl_expected, dsk_phead_t head_expected,
361 			      dsk_psect_t sector, size_t sector_len);
362 /* Format a track.
363  * Note that the geometry in these functions is not const; the CPCEMU driver
364  * will increase the number of tracks/heads as the disc image file outgrows
365  * the geometry.
366  */
367 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_pformat(DSK_PDRIVER self, DSK_GEOMETRY *geom,
368 				dsk_pcyl_t cylinder, dsk_phead_t head,
369 				const DSK_FORMAT *format, unsigned char filler);
370 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_lformat(DSK_PDRIVER self, DSK_GEOMETRY *geom,
371 				dsk_ltrack_t track, const DSK_FORMAT *format,
372 				unsigned char filler);
373 /* Read a track.
374  */
375 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_xtread(DSK_PDRIVER self, const DSK_GEOMETRY *geom,
376 				void *buf,
377 			    dsk_pcyl_t cylinder,     dsk_phead_t head,
378 				dsk_pcyl_t cyl_expected, dsk_phead_t head_expected);
379 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_ptread(DSK_PDRIVER self, const DSK_GEOMETRY *geom,
380 				void *buf, dsk_pcyl_t cylinder,
381 				dsk_phead_t head);
382 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_ltread(DSK_PDRIVER self, const DSK_GEOMETRY *geom,
383 				void *buf, dsk_ltrack_t track);
384 /* Auto-format: generates the sector headers from "geom" */
385 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_apform(DSK_PDRIVER self, DSK_GEOMETRY *geom,
386 				dsk_pcyl_t cylinder, dsk_phead_t head,
387 				unsigned char filler);
388 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_alform(DSK_PDRIVER self, DSK_GEOMETRY *geom,
389 				dsk_ltrack_t track, unsigned char filler);
390 
391 /* Probe the geometry of a disc. This will use the boot sector and any
392  * information the driver can give. */
393 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_getgeom(DSK_PDRIVER self, DSK_GEOMETRY *geom);
394 /* Convert various types of boot sector to DSK_GEOMETRY
395  * Return DSK_ERR_OK if successful, else DSK_ERR_BADFMT */
396 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dg_dosgeom(DSK_GEOMETRY *self, const unsigned char *bootsect);
397 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dg_pcwgeom(DSK_GEOMETRY *self, const unsigned char *bootsect);
398 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dg_cpm86geom(DSK_GEOMETRY *self, const unsigned char *bootsect);
399 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dg_aprigeom(DSK_GEOMETRY *self, const unsigned char *bootsect);
400 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dg_opusgeom(DSK_GEOMETRY *self, const unsigned char *bootsect);
401 
402 /* Read a random sector header from current track */
403 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_psecid(DSK_PDRIVER self, const DSK_GEOMETRY *geom,
404 				dsk_pcyl_t cylinder, dsk_phead_t head,
405 				DSK_FORMAT *result);
406 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_lsecid(DSK_PDRIVER self, const DSK_GEOMETRY *geom,
407 				dsk_ltrack_t track, DSK_FORMAT *result);
408 
409 /* Read all sector headers from current track in the order they appear.
410  * Not implemented yet; this is for future expansion. */
411 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_ptrackids(DSK_PDRIVER self,
412 				const DSK_GEOMETRY *geom,
413 				dsk_pcyl_t cylinder, dsk_phead_t head,
414 				dsk_psect_t *count, DSK_FORMAT **results);
415 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_ltrackids(DSK_PDRIVER self,
416 				const DSK_GEOMETRY *geom,
417 				dsk_ltrack_t track,
418 				dsk_psect_t *count, DSK_FORMAT **result);
419 
420 /* Read a track as it appears on the disk, including sector headers.
421  * Not implemented yet; this is for future expansion. */
422 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_rtread(DSK_PDRIVER self,
423 		const DSK_GEOMETRY *geom, void *buf,
424 	        dsk_pcyl_t cylinder,     dsk_phead_t head, int reserved);
425 
426 /* Seek to a cylinder */
427 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_lseek(DSK_PDRIVER self, const DSK_GEOMETRY *geom,
428 				dsk_ltrack_t track);
429 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_pseek(DSK_PDRIVER self, const DSK_GEOMETRY *geom,
430 				dsk_pcyl_t cylinder, dsk_phead_t head);
431 
432 /* If "index" is in range, returns the n'th driver name in (*drvname).
433  * Else sets (*drvname) to null. */
434 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_type_enum(int idx, char **drvname);
435 
436 /* If "index" is in range, returns the human-readable description of the
437  * n'th driver name in (*drvdesc).  Else sets (*drvdesc) to null. */
438 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_typedesc_enum(int idx, char **drvdesc);
439 
440 /* If "index" is in range, returns the n'th compressor name in (*compname).
441  * Else sets (*drvname) to null. */
442 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_comp_enum(int idx, char **compname);
443 
444 /* Force a drive to use head 0 or head 1 only for single-sided discs
445  * Pass 0 or 1, or -1 to unset it.
446  * Deprecated: Use dsk_{set,get}_option(self, "HEAD", n) instead */
447 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_set_forcehead(DSK_PDRIVER self, int force);
448 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_get_forcehead(DSK_PDRIVER self, int *force);
449 
450 /* Set a named option to an integer value. Returns DSK_ERR_BADOPT if the
451  * driver doesn't support the option; DSK_ERR_BADVAL if the value is out
452  * of range */
453 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_set_option(DSK_PDRIVER self, const char *name, int value);
454 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_get_option(DSK_PDRIVER self, const char *name, int *value);
455 /* If "index" is in range, returns the n'th option name in (*optname).
456  * Else sets (*optname) to null. */
457 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_option_enum(DSK_PDRIVER self, int idx, char **optname);
458 
459 /* Get or set the comment for a disc image file. Not supported by all
460  * file formats. */
461 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_set_comment(DSK_PDRIVER self, const char *comment);
462 LDPUBLIC32 dsk_err_t  LDPUBLIC16 dsk_get_comment(DSK_PDRIVER self, char **comment);
463 
464 /* Set / get the retry count. */
465 LDPUBLIC32 dsk_err_t LDPUBLIC16 dsk_set_retry(DSK_PDRIVER self, unsigned int count);
466 LDPUBLIC32 dsk_err_t LDPUBLIC16 dsk_get_retry(DSK_PDRIVER self, unsigned int *count);
467 
468 /* Get the driver name and description */
469 LDPUBLIC32 const char * LDPUBLIC16 dsk_drvname(DSK_PDRIVER self);
470 LDPUBLIC32 const char * LDPUBLIC16 dsk_drvdesc(DSK_PDRIVER self);
471 
472 /* Get the compression system name and description */
473 LDPUBLIC32 const char * LDPUBLIC16 dsk_compname(DSK_PDRIVER self);
474 LDPUBLIC32 const char * LDPUBLIC16 dsk_compdesc(DSK_PDRIVER self);
475 
476 /* Decode and act on RPC packets sent by another LIBDSK.
477  * This function is used to implement the 16-bit server app. */
478 LDPUBLIC32 dsk_err_t LDPUBLIC16 dsk_rpc_server(unsigned char *input,
479 	int inp_len, unsigned char *output, int *out_len,
480 	int *ref_count);
481 
482 /* Map a DSK_PDRIVER to an integer handle. Used for RPC and JNI.
483  * The null pointer is always mapped to zero.
484  * dsk_map_dtoi will add the pointer to the map if it isn't found. */
485 LDPUBLIC32 dsk_err_t LDPUBLIC16 dsk_map_dtoi(DSK_PDRIVER ptr, unsigned int *n);
486 /* Given an integer handle, retrieve the corresponding DSK_PDRIVER.
487  * If the handle is not found, returns *ptr = NULL. */
488 LDPUBLIC32 dsk_err_t LDPUBLIC16 dsk_map_itod(unsigned int n, DSK_PDRIVER *ptr);
489 /* Remove an integer <--> DSK_DRIVER mapping. If it was the last one, free
490  *  * all the memory used by the mapping */
491 LDPUBLIC32 dsk_err_t LDPUBLIC16 dsk_map_delete(unsigned int index);
492 
493 
494 
495 /* Define this to print on the console a trace of all mallocs */
496 #undef TRACE_MALLOCS
497 #ifdef TRACE_MALLOCS
498 void *dsk_malloc(size_t size);
499 void  dsk_free(void *ptr);
500 #else
501 #define dsk_malloc malloc
502 #define dsk_free free
503 #endif
504 
505 #ifdef __cplusplus
506 }
507 #endif
508 
509 #endif /* LIBDSK_H */
510