(MESS) flopimg: Added support for Commodore GCR encoding. [Curt Coder]

(MESS) d64/g64 floppy modernization WIP. (nw)
This commit is contained in:
Curt Coder 2013-01-14 16:27:52 +00:00
parent 408b15043d
commit cf41f05d4b
6 changed files with 695 additions and 18 deletions

View File

@ -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];

View File

@ -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 );

View File

@ -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,

View File

@ -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);

View File

@ -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

View File

@ -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 );