2 // Apple 2 floppy disk support
8 // MAX_PATH isn't defined in stdlib.h on *nix, so we do it here...
11 #define MAX_PATH _POSIX_PATH_MAX
13 #include <stdlib.h> // for MAX_PATH on MinGW/Darwin
16 #define MAX_PATH _MAX_PATH
23 enum { DT_EMPTY = 0, DT_WOZ, DT_DOS33, DT_DOS33_HDR, DT_PRODOS, DT_NYBBLE,
25 enum { DLS_OFF, DLS_READ, DLS_WRITE };
27 // N.B.: All 32/16-bit values are stored in little endian. Which means, to
28 // read/write them safely, we need to use translators as this code may or
29 // may not be compiled on an architecture that supports little endian
39 uint8_t spliceBitCount;
45 uint8_t metaTag[4]; // "META"
46 uint32_t metaSize; // Size of the META chunk
47 uint8_t data[]; // Variable length array of metadata
53 uint8_t magic[8]; // "WOZ1" $FF $0A $0D $0A
54 uint32_t crc32; // CRC32 of the remaining data in the file
57 uint8_t infoTag[4]; // "INFO"
58 uint32_t infoSize; // Always 60 bytes long
59 uint8_t infoVersion; // Currently 1
60 uint8_t diskType; // 1 = 5 1/4", 2 = 3 1/2"
61 uint8_t writeProtected; // 1 = write protected disk
62 uint8_t synchronized; // 1 = cross-track sync was used during imaging
63 uint8_t cleaned; // 1 = fake bits removed from image
64 uint8_t creator[32]; // Software that made this image, padded with 0x20
65 uint8_t pad1[23]; // Padding to 60 bytes
68 uint8_t tmapTag[4]; // "TMAP"
69 uint32_t tmapSize; // Always 160 bytes long
70 uint8_t tmap[160]; // Track map, with empty tracks set to $FF
73 uint8_t trksTag[4]; // "TRKS"
74 uint32_t trksSize; // Varies, depending on # of tracks imaged
75 WOZTrack track[]; // Variable length array for the track data proper
80 uint16_t startingBlock; // 512 byte block # where this track starts (relative to the start of the file)
81 uint16_t blockCount; // # of blocks in this track
82 uint32_t bitCount; // # of bits in this track
88 uint8_t magic[8]; // "WOZ2" $FF $0A $0D $0A
89 uint32_t crc32; // CRC32 of the remaining data in the file
92 uint8_t infoTag[4]; // "INFO"
93 uint32_t infoSize; // Always 60 bytes long
94 uint8_t infoVersion; // Currently 1
95 uint8_t diskType; // 1 = 5 1/4", 2 = 3 1/2"
96 uint8_t writeProtected; // 1 = write protected disk
97 uint8_t synchronized; // 1 = cross-track sync was used during imaging
98 uint8_t cleaned; // 1 = fake bits removed from image
99 uint8_t creator[32]; // Software that made this image, padded with 0x20
100 uint8_t diskSides; // 5 1/4" disks always have 1 side (v2 from here on)
101 uint8_t bootSectorFmt; // 5 1/4" only (0=unknown, 1=16 sector, 2=13 sector, 3=both)
102 uint8_t optimalBitTmg; // In ticks, standard for 5 1/4" is 32 (4 µs)
103 uint16_t compatibleHW; // Bitfield showing hardware compatibility (1=][, 2=][+, 4=//e (unenh), 8=//c, 16=//e (enh), 32=IIgs, 64=//c+, 128=///, 256=///+)
104 uint16_t requiredRAM; // Minimum size in K, 0=unknown
105 uint16_t largestTrack; // Number of 512 byte blocks used by largest track
106 uint8_t pad1[14]; // Padding to 60 bytes
109 uint8_t tmapTag[4]; // "TMAP"
110 uint32_t tmapSize; // Always 160 bytes long
111 uint8_t tmap[160]; // Track map, with empty tracks set to $FF
114 uint8_t trksTag[4]; // "TRKS"
115 uint32_t trksSize; // Varies, depending on # of tracks imaged
116 WOZTrack2 track[160]; // Actual track info (corresponding to TMAP data)
117 uint8_t data[]; // Variable length array for the track data proper
126 bool LoadImage(const char * filename, uint8_t driveNum = 0);
127 bool SaveImage(uint8_t driveNum = 0);
128 bool SaveImageAs(const char * filename, uint8_t driveNum = 0);
129 void CreateBlankImage(uint8_t driveNum = 0);
130 void SwapImages(void);
131 const char * ImageName(uint8_t driveNum = 0);
132 void EjectImage(uint8_t driveNum = 0);
133 bool IsEmpty(uint8_t driveNum = 0);
134 bool IsWriteProtected(uint8_t driveNum = 0);
135 void SetWriteProtect(bool, uint8_t driveNum = 0);
136 int DriveLightStatus(uint8_t driveNum = 0);
137 void SaveState(FILE *);
138 void LoadState(FILE *);
139 void InitWOZ(uint8_t driveNum = 0);
140 bool CheckWOZ(const uint8_t * wozData, uint32_t wozSize, uint8_t driveNum = 0);
141 bool SaveWOZ(uint8_t driveNum);
144 uint32_t ReadLong(FILE *);
145 void WriteLong(FILE *, uint32_t);
146 void WriteLongLE(FILE *, uint32_t);
147 void WriteWordLE(FILE *, uint16_t);
148 void WriteZeroes(FILE *, uint32_t);
150 // I/O functions ($C0Ex accesses)
153 void ControlStepper(uint8_t addr);
154 void ControlMotor(uint8_t addr);
155 void DriveEnable(uint8_t addr);
156 void SetShiftLoadSwitch(uint8_t state);
157 void SetReadWriteSwitch(uint8_t state);
158 uint8_t DataRegister(void);
159 void DataRegister(uint8_t);
160 void RunSequencer(uint32_t);
163 void DetectImageType(const char * filename, uint8_t driveNum);
164 void WriteBits(uint8_t * dest, uint8_t * src, uint16_t bits, uint16_t * start);
165 void WOZifyImage(uint8_t driveNum);
168 char imageName[2][MAX_PATH];
170 uint32_t diskSize[2];
176 uint8_t dataRegister;
181 uint32_t currentPos[2];
185 uint8_t slSwitch; // Shift/Load soft switch
186 uint8_t rwSwitch; // Read/Write soft switch
187 uint8_t readPulse; // Disk read head "pulse" signal
188 uint8_t pulseClock; // Disk read head bitstream "pulse clock"
189 uint8_t sequencerState;
190 uint32_t driveOffTimeout;
191 uint8_t zeroBitCount;
192 uint16_t trackLength[2];
194 // And here are some private class variables (to reduce function
196 static uint8_t doSector[16];
197 static uint8_t poSector[16];
198 static uint8_t wozHeader[9];
199 static uint8_t wozHeader2[9];
200 static uint8_t standardTMAP[141];
201 static uint8_t sequencerROM[256];
202 static uint8_t bitMask[8];
203 static char nameBuf[MAX_PATH];
206 void InstallFloppy(uint8_t slot);
207 extern FloppyDrive floppyDrive[];
209 #endif // __FLOPPY_H__