mirror of
https://github.com/holub/mame
synced 2025-04-20 23:42:22 +03:00
(MESS) flopimg: Added support for Commodore GCR encoding. [Curt Coder]
(MESS) d64/g64 floppy modernization WIP. (nw)
This commit is contained in:
parent
408b15043d
commit
cf41f05d4b
@ -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 ¤t_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];
|
||||
|
@ -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 ¤t_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 );
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 );
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user