1 #include "ibm.h"
2 
3 #include "config.h"
4 #include "disc.h"
5 #include "disc_fdi.h"
6 #include "disc_img.h"
7 #include "fdc.h"
8 #include "fdd.h"
9 #include "timer.h"
10 
11 int disc_drivesel = 0;
12 int disc_poll_time = 16;
13 
14 int disc_track[2];
15 int writeprot[2], fwriteprot[2];
16 
17 DRIVE drives[2];
18 int drive_type[2];
19 
20 int curdrive = 0;
21 
22 //char discfns[2][260] = {"", ""};
23 int defaultwriteprot = 0;
24 
25 int fdc_time;
26 int disc_time;
27 
28 int fdc_ready;
29 
30 int drive_empty[2] = {1, 1};
31 int disc_changed[2];
32 
33 int motorspin;
34 int motoron;
35 
36 int fdc_indexcount = 52;
37 
38 /*void (*fdc_callback)();
39 void (*fdc_data)(uint8_t dat);
40 void (*fdc_spindown)();
41 void (*fdc_finishread)();
42 void (*fdc_notfound)();
43 void (*fdc_datacrcerror)();
44 void (*fdc_headercrcerror)();
45 void (*fdc_writeprotect)();
46 int  (*fdc_getdata)(int last);
47 void (*fdc_sectorid)(uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uint8_t crc1, uint8_t crc2);
48 void (*fdc_indexpulse)();*/
49 
50 static struct
51 {
52         char *ext;
53         void (*load)(int drive, char *fn);
54         void (*close)(int drive);
55         int size;
56 }
57 loaders[]=
58 {
59         {"IMG", img_load,       img_close, -1},
60         {"IMA", img_load,       img_close, -1},
61         {"360", img_load,       img_close, -1},
62 	{"XDF", img_load,       img_close, -1},
63         {"FDI", fdi_load,       fdi_close, -1},
64         {0,0,0}
65 };
66 
67 static int driveloaders[4];
68 
disc_load(int drive,char * fn)69 void disc_load(int drive, char *fn)
70 {
71         int c = 0, size;
72         char *p;
73         FILE *f;
74 //        pclog("disc_load %i %s\n", drive, fn);
75 //        setejecttext(drive, "");
76         if (!fn) return;
77         p = get_extension(fn);
78         if (!p) return;
79 //        setejecttext(drive, fn);
80         pclog("Loading :%i %s %s\n", drive, fn,p);
81         f = fopen(fn, "rb");
82         if (!f) return;
83         fseek(f, -1, SEEK_END);
84         size = ftell(f) + 1;
85         fclose(f);
86         while (loaders[c].ext)
87         {
88                 if (!strcasecmp(p, loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1))
89                 {
90                         pclog("Loading as %s\n", p);
91                         driveloaders[drive] = c;
92                         loaders[c].load(drive, fn);
93                         drive_empty[drive] = 0;
94                         disc_changed[drive] = 1;
95                         strcpy(discfns[drive], fn);
96                         fdd_disc_changed(drive);
97                         return;
98                 }
99                 c++;
100         }
101         pclog("Couldn't load %s %s\n",fn,p);
102         drive_empty[drive] = 1;
103         discfns[drive][0] = 0;
104 }
105 
disc_close(int drive)106 void disc_close(int drive)
107 {
108 //        pclog("disc_close %i\n", drive);
109         if (loaders[driveloaders[drive]].close) loaders[driveloaders[drive]].close(drive);
110         drive_empty[drive] = 1;
111         discfns[drive][0] = 0;
112         drives[drive].hole = NULL;
113         drives[drive].poll = NULL;
114         drives[drive].seek = NULL;
115         drives[drive].readsector = NULL;
116         drives[drive].writesector = NULL;
117         drives[drive].readaddress = NULL;
118         drives[drive].format = NULL;
119 }
120 
121 int disc_notfound=0;
122 static int disc_period = 32;
123 
disc_hole(int drive)124 int disc_hole(int drive)
125 {
126 	drive ^= fdd_swap;
127 
128 	if (drive < 2 && drives[drive].hole)
129 	{
130 		return drives[drive].hole(drive);
131 	}
132 	else
133 	{
134 		return 0;
135 	}
136 }
137 
disc_poll()138 void disc_poll()
139 {
140         disc_poll_time += disc_period * TIMER_USEC;
141 
142         if (disc_drivesel < 2 && drives[disc_drivesel].poll)
143                 drives[disc_drivesel].poll();
144 
145         if (disc_notfound)
146         {
147                 disc_notfound--;
148                 if (!disc_notfound)
149                         fdc_notfound();
150         }
151 }
152 
disc_get_bitcell_period(int rate)153 int disc_get_bitcell_period(int rate)
154 {
155         int bit_rate = 0;
156 
157         switch (rate)
158         {
159                 case 0: /*High density*/
160                 bit_rate = 500;
161                 break;
162                 case 1: /*Double density (360 rpm)*/
163                 bit_rate = 300;
164                 break;
165                 case 2: /*Double density*/
166                 bit_rate = 250;
167                 break;
168                 case 3: /*Extended density*/
169                 bit_rate = 1000;
170                 break;
171         }
172 
173         return 1000000 / bit_rate*2; /*Bitcell period in ns*/
174 }
175 
176 
disc_set_rate(int drive,int drvden,int rate)177 void disc_set_rate(int drive, int drvden, int rate)
178 {
179         switch (rate)
180         {
181                 case 0: /*High density*/
182                 disc_period = 16;
183                 break;
184                 case 1:
185 		switch(drvden)
186 		{
187 			case 0: /*Double density (360 rpm)*/
188 		                disc_period = 26;
189 		                break;
190 			case 1: /*High density (360 rpm)*/
191 		                disc_period = 16;
192 		                break;
193 			case 2:
194 		                disc_period = 4;
195 		                break;
196 		}
197                 case 2: /*Double density*/
198                 disc_period = 32;
199                 break;
200                 case 3: /*Extended density*/
201                 disc_period = 8;
202                 break;
203         }
204 }
205 
disc_reset()206 void disc_reset()
207 {
208         int drive;
209 
210         curdrive = 0;
211         disc_period = 32;
212 	timer_add(disc_poll, &disc_poll_time, &motoron, NULL);
213 
214         for (drive = 0; drive < 2; drive++)
215         {
216                 if (loaders[driveloaders[drive]].close)
217                         loaders[driveloaders[drive]].close(drive);
218                 drive_empty[drive] = 1;
219                 drives[drive].hole = NULL;
220                 drives[drive].poll = NULL;
221                 drives[drive].seek = NULL;
222                 drives[drive].readsector = NULL;
223                 drives[drive].writesector = NULL;
224                 drives[drive].readaddress = NULL;
225                 drives[drive].format = NULL;
226         }
227 }
228 
disc_init()229 void disc_init()
230 {
231         disc_reset();
232 }
233 
234 int oldtrack[2] = {0, 0};
disc_seek(int drive,int track)235 void disc_seek(int drive, int track)
236 {
237 //        pclog("disc_seek: drive=%i track=%i\n", drive, track);
238         if (drive < 2 && drives[drive].seek)
239                 drives[drive].seek(drive, track);
240 //        if (track != oldtrack[drive])
241 //                fdc_discchange_clear(drive);
242 //        ddnoise_seek(track - oldtrack[drive]);
243 //        oldtrack[drive] = track;
244 }
245 
disc_readsector(int drive,int sector,int track,int side,int density,int sector_size)246 void disc_readsector(int drive, int sector, int track, int side, int density, int sector_size)
247 {
248         drive ^= fdd_swap;
249 
250         if (drive < 2 && drives[drive].readsector)
251                 drives[drive].readsector(drive, sector, track, side, density, sector_size);
252         else
253                 disc_notfound = 1000;
254 }
255 
disc_writesector(int drive,int sector,int track,int side,int density,int sector_size)256 void disc_writesector(int drive, int sector, int track, int side, int density, int sector_size)
257 {
258         drive ^= fdd_swap;
259 
260         if (drive < 2 && drives[drive].writesector)
261                 drives[drive].writesector(drive, sector, track, side, density, sector_size);
262         else
263                 disc_notfound = 1000;
264 }
265 
disc_readaddress(int drive,int track,int side,int density)266 void disc_readaddress(int drive, int track, int side, int density)
267 {
268         drive ^= fdd_swap;
269 
270         if (drive < 2 && drives[drive].readaddress)
271                 drives[drive].readaddress(drive, track, side, density);
272 }
273 
disc_format(int drive,int track,int side,int density,uint8_t fill)274 void disc_format(int drive, int track, int side, int density, uint8_t fill)
275 {
276         drive ^= fdd_swap;
277 
278         if (drive < 2 && drives[drive].format)
279                 drives[drive].format(drive, track, side, density, fill);
280         else
281                 disc_notfound = 1000;
282 }
283 
disc_stop(int drive)284 void disc_stop(int drive)
285 {
286         drive ^= fdd_swap;
287 
288         if (drive < 2 && drives[drive].stop)
289                 drives[drive].stop(drive);
290 }
291 
disc_set_drivesel(int drive)292 void disc_set_drivesel(int drive)
293 {
294         drive ^= fdd_swap;
295 
296         disc_drivesel = drive;
297 }
298