amigafdc: Upgrade [O. Galibert]
This commit is contained in:
parent
974ea3d59e
commit
c965e4ad27
@ -164,6 +164,7 @@ EMUMACHINEOBJS = \
|
|||||||
$(EMUMACHINE)/adc1213x.o \
|
$(EMUMACHINE)/adc1213x.o \
|
||||||
$(EMUMACHINE)/am53cf96.o \
|
$(EMUMACHINE)/am53cf96.o \
|
||||||
$(EMUMACHINE)/am8530h.o \
|
$(EMUMACHINE)/am8530h.o \
|
||||||
|
$(EMUMACHINE)/amigafdc.o \
|
||||||
$(EMUMACHINE)/at28c16.o \
|
$(EMUMACHINE)/at28c16.o \
|
||||||
$(EMUMACHINE)/cdp1852.o \
|
$(EMUMACHINE)/cdp1852.o \
|
||||||
$(EMUMACHINE)/cdp1871.o \
|
$(EMUMACHINE)/cdp1871.o \
|
||||||
|
@ -269,6 +269,7 @@ void floppy_image_device::stp_w(int state)
|
|||||||
} else {
|
} else {
|
||||||
if ( cyl < tracks-1 ) cyl++;
|
if ( cyl < tracks-1 ) cyl++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update disk detection if applicable */
|
/* Update disk detection if applicable */
|
||||||
if (exists())
|
if (exists())
|
||||||
{
|
{
|
||||||
@ -286,14 +287,6 @@ int floppy_image_device::find_position(int position, const UINT32 *buf, int buf_
|
|||||||
step >>= 1;
|
step >>= 1;
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
#if 0
|
|
||||||
fprintf(stderr, "%09d - %09d / %09d -- %6d %6d %6d\n",
|
|
||||||
position,
|
|
||||||
spos < 0 ? 0 : spos >= buf_size ? 200000000 :buf[spos] & floppy_image::TIME_MASK,
|
|
||||||
spos < 0 ? 0 : spos >= buf_size-1 ? 200000000 : buf[spos+1] & floppy_image::TIME_MASK,
|
|
||||||
spos, step, buf_size);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(spos >= buf_size || (spos > 0 && (buf[spos] & floppy_image::TIME_MASK) > position)) {
|
if(spos >= buf_size || (spos > 0 && (buf[spos] & floppy_image::TIME_MASK) > position)) {
|
||||||
spos -= step;
|
spos -= step;
|
||||||
step >>= 1;
|
step >>= 1;
|
||||||
@ -328,7 +321,6 @@ attotime floppy_image_device::get_next_transition(attotime from_when)
|
|||||||
const UINT32 *buf = image->get_buffer(cyl, ss);
|
const UINT32 *buf = image->get_buffer(cyl, ss);
|
||||||
int index = find_position(position, buf, cells);
|
int index = find_position(position, buf, cells);
|
||||||
|
|
||||||
// fprintf(stderr, "position=%9d, index=%d\n", position, index);
|
|
||||||
if(index == -1)
|
if(index == -1)
|
||||||
return attotime::never;
|
return attotime::never;
|
||||||
|
|
||||||
@ -340,6 +332,5 @@ attotime floppy_image_device::get_next_transition(attotime from_when)
|
|||||||
else
|
else
|
||||||
next_position = 200000000 + (buf[1] & floppy_image::TIME_MASK);
|
next_position = 200000000 + (buf[1] & floppy_image::TIME_MASK);
|
||||||
|
|
||||||
// printf("next_pos=%d, delta=%d\n", next_position, next_position-position);
|
|
||||||
return base + attotime::from_nsec(next_position*(300/rpm));
|
return base + attotime::from_nsec(next_position*(300/rpm));
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,454 @@
|
|||||||
|
/****************************************************f***********************
|
||||||
|
|
||||||
|
Amiga floppy disk controller emulation
|
||||||
|
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
#include "includes/amiga.h"
|
||||||
|
#include "formats/ami_dsk.h"
|
||||||
|
#include "formats/hxcmfm_dsk.h"
|
||||||
|
#include "formats/ipf_dsk.h"
|
||||||
|
#include "formats/mfi_dsk.h"
|
||||||
|
#include "amigafdc.h"
|
||||||
|
#include "machine/6526cia.h"
|
||||||
|
|
||||||
|
const device_type AMIGA_FDC = &device_creator<amiga_fdc>;
|
||||||
|
|
||||||
|
const floppy_format_type amiga_fdc::floppy_formats[] = {
|
||||||
|
FLOPPY_ADF_FORMAT, FLOPPY_MFM_FORMAT, FLOPPY_IPF_FORMAT, FLOPPY_MFI_FORMAT,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
amiga_fdc::amiga_fdc(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||||
|
device_t(mconfig, AMIGA_FDC, "Amiga FDC", tag, owner, clock)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
floppy = 0;
|
||||||
|
|
||||||
|
t_gen = timer_alloc(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void amiga_fdc::device_reset()
|
||||||
|
{
|
||||||
|
floppy = 0;
|
||||||
|
dsklen = 0x4000;
|
||||||
|
dsksync = 0x4489;
|
||||||
|
adkcon = 0;
|
||||||
|
dmacon = 0;
|
||||||
|
dskpt = 0;
|
||||||
|
dsklen = 0x4000;
|
||||||
|
pre_dsklen = 0x4000;
|
||||||
|
dma_value = 0;
|
||||||
|
dma_state = DMA_IDLE;
|
||||||
|
|
||||||
|
live_abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::live_start()
|
||||||
|
{
|
||||||
|
cur_live.tm = machine().time();
|
||||||
|
cur_live.state = RUNNING;
|
||||||
|
cur_live.next_state = -1;
|
||||||
|
cur_live.shift_reg = 0;
|
||||||
|
cur_live.bit_counter = 0;
|
||||||
|
cur_live.pll.reset(cur_live.tm);
|
||||||
|
cur_live.pll.set_clock(clocks_to_attotime(1));
|
||||||
|
checkpoint_live = cur_live;
|
||||||
|
|
||||||
|
live_run();
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::checkpoint()
|
||||||
|
{
|
||||||
|
checkpoint_live = cur_live;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::rollback()
|
||||||
|
{
|
||||||
|
cur_live = checkpoint_live;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::live_delay(int state)
|
||||||
|
{
|
||||||
|
cur_live.next_state = state;
|
||||||
|
t_gen->adjust(cur_live.tm - machine().time());
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::live_sync()
|
||||||
|
{
|
||||||
|
if(!cur_live.tm.is_never()) {
|
||||||
|
if(cur_live.tm > machine().time()) {
|
||||||
|
rollback();
|
||||||
|
live_run(machine().time());
|
||||||
|
} else {
|
||||||
|
if(cur_live.next_state != -1)
|
||||||
|
cur_live.state = cur_live.next_state;
|
||||||
|
if(cur_live.state == IDLE)
|
||||||
|
cur_live.tm = attotime::never;
|
||||||
|
}
|
||||||
|
cur_live.next_state = -1;
|
||||||
|
checkpoint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::live_abort()
|
||||||
|
{
|
||||||
|
cur_live.tm = attotime::never;
|
||||||
|
cur_live.state = IDLE;
|
||||||
|
cur_live.next_state = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::live_run(attotime limit)
|
||||||
|
{
|
||||||
|
if(cur_live.state == IDLE || cur_live.next_state != -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
switch(cur_live.state) {
|
||||||
|
case RUNNING: {
|
||||||
|
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))
|
||||||
|
cur_live.bit_counter--;
|
||||||
|
|
||||||
|
if(cur_live.bit_counter == 8) {
|
||||||
|
live_delay(RUNNING_SYNCPOINT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(dskbyt & 0x0400) {
|
||||||
|
if(cur_live.shift_reg != dsksync) {
|
||||||
|
live_delay(RUNNING_SYNCPOINT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(cur_live.shift_reg == dsksync) {
|
||||||
|
live_delay(RUNNING_SYNCPOINT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case RUNNING_SYNCPOINT: {
|
||||||
|
if(cur_live.shift_reg == dsksync) {
|
||||||
|
if(adkcon & 0x0400) {
|
||||||
|
if(dma_state == DMA_WAIT_START)
|
||||||
|
dma_state = DMA_RUNNING_BYTE_0;
|
||||||
|
|
||||||
|
cur_live.bit_counter = 0;
|
||||||
|
}
|
||||||
|
dskbyt |= 0x0400;
|
||||||
|
address_space *space = machine().device("maincpu")->memory().space(AS_PROGRAM);
|
||||||
|
amiga_custom_w(space, REG_INTREQ, 0x8000 | INTENA_DSKSYN, 0xffff);
|
||||||
|
} else
|
||||||
|
dskbyt &= ~0x0400;
|
||||||
|
|
||||||
|
if(cur_live.bit_counter == 8) {
|
||||||
|
dskbyt = (dskbyt & 0xff00) | 0x8000 | (cur_live.shift_reg & 0xff);
|
||||||
|
cur_live.bit_counter = 0;
|
||||||
|
|
||||||
|
switch(dma_state) {
|
||||||
|
case DMA_IDLE:
|
||||||
|
case DMA_WAIT_START:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DMA_RUNNING_BYTE_0:
|
||||||
|
dma_value = (cur_live.shift_reg & 0xff) << 8;
|
||||||
|
dma_state = DMA_RUNNING_BYTE_1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DMA_RUNNING_BYTE_1: {
|
||||||
|
dma_value |= cur_live.shift_reg & 0xff;
|
||||||
|
|
||||||
|
amiga_state *state = machine().driver_data<amiga_state>();
|
||||||
|
(*state->m_chip_ram_w)(state, dskpt, dma_value);
|
||||||
|
|
||||||
|
dskpt += 2;
|
||||||
|
dsklen--;
|
||||||
|
if(dsklen & 0x3fff)
|
||||||
|
dma_state = DMA_RUNNING_BYTE_0;
|
||||||
|
else {
|
||||||
|
dma_state = DMA_IDLE;
|
||||||
|
address_space *space = machine().device("maincpu")->memory().space(AS_PROGRAM);
|
||||||
|
amiga_custom_w(space, REG_INTREQ, 0x8000 | INTENA_DSKBLK, 0xffff);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_live.state = RUNNING;
|
||||||
|
checkpoint();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amiga_fdc::dma_enabled()
|
||||||
|
{
|
||||||
|
return (dsklen & 0x8000) && ((dmacon & 0x0210) == 0x0210);
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::dma_check()
|
||||||
|
{
|
||||||
|
if(dma_enabled() && (dsklen & 0x3fff)) {
|
||||||
|
if(dma_state == IDLE)
|
||||||
|
dma_state = adkcon & 0x0400 ? DMA_WAIT_START : DMA_RUNNING_BYTE_0;
|
||||||
|
} else
|
||||||
|
dma_state = IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::adkcon_set(UINT16 data)
|
||||||
|
{
|
||||||
|
live_sync();
|
||||||
|
adkcon = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::dsklen_w(UINT16 data)
|
||||||
|
{
|
||||||
|
live_sync();
|
||||||
|
if(!(data & 0x8000) || (data == pre_dsklen)) {
|
||||||
|
dsklen = pre_dsklen = data;
|
||||||
|
dma_check();
|
||||||
|
|
||||||
|
dskbyt = dskbyt & 0x9fff;
|
||||||
|
if(data & 0x4000)
|
||||||
|
dskbyt |= 0x2000;
|
||||||
|
if(dma_state != DMA_IDLE)
|
||||||
|
dskbyt |= 0x4000;
|
||||||
|
} else
|
||||||
|
pre_dsklen = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::dskpth_w(UINT16 data)
|
||||||
|
{
|
||||||
|
live_sync();
|
||||||
|
dskpt = (dskpt & 0xffff) | (data << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::dskptl_w(UINT16 data)
|
||||||
|
{
|
||||||
|
live_sync();
|
||||||
|
dskpt = (dskpt & 0xffff0000) | data;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT16 amiga_fdc::dskpth_r()
|
||||||
|
{
|
||||||
|
return dskpt >> 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT16 amiga_fdc::dskptl_r()
|
||||||
|
{
|
||||||
|
return dskpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::dsksync_w(UINT16 data)
|
||||||
|
{
|
||||||
|
live_sync();
|
||||||
|
dsksync = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::dmacon_set(UINT16 data)
|
||||||
|
{
|
||||||
|
live_sync();
|
||||||
|
dmacon = data;
|
||||||
|
dma_check();
|
||||||
|
dskbyt = dskbyt & 0xbfff;
|
||||||
|
if(dma_state != DMA_IDLE)
|
||||||
|
dskbyt |= 0x4000;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT16 amiga_fdc::dskbytr_r()
|
||||||
|
{
|
||||||
|
return dskbyt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||||
|
{
|
||||||
|
live_sync();
|
||||||
|
live_run();
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::setup_leds()
|
||||||
|
{
|
||||||
|
if(floppy) {
|
||||||
|
int drive =
|
||||||
|
floppy == floppy_devices[0] ? 0 :
|
||||||
|
floppy == floppy_devices[1] ? 1 :
|
||||||
|
floppy == floppy_devices[2] ? 2 :
|
||||||
|
3;
|
||||||
|
|
||||||
|
output_set_value("drive_0_led", drive == 0);
|
||||||
|
output_set_value("drive_1_led", drive == 1);
|
||||||
|
output_set_value("drive_2_led", drive == 2);
|
||||||
|
output_set_value("drive_3_led", drive == 3);
|
||||||
|
|
||||||
|
set_led_status(machine(), 1, drive == 0); /* update internal drive led */
|
||||||
|
set_led_status(machine(), 2, drive == 1); /* update external drive led */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER( amiga_fdc::ciaaprb_w )
|
||||||
|
{
|
||||||
|
live_sync();
|
||||||
|
|
||||||
|
if(!(data & 0x08))
|
||||||
|
floppy = floppy_devices[0];
|
||||||
|
else if(!(data & 0x10))
|
||||||
|
floppy = floppy_devices[1];
|
||||||
|
else if(!(data & 0x20))
|
||||||
|
floppy = floppy_devices[2];
|
||||||
|
else if(!(data & 0x40))
|
||||||
|
floppy = floppy_devices[3];
|
||||||
|
else
|
||||||
|
floppy = 0;
|
||||||
|
|
||||||
|
if(floppy) {
|
||||||
|
floppy->ss_w(!((data >> 2) & 1));
|
||||||
|
floppy->dir_w((data >> 1) & 1);
|
||||||
|
floppy->stp_w(data & 1);
|
||||||
|
floppy->mon_w((data >> 7) & 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(floppy) {
|
||||||
|
if(cur_live.state == IDLE)
|
||||||
|
live_start();
|
||||||
|
} else
|
||||||
|
live_abort();
|
||||||
|
|
||||||
|
setup_leds();
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT8 amiga_fdc::ciaapra_r()
|
||||||
|
{
|
||||||
|
UINT8 ret = 0x3c;
|
||||||
|
if(floppy) {
|
||||||
|
// fixit
|
||||||
|
ret &= ~0x20;
|
||||||
|
|
||||||
|
if(!floppy->trk00_r())
|
||||||
|
ret &= ~0x10;
|
||||||
|
if(!floppy->wpt_r())
|
||||||
|
ret &= ~0x08;
|
||||||
|
if(!floppy->dskchg_r())
|
||||||
|
ret &= ~0x04;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::index_callback(floppy_image_device *floppy, int state)
|
||||||
|
{
|
||||||
|
/* Issue a index pulse when a disk revolution completes */
|
||||||
|
device_t *cia = machine().device("cia_1");
|
||||||
|
mos6526_flag_w(cia, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::pll_t::set_clock(attotime period)
|
||||||
|
{
|
||||||
|
for(int i=0; i<38; i++)
|
||||||
|
delays[i] = period*(i+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void amiga_fdc::pll_t::reset(attotime when)
|
||||||
|
{
|
||||||
|
counter = 0;
|
||||||
|
increment = 146;
|
||||||
|
transition_time = 0xffff;
|
||||||
|
history = 0x80;
|
||||||
|
slot = 0;
|
||||||
|
ctime = when;
|
||||||
|
phase_add = 0x00;
|
||||||
|
phase_sub = 0x00;
|
||||||
|
freq_add = 0x00;
|
||||||
|
freq_sub = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
int amiga_fdc::pll_t::get_next_bit(attotime &tm, floppy_image_device *floppy, attotime limit)
|
||||||
|
{
|
||||||
|
attotime when = floppy ? floppy->get_next_transition(ctime) : attotime::never;
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
attotime etime = ctime+delays[slot];
|
||||||
|
if(etime > limit)
|
||||||
|
return -1;
|
||||||
|
if(transition_time == 0xffff && !when.is_never() && etime >= when)
|
||||||
|
transition_time = counter;
|
||||||
|
if(slot < 8) {
|
||||||
|
UINT8 mask = 1 << slot;
|
||||||
|
if(phase_add & mask)
|
||||||
|
counter += 258;
|
||||||
|
else if(phase_sub & mask)
|
||||||
|
counter += 34;
|
||||||
|
else
|
||||||
|
counter += increment;
|
||||||
|
|
||||||
|
if((freq_add & mask) && increment < 159)
|
||||||
|
increment++;
|
||||||
|
else if((freq_sub & mask) && increment > 134)
|
||||||
|
increment--;
|
||||||
|
} else
|
||||||
|
counter += increment;
|
||||||
|
|
||||||
|
slot++;
|
||||||
|
tm = etime;
|
||||||
|
if(counter & 0x800)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bit = transition_time != 0xffff;
|
||||||
|
|
||||||
|
if(transition_time != 0xffff) {
|
||||||
|
static const UINT8 pha[8] = { 0xf, 0x7, 0x3, 0x1, 0, 0, 0, 0 };
|
||||||
|
static const UINT8 phs[8] = { 0, 0, 0, 0, 0x1, 0x3, 0x7, 0xf };
|
||||||
|
static const UINT8 freqa[4][8] = {
|
||||||
|
{ 0xf, 0x7, 0x3, 0x1, 0, 0, 0, 0 },
|
||||||
|
{ 0x7, 0x3, 0x1, 0, 0, 0, 0, 0 },
|
||||||
|
{ 0x7, 0x3, 0x1, 0, 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0, 0, 0, 0, 0 }
|
||||||
|
};
|
||||||
|
static const UINT8 freqs[4][8] = {
|
||||||
|
{ 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0, 0, 0x1, 0x3, 0x7 },
|
||||||
|
{ 0, 0, 0, 0, 0, 0x1, 0x3, 0x7 },
|
||||||
|
{ 0, 0, 0, 0, 0x1, 0x3, 0x7, 0xf },
|
||||||
|
};
|
||||||
|
|
||||||
|
int cslot = transition_time >> 8;
|
||||||
|
phase_add = pha[cslot];
|
||||||
|
phase_sub = phs[cslot];
|
||||||
|
int way = transition_time & 0x400 ? 1 : 0;
|
||||||
|
if(history & 0x80)
|
||||||
|
history = way ? 0x80 : 0x83;
|
||||||
|
else if(history & 0x40)
|
||||||
|
history = way ? history & 2 : (history & 2) | 1;
|
||||||
|
freq_add = freqa[history & 3][cslot];
|
||||||
|
freq_sub = freqs[history & 3][cslot];
|
||||||
|
history = way ? (history >> 1) | 2 : history >> 1;
|
||||||
|
|
||||||
|
} else
|
||||||
|
phase_add = phase_sub = freq_add = freq_sub = 0;
|
||||||
|
|
||||||
|
counter &= 0x7ff;
|
||||||
|
|
||||||
|
ctime = tm;
|
||||||
|
transition_time = 0xffff;
|
||||||
|
slot = 0;
|
||||||
|
|
||||||
|
return bit;
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
#ifndef AMIGAFDC_H
|
||||||
|
#define AMIGAFDC_H
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
#include "imagedev/floppy.h"
|
||||||
|
|
||||||
|
#define MCFG_AMIGA_FDC_ADD(_tag, _clock) \
|
||||||
|
MCFG_DEVICE_ADD(_tag, AMIGA_FDC, _clock)
|
||||||
|
|
||||||
|
class amiga_fdc : public device_t {
|
||||||
|
public:
|
||||||
|
amiga_fdc(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
DECLARE_WRITE8_MEMBER(ciaaprb_w);
|
||||||
|
|
||||||
|
UINT8 ciaapra_r();
|
||||||
|
UINT16 dskbytr_r();
|
||||||
|
UINT16 dskpth_r();
|
||||||
|
UINT16 dskptl_r();
|
||||||
|
|
||||||
|
void dsksync_w(UINT16 data);
|
||||||
|
void dskpth_w(UINT16 data);
|
||||||
|
void dskptl_w(UINT16 data);
|
||||||
|
void dsklen_w(UINT16 data);
|
||||||
|
void adkcon_set(UINT16 data);
|
||||||
|
void dmacon_set(UINT16 data);
|
||||||
|
|
||||||
|
static const floppy_format_type floppy_formats[];
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void device_start();
|
||||||
|
virtual void device_reset();
|
||||||
|
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Running states
|
||||||
|
enum {
|
||||||
|
IDLE,
|
||||||
|
RUNNING,
|
||||||
|
RUNNING_SYNCPOINT
|
||||||
|
};
|
||||||
|
|
||||||
|
// DMA states
|
||||||
|
enum {
|
||||||
|
DMA_IDLE,
|
||||||
|
DMA_WAIT_START,
|
||||||
|
DMA_RUNNING_BYTE_0,
|
||||||
|
DMA_RUNNING_BYTE_1
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pll_t {
|
||||||
|
UINT16 counter;
|
||||||
|
UINT16 increment;
|
||||||
|
UINT16 transition_time;
|
||||||
|
UINT8 history;
|
||||||
|
UINT8 slot;
|
||||||
|
UINT8 phase_add, phase_sub, freq_add, freq_sub;
|
||||||
|
attotime ctime;
|
||||||
|
|
||||||
|
attotime delays[38];
|
||||||
|
|
||||||
|
void set_clock(attotime period);
|
||||||
|
void reset(attotime when);
|
||||||
|
int get_next_bit(attotime &tm, floppy_image_device *floppy, attotime limit);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct live_info {
|
||||||
|
attotime tm;
|
||||||
|
int state, next_state;
|
||||||
|
UINT16 shift_reg;
|
||||||
|
int bit_counter;
|
||||||
|
pll_t pll;
|
||||||
|
};
|
||||||
|
|
||||||
|
floppy_image_device *floppy;
|
||||||
|
floppy_image_device *floppy_devices[4];
|
||||||
|
|
||||||
|
live_info cur_live, checkpoint_live;
|
||||||
|
|
||||||
|
emu_timer *t_gen;
|
||||||
|
UINT16 dsklen, pre_dsklen, dsksync, dskbyt, adkcon, dmacon;
|
||||||
|
UINT32 dskpt;
|
||||||
|
UINT16 dma_value;
|
||||||
|
|
||||||
|
int dma_state;
|
||||||
|
|
||||||
|
void setup_leds();
|
||||||
|
void index_callback(floppy_image_device *floppy, int state);
|
||||||
|
bool dma_enabled();
|
||||||
|
void dma_check();
|
||||||
|
|
||||||
|
void live_start();
|
||||||
|
void checkpoint();
|
||||||
|
void rollback();
|
||||||
|
void live_delay(int state);
|
||||||
|
void live_sync();
|
||||||
|
void live_abort();
|
||||||
|
void live_run(attotime limit = attotime::never);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const device_type AMIGA_FDC;
|
||||||
|
|
||||||
|
#endif /* AMIGAFDC_H */
|
@ -685,7 +685,7 @@ static void alg_init(running_machine &machine)
|
|||||||
{
|
{
|
||||||
ANGUS_CHIP_RAM_MASK,
|
ANGUS_CHIP_RAM_MASK,
|
||||||
NULL, NULL, alg_potgo_w,
|
NULL, NULL, alg_potgo_w,
|
||||||
NULL, NULL, serial_w,
|
serial_w,
|
||||||
|
|
||||||
vsync_callback,
|
vsync_callback,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -793,7 +793,7 @@ static void arcadia_init(running_machine &machine)
|
|||||||
{
|
{
|
||||||
ANGUS_CHIP_RAM_MASK,
|
ANGUS_CHIP_RAM_MASK,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL,
|
NULL,
|
||||||
NULL, arcadia_reset_coins,
|
NULL, arcadia_reset_coins,
|
||||||
NULL,
|
NULL,
|
||||||
0
|
0
|
||||||
|
@ -834,7 +834,7 @@ static DRIVER_INIT( cd32 )
|
|||||||
{
|
{
|
||||||
AGA_CHIP_RAM_MASK,
|
AGA_CHIP_RAM_MASK,
|
||||||
NULL, NULL, cd32_potgo_w,
|
NULL, NULL, cd32_potgo_w,
|
||||||
NULL, NULL, NULL,
|
NULL,
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
NULL,
|
NULL,
|
||||||
FLAGS_AGA_CHIPSET
|
FLAGS_AGA_CHIPSET
|
||||||
@ -1454,7 +1454,7 @@ static DRIVER_INIT( odeontw2 )
|
|||||||
{
|
{
|
||||||
AGA_CHIP_RAM_MASK,
|
AGA_CHIP_RAM_MASK,
|
||||||
NULL, NULL, cd32_potgo_w,
|
NULL, NULL, cd32_potgo_w,
|
||||||
NULL, NULL, serial_w,
|
serial_w,
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
NULL,
|
NULL,
|
||||||
FLAGS_AGA_CHIPSET
|
FLAGS_AGA_CHIPSET
|
||||||
|
@ -433,7 +433,7 @@ static DRIVER_INIT(mquake)
|
|||||||
{
|
{
|
||||||
ANGUS_CHIP_RAM_MASK,
|
ANGUS_CHIP_RAM_MASK,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL,
|
NULL,
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
NULL,
|
NULL,
|
||||||
0
|
0
|
||||||
|
@ -390,7 +390,7 @@ static DRIVER_INIT( upscope )
|
|||||||
{
|
{
|
||||||
ANGUS_CHIP_RAM_MASK,
|
ANGUS_CHIP_RAM_MASK,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL,
|
NULL,
|
||||||
NULL, upscope_reset,
|
NULL, upscope_reset,
|
||||||
NULL,
|
NULL,
|
||||||
0
|
0
|
||||||
|
@ -97,7 +97,7 @@ Ernesto Corvi & Mariusz Wojcieszek
|
|||||||
#define REG_BLTBDAT (0x072/2) /* W A Blitter source B data reglster */
|
#define REG_BLTBDAT (0x072/2) /* W A Blitter source B data reglster */
|
||||||
#define REG_BLTADAT (0x074/2) /* W A Blitter source A data register */
|
#define REG_BLTADAT (0x074/2) /* W A Blitter source A data register */
|
||||||
#define REG_DENISEID (0x07C/2) /* R D Denise ID: OCS = 0xFF, ECS = 0xFC, AGA = 0xF8 */
|
#define REG_DENISEID (0x07C/2) /* R D Denise ID: OCS = 0xFF, ECS = 0xFC, AGA = 0xF8 */
|
||||||
#define REG_DSRSYNC (0x07E/2) /* W P Disk sync pattern register for disk read */
|
#define REG_DSKSYNC (0x07E/2) /* W P Disk sync pattern register for disk read */
|
||||||
#define REG_COP1LCH (0x080/2) /* W A Coprocessor first location register (high 3 bits) */
|
#define REG_COP1LCH (0x080/2) /* W A Coprocessor first location register (high 3 bits) */
|
||||||
#define REG_COP1LCL (0x082/2) /* W A Coprocessor first location register (low 15 bits) */
|
#define REG_COP1LCL (0x082/2) /* W A Coprocessor first location register (low 15 bits) */
|
||||||
#define REG_COP2LCH (0x084/2) /* W A Coprocessor second location register (high 3 bits) */
|
#define REG_COP2LCH (0x084/2) /* W A Coprocessor second location register (high 3 bits) */
|
||||||
@ -329,9 +329,6 @@ struct _amiga_machine_interface
|
|||||||
UINT16 (*joy1dat_r)(running_machine &machine);
|
UINT16 (*joy1dat_r)(running_machine &machine);
|
||||||
void (*potgo_w)(running_machine &machine, UINT16 data);
|
void (*potgo_w)(running_machine &machine, UINT16 data);
|
||||||
|
|
||||||
UINT16 (*dskbytr_r)(running_machine &machine);
|
|
||||||
void (*dsklen_w)(running_machine &machine, UINT16 data);
|
|
||||||
|
|
||||||
void (*serdat_w)(running_machine &machine, UINT16 data);
|
void (*serdat_w)(running_machine &machine, UINT16 data);
|
||||||
|
|
||||||
void (*scanline0_callback)(running_machine &machine);
|
void (*scanline0_callback)(running_machine &machine);
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#include "includes/amiga.h"
|
#include "includes/amiga.h"
|
||||||
#include "cpu/m68000/m68000.h"
|
#include "cpu/m68000/m68000.h"
|
||||||
#include "machine/6526cia.h"
|
#include "machine/6526cia.h"
|
||||||
|
#include "machine/amigafdc.h"
|
||||||
|
|
||||||
/*************************************
|
/*************************************
|
||||||
*
|
*
|
||||||
@ -1181,9 +1181,6 @@ READ16_HANDLER( amiga_custom_r )
|
|||||||
return (*state->m_intf->joy1dat_r)(space->machine());
|
return (*state->m_intf->joy1dat_r)(space->machine());
|
||||||
return input_port_read_safe(space->machine(), "JOY1DAT", 0xffff);
|
return input_port_read_safe(space->machine(), "JOY1DAT", 0xffff);
|
||||||
|
|
||||||
case REG_ADKCONR:
|
|
||||||
return CUSTOM_REG(REG_ADKCON);
|
|
||||||
|
|
||||||
case REG_POTGOR:
|
case REG_POTGOR:
|
||||||
return input_port_read_safe(space->machine(), "POTGO", 0x5500);
|
return input_port_read_safe(space->machine(), "POTGO", 0x5500);
|
||||||
|
|
||||||
@ -1194,9 +1191,7 @@ READ16_HANDLER( amiga_custom_r )
|
|||||||
return input_port_read_safe(space->machine(), "POT1DAT", 0x0000);
|
return input_port_read_safe(space->machine(), "POT1DAT", 0x0000);
|
||||||
|
|
||||||
case REG_DSKBYTR:
|
case REG_DSKBYTR:
|
||||||
if (state->m_intf->dskbytr_r != NULL)
|
return space->machine().device<amiga_fdc>("fdc")->dskbytr_r();
|
||||||
return (*state->m_intf->dskbytr_r)(space->machine());
|
|
||||||
return 0x0000;
|
|
||||||
|
|
||||||
case REG_INTENAR:
|
case REG_INTENAR:
|
||||||
return CUSTOM_REG(REG_INTENA);
|
return CUSTOM_REG(REG_INTENA);
|
||||||
@ -1219,6 +1214,12 @@ READ16_HANDLER( amiga_custom_r )
|
|||||||
|
|
||||||
case REG_DENISEID:
|
case REG_DENISEID:
|
||||||
return CUSTOM_REG(REG_DENISEID);
|
return CUSTOM_REG(REG_DENISEID);
|
||||||
|
|
||||||
|
case REG_DSKPTH:
|
||||||
|
return space->machine().device<amiga_fdc>("fdc")->dskpth_r();
|
||||||
|
|
||||||
|
case REG_DSKPTL:
|
||||||
|
return space->machine().device<amiga_fdc>("fdc")->dskptl_r();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LOG_CUSTOM)
|
if (LOG_CUSTOM)
|
||||||
@ -1267,9 +1268,20 @@ WRITE16_HANDLER( amiga_custom_w )
|
|||||||
/* read-only registers */
|
/* read-only registers */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case REG_DSKSYNC:
|
||||||
|
space->machine().device<amiga_fdc>("fdc")->dsksync_w(data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REG_DSKPTH:
|
||||||
|
space->machine().device<amiga_fdc>("fdc")->dskpth_w(data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REG_DSKPTL:
|
||||||
|
space->machine().device<amiga_fdc>("fdc")->dskptl_w(data);
|
||||||
|
break;
|
||||||
|
|
||||||
case REG_DSKLEN:
|
case REG_DSKLEN:
|
||||||
if (state->m_intf->dsklen_w != NULL)
|
space->machine().device<amiga_fdc>("fdc")->dsklen_w(data);
|
||||||
(*state->m_intf->dsklen_w)(space->machine(), data);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REG_POTGO:
|
case REG_POTGO:
|
||||||
@ -1372,7 +1384,8 @@ WRITE16_HANDLER( amiga_custom_w )
|
|||||||
/* bits BBUSY (14) and BZERO (13) are read-only */
|
/* bits BBUSY (14) and BZERO (13) are read-only */
|
||||||
data &= 0x9fff;
|
data &= 0x9fff;
|
||||||
data = (data & 0x8000) ? (CUSTOM_REG(offset) | (data & 0x7fff)) : (CUSTOM_REG(offset) & ~(data & 0x7fff));
|
data = (data & 0x8000) ? (CUSTOM_REG(offset) | (data & 0x7fff)) : (CUSTOM_REG(offset) & ~(data & 0x7fff));
|
||||||
|
space->machine().device<amiga_fdc>("fdc")->dmacon_set(data);
|
||||||
|
|
||||||
/* if 'blitter-nasty' has been turned on and we have a blit pending, reschedule it */
|
/* if 'blitter-nasty' has been turned on and we have a blit pending, reschedule it */
|
||||||
if ( ( data & 0x400 ) && ( CUSTOM_REG(REG_DMACON) & 0x4000 ) )
|
if ( ( data & 0x400 ) && ( CUSTOM_REG(REG_DMACON) & 0x4000 ) )
|
||||||
state->m_blitter_timer->adjust( downcast<cpu_device *>(&space->device())->cycles_to_attotime( BLITTER_NASTY_DELAY ));
|
state->m_blitter_timer->adjust( downcast<cpu_device *>(&space->device())->cycles_to_attotime( BLITTER_NASTY_DELAY ));
|
||||||
@ -1413,6 +1426,7 @@ WRITE16_HANDLER( amiga_custom_w )
|
|||||||
case REG_ADKCON:
|
case REG_ADKCON:
|
||||||
amiga_audio_update(state->m_sound_device);
|
amiga_audio_update(state->m_sound_device);
|
||||||
data = (data & 0x8000) ? (CUSTOM_REG(offset) | (data & 0x7fff)) : (CUSTOM_REG(offset) & ~(data & 0x7fff));
|
data = (data & 0x8000) ? (CUSTOM_REG(offset) | (data & 0x7fff)) : (CUSTOM_REG(offset) & ~(data & 0x7fff));
|
||||||
|
space->machine().device<amiga_fdc>("fdc")->adkcon_set(data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REG_AUD0LCL: case REG_AUD0LCH: case REG_AUD0LEN: case REG_AUD0PER: case REG_AUD0VOL:
|
case REG_AUD0LCL: case REG_AUD0LCH: case REG_AUD0LEN: case REG_AUD0PER: case REG_AUD0VOL:
|
||||||
|
Loading…
Reference in New Issue
Block a user