summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Curt Coder <curtcoder@mail.com>2013-01-14 16:27:52 +0000
committer Curt Coder <curtcoder@mail.com>2013-01-14 16:27:52 +0000
commitcf41f05d4ba625b1e1ca95b458a1d1fb51aeb855 (patch)
treef8dd2d48e0f52dc837e44c38b11ed68963c775f9
parent408b15043d9da0a93379febfab7026f062a2cb7f (diff)
(MESS) flopimg: Added support for Commodore GCR encoding. [Curt Coder]
(MESS) d64/g64 floppy modernization WIP. (nw)
-rw-r--r--src/lib/formats/d64_dsk.c364
-rw-r--r--src/lib/formats/d64_dsk.h87
-rw-r--r--src/lib/formats/flopimg.c61
-rw-r--r--src/lib/formats/flopimg.h12
-rw-r--r--src/lib/formats/g64_dsk.c155
-rw-r--r--src/lib/formats/g64_dsk.h34
6 files changed, 695 insertions, 18 deletions
diff --git a/src/lib/formats/d64_dsk.c b/src/lib/formats/d64_dsk.c
index add49e62d88..1cabff7e28c 100644
--- a/src/lib/formats/d64_dsk.c
+++ b/src/lib/formats/d64_dsk.c
@@ -1,3 +1,361 @@
+/***************************************************************************
+
+ Copyright Olivier Galibert
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+****************************************************************************/
+
+/*********************************************************************
+
+ formats/d64_dsk.c
+
+ Commodore 2040/8050/1541 sector disk image format
+
+*********************************************************************/
+
+#include "emu.h"
+#include "formats/d64_dsk.h"
+
+d64_format::d64_format()
+{
+}
+
+const char *d64_format::name() const
+{
+ return "d64";
+}
+
+const char *d64_format::description() const
+{
+ return "Commodore 2040/8050/1541 disk image";
+}
+
+const char *d64_format::extensions() const
+{
+ return "d64,d67,d71,d80,d82";
+}
+
+const d64_format::format d64_format::formats[] = {
+ { // d67, dos 1, 35 tracks
+ floppy_image::FF_525, floppy_image::SSSD, DOS_1, 690, 35, 1, 9, 8
+ },
+ { // d64, dos 2, 35 tracks
+ floppy_image::FF_525, floppy_image::SSSD, DOS_2, 683, 35, 1, 9, 8
+ },
+ { // d64, dos 2, 40 tracks
+ floppy_image::FF_525, floppy_image::SSSD, DOS_2, 768, 35, 1, 9, 8
+ },
+ { // d64, dos 2, 42 tracks
+ floppy_image::FF_525, floppy_image::SSSD, DOS_2, 802, 35, 1, 9, 8
+ },
+ { // d71, dos 2, 35 tracks, 2 heads
+ floppy_image::FF_525, floppy_image::DSSD, DOS_2, 683, 35, 2, 9, 8
+ },
+ { // d80, dos 2.5, 77 tracks
+ floppy_image::FF_525, floppy_image::SSQD, DOS_25, 2083, 77, 15, 9, 8
+ },
+ { // d82, dos 2.5, 77 tracks, 2 heads
+ floppy_image::FF_525, floppy_image::DSQD, DOS_25, 2083, 77, 15, 9, 8
+ },
+ {}
+};
+
+const UINT32 d64_format::dos1_cell_size[] =
+{
+ 4000, // 16MHz/16/4
+ 3750, // 16MHz/15/4
+ 3500, // 16MHz/14/4
+ 3250 // 16MHz/13/4
+};
+
+const UINT32 d64_format::dos25_cell_size[] =
+{
+ 2667, // 12MHz/16/2
+ 2500, // 12MHz/15/2
+ 2333, // 12MHz/14/2
+ 2167 // 12MHz/13/2
+};
+
+const int d64_format::dos1_sectors_per_track[] =
+{
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, // 1-17
+ 20, 20, 20, 20, 20, 20, 20, // 18-24
+ 18, 18, 18, 18, 18, 18, // 25-30
+ 17, 17, 17, 17, 17, // 31-35
+ 17, 17, 17, 17, 17, // 36-40
+ 17, 17 // 41-42
+};
+
+const int d64_format::dos2_sectors_per_track[] =
+{
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, // 1-17
+ 19, 19, 19, 19, 19, 19, 19, // 18-24
+ 18, 18, 18, 18, 18, 18, // 25-30
+ 17, 17, 17, 17, 17, // 31-35
+ 17, 17, 17, 17, 17, // 36-40
+ 17, 17 // 41-42
+};
+
+const int d64_format::dos25_sectors_per_track[] =
+{
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, // 1-39
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, // 40-53
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, // 54-64
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, // 65-77
+ 23, 23, 23, 23, 23, 23, 23 // 78-84
+};
+
+const int d64_format::dos1_speed_zone[] =
+{
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 1-17
+ 2, 2, 2, 2, 2, 2, 2, // 18-24
+ 1, 1, 1, 1, 1, 1, // 25-30
+ 0, 0, 0, 0, 0, // 31-35
+ 0, 0, 0, 0, 0, // 36-40
+ 0, 0 // 41-42
+};
+
+const int d64_format::dos25_speed_zone[] =
+{
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 1-39
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 40-53
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 54-64
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 65-77
+ 0, 0, 0, 0, 0, 0, 0 // 78-84
+};
+
+int d64_format::find_size(io_generic *io, UINT32 form_factor)
+{
+ int size = io_generic_size(io);
+ for(int i=0; formats[i].sector_count; i++) {
+ const format &f = formats[i];
+ if(size == f.sector_count*SECTOR_SIZE)
+ return i;
+ if(size == (f.sector_count*SECTOR_SIZE) + f.sector_count)
+ return i;
+ }
+ return -1;
+}
+
+int d64_format::identify(io_generic *io, UINT32 form_factor)
+{
+ int type = find_size(io, form_factor);
+
+ if(type != -1)
+ return 50;
+ return 0;
+}
+
+int d64_format::get_physical_track(const format &f, int track)
+{
+ int physical_track = 0;
+
+ switch (f.dos) {
+ case DOS_1: physical_track = track*2; break; // skip halftracks
+ case DOS_2: physical_track = track*2; break; // skip halftracks
+ case DOS_25: physical_track = track; break;
+ }
+
+ return physical_track;
+}
+
+void d64_format::get_disk_id(const format &f, io_generic *io, UINT8 &id1, UINT8 &id2)
+{
+ int offset = 0;
+
+ switch (f.dos) {
+ case DOS_1: offset = DOS1_DISK_ID_OFFSET; break;
+ case DOS_2: offset = DOS1_DISK_ID_OFFSET; break;
+ case DOS_25: offset = DOS25_DISK_ID_OFFSET; break;
+ }
+
+ UINT8 id[2];
+ io_generic_read(io, id, offset, 2);
+ id1 = id[0];
+ id2 = id[1];
+}
+
+UINT32 d64_format::get_cell_size(const format &f, int track)
+{
+ int cell_size = 0;
+
+ switch (f.dos) {
+ case DOS_1: cell_size = dos1_cell_size[dos1_speed_zone[track]]; break;
+ case DOS_2: cell_size = dos1_cell_size[dos1_speed_zone[track]]; break;
+ case DOS_25: cell_size = dos25_cell_size[dos25_speed_zone[track]]; break;
+ }
+
+ return cell_size;
+}
+
+int d64_format::get_sectors_per_track(const format &f, int track)
+{
+ int sector_count = 0;
+
+ switch (f.dos) {
+ case DOS_1: sector_count = dos1_sectors_per_track[track]; break;
+ case DOS_2: sector_count = dos1_sectors_per_track[track]; break;
+ case DOS_25: sector_count = dos25_sectors_per_track[track]; break;
+ }
+
+ return sector_count;
+}
+
+floppy_image_format_t::desc_e* d64_format::get_sector_desc(const format &f, int &current_size, int track, int sector_count, UINT8 id1, UINT8 id2, int gap_2)
+{
+ static floppy_image_format_t::desc_e desc[] = {
+ /* 00 */ { SECTOR_LOOP_START, 0, sector_count-1 },
+ /* 01 */ { RAWBYTE, 0xff, 5 },
+ /* 02 */ { GCR5, 0x08, 1 },
+ /* 03 */ { CRC, 1 },
+ /* 04 */ { CRC_CBM_START, 1 },
+ /* 05 */ { SECTOR_ID_GCR5 },
+ /* 06 */ { GCR5, track, 1 },
+ /* 07 */ { GCR5, id2, 1 },
+ /* 08 */ { GCR5, id1, 1 },
+ /* 09 */ { CRC_END, 1 },
+ /* 10 */ { GCR5, 0x0f, 2 },
+ /* 11 */ { RAWBYTE, 0x55, f.gap_1 },
+ /* 12 */ { RAWBYTE, 0xff, 5 },
+ /* 13 */ { GCR5, 0x07, 1 },
+ /* 14 */ { CRC_CBM_START, 2 },
+ /* 15 */ { SECTOR_DATA_GCR5, -1 },
+ /* 16 */ { CRC_END, 2 },
+ /* 17 */ { CRC, 2 },
+ /* 18 */ { GCR5, 0x00, 2 },
+ /* 19 */ { RAWBYTE, 0x55, gap_2 },
+ /* 20 */ { SECTOR_LOOP_END },
+ /* 21 */ { RAWBYTE, 0x55, 0 },
+ /* 22 */ { RAWBITS, 0xffff, 0 },
+ /* 23 */ { END }
+ };
+
+ current_size = 40 + (1+1+4+2)*10 + (f.gap_1)*8 + 40 + (1+SECTOR_SIZE+1+2)*10 + gap_2*8;
+ current_size *= sector_count;
+
+ return desc;
+}
+
+void d64_format::build_sector_description(const format &f, UINT8 *sectdata, desc_s *sectors, int sector_count, UINT8 *errordata) const
+{
+ int cur_offset = 0;
+
+ for(int i=0; i<f.sector_count; i++) {
+ sectors[i].data = sectdata + cur_offset;
+ sectors[i].size = SECTOR_SIZE;
+ sectors[i].sector_id = i;
+ sectors[i].sector_info = errordata[i];
+
+ cur_offset += sectors[i].size;
+ }
+}
+
+bool d64_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
+{
+ int type = find_size(io, form_factor);
+ if(type == -1)
+ return false;
+
+ const format &f = formats[type];
+ int size = io_generic_size(io);
+ UINT8 *img;
+
+ if(size == f.sector_count*SECTOR_SIZE) {
+ img = global_alloc_array(UINT8, size + f.sector_count);
+ memset(&img[size + f.sector_count], ERROR_00, f.sector_count);
+ }
+ else {
+ img = global_alloc_array(UINT8, size);
+ }
+
+ io_generic_read(io, img, 0, size);
+
+ floppy_image_format_t::desc_e *desc;
+ desc_s sectors[40];
+ int track_offset = 0, error_offset = 0;
+
+ UINT8 id1 = 0, id2 = 0;
+ get_disk_id(f, io, id1, id2);
+
+ for(int head=0; head < f.head_count; head++) {
+ for(int track=0; track < f.track_count; track++) {
+ int current_size = 0;
+ int total_size = 200000000/get_cell_size(f, track);
+
+ int physical_track = get_physical_track(f, track);
+ int sector_count = get_sectors_per_track(f, track);
+ int track_size = sector_count*SECTOR_SIZE;
+
+ desc = get_sector_desc(f, current_size, track+1, sector_count, id1, id2, f.gap_2);
+
+ int remaining_size = total_size - current_size;
+ if(remaining_size < 0)
+ throw emu_fatalerror("d64_format: Incorrect track layout, max_size=%d, current_size=%d", total_size, current_size);
+
+ // Fixup the end gap
+ desc[21].p2 = remaining_size / 8;
+ desc[22].p2 = remaining_size & 7;
+ desc[22].p1 >>= 8-(remaining_size & 7);
+
+ printf("track %u cursize %u totsize %u phystrack %u secnt %u trksize %u trkofs %u\n", track,current_size,total_size,physical_track,sector_count,track_size,track_offset);
+
+ build_sector_description(f, &img[track_offset], sectors, sector_count, &img[f.sector_count*SECTOR_SIZE + error_offset]);
+ generate_track(desc, physical_track, head, sectors, sector_count, total_size, image);
+
+ track_offset += track_size;
+ error_offset += sector_count;
+ }
+ }
+
+ image->set_variant(f.variant);
+
+ return true;
+}
+
+bool d64_format::save(io_generic *io, floppy_image *image)
+{
+ return false;
+}
+
+bool d64_format::supports_save() const
+{
+ return false;
+}
+
+const floppy_format_type FLOPPY_D64_FORMAT = &floppy_image_format_creator<d64_format>;
+
+
+// ------ LEGACY -----
+
+
/*********************************************************************
formats/d64_dsk.c
@@ -809,9 +1167,15 @@ FLOPPY_CONSTRUCT( d64_dsk_construct )
for d80 & d82 they are at track 39 bytes 0x18 & 0x19
*/
if (dos == DOS25)
+ {
+ printf("dos25 id offset %u\n", tag->track_offset[0][38] + 0x18);
floppy_image_read(floppy, id, tag->track_offset[0][38] + 0x18, 2);
+ }
else
+ {
+ printf("dos2 id offset %u\n", tag->track_offset[0][38] + 0x18);
floppy_image_read(floppy, id, tag->track_offset[0][34] + 0xa2, 2);
+ }
tag->id1 = id[0];
tag->id2 = id[1];
diff --git a/src/lib/formats/d64_dsk.h b/src/lib/formats/d64_dsk.h
index b5dc8d9d9ed..1a95954de42 100644
--- a/src/lib/formats/d64_dsk.h
+++ b/src/lib/formats/d64_dsk.h
@@ -2,18 +2,93 @@
formats/d64_dsk.h
- Floppy format code for Commodore 1541/2040/8050 disk images
+ Commodore 2040/8050/1541 sector disk image format
*********************************************************************/
-#ifndef __D64_DSK__
-#define __D64_DSK__
+#ifndef D64_DSK_H_
+#define D64_DSK_H_
#include "flopimg.h"
-/***************************************************************************
- PROTOTYPES
-***************************************************************************/
+class d64_format : public floppy_image_format_t {
+public:
+ struct format {
+ UINT32 form_factor; // See floppy_image for possible values
+ UINT32 variant; // See floppy_image for possible values
+
+ int dos;
+ int sector_count;
+ int track_count;
+ int head_count;
+ int gap_1;
+ int gap_2;
+ };
+
+ d64_format();
+
+ virtual const char *name() const;
+ virtual const char *description() const;
+ virtual const char *extensions() const;
+
+ virtual int identify(io_generic *io, UINT32 form_factor);
+ virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image);
+ virtual bool save(io_generic *io, floppy_image *image);
+ virtual bool supports_save() const;
+
+protected:
+ enum
+ {
+ DOS_1,
+ DOS_2,
+ DOS_25
+ };
+
+ enum
+ {
+ ERROR_00 = 1,
+ ERROR_20, /* header block not found */
+ ERROR_21, /* no sync character */
+ ERROR_22, /* data block not present */
+ ERROR_23, /* checksum error in data block */
+ ERROR_24, /* write verify (on format) UNIMPLEMENTED */
+ ERROR_25, /* write verify error UNIMPLEMENTED */
+ ERROR_26, /* write protect on UNIMPLEMENTED */
+ ERROR_27, /* checksum error in header block */
+ ERROR_28, /* write error UNIMPLEMENTED */
+ ERROR_29, /* disk ID mismatch */
+ ERROR_74, /* disk not ready (no device 1) UNIMPLEMENTED */
+ };
+
+ static const int SECTOR_SIZE = 256;
+
+ static const int DOS1_DISK_ID_OFFSET = 101144;
+ static const int DOS25_DISK_ID_OFFSET = 282136;
+
+ floppy_image_format_t::desc_e* get_sector_desc(const format &f, int &current_size, int track, int sector_count, UINT8 id1, UINT8 id2, int gap_2);
+
+ int find_size(io_generic *io, UINT32 form_factor);
+ int get_physical_track(const format &f, int track);
+ UINT32 get_cell_size(const format &f, int track);
+ int get_sectors_per_track(const format &f, int track);
+ void get_disk_id(const format &f, io_generic *io, UINT8 &id1, UINT8 &id2);
+ void build_sector_description(const format &f, UINT8 *sectdata, desc_s *sectors, int sector_count, UINT8 *errordata) const;
+
+ static const format formats[];
+
+ static const UINT32 dos1_cell_size[];
+ static const UINT32 dos25_cell_size[];
+
+ static const int dos1_speed_zone[];
+ static const int dos25_speed_zone[];
+
+ static const int dos1_sectors_per_track[];
+ static const int dos2_sectors_per_track[];
+ static const int dos25_sectors_per_track[];
+};
+
+extern const floppy_format_type FLOPPY_D64_FORMAT;
+
FLOPPY_IDENTIFY( d64_dsk_identify );
FLOPPY_IDENTIFY( d67_dsk_identify );
diff --git a/src/lib/formats/flopimg.c b/src/lib/formats/flopimg.c
index 23a36b3e51d..6881484bb84 100644
--- a/src/lib/formats/flopimg.c
+++ b/src/lib/formats/flopimg.c
@@ -1104,6 +1104,7 @@ bool floppy_image_format_t::type_no_data(int type) const
return type == CRC_CCITT_START ||
type == CRC_CCITT_FM_START ||
type == CRC_AMIGA_START ||
+ type == CRC_CBM_START ||
type == CRC_MACHEAD_START ||
type == CRC_END ||
type == SECTOR_LOOP_START ||
@@ -1136,6 +1137,9 @@ void floppy_image_format_t::collect_crcs(const desc_e *desc, gen_crc_info *crcs)
case CRC_AMIGA_START:
crcs[desc[i].p1].type = CRC_AMIGA;
break;
+ case CRC_CBM_START:
+ crcs[desc[i].p1].type = CRC_CBM;
+ break;
case CRC_MACHEAD_START:
crcs[desc[i].p1].type = CRC_MACHEAD;
break;
@@ -1155,6 +1159,7 @@ int floppy_image_format_t::crc_cells_size(int type) const
case CRC_CCITT: return 32;
case CRC_CCITT_FM: return 32;
case CRC_AMIGA: return 64;
+ case CRC_CBM: return 10;
case CRC_MACHEAD: return 8;
default: return 0;
}
@@ -1215,6 +1220,14 @@ void floppy_image_format_t::mfm_half_w(UINT32 *buffer, int &offset, int start_bi
}
}
+void floppy_image_format_t::gcr5_w(UINT32 *buffer, int &offset, int n, UINT32 val, UINT32 size)
+{
+ UINT32 e0 = gcr5fw_tb[val >> 4];
+ UINT32 e1 = gcr5fw_tb[val & 0x0f];
+ raw_w(buffer, offset, 5, e0, size);
+ raw_w(buffer, offset, 5, e1, size);
+}
+
void floppy_image_format_t::fixup_crc_amiga(UINT32 *buffer, const gen_crc_info *crc)
{
UINT16 res = 0;
@@ -1227,6 +1240,17 @@ void floppy_image_format_t::fixup_crc_amiga(UINT32 *buffer, const gen_crc_info *
mfm_w(buffer, offset, 16, res);
}
+void floppy_image_format_t::fixup_crc_cbm(UINT32 *buffer, const gen_crc_info *crc)
+{
+ UINT8 v = 0;
+ for(int o = crc->start; o < crc->end; o+=10) {
+ v = v ^ (gcr5bw_tb[bitn_r(buffer, o, 5)] << 4);
+ v = v ^ gcr5bw_tb[bitn_r(buffer, o+5, 5)];
+ }
+ int offset = crc->write;
+ gcr5_w(buffer, offset, 8, v);
+}
+
UINT16 floppy_image_format_t::calc_crc_ccitt(const UINT32 *buffer, int start, int end)
{
UINT32 res = 0xffff;
@@ -1268,6 +1292,7 @@ void floppy_image_format_t::fixup_crcs(UINT32 *buffer, gen_crc_info *crcs)
if(crcs[i].write != -1) {
switch(crcs[i].type) {
case CRC_AMIGA: fixup_crc_amiga(buffer, crcs+i); break;
+ case CRC_CBM: fixup_crc_cbm(buffer, crcs+i); break;
case CRC_CCITT: fixup_crc_ccitt(buffer, crcs+i); break;
case CRC_CCITT_FM:fixup_crc_ccitt_fm(buffer, crcs+i); break;
case CRC_MACHEAD: fixup_crc_machead(buffer, crcs+i); break;
@@ -1365,11 +1390,21 @@ void floppy_image_format_t::generate_track(const desc_e *desc, int track, int he
mfm_w(buffer, offset, desc[index].p2, desc[index].p1);
break;
+ case GCR5:
+ for(int i=0; i<desc[index].p2; i++)
+ gcr5_w(buffer, offset, 8, desc[index].p1);
+ break;
+
case RAW:
for(int i=0; i<desc[index].p2; i++)
raw_w(buffer, offset, 16, desc[index].p1);
break;
+ case RAWBYTE:
+ for(int i=0; i<desc[index].p2; i++)
+ raw_w(buffer, offset, 8, desc[index].p1);
+ break;
+
case RAWBITS:
raw_w(buffer, offset, desc[index].p2, desc[index].p1);
break;
@@ -1410,6 +1445,10 @@ void floppy_image_format_t::generate_track(const desc_e *desc, int track, int he
fm_w(buffer, offset, 8, sect[sector_idx].sector_id);
break;
+ case SECTOR_ID_GCR5:
+ gcr5_w(buffer, offset, 8, sect[sector_idx].sector_id);
+ break;
+
case SECTOR_ID_GCR6:
raw_w(buffer, offset, 8, gcr6fw_tb[sect[sector_idx].sector_id]);
break;
@@ -1482,6 +1521,7 @@ void floppy_image_format_t::generate_track(const desc_e *desc, int track, int he
break;
case CRC_AMIGA_START:
+ case CRC_CBM_START:
case CRC_CCITT_START:
case CRC_CCITT_FM_START:
case CRC_MACHEAD_START:
@@ -1525,6 +1565,13 @@ void floppy_image_format_t::generate_track(const desc_e *desc, int track, int he
break;
}
+ case SECTOR_DATA_GCR5: {
+ const desc_s *csect = sect + (desc[index].p1 >= 0 ? desc[index].p1 : sector_idx);
+ for(int i=0; i != csect->size; i++)
+ gcr5_w(buffer, offset, 8, csect->data[i]);
+ break;
+ }
+
case SECTOR_DATA_MAC: {
const desc_s *csect = sect + (desc[index].p1 >= 0 ? desc[index].p1 : sector_idx);
const UINT8 *data = csect->data;
@@ -1696,6 +1743,20 @@ void floppy_image_format_t::generate_track_from_levels(int track, int head, UINT
image->set_write_splice_position(track, head, splice_angular_pos);
}
+const UINT8 floppy_image_format_t::gcr5fw_tb[0x10] =
+{
+ 0x0a, 0x0b, 0x12, 0x13, 0x0e, 0x0f, 0x16, 0x17,
+ 0x09, 0x19, 0x1a, 0x1b, 0x0d, 0x1d, 0x1e, 0x15
+};
+
+const UINT8 floppy_image_format_t::gcr5bw_tb[0x20] =
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x01, 0x00, 0x0c, 0x04, 0x05,
+ 0x00, 0x00, 0x02, 0x03, 0x00, 0x0f, 0x06, 0x07,
+ 0x00, 0x09, 0x0a, 0x0b, 0x00, 0x0d, 0x0e, 0x00
+};
+
const UINT8 floppy_image_format_t::gcr6fw_tb[0x40] =
{
0x96, 0x97, 0x9a, 0x9b, 0x9d, 0x9e, 0x9f, 0xa6,
diff --git a/src/lib/formats/flopimg.h b/src/lib/formats/flopimg.h
index 58887426a92..fdf0a1d97c2 100644
--- a/src/lib/formats/flopimg.h
+++ b/src/lib/formats/flopimg.h
@@ -301,7 +301,9 @@ protected:
FM, //!< One byte in p1 to be fm-encoded, msb first, repeated p2 times
MFM, //!< One byte in p1 to be mfm-encoded, msb first, repeated p2 times
MFMBITS, //!< A value of p2 bits in p1 to be mfm-encoded, msb first
+ GCR5, //!< One byte in p1 to be gcr5-encoded, repeated p2 times
RAW, //!< One 16 bits word in p1 to be written raw, msb first, repeated p2 times
+ RAWBYTE, //!< One 8 bit byte in p1 to be written raw, msb first, repeated p2 times
RAWBITS, //!< A value of p2 bits in p1 to be copied as-is, msb first
TRACK_ID, //!< Track id byte, mfm-encoded
TRACK_ID_FM, //!< Track id byte, fm-encoded
@@ -312,6 +314,7 @@ protected:
TRACK_HEAD_ID_GCR6, //!< Track id 7th bit + head, gc6-encoded
SECTOR_ID, //!< Sector id byte, mfm-encoded
SECTOR_ID_FM, //!< Sector id byte, fm-encoded
+ SECTOR_ID_GCR5, //!< Sector id byte, gcr5-encoded
SECTOR_ID_GCR6, //!< Sector id byte, gcr6-encoded
SIZE_ID, //!< Sector size code on one byte [log2(size/128)], mfm-encoded
SIZE_ID_FM, //!< Sector size code on one byte [log2(size/128)], fm-encoded
@@ -327,11 +330,13 @@ protected:
SECTOR_DATA_FM, //!< Sector data to fm-encode, which in p1, -1 for the current one per the sector id
SECTOR_DATA_O, //!< Sector data to mfm-encode, odd bits only, which in p1, -1 for the current one per the sector id
SECTOR_DATA_E, //!< Sector data to mfm-encode, even bits only, which in p1, -1 for the current one per the sector id
+ SECTOR_DATA_GCR5, //!< Sector data to gcr5-encode, which in p1, -1 for the current one per the sector id
SECTOR_DATA_MAC, //!< Transformed sector data + checksum, mac style, id in p1, -1 for the current one per the sector id
CRC_CCITT_START, //!< Start a CCITT CRC calculation, with the usual x^16 + x^12 + x^5 + 1 (11021) polynomial, p1 = crc id
CRC_CCITT_FM_START, //!< Start a CCITT CRC calculation, with the usual x^16 + x^12 + x^5 + 1 (11021) polynomial, p1 = crc id
CRC_AMIGA_START, //!< Start an amiga checksum calculation, p1 = crc id
+ CRC_CBM_START, //<! Start a CBM checksum calculation (xor of original data values, gcr5-encoded), p1 = crc id
CRC_MACHEAD_START, //!< Start of the mac gcr6 sector header checksum calculation (xor of pre-encode 6-bits values, gcr6-encoded)
CRC_END, //!< End the checksum, p1 = crc id
CRC, //!< Write a checksum in the apporpriate format, p1 = crc id
@@ -391,7 +396,7 @@ protected:
void normalize_times(UINT32 *buffer, int bitlen);
// Some conversion tables for gcr
- static const UINT8 gcr5fw_tb[0x20], gcr5bw_tb[0x100];
+ static const UINT8 gcr5fw_tb[0x10], gcr5bw_tb[0x20];
static const UINT8 gcr6fw_tb[0x40], gcr6bw_tb[0x100];
// Some useful descriptions shared by multiple formats
@@ -536,6 +541,8 @@ protected:
void mfm_w(UINT32 *buffer, int &offset, int n, UINT32 val, UINT32 size = 1000);
//! MFM-encode every two bits and write
void mfm_half_w(UINT32 *buffer, int &offset, int start_bit, UINT32 val, UINT32 size = 1000);
+ //! GCR5-encode and write a series of bits
+ void gcr5_w(UINT32 *buffer, int &offset, int n, UINT32 val, UINT32 size = 1000);
//! GCR4 encode (Apple II sector header)
UINT16 gcr4_encode(UINT8 va);
//! GCR4 decode
@@ -546,7 +553,7 @@ protected:
void gcr6_decode(UINT8 e0, UINT8 e1, UINT8 e2, UINT8 e3, UINT8 &va, UINT8 &vb, UINT8 &vc);
private:
- enum { CRC_NONE, CRC_AMIGA, CRC_CCITT, CRC_CCITT_FM, CRC_MACHEAD };
+ enum { CRC_NONE, CRC_AMIGA, CRC_CBM, CRC_CCITT, CRC_CCITT_FM, CRC_MACHEAD };
enum { MAX_CRC_COUNT = 64 };
//! Holds data used internally for generating CRCs.
@@ -563,6 +570,7 @@ private:
int crc_cells_size(int type) const;
void fixup_crc_amiga(UINT32 *buffer, const gen_crc_info *crc);
+ void fixup_crc_cbm(UINT32 *buffer, const gen_crc_info *crc);
void fixup_crc_ccitt(UINT32 *buffer, const gen_crc_info *crc);
void fixup_crc_ccitt_fm(UINT32 *buffer, const gen_crc_info *crc);
void fixup_crc_machead(UINT32 *buffer, const gen_crc_info *crc);
diff --git a/src/lib/formats/g64_dsk.c b/src/lib/formats/g64_dsk.c
index 2e71e979950..f6a6ae8cc0d 100644
--- a/src/lib/formats/g64_dsk.c
+++ b/src/lib/formats/g64_dsk.c
@@ -1,3 +1,158 @@
+/***************************************************************************
+
+ Copyright Olivier Galibert
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+****************************************************************************/
+
+/*********************************************************************
+
+ formats/g64_dsk.c
+
+ Commodore 1541 GCR disk image format
+
+*********************************************************************/
+
+#include "emu.h"
+#include "formats/g64_dsk.h"
+
+#define G64_FORMAT_HEADER "GCR-1541"
+
+g64_format::g64_format()
+{
+}
+
+const char *g64_format::name() const
+{
+ return "g64";
+}
+
+const char *g64_format::description() const
+{
+ return "Commodore 1541 GCR disk image";
+}
+
+const char *g64_format::extensions() const
+{
+ return "g64";
+}
+
+const UINT32 g64_format::c1541_cell_size[] =
+{
+ 4000, // 16MHz/16/4
+ 3750, // 16MHz/15/4
+ 3500, // 16MHz/14/4
+ 3250 // 16MHz/13/4
+};
+
+int g64_format::identify(io_generic *io, UINT32 form_factor)
+{
+ UINT8 header[8];
+
+ io_generic_read(io, &header, 0, sizeof(header));
+ if ( memcmp( header, G64_FORMAT_HEADER, 8 ) ==0) {
+ return 100;
+ }
+ return 0;
+}
+
+bool g64_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
+{
+ int size = io_generic_size(io);
+ UINT8 *img = global_alloc_array(UINT8, size);
+ io_generic_read(io, img, 0, size);
+
+ int track_count = pick_integer_le(img, 9, 2);
+
+ int pos = 0x0c;
+ int track_offset[track_count];
+ for(int track = 0; track < track_count; track++) {
+ track_offset[track] = pick_integer_le(img, pos, 4);
+ pos += 4;
+ }
+
+ int speed_zone_offset[track_count];
+ for(int track = 0; track < track_count; track++) {
+ speed_zone_offset[track] = pick_integer_le(img, pos, 4);
+ pos += 4;
+ }
+
+ for(int track = 0; track < track_count; track++) {
+ int track_size = 0;
+ pos = track_offset[track];
+ if (pos > 0) {
+ track_size = pick_integer_le(img, pos, 2);
+ pos +=2;
+ }
+
+ if (speed_zone_offset[track] > 3)
+ throw emu_fatalerror("g64_format: Unsupported variable speed zones on track %d", track);
+
+ UINT32 cell_size = c1541_cell_size[speed_zone_offset[track]];
+ int total_size = 200000000/cell_size;
+ UINT32 *buffer = global_alloc_array_clear(UINT32, total_size);
+ int offset = 0;
+
+ if (pos > 0) {
+ for (int i=0; i<track_size; i++) {
+ raw_w(buffer, offset, 8, img[pos++], cell_size);
+ }
+
+ if (offset >= total_size)
+ throw emu_fatalerror("g64_format: Too many cells for track %d", track);
+ }
+
+ generate_track_from_levels(track, 0, buffer, total_size, 0, image);
+ global_free(buffer);
+ }
+
+ image->set_variant(floppy_image::SSSD);
+
+ return true;
+}
+
+bool g64_format::save(io_generic *io, floppy_image *image)
+{
+ return false;
+}
+
+bool g64_format::supports_save() const
+{
+ return false;
+}
+
+const floppy_format_type FLOPPY_G64_FORMAT = &floppy_image_format_creator<g64_format>;
+
+
+// ------ LEGACY -----
+
+
/*********************************************************************
formats/g64_dsk.c
diff --git a/src/lib/formats/g64_dsk.h b/src/lib/formats/g64_dsk.h
index 287446a4b88..1a8365bd6d4 100644
--- a/src/lib/formats/g64_dsk.h
+++ b/src/lib/formats/g64_dsk.h
@@ -2,19 +2,37 @@
formats/g64_dsk.h
- Floppy format code for Commodore 1541 GCR disk images
+ Commodore 1541 GCR disk image format
*********************************************************************/
-#ifndef __G64_DSK__
-#define __G64_DSK__
+#ifndef G64_DSK_H_
+#define G64_DSK_H_
#include "flopimg.h"
+#include "imageutl.h"
-/***************************************************************************
- MACROS / CONSTANTS
-***************************************************************************/
+class g64_format : public floppy_image_format_t {
+public:
+ g64_format();
+ virtual const char *name() const;
+ virtual const char *description() const;
+ virtual const char *extensions() const;
+
+ virtual int identify(io_generic *io, UINT32 form_factor);
+ virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image);
+ virtual bool save(io_generic *io, floppy_image *image);
+ virtual bool supports_save() const;
+
+protected:
+ static const UINT32 c1541_cell_size[];
+};
+
+extern const floppy_format_type FLOPPY_G64_FORMAT;
+
+
+// legacy
#define G64_SYNC_MARK 0x3ff /* 10 consecutive 1-bits */
#define G64_BUFFER_SIZE 16384
@@ -36,10 +54,6 @@ const int C8050_BITRATE[] =
XTAL_12MHz/2/13 /* tracks 65-84 */
};
-/***************************************************************************
- PROTOTYPES
-***************************************************************************/
-
FLOPPY_IDENTIFY( g64_dsk_identify );
FLOPPY_CONSTRUCT( g64_dsk_construct );