Sync with MESS, OG work, credited there (no whatsnew)

This commit is contained in:
Miodrag Milanovic 2011-11-09 13:20:10 +00:00
parent c9fb7c59f8
commit c041a6eddc
6 changed files with 384 additions and 60 deletions

View File

@ -9,15 +9,50 @@
#include "formats/imageutl.h"
// device type definition
const device_type FLOPPY = &device_creator<floppy_image_device>;
const device_type FLOPPY_CONNECTOR = &device_creator<floppy_connector>;
const device_type FLOPPY_35_DD = &device_creator<floppy_35_dd>;
const device_type FLOPPY_35_HD = &device_creator<floppy_35_hd>;
const device_type FLOPPY_525_DD = &device_creator<floppy_525_dd>;
floppy_connector::floppy_connector(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
device_t(mconfig, FLOPPY_CONNECTOR, "Floppy drive connector abstraction", tag, owner, clock),
device_slot_interface(mconfig, *this)
{
}
floppy_connector::~floppy_connector()
{
}
void floppy_connector::set_formats(const floppy_format_type *_formats)
{
formats = _formats;
}
void floppy_connector::device_start()
{
}
void floppy_connector::device_config_complete()
{
floppy_image_device *dev = dynamic_cast<floppy_image_device *>(get_card_device());
if(dev)
dev->set_formats(formats);
}
floppy_image_device *floppy_connector::get_device()
{
return dynamic_cast<floppy_image_device *>(get_card_device());
}
//-------------------------------------------------
// floppy_image_device - constructor
//-------------------------------------------------
floppy_image_device::floppy_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, FLOPPY, "Floppy drive", tag, owner, clock),
floppy_image_device::floppy_image_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, type, name, tag, owner, clock),
device_image_interface(mconfig, *this),
device_slot_card_interface(mconfig, *this),
image(NULL)
{
}
@ -45,12 +80,8 @@ void floppy_image_device::setup_index_pulse_cb(index_pulse_cb cb)
cur_index_pulse_cb = cb;
}
void floppy_image_device::set_info(int _type, int _tracks, int _sides, const floppy_format_type *formats)
void floppy_image_device::set_formats(const floppy_format_type *formats)
{
type = _type;
tracks = _tracks;
sides = _sides;
image_device_format **formatptr;
image_device_format *format;
formatptr = &m_formatlist;
@ -103,6 +134,9 @@ void floppy_image_device::set_rpm(float _rpm)
void floppy_image_device::device_start()
{
rpm = 0;
setup_limits();
idx = 0;
/* motor off */
@ -110,9 +144,6 @@ void floppy_image_device::device_start()
/* set write protect on */
wpt = 0;
rpm = 0;
set_rpm(300);
cyl = 0;
ss = 1;
stp = 1;
@ -139,7 +170,6 @@ bool floppy_image_device::call_load()
io.file = (device_image_interface *)this;
io.procs = &image_ioprocs;
io.filler = 0xff;
int best = 0;
floppy_image_format_t *best_format = 0;
for(floppy_image_format_t *format = fif_list; format; format = format->next) {
@ -279,7 +309,7 @@ void floppy_image_device::stp_w(int state)
}
}
int floppy_image_device::find_position(int position, const UINT32 *buf, int buf_size)
int floppy_image_device::find_index(UINT32 position, const UINT32 *buf, int buf_size)
{
int spos = (buf_size >> 1)-1;
int step;
@ -298,6 +328,21 @@ int floppy_image_device::find_position(int position, const UINT32 *buf, int buf_
}
}
UINT32 floppy_image_device::find_position(attotime &base, attotime when)
{
base = revolution_start_time;
UINT32 revc = revolution_count;
attotime delta = when - base;
while(delta >= rev_time) {
delta -= rev_time;
base += rev_time;
revc++;
}
return (delta*(rpm/300)).as_ticks(1000000000);
}
attotime floppy_image_device::get_next_transition(attotime from_when)
{
if(!image || mon)
@ -307,24 +352,16 @@ attotime floppy_image_device::get_next_transition(attotime from_when)
if(cells <= 1)
return attotime::never;
attotime base = revolution_start_time;
UINT32 revc = revolution_count;
attotime delta = from_when - base;
while(delta >= rev_time) {
delta -= rev_time;
base += rev_time;
revc++;
}
int position = (delta*(rpm/300)).as_ticks(1000000000);
attotime base;
UINT32 position = find_position(base, from_when);
const UINT32 *buf = image->get_buffer(cyl, ss);
int index = find_position(position, buf, cells);
int index = find_index(position, buf, cells);
if(index == -1)
return attotime::never;
int next_position;
UINT32 next_position;
if(index < cells-1)
next_position = buf[index+1] & floppy_image::TIME_MASK;
else if((buf[index]^buf[0]) & floppy_image::MG_MASK)
@ -332,5 +369,206 @@ attotime floppy_image_device::get_next_transition(attotime from_when)
else
next_position = 200000000 + (buf[1] & floppy_image::TIME_MASK);
return base + attotime::from_nsec(next_position*(300/rpm));
}
void floppy_image_device::write_flux(attotime start, attotime end, int transition_count, const attotime *transitions)
{
attotime base;
int start_pos = find_position(base, start);
int end_pos = find_position(base, end);
int *trans_pos = transition_count ? global_alloc_array(int, transition_count) : 0;
for(int i=0; i != transition_count; i++)
trans_pos[i] = find_position(base, transitions[i]);
int cells = image->get_track_size(cyl, ss);
UINT32 *buf = image->get_buffer(cyl, ss);
int index;
if(cells)
index = find_index(start_pos, buf, cells);
else {
index = 0;
buf[cells++] = floppy_image::MG_N | 200000000;
}
if(index && (buf[index] & floppy_image::TIME_MASK) == start_pos)
index--;
UINT32 cur_mg = buf[index] & floppy_image::MG_MASK;
if(cur_mg == floppy_image::MG_N || cur_mg == floppy_image::MG_D)
cur_mg = floppy_image::MG_A;
UINT32 pos = start_pos;
int ti = 0;
while(pos != end_pos) {
UINT32 next_pos;
if(ti != transition_count)
next_pos = trans_pos[ti++];
else
next_pos = end_pos;
if(next_pos > pos)
write_zone(buf, cells, index, pos, next_pos, cur_mg);
else {
write_zone(buf, cells, index, pos, 200000000, cur_mg);
write_zone(buf, cells, index, 0, next_pos, cur_mg);
}
pos = next_pos;
cur_mg = cur_mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
}
image->set_track_size(cyl, ss, cells);
if(trans_pos)
global_free(trans_pos);
}
void floppy_image_device::write_zone(UINT32 *buf, int &cells, int &index, UINT32 spos, UINT32 epos, UINT32 mg)
{
while(spos < epos) {
while(index != cells-1 && (buf[index+1] & floppy_image::TIME_MASK) <= spos)
index++;
UINT32 ref_start = buf[index] & floppy_image::TIME_MASK;
UINT32 ref_end = index == cells-1 ? 200000000 : buf[index+1] & floppy_image::TIME_MASK;
UINT32 ref_mg = buf[index] & floppy_image::MG_MASK;
// Can't overwrite a damaged zone
if(ref_mg == floppy_image::MG_D) {
spos = ref_end;
continue;
}
// If the zone is of the type we want, we don't need to touch it
if(ref_mg == mg) {
spos = ref_end;
continue;
}
// Check the overlaps, act accordingly
if(spos == ref_start) {
if(epos >= ref_end) {
// Full overlap, that cell is dead, we need to see which ones we can extend
UINT32 prev_mg = index != 0 ? buf[index-1] & floppy_image::MG_MASK : ~0;
UINT32 next_mg = index != cells-1 ? buf[index+1] & floppy_image::MG_MASK : ~0;
if(prev_mg == mg) {
if(next_mg == mg) {
// Both match, merge all three in one
memmove(buf+index, buf+index+2, (cells-index-2)*sizeof(UINT32));
cells -= 2;
index--;
} else {
// Previous matches, drop the current cell
memmove(buf+index, buf+index+1, (cells-index-1)*sizeof(UINT32));
cells --;
}
} else {
if(next_mg == mg) {
// Following matches, extend it
memmove(buf+index, buf+index+1, (cells-index-1)*sizeof(UINT32));
cells --;
buf[index] = mg | spos;
} else {
// None match, convert the current cell
buf[index] = mg | spos;
index++;
}
}
spos = ref_end;
} else {
// Overlap at the start only
// Check if we can just extend the previous cell
if(index != 0 && (buf[index-1] & floppy_image::MG_MASK) == mg)
buf[index] = ref_mg | epos;
else {
// Otherwise we need to insert a new cell
if(index != cells-1)
memmove(buf+index+1, buf+index, (cells-index)*sizeof(UINT32));
cells++;
buf[index] = mg | spos;
buf[index+1] = ref_mg | epos;
}
spos = epos;
}
} else {
if(epos >= ref_end) {
// Overlap at the end only
// If we can't just extend the following cell, we need to insert a new one
if(index == cells-1 || (buf[index+1] & floppy_image::MG_MASK) != mg) {
if(index != cells-1)
memmove(buf+index+2, buf+index+1, (cells-index-1)*sizeof(UINT32));
cells++;
}
buf[index+1] = mg | spos;
index++;
spos = ref_end;
} else {
// Full inclusion
// We need to split the zone in 3
if(index != cells-1)
memmove(buf+index+3, buf+index+1, (cells-index-1)*sizeof(UINT32));
cells += 2;
buf[index+1] = mg | spos;
buf[index+2] = ref_mg | epos;
spos = epos;
}
}
}
}
floppy_35_dd::floppy_35_dd(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
floppy_image_device(mconfig, FLOPPY_35_DD, "3.5\" double density floppy drive", tag, owner, clock)
{
}
floppy_35_dd::~floppy_35_dd()
{
}
void floppy_35_dd::setup_limits()
{
tracks = 84;
sides = 2;
set_rpm(300);
}
floppy_35_hd::floppy_35_hd(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
floppy_image_device(mconfig, FLOPPY_35_HD, "3.5\" high density floppy drive", tag, owner, clock)
{
}
floppy_35_hd::~floppy_35_hd()
{
}
void floppy_35_hd::setup_limits()
{
tracks = 84;
sides = 2;
set_rpm(300);
}
floppy_525_dd::floppy_525_dd(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
floppy_image_device(mconfig, FLOPPY_525_DD, "3.5\" high density floppy drive", tag, owner, clock)
{
}
floppy_525_dd::~floppy_525_dd()
{
}
void floppy_525_dd::setup_limits()
{
tracks = 42;
sides = 1;
set_rpm(300);
}

View File

@ -9,33 +9,30 @@
#include "formats/flopimg.h"
#define MCFG_FLOPPY_DRIVE_ADD(_tag, _type, _tracks, _sides, _formats) \
MCFG_DEVICE_ADD(_tag, FLOPPY, 0) \
downcast<floppy_image_device *>(device)->set_info(_type, _tracks, _sides, _formats);
#define MCFG_FLOPPY_DRIVE_ADD(_tag, _slot_intf, _def_slot, _def_inp, _formats) \
MCFG_DEVICE_ADD(_tag, FLOPPY_CONNECTOR, 0) \
MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, _def_inp) \
static_cast<floppy_connector *>(device)->set_formats(_formats);
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
class floppy_image_device : public device_t,
public device_image_interface
public device_image_interface,
public device_slot_card_interface
{
public:
enum {
TYPE_35_SD, TYPE_35_DD, TYPE_35_HD, TYPE_35_ED,
TYPE_525_SD, TYPE_525_DD, TYPE_525_HD
};
typedef delegate<int (floppy_image_device *)> load_cb;
typedef delegate<void (floppy_image_device *)> unload_cb;
typedef delegate<void (floppy_image_device *, int)> index_pulse_cb;
// construction/destruction
floppy_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
floppy_image_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
virtual ~floppy_image_device();
void set_info(int type, int tracks, int sides, const floppy_format_type *formats);
void set_formats(const floppy_format_type *formats);
void set_rpm(float rpm);
// image-level overrides
@ -46,11 +43,11 @@ public:
virtual iodevice_t image_type() const { return IO_FLOPPY; }
virtual bool is_readable() const { return 1; }
virtual bool is_writeable() const { return 1; }
virtual bool is_creatable() const { return 0; }
virtual bool must_be_loaded() const { return 0; }
virtual bool is_reset_on_load() const { return 0; }
virtual bool is_readable() const { return true; }
virtual bool is_writeable() const { return true; }
virtual bool is_creatable() const { return true; }
virtual bool must_be_loaded() const { return false; }
virtual bool is_reset_on_load() const { return false; }
virtual const char *file_extensions() const { return extension_list; }
virtual const option_guide *create_option_guide() const { return NULL; }
@ -77,6 +74,7 @@ public:
void index_resync();
attotime time_next_index();
attotime get_next_transition(attotime from_when);
void write_flux(attotime start, attotime end, int transition_count, const attotime *transitions);
protected:
// device-level overrides
@ -85,14 +83,15 @@ protected:
virtual void device_reset();
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
virtual void setup_limits() = 0;
image_device_format format;
floppy_image *image;
char extension_list[256];
floppy_image_format_t *fif_list;
emu_timer *index_timer;
/* Physical characteristics */
int type; /* reader type */
/* Physical characteristics, filled by setup_limits */
int tracks; /* addressable tracks */
int sides; /* number of heads */
@ -120,10 +119,61 @@ protected:
unload_cb cur_unload_cb;
index_pulse_cb cur_index_pulse_cb;
int find_position(int position, const UINT32 *buf, int buf_size);
UINT32 find_position(attotime &base, attotime when);
int find_index(UINT32 position, const UINT32 *buf, int buf_size);
void write_zone(UINT32 *buf, int &cells, int &index, UINT32 spos, UINT32 epos, UINT32 mg);
};
class floppy_35_dd : public floppy_image_device {
public:
floppy_35_dd(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
virtual ~floppy_35_dd();
protected:
virtual void setup_limits();
};
class floppy_35_hd : public floppy_image_device {
public:
floppy_35_hd(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
virtual ~floppy_35_hd();
protected:
virtual void setup_limits();
};
class floppy_525_dd : public floppy_image_device {
public:
floppy_525_dd(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
virtual ~floppy_525_dd();
protected:
virtual void setup_limits();
};
class floppy_connector: public device_t,
public device_slot_interface
{
public:
floppy_connector(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
virtual ~floppy_connector();
void set_formats(const floppy_format_type *formats);
floppy_image_device *get_device();
protected:
virtual void device_start();
virtual void device_config_complete();
private:
const floppy_format_type *formats;
};
// device type definition
extern const device_type FLOPPY;
extern const device_type FLOPPY_CONNECTOR;
extern const device_type FLOPPY_35_DD;
extern const device_type FLOPPY_35_HD;
extern const device_type FLOPPY_525_DD;
#endif /* FLOPPY_H */

View File

@ -4,7 +4,7 @@
We do not support diff files as it will involve some changes in
the image code. Additionally, the need for diff files comes
from MAME's need for "cannonical" hard drive images.
from MAME's need for "canonical" hard drive images.
Raphael Nabet 2003

View File

@ -29,10 +29,15 @@ amiga_fdc::amiga_fdc(const machine_config &mconfig, const char *tag, device_t *o
void amiga_fdc::device_start()
{
floppy_devices[0] = machine().device<floppy_image_device>("fd0");
floppy_devices[1] = machine().device<floppy_image_device>("fd1");
floppy_devices[2] = machine().device<floppy_image_device>("fd2");
floppy_devices[3] = machine().device<floppy_image_device>("fd3");
static const char *names[] = { "fd0", "fd1", "fd2", "fd3" };
for(int i=0; i != 4; i++) {
floppy_connector *con = machine().device<floppy_connector>(names[i]);
if(con)
floppy_devices[i] = con->get_device();
else
floppy_devices[i] = 0;
}
floppy = 0;
t_gen = timer_alloc(0);
@ -82,7 +87,8 @@ void amiga_fdc::rollback()
void amiga_fdc::live_delay(int state)
{
cur_live.next_state = state;
t_gen->adjust(cur_live.tm - machine().time());
if(cur_live.tm != machine().time())
t_gen->adjust(cur_live.tm - machine().time());
}
void amiga_fdc::live_sync()
@ -91,13 +97,15 @@ void amiga_fdc::live_sync()
if(cur_live.tm > machine().time()) {
rollback();
live_run(machine().time());
} else {
if(cur_live.next_state != -1)
}
if(cur_live.tm == machine().time()) {
if(cur_live.next_state != -1) {
cur_live.state = cur_live.next_state;
cur_live.next_state = -1;
}
if(cur_live.state == IDLE)
cur_live.tm = attotime::never;
}
cur_live.next_state = -1;
checkpoint();
}
}
@ -120,12 +128,21 @@ void amiga_fdc::live_run(attotime limit)
int bit = cur_live.pll.get_next_bit(cur_live.tm, floppy, limit);
if(bit < 0)
return;
cur_live.shift_reg = (cur_live.shift_reg << 1) | bit;
cur_live.bit_counter++;
if((adkcon & 0x0200) && !(cur_live.shift_reg & 0x80))
if((adkcon & 0x0200) && !(cur_live.shift_reg & 0x80)) {
cur_live.bit_counter--;
// Avoid any risk of livelock
live_delay(RUNNING_SYNCPOINT);
return;
}
if(cur_live.bit_counter > 8)
abort();
if(cur_live.bit_counter == 8) {
live_delay(RUNNING_SYNCPOINT);
return;
@ -147,10 +164,11 @@ void amiga_fdc::live_run(attotime limit)
case RUNNING_SYNCPOINT: {
if(cur_live.shift_reg == dsksync) {
if(adkcon & 0x0400) {
if(dma_state == DMA_WAIT_START)
if(dma_state == DMA_WAIT_START) {
dma_state = DMA_RUNNING_BYTE_0;
cur_live.bit_counter = 0;
cur_live.bit_counter = 0;
} else if(cur_live.bit_counter != 8)
cur_live.bit_counter = 0;
}
dskbyt |= 0x0400;
address_space *space = machine().device("maincpu")->memory().space(AS_PROGRAM);
@ -218,6 +236,7 @@ void amiga_fdc::adkcon_set(UINT16 data)
{
live_sync();
adkcon = data;
live_run();
}
void amiga_fdc::dsklen_w(UINT16 data)
@ -234,18 +253,21 @@ void amiga_fdc::dsklen_w(UINT16 data)
dskbyt |= 0x4000;
} else
pre_dsklen = data;
live_run();
}
void amiga_fdc::dskpth_w(UINT16 data)
{
live_sync();
dskpt = (dskpt & 0xffff) | (data << 16);
live_run();
}
void amiga_fdc::dskptl_w(UINT16 data)
{
live_sync();
dskpt = (dskpt & 0xffff0000) | data;
live_run();
}
UINT16 amiga_fdc::dskpth_r()
@ -262,6 +284,7 @@ void amiga_fdc::dsksync_w(UINT16 data)
{
live_sync();
dsksync = data;
live_run();
}
void amiga_fdc::dmacon_set(UINT16 data)
@ -272,6 +295,7 @@ void amiga_fdc::dmacon_set(UINT16 data)
dskbyt = dskbyt & 0xbfff;
if(dma_state != DMA_IDLE)
dskbyt |= 0x4000;
live_run();
}
UINT16 amiga_fdc::dskbytr_r()
@ -306,6 +330,8 @@ void amiga_fdc::setup_leds()
WRITE8_MEMBER( amiga_fdc::ciaaprb_w )
{
floppy_image_device *old_floppy = floppy;
live_sync();
if(!(data & 0x08))
@ -319,6 +345,13 @@ WRITE8_MEMBER( amiga_fdc::ciaaprb_w )
else
floppy = 0;
if(old_floppy != floppy) {
if(old_floppy)
old_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb());
if(floppy)
floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(FUNC(amiga_fdc::index_callback), this));
}
if(floppy) {
floppy->ss_w(!((data >> 2) & 1));
floppy->dir_w((data >> 1) & 1);
@ -333,6 +366,7 @@ WRITE8_MEMBER( amiga_fdc::ciaaprb_w )
live_abort();
setup_leds();
live_run();
}
UINT8 amiga_fdc::ciaapra_r()

View File

@ -739,6 +739,8 @@ static void start_handler(void *data, const char *tagname, const char **attribut
romflags = ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2);
else if ( str_loadflag && !strcmp(str_loadflag, "load32_word") )
romflags = ROM_GROUPWORD | ROM_SKIP(2);
else if ( str_loadflag && !strcmp(str_loadflag, "load32_byte") )
romflags = ROM_SKIP(3);
/* ROM_LOAD( name, offset, length, hash ) */
add_rom_entry( swlist, s_name, hashdata, offset, length, ROMENTRYTYPE_ROM | romflags );

View File

@ -447,7 +447,7 @@ void ipf_format::track_write_mfm(UINT32 *&track, const UINT8 *data, UINT32 start
void ipf_format::track_write_weak(UINT32 *&track, UINT32 cells)
{
for(UINT32 i=0; i != cells; i++)
*track++ = MG_W;
*track++ = floppy_image::MG_N;
}
bool ipf_format::generate_block_data(const UINT8 *data, const UINT8 *dlimit, UINT32 *track, UINT32 *tlimit, bool &context)