Previous 15994 Revisions Next

r7599 Thursday 18th March, 2010 at 13:07:34 UTC by Curt Coder
Implemented Commodore DOS errors 21, 22, and 23 in D64 images. "Microsoft Multiplan" now loads on C64. (bug #1932)
[src/mess/formats]d64_dsk.c d64_dsk.h

src/mess/formats/d64_dsk.c
r7598r7599
22
33    formats/d64_dsk.c
44
5    Floppy format code for Commodore 2040/8050 type disk images
6    and for Commodore 1541 D64 disk images
5    Floppy format code for Commodore 1541/2040/8050 disk images
76
87*********************************************************************/
98
r7598r7599
1110
1211    TODO:
1312
14    - disk errors
13   - write to disk
14    - disk errors 24, 25, 26, 28, 74
1515    - variable gaps
1616
17    2010-02 FP: I added partial support for disk images with errors
18    but due to lack of docs I'm not sure if we can do better
1917*/
2018
2119#include "emu.h"
r7598r7599
6664   ERROR_21,      /* no sync character */
6765   ERROR_22,      /* data block not present */
6866   ERROR_23,      /* checksum error in data block */
69   ERROR_24,      /* write verify (on format) */
70   ERROR_25,      /* write verify error */
71   ERROR_26,      /* write protect on */
67   ERROR_24,      /* write verify (on format) UNIMPLEMENTED */
68   ERROR_25,      /* write verify error UNIMPLEMENTED */
69   ERROR_26,      /* write protect on UNIMPLEMENTED */
7270   ERROR_27,      /* checksum error in header block */
73   ERROR_28,      /* write error */
71   ERROR_28,      /* write error UNIMPLEMENTED */
7472   ERROR_29,      /* disk ID mismatch */
75   ERROR_74,      /* disk not ready (no device 1) */
73   ERROR_74,      /* disk not ready (no device 1) UNIMPLEMENTED */
7674};
7775
76static const char *const ERROR_CODE[] = { "00", "00", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "74" };
77
7878static const UINT8 bin_2_gcr[] =
7979{
8080   0x0a, 0x0b, 0x12, 0x13, 0x0e, 0x0f, 0x16, 0x17,
r7598r7599
158158   int dos_tracks;                        /* number of logical tracks */
159159   int track_offset[MAX_HEADS][MAX_TRACKS];   /* offset within image for each physical track */
160160   UINT32 speed_zone[MAX_TRACKS];            /* speed zone for each physical track */
161   bool has_errors;                  /* flag to check for available error codes */
162   int error[MAX_ERROR_SECTORS];            /* error code for each logical sector */
161   bool has_errors;                     /* flag to check for available error codes */
162   UINT8 error[MAX_ERROR_SECTORS];            /* error code for each logical sector */
163   int error_offset[MAX_HEADS][MAX_TRACKS];   /* offset within error array for sector 0 of each logical track */
163164
164165   UINT8 id1, id2;                        /* DOS disk format ID */
165166};
r7598r7599
243244}
244245
245246/*-------------------------------------------------
246    d64_get_sectors_per_track - returns the offset
247    of the error correspondent to the 1st sector
248    of a given track
247    get_sector_error_code - returns the error
248   code for the given sector
249249-------------------------------------------------*/
250250
251static int d64_get_error_offset(floppy_image *floppy, int head, int track)
251static int get_sector_error_code(floppy_image *floppy, int head, int dos_track, int sector)
252252{
253253   struct d64dsk_tag *tag = get_tag(floppy);
254   int i, j;
255   int error_offset = 0;
254   int sector_error = tag->error[tag->error_offset[head][dos_track] + sector];
256255
257   for (i = 0; i <= head; i++)
256   if (sector_error)
258257   {
259      for (j = 0; j < track; j++)
260      {
261         if (tag->dos == DOS25)
262         {
263            error_offset += DOS25_SECTORS_PER_TRACK[j];
264         }
265         else if (tag->dos == DOS2)
266         {
267            if(!(j % 2))
268               error_offset += DOS2_SECTORS_PER_TRACK[j / 2];
269         }
270         else
271         {
272            if(!(j % 2))
273               error_offset += DOS1_SECTORS_PER_TRACK[j / 2];
274         }
275      }
258      logerror("D64 error %s head %u track %u sector %u\n", ERROR_CODE[sector_error], head, dos_track, sector);
276259   }
277260
278   return error_offset;
261   return sector_error;
279262}
280263
281264/*-------------------------------------------------
r7598r7599
389372      UINT16 gcr_track_size;
390373      UINT8 *gcr_track_data;
391374      UINT64 gcr_pos = G64_DATA_START;
392      int error_offset = 0, tmp1, tmp2;
375      int error_offset = 0;
393376
394377      /* determine logical track number */
395378      int dos_track = get_dos_track(track);
r7598r7599
405388      /* determine number of sectors per track */
406389      sectors_per_track = d64_get_sectors_per_track(floppy, head, track);
407390
408      /* determine the position of the error byte for the first sector of this track */
409      if (tag->has_errors)
410         error_offset = d64_get_error_offset(floppy, head, track);
411
412391      /* allocate D64 track data buffer */
413392      d64_track_size = sectors_per_track * SECTOR_SIZE;
414393      d64_track_data = (UINT8 *)alloca(d64_track_size);
r7598r7599
431410      {
432411         // here we convert the sector data to gcr directly!
433412         // IMPORTANT: errors in reading sectors can modify e.g. header info $01 & $05
413         int sector_error = get_sector_error_code(floppy, head, track, sector);
434414
435415         /* first we set the position at which sector data starts in the image */
436416         UINT64 d64_pos = sector * SECTOR_SIZE;
r7598r7599
445425                6. Inter-sector gap  55 55 55 55...55 55 (4 to 19 bytes, never read)
446426            */
447427
448         if (tag->has_errors)
449         {
450            error_offset += sector;
428         if (sector_error == ERROR_29)
429            id1 ^= 0xff;
451430
452            if (tag->error[error_offset] == ERROR_29)
453               id1 ^= 0xff;
431         /* Header sync */
432         if (sector_error != ERROR_21)
433         {
434            for (i = 0; i < 5; i++)
435               gcr_track_data[gcr_pos + i] = 0xff;
436            gcr_pos += 5;
454437         }
455438
456         /* Header sync */
457         for (i = 0; i < 5; i++)
458            gcr_track_data[gcr_pos + i] = 0xff;
459         gcr_pos += 5;
460
461
462439         /* Header info */
463440         /* These are 8 bytes unencoded, which become 10 bytes encoded */
464441         // $00 - header block ID ($08)                      // this byte can be modified by error code 20 -> 0xff
465442         // $01 - header block checksum (EOR of $02-$05)     // this byte can be modified by error code 27 -> ^ 0xff
466443         // $02 - Sector# of data block
467444         // $03 - Track# of data block
468         tmp1 = (tag->has_errors && tag->error[error_offset] == ERROR_20) ? 0xff : 0x08;
469         tmp2 = sector ^ dos_track ^ id2 ^ id1;
445         UINT8 header_block_id = (sector_error == ERROR_20) ? 0xff : 0x08;
446         UINT8 header_block_checksum = sector ^ dos_track ^ id2 ^ id1;
470447
471         if (tag->has_errors && tag->error[error_offset] == ERROR_27)
472            tmp2 ^= 0xff;
448         if (sector_error == ERROR_27)
449            header_block_checksum ^= 0xff;
473450
474         gcr_double_2_gcr(tmp1, tmp2, sector, dos_track, gcr_track_data + gcr_pos);
451         gcr_double_2_gcr(header_block_id, header_block_checksum, sector, dos_track, gcr_track_data + gcr_pos);
475452         gcr_pos += 5;
476453
477454         // $04 - Format ID byte #2
r7598r7599
492469         gcr_pos += 5;
493470
494471         /* Data block */
472         UINT8 data_block_id = (sector_error == ERROR_22) ? 0xff : 0x07;
473
495474         // we first need to calculate the checksum of the 256 bytes of the sector
496475         UINT8 sector_checksum = d64_track_data[d64_pos];
497476         for (i = 1; i < 256; i++)
498477            sector_checksum ^= d64_track_data[d64_pos + i];
499
478         
479         if (sector_error == ERROR_23)
480            sector_checksum ^= 0xff;
481         
500482         /*
501483                $00      - data block ID ($07)
502484                $01-100  - 256 bytes sector data
503485                $101     - data block checksum (EOR of $01-100)
504486                $102-103 - $00 ("off" bytes, to make the sector size a multiple of 5)
505487            */
506         gcr_double_2_gcr(0x07, d64_track_data[d64_pos], d64_track_data[d64_pos + 1], d64_track_data[d64_pos + 2], gcr_track_data + gcr_pos);
488         gcr_double_2_gcr(data_block_id, d64_track_data[d64_pos], d64_track_data[d64_pos + 1], d64_track_data[d64_pos + 2], gcr_track_data + gcr_pos);
507489         gcr_pos += 5;
508490
509491         for (i = 1; i < 64; i++)
r7598r7599
522504         for (i = 0; i < 14; i++)
523505            gcr_track_data[gcr_pos + i] = 0x55;
524506         gcr_pos += 14;
507
508         error_offset++;
525509      }
526510
527511      /* copy GCR track data to buffer */
r7598r7599
736720            else
737721            {
738722               tag->track_offset[head][track] = track_offset;
739               track_offset += DOS25_SECTORS_PER_TRACK[track] * SECTOR_SIZE;
723               tag->error_offset[head][track] = errors_size;
740724
725               track_offset += DOS25_SECTORS_PER_TRACK[track] * SECTOR_SIZE;
741726               /* also store an error entry for each sector */
742727               errors_size += DOS25_SECTORS_PER_TRACK[track];
743728
744               if (LOG) logerror("D64 head %u track %u data offset: %04x\n", head, track + 1, tag->track_offset[head][track]);
729               if (LOG)
730               {
731                  logerror("D64 head %u track %u data offset: %04x\n", head, track + 1, tag->track_offset[head][track]);
732                  logerror("D64 head %u track %u error offset: %04x\n", head, track + 1, tag->error_offset[head][track]);
733               }
745734            }
746735         }
747736         else
r7598r7599
755744            {
756745               /* full track */
757746               tag->track_offset[head][track] = track_offset;
747               tag->error_offset[head][track] = errors_size;
758748
759749               if (dos == DOS1)
760750               {
r7598r7599
769759                  errors_size += DOS2_SECTORS_PER_TRACK[track / 2];
770760               }
771761
772               if (LOG) logerror("D64 head %u track %.1f data offset: %04x\n", head, get_dos_track(track), tag->track_offset[head][track]);
762               if (LOG)
763               {
764                  logerror("D64 head %u track %.1f data offset: %04x\n", head, get_dos_track(track), tag->track_offset[head][track]);
765                  logerror("D64 head %u track %.1f error offset: %04x\n", head, get_dos_track(track), tag->error_offset[head][track]);
766               }
773767            }
774768         }
775769      }
r7598r7599
811805
812806   /* read errors */
813807   if (tag->has_errors)
808   {
809      if (LOG) logerror("D64 error blocks: %u %u\n", errors_size, track_offset);
814810      floppy_image_read(floppy, tag->error, track_offset, errors_size);
811   }
815812   else
816      memset(tag->error, 0, MAX_ERROR_SECTORS);
813   {
814      memset(tag->error, ERROR_00, MAX_ERROR_SECTORS);
815   }
817816
818817   /* set callbacks */
819818   callbacks = floppy_callbacks(floppy);
src/mess/formats/d64_dsk.h
r7598r7599
22
33    formats/d64_dsk.h
44
5    Floppy format code for Commodore 2040/8050 type disk images
5    Floppy format code for Commodore 1541/2040/8050 disk images
66
77*********************************************************************/
88

Previous 15994 Revisions Next


© 1998-2018 The MESS Team