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