(MESS) c1581: Modernized floppy, WIP. (nw)

This commit is contained in:
Curt Coder 2012-12-14 17:30:42 +00:00
parent 0e904825d4
commit e759cbccab
9 changed files with 416 additions and 307 deletions

View File

@ -935,6 +935,32 @@ READ8_MEMBER( mos6526_device::read )
return data;
}
READ8_MEMBER( mos8520_device::read )
{
UINT8 data = 0;
switch (offset)
{
case TOD_MIN:
if (!m_tod_latched)
{
m_tod_latched = true;
m_tod_latch = m_tod;
}
data = read_tod(2);
break;
case TOD_HR:
data = read_tod(3);
break;
default:
data = mos6526_device::read(space, offset);
}
return data;
}
//-------------------------------------------------
// write -
@ -1070,6 +1096,25 @@ WRITE8_MEMBER( mos6526_device::write )
}
}
WRITE8_MEMBER( mos8520_device::write )
{
switch (offset)
{
default:
mos6526_device::write(space, offset, data);
break;
case TOD_MIN:
m_tod_stopped = true;
write_tod(2, data);
break;
case TOD_HR:
write_tod(3, data);
break;
}
}
//-------------------------------------------------
// pa_r - port A read

View File

@ -247,8 +247,8 @@ class mos8520_device : public mos6526_device
public:
mos8520_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
//DECLARE_READ8_MEMBER( read );
//DECLARE_WRITE8_MEMBER( write );
DECLARE_READ8_MEMBER( read );
DECLARE_WRITE8_MEMBER( write );
protected:
inline void clock_tod();

View File

@ -1,32 +1,69 @@
/***************************************************************************
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/d81_dsk.c
Floppy format code for Commodore 1581 disk images
Commodore 1581 disk image format
*********************************************************************/
#include "basicdsk.h"
#include "d81_dsk.h"
/***************************************************************************
PARAMETERS
***************************************************************************/
#define D81_SIZE 819200
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
/*-------------------------------------------------
d81_translate_offset - translates the
physical offset to a logical offset within
the disk image
-------------------------------------------------*/
/*
PER TRACK ORGANIZATION:
Hex 4E written as a gap, with 10 sectors of data, with full gaps written for motor speed variation.
PER SECTOR ORGANIZATION:
MFM Encoding
12 Bytes of Hex 00
3 Bytes of Hex A1 (Data Hex A1, Clock Hex 0A)
1 Byte of Hex FE (ID Address Mark)
1 Byte (Track Number)
1 Byte (Side Number)
1 Byte (Sector Number)
1 Byte (Sector Length, 02 for 512 Byte Sectors)
2 Bytes CRC (Cyclic Redundancy Check)
22 Bytes of Hex 22
12 Bytes of Hex 00
3 Bytes of Hex A1 (Data Hex A1, Clock Hex 0A)
1 Byte of Hex FB (Data Address Mark)
512 Bytes of Data
2 Bytes of CRC (Cyclic Redundancy Check)
38 Bytes of Hex 4E
file offset | CBM logical | drive physical | specials
decimal sedecimal | track/sector | cyl head sec offs |
------------------+--------------+-------------------+--------------
@ -67,65 +104,107 @@
*/
static UINT64 d81_translate_offset(floppy_image_legacy *floppy, const struct basicdsk_geometry *geom, int track, int head, int sector)
{
UINT64 offset = (track * 20) + (!head * 10) + sector;
#include "emu.h"
#include "formats/d81_dsk.h"
return offset;
d81_format::d81_format() : wd177x_format(formats)
{
}
/*-------------------------------------------------
FLOPPY_IDENTIFY( d81_dsk_identify )
-------------------------------------------------*/
FLOPPY_IDENTIFY( d81_dsk_identify )
const char *d81_format::name() const
{
*vote = (floppy_image_size(floppy) == D81_SIZE) ? 100 : 0;
return FLOPPY_ERROR_SUCCESS;
return "d81";
}
/*-------------------------------------------------
FLOPPY_CONSTRUCT( d81_dsk_construct )
-------------------------------------------------*/
/*
PER TRACK ORGANIZATION:
Hex 4E written as a gap, with 10 sectors of data, with full gaps written for motor speed variation.
PER SECTOR ORGANIZATION:
MFM Encoding
12 Bytes of Hex 00
3 Bytes of Hex A1 (Data Hex A1, Clock Hex 0A)
1 Byte of Hex FE (ID Address Mark)
1 Byte (Track Number)
1 Byte (Side Number)
1 Byte (Sector Number)
1 Byte (Sector Length, 02 for 512 Byte Sectors)
2 Bytes CRC (Cyclic Redundancy Check)
22 Bytes of Hex 22
12 Bytes of Hex 00
3 Bytes of Hex A1 (Data Hex A1, Clock Hex 0A)
1 Byte of Hex FB (Data Address Mark)
512 Bytes of Data
2 Bytes of CRC (Cyclic Redundancy Check)
38 Bytes of Hex 4E
*/
FLOPPY_CONSTRUCT( d81_dsk_construct )
const char *d81_format::description() const
{
struct basicdsk_geometry geometry;
memset(&geometry, 0, sizeof(geometry));
geometry.heads = 2;
geometry.first_sector_id = 1;
geometry.sector_length = 512;
geometry.tracks = 80;
geometry.sectors = 10;
geometry.translate_offset = d81_translate_offset;
return basicdsk_construct(floppy, &geometry);
return "Commodore 1581 disk image";
}
const char *d81_format::extensions() const
{
return "d81";
}
// Unverified gap sizes
const d81_format::format d81_format::formats[] = {
{
floppy_image::FF_35, floppy_image::DSDD,
2000, 10, 80, 2, 512, {}, 1, {}, 32, 22, 35
},
{}
};
bool d81_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];
floppy_image_format_t::desc_e desc[] = {
/* 00 */ { MFM, 0x4e, f.gap_1 },
/* 01 */ { SECTOR_LOOP_START, 0, f.sector_count-1 },
/* 02 */ { MFM, 0x00, 12 },
/* 03 */ { CRC_CCITT_START, 1 },
/* 04 */ { RAW, 0x4489, 3 },
/* 05 */ { MFM, 0xfe, 1 },
/* 06 */ { TRACK_ID },
/* 07 */ { HEAD_ID_SWAP },
/* 08 */ { SECTOR_ID },
/* 09 */ { SIZE_ID },
/* 10 */ { CRC_END, 1 },
/* 11 */ { CRC, 1 },
/* 12 */ { MFM, 0x4e, f.gap_2 },
/* 13 */ { MFM, 0x00, 12 },
/* 14 */ { CRC_CCITT_START, 2 },
/* 15 */ { RAW, 0x4489, 3 },
/* 16 */ { MFM, 0xfb, 1 },
/* 17 */ { SECTOR_DATA, -1 },
/* 18 */ { CRC_END, 2 },
/* 19 */ { CRC, 2 },
/* 20 */ { MFM, 0x4e, f.gap_3 },
/* 21 */ { SECTOR_LOOP_END },
/* 22 */ { MFM, 0x4e, 0 },
/* 23 */ { RAWBITS, 0x9254, 0 },
/* 24 */ { END }
};
int current_size = f.gap_1*16;
if(f.sector_base_size)
current_size += f.sector_base_size * f.sector_count * 16;
else {
for(int j=0; j != f.sector_count; j++)
current_size += f.per_sector_size[j] * 16;
}
current_size += (12+3+1+4+2+f.gap_2+12+3+1+2+f.gap_3) * f.sector_count * 16;
int total_size = 200000000/f.cell_size;
int remaining_size = total_size - current_size;
if(remaining_size < 0)
throw emu_fatalerror("d81_format: Incorrect track layout, max_size=%d, current_size=%d", total_size, current_size);
// Fixup the end gap
desc[22].p2 = remaining_size / 16;
desc[23].p2 = remaining_size & 15;
desc[23].p1 >>= 16-(remaining_size & 15);
int track_size = compute_track_size(f);
UINT8 sectdata[40*512];
desc_s sectors[40];
build_sector_description(f, sectdata, sectors);
for(int track=0; track < f.track_count; track++)
for(int head=0; head < f.head_count; head++) {
io_generic_read(io, sectdata, (track*f.head_count + !head)*track_size, track_size);
generate_track(desc, track, head, sectors, f.sector_count, total_size, image);
}
image->set_variant(f.variant);
return true;
}
const floppy_format_type FLOPPY_D81_FORMAT = &floppy_image_format_creator<d81_format>;

View File

@ -2,20 +2,29 @@
formats/d81_dsk.h
Floppy format code for Commodore 1581 disk images
Commodore 1581 disk image format
*********************************************************************/
#ifndef __D81_DSK__
#define __D81_DSK__
#ifndef D81_DSK_H_
#define D81_DSK_H_
#include "flopimg.h"
#include "wd177x_dsk.h"
/***************************************************************************
PROTOTYPES
***************************************************************************/
class d81_format : public wd177x_format {
public:
d81_format();
FLOPPY_IDENTIFY( d81_dsk_identify );
FLOPPY_CONSTRUCT( d81_dsk_construct );
virtual const char *name() const;
virtual const char *description() const;
virtual const char *extensions() const;
virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image);
private:
static const format formats[];
};
extern const floppy_format_type FLOPPY_D81_FORMAT;
#endif

View File

@ -1369,6 +1369,10 @@ void floppy_image_format_t::generate_track(const desc_e *desc, int track, int he
mfm_w(buffer, offset, 8, head);
break;
case HEAD_ID_SWAP:
mfm_w(buffer, offset, 8, !head);
break;
case TRACK_HEAD_ID_GCR6:
raw_w(buffer, offset, 8, gcr6fw_tb[(track & 0x40 ? 1 : 0) | (head ? 0x20 : 0)]);
break;

View File

@ -308,6 +308,7 @@ protected:
TRACK_ID, //!< Track id byte, mfm-encoded
TRACK_ID_GCR6, //!< Track id low 6 bits, gcr6-encoded
HEAD_ID, //!< Head id byte, mfm-encoded
HEAD_ID_SWAP, //!< Head id byte swapped (0->1, 1->0), mfm-encoded
TRACK_HEAD_ID_GCR6, //!< Track id 7th bit + head, gc6-encoded
SECTOR_ID, //!< Sector id byte, mfm-encoded
SECTOR_ID_GCR6, //!< Sector id byte, gcr6-encoded

View File

@ -39,7 +39,7 @@ public:
virtual bool save(io_generic *io, floppy_image *image);
virtual bool supports_save() const;
private:
protected:
const format *formats;
int find_size(io_generic *io, UINT32 form_factor);
int compute_track_size(const format &f) const;

View File

@ -7,6 +7,14 @@
**********************************************************************/
/*
TODO:
- wd_fdc drops the busy bit too soon, c1581 aborts reading the sector ID after the first CRC byte @CD17
*/
#include "c1581.h"
@ -17,7 +25,7 @@
#define M6502_TAG "u1"
#define M8520_TAG "u5"
#define WD1770_TAG "u4"
#define WD1772_TAG "u4"
enum
@ -64,7 +72,7 @@ void base_c1581_device::device_config_complete()
ROM_START( c1581 )
ROM_REGION( 0x8000, M6502_TAG, 0 )
ROM_DEFAULT_BIOS("r2")
ROM_DEFAULT_BIOS("r1")
ROM_SYSTEM_BIOS( 0, "beta", "Beta" )
ROMX_LOAD( "beta.u2", 0x0000, 0x8000, CRC(ecc223cd) SHA1(a331d0d46ead1f0275b4ca594f87c6694d9d9594), ROM_BIOS(1) )
ROM_SYSTEM_BIOS( 1, "r1", "Revision 1" )
@ -109,9 +117,9 @@ const rom_entry *base_c1581_device::device_rom_region() const
//-------------------------------------------------
static ADDRESS_MAP_START( c1581_mem, AS_PROGRAM, 8, base_c1581_device )
AM_RANGE(0x0000, 0x1fff) AM_MIRROR(0x2000) AM_RAM
AM_RANGE(0x0000, 0x1fff) AM_RAM
AM_RANGE(0x4000, 0x400f) AM_MIRROR(0x1ff0) AM_DEVREADWRITE(M8520_TAG, mos8520_device, read, write)
AM_RANGE(0x6000, 0x6003) AM_MIRROR(0x1ffc) AM_DEVREADWRITE_LEGACY(WD1770_TAG, wd17xx_r, wd17xx_w)
AM_RANGE(0x6000, 0x6003) AM_MIRROR(0x1ffc) AM_DEVREADWRITE(WD1772_TAG, wd1772_t, read, write)
AM_RANGE(0x8000, 0xffff) AM_ROM AM_REGION(M6502_TAG, 0)
ADDRESS_MAP_END
@ -122,18 +130,16 @@ ADDRESS_MAP_END
WRITE_LINE_MEMBER( base_c1581_device::cnt_w )
{
// fast serial clock out
m_cnt_out = state;
set_iec_srq();
update_iec();
}
WRITE_LINE_MEMBER( base_c1581_device::sp_w )
{
// fast serial data out
m_sp_out = state;
set_iec_data();
update_iec();
}
READ8_MEMBER( base_c1581_device::cia_pa_r )
@ -156,13 +162,13 @@ READ8_MEMBER( base_c1581_device::cia_pa_r )
UINT8 data = 0;
// ready
data |= !(floppy_drive_get_flag_state(m_image, FLOPPY_DRIVE_READY) == FLOPPY_DRIVE_READY) << 1;
data |= !m_floppy->ready_r() << 1;
// device number
data |= (m_address - 8) << 3;
// disk change
data |= floppy_dskchg_r(m_image) << 7;
data |= m_floppy->dskchg_r() << 7;
return data;
}
@ -184,13 +190,11 @@ WRITE8_MEMBER( base_c1581_device::cia_pa_w )
*/
// side 0
wd17xx_set_side(m_fdc, !BIT(data, 0));
// side select
m_floppy->ss_w(BIT(data, 0));
// motor
int motor = BIT(data, 2);
floppy_mon_w(m_image, motor);
floppy_drive_set_ready_state(m_image, !motor, 1);
m_floppy->mon_w(BIT(data, 2));
// power led
output_set_led_value(LED_POWER, BIT(data, 5));
@ -225,7 +229,7 @@ READ8_MEMBER( base_c1581_device::cia_pb_r )
data |= !m_bus->clk_r() << 2;
// write protect
data |= !floppy_wpt_r(m_image) << 6;
data |= !m_floppy->wpt_r() << 6;
// attention in
data |= !m_bus->atn_r() << 7;
@ -260,18 +264,9 @@ WRITE8_MEMBER( base_c1581_device::cia_pb_w )
m_atn_ack = BIT(data, 4);
// fast serial direction
int fast_ser_dir = BIT(data, 5);
m_fast_ser_dir = BIT(data, 5);
if (m_fast_ser_dir != fast_ser_dir)
{
m_fast_ser_dir = fast_ser_dir;
set_iec_data();
set_iec_srq();
m_cia->cnt_w(m_fast_ser_dir || m_bus->srq_r());
m_cia->sp_w(m_fast_ser_dir || m_bus->data_r());
}
update_iec();
}
static MOS8520_INTERFACE( cia_intf )
@ -288,43 +283,21 @@ static MOS8520_INTERFACE( cia_intf )
//-------------------------------------------------
// wd17xx_interface fdc_intf
// SLOT_INTERFACE( c1581_floppies )
//-------------------------------------------------
static const wd17xx_interface fdc_intf =
{
DEVCB_LINE_GND,
DEVCB_NULL,
DEVCB_NULL,
{ FLOPPY_0, NULL, NULL, NULL }
};
static SLOT_INTERFACE_START( c1581_floppies )
SLOT_INTERFACE( "35dd", FLOPPY_35_DD ) // Chinon F-354-E
SLOT_INTERFACE_END
//-------------------------------------------------
// LEGACY_FLOPPY_OPTIONS( c1581 )
// FLOPPY_FORMATS( c1581_device::floppy_formats )
//-------------------------------------------------
static LEGACY_FLOPPY_OPTIONS_START( c1581 )
LEGACY_FLOPPY_OPTION( c1581, "d81", "Commodore 1581 Disk Image", d81_dsk_identify, d81_dsk_construct, NULL, NULL )
LEGACY_FLOPPY_OPTIONS_END
//-------------------------------------------------
// floppy_interface c1581_floppy_interface
//-------------------------------------------------
static const floppy_interface c1581_floppy_interface =
{
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
FLOPPY_STANDARD_3_5_DSDD,
LEGACY_FLOPPY_OPTIONS_NAME(c1581),
"floppy_3_5",
NULL
};
FLOPPY_FORMATS_MEMBER( base_c1581_device::floppy_formats )
FLOPPY_D81_FORMAT
FLOPPY_FORMATS_END
//-------------------------------------------------
@ -336,9 +309,9 @@ static MACHINE_CONFIG_FRAGMENT( c1581 )
MCFG_CPU_PROGRAM_MAP(c1581_mem)
MCFG_MOS8520_ADD(M8520_TAG, XTAL_16MHz/8, 0, cia_intf)
MCFG_WD1770_ADD(WD1770_TAG, /*XTAL_16MHz/2,*/ fdc_intf)
MCFG_WD1772x_ADD(WD1772_TAG, XTAL_16MHz/2)
MCFG_LEGACY_FLOPPY_DRIVE_ADD(FLOPPY_0, c1581_floppy_interface)
MCFG_FLOPPY_DRIVE_ADD(WD1772_TAG":0", c1581_floppies, "35dd", 0, base_c1581_device::floppy_formats)
MACHINE_CONFIG_END
@ -354,42 +327,6 @@ machine_config_constructor base_c1581_device::device_mconfig_additions() const
//**************************************************************************
// INLINE HELPERS
//**************************************************************************
//-------------------------------------------------
// base_c1581_device - constructor
//-------------------------------------------------
inline void base_c1581_device::set_iec_data()
{
int atn = m_bus->atn_r();
int data = !m_data_out && !(m_atn_ack && !atn);
// fast serial data
if (m_fast_ser_dir) data &= m_sp_out;
m_bus->data_w(this, data);
}
//-------------------------------------------------
// base_c1581_device - constructor
//-------------------------------------------------
inline void base_c1581_device::set_iec_srq()
{
int srq = 1;
// fast serial clock
if (m_fast_ser_dir) srq &= m_cnt_out;
m_bus->srq_w(this, srq);
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@ -403,8 +340,13 @@ base_c1581_device::base_c1581_device(const machine_config &mconfig, device_type
device_cbm_iec_interface(mconfig, *this),
m_maincpu(*this, M6502_TAG),
m_cia(*this, M8520_TAG),
m_fdc(*this, WD1770_TAG),
m_image(*this, FLOPPY_0),
m_fdc(*this, WD1772_TAG),
m_floppy(*this, WD1772_TAG":0:35dd"),
m_data_out(0),
m_atn_ack(0),
m_fast_ser_dir(0),
m_sp_out(1),
m_cnt_out(1),
m_variant(variant)
{
}
@ -450,12 +392,15 @@ void base_c1581_device::device_reset()
m_maincpu->reset();
m_cia->reset();
m_fdc->reset();
wd17xx_mr_w(m_fdc, 0);
wd17xx_mr_w(m_fdc, 1);
m_fdc->set_floppy(m_floppy);
m_fdc->dden_w(0);
m_sp_out = 1;
m_cnt_out = 1;
update_iec();
}
@ -465,7 +410,7 @@ void base_c1581_device::device_reset()
void base_c1581_device::cbm_iec_srq(int state)
{
m_cia->cnt_w(m_fast_ser_dir || state);
update_iec();
}
@ -475,9 +420,7 @@ void base_c1581_device::cbm_iec_srq(int state)
void base_c1581_device::cbm_iec_atn(int state)
{
m_cia->flag_w(state);
set_iec_data();
update_iec();
}
@ -487,7 +430,7 @@ void base_c1581_device::cbm_iec_atn(int state)
void base_c1581_device::cbm_iec_data(int state)
{
m_cia->sp_w(m_fast_ser_dir || state);
update_iec();
}
@ -502,3 +445,31 @@ void base_c1581_device::cbm_iec_reset(int state)
device_reset();
}
}
//-------------------------------------------------
// update_iec -
//-------------------------------------------------
void base_c1581_device::update_iec()
{
int atn = m_bus->atn_r();
m_cia->cnt_w(m_fast_ser_dir || m_bus->srq_r());
m_cia->sp_w(m_fast_ser_dir || m_bus->data_r());
m_cia->flag_w(atn);
// serial data
int data = !m_data_out && !(m_atn_ack && !atn);
if (m_fast_ser_dir) data &= m_sp_out;
m_bus->data_w(this, data);
// fast clock
int srq = 1;
if (m_fast_ser_dir) srq &= m_cnt_out;
m_bus->srq_w(this, srq);
}

View File

@ -15,11 +15,10 @@
#include "emu.h"
#include "cpu/m6502/m6502.h"
#include "imagedev/flopdrv.h"
#include "formats/d81_dsk.h"
#include "machine/cbmiec.h"
#include "machine/mos6526.h"
#include "machine/wd17xx.h"
#include "machine/wd_fdc.h"
@ -63,6 +62,8 @@ public:
DECLARE_READ8_MEMBER( cia_pb_r );
DECLARE_WRITE8_MEMBER( cia_pb_w );
DECLARE_FLOPPY_FORMATS( floppy_formats );
protected:
// device-level overrides
virtual void device_config_complete();
@ -75,13 +76,12 @@ protected:
virtual void cbm_iec_data(int state);
virtual void cbm_iec_reset(int state);
inline void set_iec_data();
inline void set_iec_srq();
void update_iec();
required_device<cpu_device> m_maincpu;
required_device<mos6526_device> m_cia;
required_device<wd1770_device> m_fdc;
required_device<legacy_floppy_image_device> m_image;
required_device<wd1772_t> m_fdc;
required_device<floppy_image_device> m_floppy;
int m_data_out; // serial data out
int m_atn_ack; // attention acknowledge