void z80dma_device::write(UINT8 data) { if (LOG) logerror("Z80DMA '%s' Write %02x\n", tag(), data); if (m_num_follow == 0) { m_reset_pointer = 0; if ((data & 0x87) == 0) // WR2 { WR2 = data; if (data & 0x40) m_regs_follow[m_num_follow++] = GET_REGNUM(PORTB_TIMING); } else if ((data & 0x87) == 0x04) // WR1 { WR1 = data; if (data & 0x40) m_regs_follow[m_num_follow++] = GET_REGNUM(PORTA_TIMING); } else if ((data & 0x80) == 0) // WR0 { WR0 = data; if (data & 0x08) m_regs_follow[m_num_follow++] = GET_REGNUM(PORTA_ADDRESS_L); if (data & 0x10) m_regs_follow[m_num_follow++] = GET_REGNUM(PORTA_ADDRESS_H); if (data & 0x20) m_regs_follow[m_num_follow++] = GET_REGNUM(BLOCKLEN_L); if (data & 0x40) m_regs_follow[m_num_follow++] = GET_REGNUM(BLOCKLEN_H); } else if ((data & 0x83) == 0x80) // WR3 { WR3 = data; if (data & 0x08) m_regs_follow[m_num_follow++] = GET_REGNUM(MASK_BYTE); if (data & 0x10) m_regs_follow[m_num_follow++] = GET_REGNUM(MATCH_BYTE); } else if ((data & 0x83) == 0x81) // WR4 { WR4 = data; if (data & 0x04) m_regs_follow[m_num_follow++] = GET_REGNUM(PORTB_ADDRESS_L); if (data & 0x08) m_regs_follow[m_num_follow++] = GET_REGNUM(PORTB_ADDRESS_H); if (data & 0x10) m_regs_follow[m_num_follow++] = GET_REGNUM(INTERRUPT_CTRL); } else if ((data & 0xC7) == 0x82) // WR5 { WR5 = data; } else if ((data & 0x83) == 0x83) // WR6 { m_dma_enabled = 0; WR6 = data; switch (data) { case COMMAND_ENABLE_AFTER_RETI: fatalerror("Z80DMA '%s' Unimplemented WR6 command %02x", tag(), data); break; case COMMAND_READ_STATUS_BYTE: if (LOG) logerror("Z80DMA '%s' CMD Read status Byte\n", tag()); READ_MASK = 0; break; case COMMAND_RESET_AND_DISABLE_INTERRUPTS: WR3 &= ~0x20; m_ip = 0; m_ius = 0; m_force_ready = 0; m_status |= 0x08; break; case COMMAND_INITIATE_READ_SEQUENCE: if (LOG) logerror("Z80DMA '%s' Initiate Read Sequence\n", tag()); m_read_cur_follow = m_read_num_follow = 0; if(READ_MASK & 0x01) { m_read_regs_follow[m_read_num_follow++] = m_status; } if(READ_MASK & 0x02) { m_read_regs_follow[m_read_num_follow++] = BLOCKLEN_L; } //byte counter (low) if(READ_MASK & 0x04) { m_read_regs_follow[m_read_num_follow++] = BLOCKLEN_H; } //byte counter (high) if(READ_MASK & 0x08) { m_read_regs_follow[m_read_num_follow++] = PORTA_ADDRESS_L; } //port A address (low) if(READ_MASK & 0x10) { m_read_regs_follow[m_read_num_follow++] = PORTA_ADDRESS_H; } //port A address (high) if(READ_MASK & 0x20) { m_read_regs_follow[m_read_num_follow++] = PORTB_ADDRESS_L; } //port B address (low) if(READ_MASK & 0x40) { m_read_regs_follow[m_read_num_follow++] = PORTB_ADDRESS_H; } //port B address (high) break; case COMMAND_RESET: if (LOG) logerror("Z80DMA '%s' Reset\n", tag()); m_dma_enabled = 0; m_force_ready = 0; m_ip = 0; m_ius = 0; interrupt_check(); // Needs six reset commands to reset the DMA { UINT8 WRi; for(WRi=0;WRi<7;WRi++) REG(WRi,m_reset_pointer) = 0; m_reset_pointer++; if(m_reset_pointer >= 6) { m_reset_pointer = 0; } } m_status = 0x38; break; case COMMAND_LOAD: m_force_ready = 0; m_addressA = PORTA_ADDRESS; m_addressB = PORTB_ADDRESS; m_count = BLOCKLEN; m_status |= 0x30; if (LOG) logerror("Z80DMA '%s' Load A: %x B: %x N: %x\n", tag(), m_addressA, m_addressB, m_count); break; case COMMAND_DISABLE_DMA: if (LOG) logerror("Z80DMA '%s' Disable DMA\n", tag()); m_dma_enabled = 0; break; case COMMAND_ENABLE_DMA: if (LOG) logerror("Z80DMA '%s' Enable DMA\n", tag()); m_dma_enabled = 1; update_status(); break; case COMMAND_READ_MASK_FOLLOWS: if (LOG) logerror("Z80DMA '%s' Set Read Mask\n", tag()); m_regs_follow[m_num_follow++] = GET_REGNUM(READ_MASK); break; case COMMAND_CONTINUE: if (LOG) logerror("Z80DMA '%s' Continue\n", tag()); m_count = BLOCKLEN; m_dma_enabled = 1; //"match not found" & "end of block" status flags zeroed here m_status |= 0x30; break; case COMMAND_RESET_PORT_A_TIMING: if (LOG) logerror("Z80DMA '%s' Reset Port A Timing\n", tag()); PORTA_TIMING = 0; break; case COMMAND_RESET_PORT_B_TIMING: if (LOG) logerror("Z80DMA '%s' Reset Port B Timing\n", tag()); PORTB_TIMING = 0; break; case COMMAND_FORCE_READY: if (LOG) logerror("Z80DMA '%s' Force Ready\n", tag()); m_force_ready = 1; update_status(); break; case COMMAND_ENABLE_INTERRUPTS: if (LOG) logerror("Z80DMA '%s' Enable IRQ\n", tag()); WR3 |= 0x20; break; case COMMAND_DISABLE_INTERRUPTS: if (LOG) logerror("Z80DMA '%s' Disable IRQ\n", tag()); WR3 &= ~0x20; break; case COMMAND_REINITIALIZE_STATUS_BYTE: if (LOG) logerror("Z80DMA '%s' Reinitialize status byte\n", tag()); m_status |= 0x30; m_ip = 0; break; case 0xFB: if (LOG) logerror("Z80DMA '%s' undocumented command triggered 0x%02X!\n", tag(), data); break; default: fatalerror("Z80DMA '%s' Unknown WR6 command %02x", tag(), data); } } else fatalerror("Z80DMA '%s' Unknown base register %02x", tag(), data); m_cur_follow = 0; } else { int nreg = m_regs_follow[m_cur_follow]; m_regs[nreg] = data; m_cur_follow++; if (m_cur_follow>=m_num_follow) m_num_follow = 0; if (nreg == REGNUM(4,3)) { m_num_follow=0; if (data & 0x08) m_regs_follow[m_num_follow++] = GET_REGNUM(PULSE_CTRL); if (data & 0x10) m_regs_follow[m_num_follow++] = GET_REGNUM(INTERRUPT_VECTOR); m_cur_follow = 0; } m_reset_pointer++; if(m_reset_pointer >= 6) { m_reset_pointer = 0; } } }
void z80dma_device::write(UINT8 data) { if (m_num_follow == 0) { m_reset_pointer = 0; if ((data & 0x87) == 0) // WR2 { if (LOG) logerror("Z80DMA '%s' WR2 %02x\n", tag(), data); WR2 = data; if (data & 0x40) m_regs_follow[m_num_follow++] = GET_REGNUM(PORTB_TIMING); } else if ((data & 0x87) == 0x04) // WR1 { if (LOG) logerror("Z80DMA '%s' WR1 %02x\n", tag(), data); WR1 = data; if (data & 0x40) m_regs_follow[m_num_follow++] = GET_REGNUM(PORTA_TIMING); } else if ((data & 0x80) == 0) // WR0 { if (LOG) logerror("Z80DMA '%s' WR0 %02x\n", tag(), data); WR0 = data; if (data & 0x08) m_regs_follow[m_num_follow++] = GET_REGNUM(PORTA_ADDRESS_L); if (data & 0x10) m_regs_follow[m_num_follow++] = GET_REGNUM(PORTA_ADDRESS_H); if (data & 0x20) m_regs_follow[m_num_follow++] = GET_REGNUM(BLOCKLEN_L); if (data & 0x40) m_regs_follow[m_num_follow++] = GET_REGNUM(BLOCKLEN_H); } else if ((data & 0x83) == 0x80) // WR3 { if (LOG) logerror("Z80DMA '%s' WR3 %02x\n", tag(), data); WR3 = data; if (data & 0x08) m_regs_follow[m_num_follow++] = GET_REGNUM(MASK_BYTE); if (data & 0x10) m_regs_follow[m_num_follow++] = GET_REGNUM(MATCH_BYTE); } else if ((data & 0x83) == 0x81) // WR4 { if (LOG) logerror("Z80DMA '%s' WR4 %02x\n", tag(), data); WR4 = data; if (data & 0x04) m_regs_follow[m_num_follow++] = GET_REGNUM(PORTB_ADDRESS_L); if (data & 0x08) m_regs_follow[m_num_follow++] = GET_REGNUM(PORTB_ADDRESS_H); if (data & 0x10) m_regs_follow[m_num_follow++] = GET_REGNUM(INTERRUPT_CTRL); } else if ((data & 0xC7) == 0x82) // WR5 { if (LOG) logerror("Z80DMA '%s' WR5 %02x\n", tag(), data); WR5 = data; } else if ((data & 0x83) == 0x83) // WR6 { if (LOG) logerror("Z80DMA '%s' WR6 %02x\n", tag(), data); m_dma_enabled = 0; WR6 = data; switch (data) { case COMMAND_ENABLE_AFTER_RETI: fatalerror("Z80DMA '%s' Unimplemented WR6 command %02x\n", tag(), data); case COMMAND_READ_STATUS_BYTE: if (LOG) logerror("Z80DMA '%s' CMD Read status Byte\n", tag()); READ_MASK = 1; m_read_regs_follow[0] = m_status; break; case COMMAND_RESET_AND_DISABLE_INTERRUPTS: WR3 &= ~0x20; m_ip = 0; m_ius = 0; m_force_ready = 0; m_status |= 0x08; break; case COMMAND_INITIATE_READ_SEQUENCE: if (LOG) logerror("Z80DMA '%s' Initiate Read Sequence\n", tag()); m_read_cur_follow = m_read_num_follow = 0; if(READ_MASK & 0x01) { m_read_regs_follow[m_read_num_follow++] = m_status; } if(READ_MASK & 0x02) { m_read_regs_follow[m_read_num_follow++] = m_count & 0xff; } //byte counter (low) if(READ_MASK & 0x04) { m_read_regs_follow[m_read_num_follow++] = m_count >> 8; } //byte counter (high) if(READ_MASK & 0x08) { m_read_regs_follow[m_read_num_follow++] = m_addressA & 0xff; } //port A address (low) if(READ_MASK & 0x10) { m_read_regs_follow[m_read_num_follow++] = m_addressA >> 8; } //port A address (high) if(READ_MASK & 0x20) { m_read_regs_follow[m_read_num_follow++] = m_addressB & 0xff; } //port B address (low) if(READ_MASK & 0x40) { m_read_regs_follow[m_read_num_follow++] = m_addressB >> 8; } //port B address (high)