1 /*****************************************************************************
2 ** $Source: /cygdrive/d/Private/_SVNROOT/bluemsx/blueMSX/Src/IoDevice/Disk.c,v $
3 **
4 ** $Revision: 1.25 $
5 **
6 ** $Date: 2009-07-18 15:08:04 $
7 **
8 ** More info: http://www.bluemsx.com
9 **
10 ** Copyright (C) 2003-2006 Daniel Vik, Tomas Karlsson
11 **
12 ** This program is free software; you can redistribute it and/or modify
13 ** it under the terms of the GNU General Public License as published by
14 ** the Free Software Foundation; either version 2 of the License, or
15 ** (at your option) any later version.
16 **
17 ** This program is distributed in the hope that it will be useful,
18 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 ** GNU General Public License for more details.
21 **
22 ** You should have received a copy of the GNU General Public License
23 ** along with this program; if not, write to the Free Software
24 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 **
26 ******************************************************************************
27 */
28 #include "Disk.h"
29 #include "DirAsDisk.h"
30 #include "ziphelper.h"
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <sys/stat.h>
35 
36 // PacketFileSystem.h Need to be included after all other includes
37 #include "PacketFileSystem.h"
38 
39 #define MAXSECTOR (2 * 9 * 81)
40 
41 #define DISK_ERRORS_HEADER      "DiskImage errors\r\n\032"
42 #define DISK_ERRORS_HEADER_SIZE 0x14
43 #define DISK_ERRORS_SIZE        ((MAXSECTOR+7)/8)
44 
45 static int   drivesEnabled[MAXDRIVES] = { 1, 1 };
46 static int   drivesIsCdrom[MAXDRIVES];
47 static FILE* drives[MAXDRIVES];
48 static int   RdOnly[MAXDRIVES];
49 static char* ramImageBuffer[MAXDRIVES];
50 static int   ramImageSize[MAXDRIVES];
51 static int   sectorsPerTrack[MAXDRIVES];
52 static int   sectorSize[MAXDRIVES];
53 static int   fileSize[MAXDRIVES];
54 static int   sides[MAXDRIVES];
55 static int   tracks[MAXDRIVES];
56 static int   changed[MAXDRIVES];
57 static int   diskType[MAXDRIVES];
58 static int   maxSector[MAXDRIVES];
59 static char* drivesErrors[MAXDRIVES];
60 static const UInt8 svi328Cpm80track[] = "CP/M-80";
61 static void diskHdUpdateInfo(int driveId);
62 static void diskReadHdIdentifySector(int driveId, UInt8* buffer);
63 
64 enum { MSX_DISK, SVI328_DISK, IDEHD_DISK } diskTypes;
65 
diskEnabled(int driveId)66 UInt8 diskEnabled(int driveId)
67 {
68     return driveId >= 0 && driveId < MAXDRIVES && drivesEnabled[driveId];
69 }
70 
diskIsCdrom(int driveId)71 int diskIsCdrom(int driveId)
72 {
73     return driveId >= 0 && driveId < MAXDRIVES && drivesIsCdrom[driveId];
74 }
75 
76 
diskReadOnly(int driveId)77 UInt8 diskReadOnly(int driveId)
78 {
79     if (!diskPresent(driveId)) {
80         return 0;
81     }
82     return RdOnly[driveId];
83 }
84 
diskEnable(int driveId,int enable)85 void  diskEnable(int driveId, int enable)
86 {
87     if (driveId >= 0 && driveId < MAXDRIVES)
88         drivesEnabled[driveId] = enable;
89 }
90 
diskPresent(int driveId)91 UInt8 diskPresent(int driveId)
92 {
93     return driveId >= 0 && driveId < MAXDRIVES &&
94         (drives[driveId] != NULL || ramImageBuffer[driveId] != NULL);
95 }
96 
diskGetSectorsPerTrack(int driveId)97 int diskGetSectorsPerTrack(int driveId)
98 {
99     if (driveId < MAXDRIVES)
100         return sectorsPerTrack[driveId];
101 
102     return 0;
103 }
104 
diskGetSides(int driveId)105 int diskGetSides(int driveId)
106 {
107     if (driveId < MAXDRIVES)
108         return sides[driveId];
109 
110     return 0;
111 }
112 
diskGetSectorSize(int driveId,int side,int track,int density)113 int diskGetSectorSize(int driveId, int side, int track, int density)
114 {
115     int secSize;
116 
117     if (driveId >= MAXDRIVES)
118         return 0;
119 
120     if (diskType[driveId] == SVI328_DISK) {
121         secSize = (track==0 && side==0 && density==1) ? 128 : 256;
122     }
123     else {
124         secSize = sectorSize[driveId];
125     }
126 
127     return secSize;
128 }
129 
diskGetSectorOffset(int driveId,int sector,int side,int track,int density)130 static int diskGetSectorOffset(int driveId, int sector, int side, int track, int density)
131 {
132     int offset;
133     int secSize;
134 
135     if (driveId >= MAXDRIVES)
136         return 0;
137 
138     secSize = diskGetSectorSize(driveId, side, track, density);
139 
140     if (diskType[driveId] == SVI328_DISK) {
141         if (track==0 && side==0 && density==1)
142             offset = (sector-1)*128;
143         else
144             offset = ((track*sides[driveId]+side)*17+sector-1)*256-2048;
145     }
146     else {
147         offset =  sector - 1 + diskGetSectorsPerTrack(driveId) * (track * diskGetSides(driveId) + side);
148         offset *= secSize;
149     }
150     return offset;
151 }
152 
diskChanged(int driveId)153 int diskChanged(int driveId)
154 {
155     if (driveId < MAXDRIVES) {
156         int isChanged = changed[driveId];
157         changed[driveId] = 0;
158 
159         return isChanged;
160     }
161 
162     return 0;
163 }
164 
diskReadError(int driveId,int sector)165 static DSKE diskReadError(int driveId, int sector)
166 {
167     if( drivesErrors[driveId] == NULL ) {
168         return DSKE_OK;
169     }else{
170         return (drivesErrors[driveId][sector >> 3] & (0x80 >> (sector & 7)))?
171                DSKE_CRC_ERROR : DSKE_OK;
172     }
173 }
174 
diskRead(int driveId,UInt8 * buffer,int sector)175 DSKE diskRead(int driveId, UInt8* buffer, int sector)
176 {
177     if (!diskPresent(driveId))
178         return DSKE_NO_DATA;
179 
180     if (ramImageBuffer[driveId] != NULL) {
181         int offset = sector * sectorSize[driveId];
182 
183         if (ramImageSize[driveId] < offset + sectorSize[driveId]) {
184             return DSKE_NO_DATA;
185         }
186 
187         memcpy(buffer, ramImageBuffer[driveId] + offset, sectorSize[driveId]);
188         return DSKE_OK;
189     }
190     else {
191         if ((drives[driveId] != NULL)) {
192             if (0 == fseek(drives[driveId], sector * sectorSize[driveId], SEEK_SET)) {
193                 UInt8 success = fread(buffer, 1, sectorSize[driveId], drives[driveId]) == sectorSize[driveId];
194                 return success? diskReadError(driveId, sector) : DSKE_NO_DATA;
195             }
196         }
197     }
198     return DSKE_NO_DATA;
199 }
200 
diskReadSector(int driveId,UInt8 * buffer,int sector,int side,int track,int density,int * sectorSize)201 DSKE diskReadSector(int driveId, UInt8* buffer, int sector, int side, int track, int density, int *sectorSize)
202 {
203     int secSize;
204     int offset;
205 
206     if (!diskPresent(driveId))
207         return DSKE_NO_DATA;
208 
209     if (diskType[driveId] == IDEHD_DISK && sector == -1) {
210         diskReadHdIdentifySector(driveId, buffer);
211         return DSKE_OK;
212     }
213 
214     offset = diskGetSectorOffset(driveId, sector, side, track, density);
215     secSize = diskGetSectorSize(driveId, side, track, density);
216 
217     if (sectorSize != NULL) {
218         *sectorSize = secSize;
219     }
220 
221     if (ramImageBuffer[driveId] != NULL) {
222         int sectornum;
223         if (ramImageSize[driveId] < offset + secSize) {
224             return DSKE_NO_DATA;
225         }
226 
227         memcpy(buffer, ramImageBuffer[driveId] + offset, secSize);
228         sectornum = sector - 1 + diskGetSectorsPerTrack(driveId) * (track * diskGetSides(driveId) + side);
229         return diskReadError(driveId, sectornum);
230     }
231     else {
232         if ((drives[driveId] != NULL)) {
233             if (0 == fseek(drives[driveId], offset, SEEK_SET)) {
234                 UInt8 success = fread(buffer, 1, secSize, drives[driveId]) == secSize;
235                 int sectornum = sector - 1 + diskGetSectorsPerTrack(driveId) * (track * diskGetSides(driveId) + side);
236                 return success? diskReadError(driveId, sectornum) : DSKE_NO_DATA;
237             }
238         }
239     }
240 
241     return DSKE_NO_DATA;
242 }
243 
isSectorSize256(const UInt8 * buf)244 static int isSectorSize256(const UInt8* buf)
245 {
246     // This implementation is quite rough, but it assmues that a disk with
247     // 256 sectors have content in sector 1, while a 512 sector disk has
248     // no data in the second half of the boot sector.
249     UInt8 rv = 0;
250     int cnt = 0xc0;
251     buf += 0x120;
252 
253     while (cnt--) {
254         rv |= *buf++;
255     }
256     return rv != 0;
257 }
258 
diskUpdateInfo(int driveId)259 static void diskUpdateInfo(int driveId)
260 {
261 	UInt8 buf[512];
262     int secSize;
263     DSKE rv;
264 
265     sectorsPerTrack[driveId] = 9;
266     sides[driveId]           = 2;
267     tracks[driveId]          = 80;
268     changed[driveId]         = 1;
269     sectorSize[driveId]      = 512;
270     diskType[driveId]        = MSX_DISK;
271     maxSector[driveId]       = MAXSECTOR;
272 
273     if (fileSize[driveId] > 2 * 1024 * 1024) {
274         // HD image
275         diskHdUpdateInfo(driveId);
276         return;
277     }
278 
279     if (fileSize[driveId] / 512 == 1440) {
280         return;
281     }
282 
283     rv = diskReadSector(driveId, buf, 1, 0, 0, 512, &secSize);
284     if (rv != DSKE_OK) {
285         return;
286     }
287 
288     switch (fileSize[driveId]) {
289         case 163840:
290             if (isSectorSize256(buf)) {
291                 sectorSize[driveId]      = 256;
292                 sectorsPerTrack[driveId] = 16;
293                 tracks[driveId]          = 40;
294                 sides[driveId]           = 1;
295             }
296             break;
297         case 172032:  /* SVI-328 40 SS */
298             sides[driveId] = 1;
299             tracks[driveId] = 40;
300             sectorsPerTrack[driveId] = 17;
301             diskType[driveId] = SVI328_DISK;
302             return;
303         case 184320:  /* BW 12 SSDD */
304             if (isSectorSize256(buf)) {
305                 sectorSize[driveId] = 256;
306                 sectorsPerTrack[driveId] = 18;
307                 tracks[driveId] = 40;
308                 sides[driveId] = 1;
309             }
310             return;
311         case 204800:  /* Kaypro II SSDD */
312             sectorSize[driveId] = 512;
313             sectorsPerTrack[driveId] = 10;
314             tracks[driveId] = 40;
315             sides[driveId] = 1;
316             return;
317         case 346112:  /* SVI-328 40 DS/80 SS */
318             sides[driveId] = 1;
319             tracks[driveId] = 80;
320             sectorsPerTrack[driveId] = 17;
321             diskType[driveId] = SVI328_DISK;
322             rv = diskReadSector(driveId, buf, 15, 0, 40, 0, &secSize);
323             if (rv != DSKE_OK) {
324                 return;
325             }
326             // Is it formatted for 80 track Disk BASIC?
327             if (buf[0] == 0xfe && buf[1] == 0xfe && buf[2] == 0xfe && buf[20] != 0xfe && buf[40] == 0xfe) {
328             	return;
329             }
330             rv = diskReadSector(driveId, buf, 1, 0, 1, 0, &secSize);
331             if (rv != DSKE_OK) {
332                 return;
333             }
334             // Is it sysgend for 80 track CP/M?
335             if (memcmp(&buf[176], &svi328Cpm80track[0], strlen(svi328Cpm80track)) == 0) {
336                 rv = diskReadSector(driveId, buf, 2, 0, 0, 1, &secSize);
337                 if (rv != DSKE_OK) {
338                     return;
339                 }
340                 if (buf[115] == 0x50 || buf[116] == 0x50) {
341                     return;
342                 }
343             }
344             sides[driveId] = 2;
345             tracks[driveId] = 40;
346             return;
347         case 348160:  /* SVI-728 DSDD (CP/M) */
348             if (isSectorSize256(buf)) {
349                 sectorSize[driveId] = 256;
350                 sectorsPerTrack[driveId] = 17;
351                 tracks[driveId] = 40;
352                 sides[driveId] = 2;
353             }
354             return;
355 	}
356 
357     if (buf[0] ==0xeb) {
358         switch (buf[0x15]) {
359         case 0xf8:
360 	        sides[driveId]           = 1;
361             tracks[driveId]          = 80;
362 	        sectorsPerTrack[driveId] = 9;
363             return;
364         case 0xf9:
365 	        sides[driveId]           = 2;
366             tracks[driveId]          = 80;
367 	        sectorsPerTrack[driveId] = 9;
368             // This check is needed to get the SVI-738 MSX-DOS disks to work
369             // Maybe it should be applied to other cases as well
370             rv = diskReadSector(driveId, buf, 2, 0, 0, 512, &secSize);
371             if (rv == DSKE_OK && buf[0] == 0xf8) {
372 	            sides[driveId] = 1;
373             }
374             return;
375         case 0xfa:
376 	        sides[driveId]           = 1;
377             tracks[driveId]          = 80;
378 	        sectorsPerTrack[driveId] = 8;
379             if (fileSize[driveId] == 368640) {
380 	            sectorsPerTrack[driveId] = 9;
381             }
382             return;
383         case 0xfb:
384 	        sides[driveId]           = 2;
385             tracks[driveId]          = 80;
386 	        sectorsPerTrack[driveId] = 8;
387             return;
388         case 0xfc:
389 	        sides[driveId]           = 1;
390             tracks[driveId]          = 40;
391 	        sectorsPerTrack[driveId] = 9;
392             return;
393         case 0xfd:
394 	        sides[driveId]           = 2;
395             tracks[driveId]          = 40;
396 	        sectorsPerTrack[driveId] = 9;
397             return;
398         case 0xfe:
399 	        sides[driveId]           = 1;
400             tracks[driveId]          = 40;
401 	        sectorsPerTrack[driveId] = 8;
402             return;
403         case 0xff:
404 	        sides[driveId]           = 2;
405             tracks[driveId]          = 40;
406 	        sectorsPerTrack[driveId] = 8;
407             return;
408         }
409     }
410 
411     if ((buf[0] == 0xe9) || (buf[0] ==0xeb)) {
412 	    sectorsPerTrack[driveId] = buf[0x18] + 256 * buf[0x19];
413 	    sides[driveId]           = buf[0x1a] + 256 * buf[0x1b];
414     }
415     else {
416         rv = diskReadSector(driveId, buf, 2, 0, 0, 512, &secSize);
417         if (rv != DSKE_OK) {
418             return;
419         }
420 		if (buf[0] >= 0xF8) {
421 			sectorsPerTrack[driveId] = (buf[0] & 2) ? 8 : 9;
422 			sides[driveId]           = (buf[0] & 1) ? 2 : 1;
423 		}
424     }
425 
426     if (sectorsPerTrack[driveId] == 0  || sides[driveId] == 0 ||
427         sectorsPerTrack[driveId] > 255 || sides[driveId] > 2)
428     {
429     	switch (fileSize[driveId]) {
430         case 163840:
431             sectorSize[driveId]      = 256;
432 	        sectorsPerTrack[driveId] = 16;
433             tracks[driveId]          = 40;
434 	        sides[driveId]           = 1;
435             break;
436         case 327680:  /* 80 tracks, 1 side, 8 sectors/track */
437 	        sectorsPerTrack[driveId] = 8;
438 	        sides[driveId] = 1;
439             break;
440         case 368640:  /* 80 tracks, 1 side, 9 sectors/track */
441 	        sectorsPerTrack[driveId] = 9;
442 	        sides[driveId] = 1;
443             break;
444         case 655360:  /* 80 tracks, 2 side, 8 sectors/track */
445 	        sectorsPerTrack[driveId] = 8;
446 	        sides[driveId] = 2;
447             break;
448         default:
449             sectorsPerTrack[driveId] = 9;
450             sides[driveId]           = 2;
451         }
452     }
453 }
454 
diskWrite(int driveId,UInt8 * buffer,int sector)455 UInt8 diskWrite(int driveId, UInt8 *buffer, int sector)
456 {
457     if (!diskPresent(driveId)) {
458         return 0;
459     }
460 
461     if (sector >= maxSector[driveId]) {
462         return 0;
463     }
464 
465     if (ramImageBuffer[driveId] != NULL) {
466         int offset = sector * sectorSize[driveId];
467 
468         if (ramImageSize[driveId] < offset + sectorSize[driveId]) {
469             return 0;
470         }
471 
472         memcpy(ramImageBuffer[driveId] + offset, buffer, sectorSize[driveId]);
473         return 1;
474     }
475     else {
476         if (drives[driveId] != NULL && !RdOnly[driveId]) {
477             if (0 == fseek(drives[driveId], sector * sectorSize[driveId], SEEK_SET)) {
478                 UInt8 success = fwrite(buffer, 1, sectorSize[driveId], drives[driveId]) == sectorSize[driveId];
479                 if (success && sector == 0) {
480                     diskUpdateInfo(driveId);
481                 }
482                 return success;
483             }
484         }
485     }
486     return 0;
487 }
488 
diskWriteSector(int driveId,UInt8 * buffer,int sector,int side,int track,int density)489 UInt8 diskWriteSector(int driveId, UInt8 *buffer, int sector, int side, int track, int density)
490 {
491     int secSize;
492     int offset;
493 
494     if (!diskPresent(driveId))
495         return 0;
496 
497     if (sector >= maxSector[driveId])
498         return 0;
499 
500     if (density == 0) {
501         density = sectorSize[driveId];
502     }
503 
504     offset = diskGetSectorOffset(driveId, sector, side, track, density);
505     secSize = diskGetSectorSize(driveId, side, track, density);
506 
507     if (ramImageBuffer[driveId] != NULL) {
508         if (ramImageSize[driveId] < offset + secSize) {
509             return 0;
510         }
511 
512         memcpy(ramImageBuffer[driveId] + offset, buffer, secSize);
513         return 1;
514     }
515     else {
516         if (drives[driveId] != NULL && !RdOnly[driveId]) {
517             if (0 == fseek(drives[driveId], offset, SEEK_SET)) {
518                 UInt8 success = fwrite(buffer, 1, secSize, drives[driveId]) == secSize;
519                 return success;
520             }
521         }
522     }
523     return 0;
524 }
525 
diskSetInfo(int driveId,char * fileName,const char * fileInZipFile)526 void diskSetInfo(int driveId, char* fileName, const char* fileInZipFile)
527 {
528     drivesIsCdrom[driveId] = fileName && strcmp(fileName, DISK_CDROM) == 0;
529 }
530 
makeErrorsFileName(const char * fileName)531 static char *makeErrorsFileName(const char *fileName)
532 {
533     char *p, *fname = (char*)malloc(strlen(fileName)+4);
534     strcpy(fname, fileName);
535     p = &fname[strlen(fname)-1];
536     while(*p != '.' && p != fname) p--;
537     if (p != fname) {
538         strcpy(p, ".der");
539         return fname;
540     }else{
541         free(p);
542         return NULL;
543     }
544 }
545 
diskChange(int driveId,const char * fileName,const char * fileInZipFile)546 UInt8 diskChange(int driveId, const char* fileName, const char* fileInZipFile)
547 {
548     struct stat s;
549     int rv;
550     char *fname;
551 
552     if (driveId >= MAXDRIVES)
553         return 0;
554 
555     drivesIsCdrom[driveId] = 0;
556 
557     /* Close previous disk image */
558     if(drives[driveId] != NULL) {
559         fclose(drives[driveId]);
560         drives[driveId] = NULL;
561     }
562 
563     if (ramImageBuffer[driveId] != NULL) {
564         // Flush to file??
565         free(ramImageBuffer[driveId]);
566         ramImageBuffer[driveId] = NULL;
567     }
568 
569     if (drivesErrors[driveId] != NULL) {
570         free(drivesErrors[driveId]);
571         drivesErrors[driveId] = NULL;
572     }
573 
574     if(!fileName) {
575         return 1;
576     }
577 
578     if (strcmp(fileName, DISK_CDROM) == 0) {
579         drivesIsCdrom[driveId] = 1;
580         return 1;
581     }
582 
583     rv = stat(fileName, &s);
584     if (rv == 0) {
585         if (s.st_mode & S_IFDIR) {
586             ramImageBuffer[driveId] = dirLoadFile(DDT_MSX, fileName, &ramImageSize[driveId]);
587             fileSize[driveId] = ramImageSize[driveId];
588             diskUpdateInfo(driveId);
589             return ramImageBuffer[driveId] != NULL;
590         }
591     }
592 
593     if (fileInZipFile != NULL) {
594         ramImageBuffer[driveId] = zipLoadFile(fileName, fileInZipFile, &ramImageSize[driveId]);
595         fileSize[driveId] = ramImageSize[driveId];
596 
597         fname = makeErrorsFileName(fileInZipFile);
598         if( fname != NULL ) {
599             int size=0;
600             drivesErrors[driveId] = zipLoadFile(fileName, fname, &size);
601             if( drivesErrors[driveId] != NULL && size > DISK_ERRORS_HEADER_SIZE &&
602                 strcmp(drivesErrors[driveId], DISK_ERRORS_HEADER)==0 ) {
603                 memcpy(drivesErrors[driveId],
604                        drivesErrors[driveId] + DISK_ERRORS_HEADER_SIZE,
605                        size - DISK_ERRORS_HEADER_SIZE);
606             }
607             free(fname);
608         }
609 
610         diskUpdateInfo(driveId);
611         return ramImageBuffer[driveId] != NULL;
612     }
613 
614     drives[driveId] = fopen(fileName, "r+b");
615     RdOnly[driveId] = 0;
616 
617     if (drives[driveId] == NULL) {
618         drives[driveId] = fopen(fileName, "rb");
619         RdOnly[driveId] = 1;
620     }
621 
622     if (drives[driveId] == NULL) {
623         return 0;
624     }
625 
626     fname = makeErrorsFileName(fileName);
627     if( fname != NULL ) {
628         FILE *f = fopen(fname, "rb");
629         if( f != NULL ) {
630             char *p = (char*)malloc(DISK_ERRORS_SIZE);
631             if( fread(p, 1, DISK_ERRORS_HEADER_SIZE, f) == DISK_ERRORS_HEADER_SIZE ) {
632                 if( strcmp(p, DISK_ERRORS_HEADER) == 0 ) {
633                     fread(p, 1, DISK_ERRORS_SIZE, f);
634                     drivesErrors[driveId] = p;
635                     p = NULL;
636                 }
637             }
638                         if( p != NULL ) {
639                 free(p);
640             }
641             fclose(f);
642         }
643         free(fname);
644     }
645 
646     fseek(drives[driveId],0,SEEK_END);
647     fileSize[driveId] = ftell(drives[driveId]);
648 
649     diskUpdateInfo(driveId);
650 
651     return 1;
652 }
653 
654 /* Harddisk IDE HD */
655 
656 static const UInt8 hdIdentifyBlock[512] = {
657     0x5a,0x0c,0xba,0x09,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,
658     0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
659     0x20,0x20,0x20,0x20,0x20,0x20,0x31,0x20,0x00,0x00,0x00,0x01,0x04,0x00,0x31,0x56,
660     0x30,0x2e,0x20,0x20,0x20,0x20,0x6c,0x62,0x65,0x75,0x53,0x4d,0x00,0x58,0x48,0x20,
661     0x52,0x41,0x20,0x44,0x49,0x44,0x4b,0x53,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
662     0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x10,0x80,
663     0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x02,0x00,0x02,0x03,0x00,0xba,0x09,0x10,0x00,
664     0x3f,0x00,0x60,0x4c,0x26,0x00,0x00,0x00,0xe0,0x53,0x26,0x00,0x07,0x00,0x07,0x04,
665     0x03,0x00,0x78,0x00,0x78,0x00,0xf0,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
666     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
667     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
668     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
669     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
670     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
671     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
672     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
673     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
674     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
675     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
676     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
677     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
678     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
679     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
680     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
681     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
682     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
683     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
684     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
685     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
686     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
687     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
688     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
689 };
690 
diskReadHdIdentifySector(int driveId,UInt8 * buffer)691 static void diskReadHdIdentifySector(int driveId, UInt8* buffer)
692 {
693     UInt32 totalSectors = fileSize[driveId] / 512;
694     UInt16 heads = 16;
695     UInt16 sectors = 32;
696     UInt16 cylinders = (UInt16)(totalSectors / (heads * sectors));
697 
698     memcpy(buffer, hdIdentifyBlock, 512);
699 
700     buffer[0x02] = cylinders & 0xff;
701     buffer[0x03] = cylinders >> 8;
702     buffer[0x06] = heads & 0xff;
703     buffer[0x07] = heads >> 8;
704     buffer[0x0c] = sectors & 0xff;
705     buffer[0x0d] = sectors >> 8;
706     buffer[0x78] = (UInt8)((totalSectors & 0x000000ff) >>  0);
707     buffer[0x79] = (UInt8)((totalSectors & 0x0000ff00) >>  8);
708     buffer[0x7a] = (UInt8)((totalSectors & 0x00ff0000) >> 16);
709     buffer[0x7b] = (UInt8)((totalSectors & 0xff000000) >> 24);
710 }
711 
diskHdUpdateInfo(int driveId)712 static void diskHdUpdateInfo(int driveId)
713 {
714     sectorSize[driveId]      = 512;
715     sectorsPerTrack[driveId] = fileSize[driveId] / 512;
716     tracks[driveId]          = 1;
717     changed[driveId]         = 1;
718     sides[driveId]           = 1;
719     diskType[driveId]        = IDEHD_DISK;
720     maxSector[driveId]       = 99999999;
721 }
722 
723 /* SCSI device */
724 
725 /*
726     for ScsiDevice.c
727     corresponds to harddisk and floppy disk
728 */
729 
_diskGetTotalSectors(int driveId)730 int _diskGetTotalSectors(int driveId)
731 {
732     if ((diskPresent(driveId)) && (driveId < MAXDRIVES))
733         return fileSize[driveId] / 512;
734     return 0;
735 }
736 
737 /*
738     optimized routine for ScsiDevice.c
739 */
_diskRead2(int driveId,UInt8 * buffer,int sector,int numSectors)740 int _diskRead2(int driveId, UInt8* buffer, int sector, int numSectors)
741 {
742     int length  = numSectors * 512;
743     if (!diskPresent(driveId))
744         return 0;
745 
746     if (ramImageBuffer[driveId] == NULL) {
747         if ((drives[driveId] != NULL)) {
748             if (0 == fseek(drives[driveId], sector * 512, SEEK_SET))
749                 return (fread(buffer, 1, length, drives[driveId]) == length);
750         }
751         return 0;
752     }
753 
754     memcpy(buffer, ramImageBuffer[driveId] + sector * 512, numSectors * 512);
755     return 1;
756 }
757 
758 /*
759     optimized routine for ScsiDevice.c
760 */
_diskWrite2(int driveId,UInt8 * buffer,int sector,int numSectors)761 int _diskWrite2(int driveId, UInt8* buffer, int sector, int numSectors)
762 {
763     int length  = numSectors * 512;
764     if (!diskPresent(driveId))
765         return 0;
766 
767     if (ramImageBuffer[driveId] == NULL) {
768         if ((drives[driveId] != NULL)) {
769             if (0 == fseek(drives[driveId], sector * 512, SEEK_SET))
770                 return (fwrite(buffer, 1, length, drives[driveId]) == length);
771         }
772         return 0;
773     }
774 
775     memcpy(ramImageBuffer[driveId] + sector * 512, buffer, length);
776     return 1;
777 }
778