summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/machine/i8257.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/machine/i8257.c')
-rw-r--r--src/emu/machine/i8257.c83
1 files changed, 56 insertions, 27 deletions
diff --git a/src/emu/machine/i8257.c b/src/emu/machine/i8257.c
index a6a521de0c4..6de5771afbe 100644
--- a/src/emu/machine/i8257.c
+++ b/src/emu/machine/i8257.c
@@ -219,22 +219,35 @@ inline void i8257n_device::dma_write()
// end_of_process -
//-------------------------------------------------
-inline void i8257n_device::end_of_process()
+inline void i8257n_device::advance()
{
- m_status |= 1 << m_current_channel;
- m_request &= ~(1 << m_current_channel);
- set_tc(1);
+ bool tc = (m_channel[m_current_channel].m_count == 0);
+ bool al = (MODE_AUTOLOAD && (m_current_channel == 2));
- if (MODE_AUTOLOAD && (m_current_channel == 2))
+ if(tc)
{
- // autoinitialize
- m_channel[2].m_address = m_channel[3].m_address;
- m_channel[2].m_count = m_channel[3].m_count;
- m_channel[2].m_mode = m_channel[3].m_mode;
+ m_status |= 1 << m_current_channel;
+ m_request &= ~(1 << m_current_channel); // docs imply this isn't right but pc-8001 works better with it
+ set_tc(1);
+
+ if(al)
+ {
+ // autoinitialize
+ m_channel[2].m_address = m_channel[3].m_address;
+ m_channel[2].m_count = m_channel[3].m_count;
+ m_channel[2].m_mode = m_channel[3].m_mode;
+ }
+ else if(MODE_TC_STOP)
+ // disable channel
+ m_transfer_mode &= ~(1 << m_current_channel);
+ }
+
+ if(!(al && tc))
+ {
+ m_channel[m_current_channel].m_count--;
+ m_channel[m_current_channel].m_count &= 0x3fff;
+ m_channel[m_current_channel].m_address++;
}
- else if(MODE_TC_STOP)
- // disable channel
- m_transfer_mode &= ~(1 << m_current_channel);
}
@@ -251,6 +264,7 @@ i8257n_device::i8257n_device(const machine_config &mconfig, const char *tag, dev
: device_t(mconfig, I8257N, "I8257N", tag, owner, clock, "i8257n", __FILE__),
device_execute_interface(mconfig, *this),
m_icount(0),
+ m_reverse_rw(0),
m_tc(false),
m_msb(0),
m_hreq(CLEAR_LINE),
@@ -310,13 +324,6 @@ void i8257n_device::device_start()
m_out_dack_2_cb.resolve_safe();
m_out_dack_3_cb.resolve_safe();
- for (int i = 0; i < 4; i++)
- {
- m_channel[i].m_address = 0;
- m_channel[i].m_count = 0;
- m_channel[i].m_mode = 0;
- }
-
// state saving
save_item(NAME(m_msb));
save_item(NAME(m_hreq));
@@ -328,6 +335,19 @@ void i8257n_device::device_start()
save_item(NAME(m_transfer_mode));
save_item(NAME(m_status));
save_item(NAME(m_request));
+
+ save_item(NAME(m_channel[0].m_address));
+ save_item(NAME(m_channel[0].m_count));
+ save_item(NAME(m_channel[0].m_mode));
+ save_item(NAME(m_channel[1].m_address));
+ save_item(NAME(m_channel[1].m_count));
+ save_item(NAME(m_channel[1].m_mode));
+ save_item(NAME(m_channel[2].m_address));
+ save_item(NAME(m_channel[2].m_count));
+ save_item(NAME(m_channel[2].m_mode));
+ save_item(NAME(m_channel[3].m_address));
+ save_item(NAME(m_channel[3].m_count));
+ save_item(NAME(m_channel[3].m_mode));
}
@@ -347,6 +367,12 @@ void i8257n_device::device_reset()
m_hreq = -1;
m_tc = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ m_channel[i].m_address = 0;
+ m_channel[i].m_count = 0;
+ m_channel[i].m_mode = 0;
+ }
set_hreq(0);
set_dack();
}
@@ -444,12 +470,7 @@ void i8257n_device::execute_run()
{
dma_write();
}
- m_channel[m_current_channel].m_count--;
- m_channel[m_current_channel].m_count &= 0x3fff;
- m_channel[m_current_channel].m_address++;
-
- if(!m_channel[m_current_channel].m_count)
- end_of_process();
+ advance();
if(next_channel())
m_state = STATE_S1;
@@ -495,7 +516,11 @@ READ8_MEMBER( i8257n_device::read )
case REGISTER_WORD_COUNT:
if (m_msb)
{
- data = (m_channel[channel].m_count >> 8) | (m_channel[channel].m_mode << 6);
+ data = (m_channel[channel].m_count >> 8);
+ if(m_reverse_rw && m_channel[channel].m_mode)
+ data |= (m_channel[channel].m_mode == 1) ? 0x2000 : 0x1000;
+ else
+ data |= (m_channel[channel].m_mode << 6);
}
else
{
@@ -550,10 +575,14 @@ WRITE8_MEMBER( i8257n_device::write )
{
m_channel[channel].m_count = ((data & 0x3f) << 8) | (m_channel[channel].m_count & 0xff);
m_channel[channel].m_mode = (data >> 6);
+
+ if(m_reverse_rw && m_channel[channel].m_mode)
+ m_channel[channel].m_mode = (m_channel[channel].m_mode == 1) ? 2 : 1;
+
if(MODE_AUTOLOAD && (channel == 2))
{
m_channel[3].m_count = ((data & 0x3f) << 8) | (m_channel[3].m_count & 0xff);
- m_channel[3].m_mode = (data >> 6);
+ m_channel[3].m_mode = m_channel[2].m_mode;
}
}
else