diff options
Diffstat (limited to 'src/devices/machine/amigafdc.cpp')
-rw-r--r-- | src/devices/machine/amigafdc.cpp | 102 |
1 files changed, 47 insertions, 55 deletions
diff --git a/src/devices/machine/amigafdc.cpp b/src/devices/machine/amigafdc.cpp index ad83a268039..662a80dffe4 100644 --- a/src/devices/machine/amigafdc.cpp +++ b/src/devices/machine/amigafdc.cpp @@ -1,10 +1,29 @@ // license:BSD-3-Clause // copyright-holders:Olivier Galibert -/*************************************************************************** +/************************************************************************************************** - Amiga floppy disk controller emulation + Amiga floppy disk controller emulation "Trackdisk" -***************************************************************************/ + Contained inside MOS 8364 Paula device + + TODO: + - Some games currently writes 2+ dsksync to the buffer (marked as "[FDC] dsksync" in SW list): + Current workaround: + 1. comment out dma_write in DMA_WAIT_START handling and change the dma_state *only*; + 2. remove all of the non-DMA_WAIT_START phase inside the dsksync sub-section; + NB: according to documentation syncing doesn't really write anything on the bus, + so technically this "workaround" is more correct. + However it unfortunately causes other SW regressions, most notably in Workbench. + - Other games trashes memory or refuses to boot, in a few instances randomly + (marked as "[FDC] with adkcon=1100", implies dsksync disabled): + they often uses the AmigaDOS trackdisk BIOS functions, which may be expecting a + different timing. May be worth testing this out with the SDK; + - "[FDC] format" or in general writing to disks doesn't work properly. + i.e. formatting a disk in any Workbench version will cause a system crash once it completes. + - Fix ready line read handling; + - FDC LED output callback; + +**************************************************************************************************/ #include "emu.h" @@ -24,7 +43,7 @@ #define LOGDMA(...) LOGMASKED(LOG_DMA, __VA_ARGS__) #define LOGSYNC(...) LOGMASKED(LOG_SYNC, __VA_ARGS__) -DEFINE_DEVICE_TYPE(AMIGA_FDC, amiga_fdc_device, "amiga_fdc", "Amiga FDC") +DEFINE_DEVICE_TYPE(AMIGA_FDC, amiga_fdc_device, "amiga_fdc", "Amiga \"Trackdisk\" FDC") void amiga_fdc_device::floppy_formats(format_registration &fr) { @@ -33,26 +52,21 @@ void amiga_fdc_device::floppy_formats(format_registration &fr) fr.add(FLOPPY_IPF_FORMAT); } -amiga_fdc_device::amiga_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, AMIGA_FDC, tag, owner, clock), - m_write_index(*this), - m_read_dma(*this), - m_write_dma(*this), - m_write_dskblk(*this), - m_write_dsksyn(*this), - m_leds(*this, "led%u", 1U), - m_fdc_led(*this, "fdc_led"), - floppy(nullptr), t_gen(nullptr), dsklen(0), pre_dsklen(0), dsksync(0), dskbyt(0), adkcon(0), dmacon(0), dskpt(0), dma_value(0), dma_state(0) +amiga_fdc_device::amiga_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, AMIGA_FDC, tag, owner, clock) + , m_write_index(*this) + , m_read_dma(*this, 0) + , m_write_dma(*this) + , m_write_dskblk(*this) + , m_write_dsksyn(*this) + , m_leds(*this, "led%u", 1U) + , m_fdc_led(*this, "fdc_led") + , floppy(nullptr), t_gen(nullptr), dsklen(0), pre_dsklen(0), dsksync(0), dskbyt(0), adkcon(0), dmacon(0), dskpt(0), dma_value(0), dma_state(0) { } void amiga_fdc_device::device_start() { - m_write_index.resolve_safe(); - m_read_dma.resolve_safe(0); - m_write_dma.resolve_safe(); - m_write_dskblk.resolve_safe(); - m_write_dsksyn.resolve_safe(); m_leds.resolve(); m_fdc_led.resolve(); @@ -67,10 +81,9 @@ void amiga_fdc_device::device_start() floppy = nullptr; - t_gen = timer_alloc(0); + t_gen = timer_alloc(FUNC(amiga_fdc_device::update_tick), this); } - void amiga_fdc_device::device_reset() { floppy = nullptr; @@ -267,39 +280,16 @@ void amiga_fdc_device::live_run(const attotime &limit) if(!(dskbyt & 0x2000)) { if(cur_live.shift_reg == dsksync) { if(adkcon & 0x0400) { - // FIXME: exact dsksync behaviour - // - Some games currently writes two dsksync to the buffer (marked as "[FDC] dsksync"), - // removing one will make most of them happy. - // This is reported as 0-lower cylinder good and everything else as bad in the ATK suite; - // - Some games trashes memory, mostly the ones with "[FDC] dsksync bootblock": - // they attempt to load the tracks in AmigaDOS in the same way that's done by the - // Kickstart to check if the disk is bootable. - // This is reported as 0-upper cylinder bad in the ATK suite; + // FIXME: exact dsksync behaviour, cfr. note at top if(dma_state == DMA_WAIT_START) { cur_live.bit_counter = 0; - if(!(dsklen & 0x3fff)) + if(dsklen & 0x3fff) + dma_state = DMA_RUNNING_BYTE_0; + else dma_done(); - else if(dsklen & 0x4000) { - dskbyt |= 0x2000; - cur_live.bit_counter = 0; - dma_value = dma_read(); - - } else { - LOGSYNC("%s: DSKSYNC on %06x %d\n", this->tag(), dskpt, dma_state); - dma_write(dsksync); - } - - } else if(dma_state != DMA_IDLE) { - LOGSYNC("%s: DSKSYNC on %06x %d\n", this->tag(), dskpt, dma_state); - dma_write(dsksync); - cur_live.bit_counter = 0; - - } else if(cur_live.bit_counter != 8) - cur_live.bit_counter = 0; + } } - //else - // LOGSYNC("%s: no DSKSYNC\n", this->tag()); dskbyt |= 0x1000; m_write_dsksyn(1); @@ -320,12 +310,11 @@ void amiga_fdc_device::live_run(const attotime &limit) dma_state = DMA_RUNNING_BYTE_1; break; - case DMA_RUNNING_BYTE_1: { + case DMA_RUNNING_BYTE_1: dma_value |= cur_live.shift_reg & 0xff; dma_write(dma_value); break; } - } } } else { if(cur_live.bit_counter != 8) @@ -366,9 +355,9 @@ void amiga_fdc_device::dma_check() bool was_writing = dskbyt & 0x2000; dskbyt &= 0x9fff; if(dma_enabled()) { - LOGDMA("%s: DMA start dskpt=%08x dsklen=%04x dir=%s adkcon=%04x dsksync=%04x\n", + LOGDMA("%s: DMA start dskpt=%08x dsklen=%04x dir=%s adkcon=%04x dsksync=%04x state=%d\n", machine().describe_context(), - dskpt, dsklen & 0x3fff, BIT(dsklen, 14) ? "RAM->disk" : "disk->RAM", adkcon, dsksync + dskpt, dsklen & 0x3fff, BIT(dsklen, 14) ? "RAM->disk" : "disk->RAM", adkcon, dsksync, dma_state ); if(dma_state == IDLE) { @@ -454,7 +443,10 @@ void amiga_fdc_device::dsksync_w(uint16_t data) void amiga_fdc_device::dmacon_set(uint16_t data) { live_sync(); - LOGDMA("%s: DMACON set DSKEN %d DMAEN %d (%04x)\n", machine().describe_context(), BIT(data, 4), BIT(data, 9), data); + // log changes only + // FIXME: needs better boilerplate code on top level + if ((data & 0x210) != (dmacon & 0x210)) + LOGDMA("%s: DMACON set DSKEN %d DMAEN %d (%04x)\n", machine().describe_context(), BIT(data, 4), BIT(data, 9), data); dmacon = data; dma_check(); live_run(); @@ -474,7 +466,7 @@ uint16_t amiga_fdc_device::dskbytr_r() return res; } -void amiga_fdc_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +TIMER_CALLBACK_MEMBER(amiga_fdc_device::update_tick) { live_sync(); live_run(); |