diff --git a/src/emu/imagedev/floppy.c b/src/emu/imagedev/floppy.c index 725e7681f9d..7348dd0a7cc 100644 --- a/src/emu/imagedev/floppy.c +++ b/src/emu/imagedev/floppy.c @@ -9,15 +9,50 @@ #include "formats/imageutl.h" // device type definition -const device_type FLOPPY = &device_creator; +const device_type FLOPPY_CONNECTOR = &device_creator; +const device_type FLOPPY_35_DD = &device_creator; +const device_type FLOPPY_35_HD = &device_creator; +const device_type FLOPPY_525_DD = &device_creator; + +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(get_card_device()); + if(dev) + dev->set_formats(formats); +} + +floppy_image_device *floppy_connector::get_device() +{ + return dynamic_cast(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); +} diff --git a/src/emu/imagedev/floppy.h b/src/emu/imagedev/floppy.h index de0a1f4017f..c4c0d2702b4 100644 --- a/src/emu/imagedev/floppy.h +++ b/src/emu/imagedev/floppy.h @@ -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(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(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 load_cb; typedef delegate unload_cb; typedef delegate 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 */ diff --git a/src/emu/imagedev/harddriv.c b/src/emu/imagedev/harddriv.c index 19ec4128a5e..6f3c6c7b0a8 100644 --- a/src/emu/imagedev/harddriv.c +++ b/src/emu/imagedev/harddriv.c @@ -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 diff --git a/src/emu/machine/amigafdc.c b/src/emu/machine/amigafdc.c index 8312ace7a7d..52d5e793c8d 100644 --- a/src/emu/machine/amigafdc.c +++ b/src/emu/machine/amigafdc.c @@ -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("fd0"); - floppy_devices[1] = machine().device("fd1"); - floppy_devices[2] = machine().device("fd2"); - floppy_devices[3] = machine().device("fd3"); + static const char *names[] = { "fd0", "fd1", "fd2", "fd3" }; + for(int i=0; i != 4; i++) { + floppy_connector *con = machine().device(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() diff --git a/src/emu/softlist.c b/src/emu/softlist.c index 157c6d1e4fa..6fd48b5bb76 100644 --- a/src/emu/softlist.c +++ b/src/emu/softlist.c @@ -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 ); diff --git a/src/lib/formats/ipf_dsk.c b/src/lib/formats/ipf_dsk.c index db17bcc550e..25a08136952 100644 --- a/src/lib/formats/ipf_dsk.c +++ b/src/lib/formats/ipf_dsk.c @@ -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)