From 8af5aa8dd33b111e47eb9a9b686cc423ee5b79bb Mon Sep 17 00:00:00 2001 From: cracyc Date: Mon, 19 Aug 2013 02:58:15 +0000 Subject: [PATCH] i186: move 80186 peripherals into the cpu [Carl] leland: finish modernizing the leland sound and use new 80186 [Carl] --- .gitattributes | 2 + src/emu/cpu/cpu.mak | 6 + src/emu/cpu/i86/i186.c | 1683 +++++++++++++++++++++++++ src/emu/cpu/i86/i186.h | 154 +++ src/emu/cpu/i86/i86.c | 477 +------- src/emu/cpu/i86/i86.h | 42 +- src/mame/audio/leland.c | 2243 ++++++---------------------------- src/mame/drivers/ataxx.c | 30 +- src/mame/drivers/bingo.c | 2 +- src/mame/drivers/bingor.c | 2 +- src/mame/drivers/gambl186.c | 2 +- src/mame/drivers/highvdeo.c | 12 +- src/mame/drivers/leland.c | 33 +- src/mame/drivers/neptunp2.c | 2 +- src/mame/drivers/subsino2.c | 2 +- src/mame/drivers/timetrv.c | 2 +- src/mame/includes/leland.h | 129 +- src/mame/machine/leland.c | 2 +- src/mame/video/leland.c | 9 +- src/mess/drivers/compis.c | 5 +- src/mess/drivers/rainbow.c | 8 +- src/mess/drivers/rmnimbus.c | 5 +- src/mess/drivers/tandy2k.c | 8 +- src/mess/drivers/tek410x.c | 2 +- src/mess/includes/compis.h | 24 +- src/mess/includes/rmnimbus.h | 33 +- src/mess/includes/tandy2k.h | 4 +- src/mess/machine/compis.c | 33 +- src/mess/machine/rmnimbus.c | 59 +- 29 files changed, 2437 insertions(+), 2578 deletions(-) create mode 100644 src/emu/cpu/i86/i186.c create mode 100644 src/emu/cpu/i86/i186.h diff --git a/.gitattributes b/.gitattributes index 1723c765ad6..16ec5f943a1 100644 --- a/.gitattributes +++ b/.gitattributes @@ -512,6 +512,8 @@ src/emu/cpu/i8085/8085dasm.c svneol=native#text/plain src/emu/cpu/i8085/i8085.c svneol=native#text/plain src/emu/cpu/i8085/i8085.h svneol=native#text/plain src/emu/cpu/i8085/i8085cpu.h svneol=native#text/plain +src/emu/cpu/i86/i186.c svneol=native#text/plain +src/emu/cpu/i86/i186.h svneol=native#text/plain src/emu/cpu/i86/i286.c svneol=native#text/plain src/emu/cpu/i86/i286.h svneol=native#text/plain src/emu/cpu/i86/i86.c svneol=native#text/plain diff --git a/src/emu/cpu/cpu.mak b/src/emu/cpu/cpu.mak index c6437c33623..989ed1ed979 100644 --- a/src/emu/cpu/cpu.mak +++ b/src/emu/cpu/cpu.mak @@ -798,6 +798,7 @@ $(CPUOBJ)/mcs96/i8xc196.inc: $(CPUSRC)/mcs96/mcs96make.py $(CPUSRC)/mcs96/mcs96o ifneq ($(filter I86,$(CPUS)),) OBJDIRS += $(CPUOBJ)/i86 $(CPUOBJ)/i386 CPUOBJS += $(CPUOBJ)/i86/i86.o +CPUOBJS += $(CPUOBJ)/i86/i186.o CPUOBJS += $(CPUOBJ)/i86/i286.o DASMOBJS += $(CPUOBJ)/i386/i386dasm.o endif @@ -812,6 +813,11 @@ $(CPUOBJ)/i86/i86.o: $(CPUSRC)/i86/i86.c \ $(CPUSRC)/i86/i86.h \ $(CPUSRC)/i86/i86inline.h +$(CPUOBJ)/i86/i186.o: $(CPUSRC)/i86/i186.c \ + $(CPUSRC)/i86/i86.h \ + $(CPUSRC)/i86/i186.h \ + $(CPUSRC)/i86/i86inline.h + $(CPUOBJ)/i86/i286.o: $(CPUSRC)/i86/i286.c \ $(CPUSRC)/i86/i86.h \ $(CPUSRC)/i86/i286.h \ diff --git a/src/emu/cpu/i86/i186.c b/src/emu/cpu/i86/i186.c new file mode 100644 index 00000000000..eaa3ac9b2db --- /dev/null +++ b/src/emu/cpu/i86/i186.c @@ -0,0 +1,1683 @@ +// Peripheral code from rmnimbus driver by Phill Harvey-Smith which is +// based on the Leland sound driver by Aaron Giles and Paul Leaman + +#include "i186.h" +#include "debugger.h" +#include "i86inline.h" + +#define LATCH_INTS 1 +#define LOG_PORTS 0 +#define LOG_INTERRUPTS 0 +#define LOG_INTERRUPTS_EXT 0 +#define LOG_TIMER 0 +#define LOG_OPTIMIZATION 0 +#define LOG_DMA 0 +#define CPU_RESUME_TRIGGER 7123 + +/* external int priority masks */ + +#define EXTINT_CTRL_PRI_MASK 0x07 +#define EXTINT_CTRL_MSK 0x08 +#define EXTINT_CTRL_LTM 0x10 +#define EXTINT_CTRL_CASCADE 0x20 +#define EXTINT_CTRL_SFNM 0x40 + +/* DMA control register */ + +#define DEST_MIO 0x8000 +#define DEST_DECREMENT 0x4000 +#define DEST_INCREMENT 0x2000 +#define DEST_NO_CHANGE (DEST_DECREMENT | DEST_INCREMENT) +#define DEST_INCDEC_MASK (DEST_DECREMENT | DEST_INCREMENT) +#define SRC_MIO 0X1000 +#define SRC_DECREMENT 0x0800 +#define SRC_INCREMENT 0x0400 +#define SRC_NO_CHANGE (SRC_DECREMENT | SRC_INCREMENT) +#define SRC_INCDEC_MASK (SRC_DECREMENT | SRC_INCREMENT) +#define TERMINATE_ON_ZERO 0x0200 +#define INTERRUPT_ON_ZERO 0x0100 +#define SYNC_MASK 0x00C0 +#define SYNC_SOURCE 0x0040 +#define SYNC_DEST 0x0080 +#define CHANNEL_PRIORITY 0x0020 +#define TIMER_DRQ 0x0010 +#define CHG_NOCHG 0x0004 +#define ST_STOP 0x0002 +#define BYTE_WORD 0x0001 + +/* these come from the Intel 80186 datasheet */ +const UINT8 i80186_cpu_device::m_i80186_timing[] = +{ + 45,28, /* exception, IRET */ + 0, 2, 4, 3, /* INTs */ + 2, /* segment overrides */ + 2, 2, 3, /* flag operations */ + 8, 7,19,15, /* arithmetic adjusts */ + 4, 4, /* decimal adjusts */ + 2, 4, /* sign extension */ + 2,18, 6, 2, 6,11, /* misc */ + + 14,14,14, /* direct JMPs */ + 11,17,26, /* indirect JMPs */ + 15,23, /* direct CALLs */ + 13,19,38, /* indirect CALLs */ + 16,22,18,25, /* returns */ + 4,13, 5,15, /* conditional JMPs */ + 6,16, 6,16, /* loops */ + + 10,10, 8, 8, /* port reads */ + 9, 9, 7, 7, /* port writes */ + + 2, 9,12, /* move, 8-bit */ + 3,12, /* move, 8-bit immediate */ + 2, 9,12, /* move, 16-bit */ + 4,13, /* move, 16-bit immediate */ + 8, 8, 9, 9, /* move, AL/AX memory */ + 2,11, 2,11, /* move, segment registers */ + 4,17, /* exchange, 8-bit */ + 4,17, 3, /* exchange, 16-bit */ + + 10,16, 9, 9, /* pushes */ + 10,20, 8, 8, /* pops */ + + 3,10,10, /* ALU ops, 8-bit */ + 4,16,10, /* ALU ops, 8-bit immediate */ + 3,10,10, /* ALU ops, 16-bit */ + 4,16,10, /* ALU ops, 16-bit immediate */ + 4,16,10, /* ALU ops, 16-bit w/8-bit immediate */ + 26,35,32,41, /* MUL */ + 25,34,31,40, /* IMUL */ + 29,38,35,44, /* DIV */ + 44,53,50,59, /* IDIV */ + 3, 3,15,15, /* INC/DEC */ + 3, 3,10,10, /* NEG/NOT */ + + 2, 5, 1, /* reg shift/rotate */ + 15,17, 1, /* m8 shift/rotate */ + 15,17, 1, /* m16 shift/rotate */ + + 22, 5,22, /* CMPS 8-bit */ + 22, 5,22, /* CMPS 16-bit */ + 15, 5,15, /* SCAS 8-bit */ + 15, 5,15, /* SCAS 16-bit */ + 12, 6,11, /* LODS 8-bit */ + 12, 6,11, /* LODS 16-bit */ + 10, 6, 9, /* STOS 8-bit */ + 10, 6, 9, /* STOS 16-bit */ + 14, 8, 8, /* MOVS 8-bit */ + 14, 8, 8, /* MOVS 16-bit */ + + 14, 8, 8, /* (80186) INS 8-bit */ + 14, 8, 8, /* (80186) INS 16-bit */ + 14, 8, 8, /* (80186) OUTS 8-bit */ + 14, 8, 8, /* (80186) OUTS 16-bit */ + 14,68,83, /* (80186) PUSH immediate, PUSHA/POPA */ + 22,29, /* (80186) IMUL immediate 8-bit */ + 25,32, /* (80186) IMUL immediate 16-bit */ + 15,25,4,16, 8, /* (80186) ENTER/LEAVE */ + 33, /* (80186) BOUND */ +}; + +const device_type I80186 = &device_creator; +const device_type I80188 = &device_creator; + +i80188_cpu_device::i80188_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : i80186_cpu_device(mconfig, I80188, "I80188", tag, owner, clock, "i80188", __FILE__, 8) +{ + memcpy(m_timing, m_i80186_timing, sizeof(m_i80186_timing)); + m_fetch_xor = 0; +} + +i80186_cpu_device::i80186_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : i8086_common_cpu_device(mconfig, I80186, "I80186", tag, owner, clock, "i80186", __FILE__) + , m_program_config("program", ENDIANNESS_LITTLE, 16, 20, 0) + , m_io_config("io", ENDIANNESS_LITTLE, 16, 16, 0) + , m_read_slave_ack_func(*this) + , m_out_chip_select_func(*this) + , m_out_tmrout0_func(*this) + , m_out_tmrout1_func(*this) +{ + memcpy(m_timing, m_i80186_timing, sizeof(m_i80186_timing)); + m_fetch_xor = BYTE_XOR_LE(0); +} + +i80186_cpu_device::i80186_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source, int data_bus_size) + : i8086_common_cpu_device(mconfig, type, name, tag, owner, clock, shortname, source) + , m_program_config("program", ENDIANNESS_LITTLE, data_bus_size, 20, 0) + , m_io_config("io", ENDIANNESS_LITTLE, data_bus_size, 16, 0) + , m_read_slave_ack_func(*this) + , m_out_chip_select_func(*this) + , m_out_tmrout0_func(*this) + , m_out_tmrout1_func(*this) +{ +} + +UINT8 i80186_cpu_device::fetch_op() +{ + UINT8 data; + data = m_direct->read_decrypted_byte(pc(), m_fetch_xor); + m_ip++; + return data; +} + +UINT8 i80186_cpu_device::fetch() +{ + UINT8 data; + data = m_direct->read_raw_byte(pc(), m_fetch_xor); + m_ip++; + return data; +} + +void i80186_cpu_device::execute_run() +{ + while(m_icount > 0 ) + { + if ( m_seg_prefix_next ) + { + m_seg_prefix = true; + m_seg_prefix_next = false; + } + else + { + m_prev_ip = m_ip; + m_seg_prefix = false; + + /* Dispatch IRQ */ + if ( m_pending_irq && m_no_interrupt == 0 ) + { + if ( m_pending_irq & NMI_IRQ ) + { + interrupt(2); + m_pending_irq &= ~NMI_IRQ; + m_halt = false; + } + else if ( m_IF ) + { + /* the actual vector is retrieved after pushing flags */ + /* and clearing the IF */ + interrupt(-1); + m_halt = false; + } + } + + if(m_halt) + { + m_icount = 0; + return; + } + + /* No interrupt allowed between last instruction and this one */ + if ( m_no_interrupt ) + { + m_no_interrupt--; + } + + /* trap should allow one instruction to be executed */ + if ( m_fire_trap ) + { + if ( m_fire_trap >= 2 ) + { + interrupt(1); + m_fire_trap = 0; + } + else + { + m_fire_trap++; + } + } + } + + debugger_instruction_hook( this, pc() ); + + UINT8 op = fetch_op(); + + switch(op) + { + case 0x60: // i_pusha + { + UINT32 tmp = m_regs.w[SP]; + + PUSH(m_regs.w[AX]); + PUSH(m_regs.w[CX]); + PUSH(m_regs.w[DX]); + PUSH(m_regs.w[BX]); + PUSH(tmp); + PUSH(m_regs.w[BP]); + PUSH(m_regs.w[SI]); + PUSH(m_regs.w[DI]); + CLK(PUSHA); + } + break; + + case 0x61: // i_popa + m_regs.w[DI] = POP(); + m_regs.w[SI] = POP(); + m_regs.w[BP] = POP(); + POP(); + m_regs.w[BX] = POP(); + m_regs.w[DX] = POP(); + m_regs.w[CX] = POP(); + m_regs.w[AX] = POP(); + CLK(POPA); + break; + + case 0x62: // i_bound + { + UINT32 low,high,tmp; + m_modrm = fetch(); + low = GetRMWord(); + high = GetnextRMWord(); + tmp = RegWord(); + if (tmphigh) + interrupt(5); + CLK(BOUND); + logerror("%s: %06x: bound %04x high %04x low %04x tmp\n", tag(), pc(), high, low, tmp); + } + break; + + case 0x68: // i_push_d16 + PUSH( fetch_word() ); + CLK(PUSH_IMM); + break; + + case 0x69: // i_imul_d16 + { + UINT32 tmp; + DEF_r16w(); + tmp = fetch_word(); + m_dst = (INT32)((INT16)m_src)*(INT32)((INT16)tmp); + m_CarryVal = m_OverVal = (((INT32)m_dst) >> 15 != 0) && (((INT32)m_dst) >> 15 != -1); + RegWord(m_dst); + CLKM(IMUL_RRI16, IMUL_RMI16); + } + break; + + case 0x6a: // i_push_d8 + PUSH( (UINT16)((INT16)((INT8)fetch())) ); + CLK(PUSH_IMM); + break; + + case 0x6b: // i_imul_d8 + { + UINT32 src2; + DEF_r16w(); + src2= (UINT16)((INT16)((INT8)fetch())); + m_dst = (INT32)((INT16)m_src)*(INT32)((INT16)src2); + m_CarryVal = m_OverVal = (((INT32)m_dst) >> 15 != 0) && (((INT32)m_dst) >> 15 != -1); + RegWord(m_dst); + CLKM(IMUL_RRI8, IMUL_RMI8); + } + break; + + case 0x6c: // i_insb + i_insb(); + break; + + case 0x6d: // i_insw + i_insw(); + break; + + case 0x6e: // i_outsb + i_outsb(); + break; + + case 0x6f: // i_outsw + i_outsw(); + break; + + case 0x8e: // i_mov_sregw + m_modrm = fetch(); + m_src = GetRMWord(); + CLKM(MOV_SR,MOV_SM); + switch (m_modrm & 0x38) + { + case 0x00: /* mov es,ew */ + m_sregs[ES] = m_src; + break; + case 0x10: /* mov ss,ew */ + m_sregs[SS] = m_src; + m_no_interrupt = 1; + break; + case 0x18: /* mov ds,ew */ + m_sregs[DS] = m_src; + break; + default: + logerror("%s: %06x: Mov Sreg - Invalid register\n", tag(), pc()); + m_ip = m_prev_ip; + interrupt(6); + } + break; + + case 0xc0: // i_rotshft_bd8 + { + UINT8 c; + m_modrm = fetch(); + m_src = GetRMByte(); + m_dst = m_src; + c = fetch() & 0x1f; + CLKM(ROT_REG_BASE,ROT_M8_BASE); + m_icount -= m_timing[ROT_REG_BIT] * c; + if (c) + { + switch ( m_modrm & 0x38 ) + { + case 0x00: do { ROL_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; + case 0x08: do { ROR_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; + case 0x10: do { ROLC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; + case 0x18: do { RORC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; + case 0x30: + case 0x20: SHL_BYTE(c); break; + case 0x28: SHR_BYTE(c); break; + case 0x38: SHRA_BYTE(c); break; + } + } + } + break; + + case 0xc1: // i_rotshft_wd8 + { + UINT8 c; + m_modrm = fetch(); + m_src = GetRMWord(); + m_dst = m_src; + c = fetch() & 0x1f; + CLKM(ROT_REG_BASE,ROT_M16_BASE); + m_icount -= m_timing[ROT_REG_BIT] * c; + if (c) + { + switch ( m_modrm & 0x38 ) + { + case 0x00: do { ROL_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; + case 0x08: do { ROR_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; + case 0x10: do { ROLC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; + case 0x18: do { RORC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; + case 0x30: + case 0x20: SHL_WORD(c); break; + case 0x28: SHR_WORD(c); break; + case 0x38: SHRA_WORD(c); break; + } + } + } + break; + + case 0xc8: // i_enter + { + UINT16 nb = fetch(); + UINT32 level; + + nb |= fetch() << 8; + level = fetch(); + CLK(!level ? ENTER0 : (level == 1) ? ENTER1 : ENTER_BASE); + if(level > 1) + m_icount -= level * m_timing[ENTER_COUNT]; + PUSH(m_regs.w[BP]); + m_regs.w[BP] = m_regs.w[SP]; + m_regs.w[SP] -= nb; + for (int i=1; i0); PutbackRMByte(m_dst); break; + case 0x08: do { ROR_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; + case 0x10: do { ROLC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; + case 0x18: do { RORC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; + case 0x30: + case 0x20: SHL_BYTE(c); break; + case 0x28: SHR_BYTE(c); break; + case 0x38: SHRA_BYTE(c); break; + } + } + } + break; + + case 0xd3: // i_rotshft_wcl + { + UINT8 c; + + m_modrm = fetch(); + m_src = GetRMWord(); + m_dst = m_src; + c = m_regs.b[CL] & 0x1f; + CLKM(ROT_REG_BASE,ROT_M16_BASE); + m_icount -= m_timing[ROT_REG_BIT] * c; + if (c) + { + switch ( m_modrm & 0x38 ) + { + case 0x00: do { ROL_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; + case 0x08: do { ROR_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; + case 0x10: do { ROLC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; + case 0x18: do { RORC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; + case 0x30: + case 0x20: SHL_WORD(c); break; + case 0x28: SHR_WORD(c); break; + case 0x38: SHRA_WORD(c); break; + } + } + } + break; + + case 0xd8: // i_esc + case 0xd9: + case 0xda: + case 0xdb: + case 0xdc: + case 0xdd: + case 0xde: + case 0xdf: + if(m_reloc & 0x8000) + { + m_ip = m_prev_ip; + interrupt(7); + break; + } + m_modrm = fetch(); + GetRMByte(); + CLK(NOP); + // The 80187 has the FSTSW AX instruction + if((m_modrm == 0xe0) && (op == 0xdf)) + m_regs.w[AX] = 0xffff; // FPU not present + break; + + case 0xf2: // i_repne + case 0xf3: + { + bool pass = false; + UINT8 next = repx_op(); + UINT16 c = m_regs.w[CX]; + + switch (next) + { + case 0x6c: CLK(OVERRIDE); if (c) do { i_insb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; + case 0x6d: CLK(OVERRIDE); if (c) do { i_insw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; + case 0x6e: CLK(OVERRIDE); if (c) do { i_outsb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; + case 0x6f: CLK(OVERRIDE); if (c) do { i_outsw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; + default: + // Decrement IP and pass on + m_ip -= 1 + (m_seg_prefix_next ? 1 : 0); + pass = true; + } + if(!pass) + { + if(c) + m_ip = m_prev_ip; + break; + } + } + + default: + if(!common_op(op)) + { + m_icount -= 10; // UD fault timing? + logerror("%s: %06x: Invalid Opcode %02x\n", tag(), pc(), op); + m_ip = m_prev_ip; + interrupt(6); // 80186 has #UD + break; + } + } + } +} + +void i80186_cpu_device::device_start() +{ + i8086_common_cpu_device::device_start(); + state_add( I8086_ES, "ES", m_sregs[ES] ).callimport().callexport().formatstr("%04X"); + state_add( I8086_CS, "CS", m_sregs[CS] ).callimport().callexport().formatstr("%04X"); + state_add( I8086_SS, "SS", m_sregs[SS] ).callimport().callexport().formatstr("%04X"); + state_add( I8086_DS, "DS", m_sregs[DS] ).callimport().callexport().formatstr("%04X"); + state_add( I8086_VECTOR, "V", m_int_vector).callimport().callexport().formatstr("%02X"); + + state_add(STATE_GENPC, "curpc", m_pc).callimport().callexport().formatstr("%05X"); + + save_item(NAME(m_timer[0].control)); + save_item(NAME(m_timer[0].maxA)); + save_item(NAME(m_timer[0].maxB)); + save_item(NAME(m_timer[0].active_count)); + save_item(NAME(m_timer[0].count)); + save_item(NAME(m_timer[0].time_timer_active)); + save_item(NAME(m_timer[0].last_time)); + save_item(NAME(m_timer[1].control)); + save_item(NAME(m_timer[1].maxA)); + save_item(NAME(m_timer[1].maxB)); + save_item(NAME(m_timer[1].active_count)); + save_item(NAME(m_timer[1].count)); + save_item(NAME(m_timer[1].time_timer_active)); + save_item(NAME(m_timer[1].last_time)); + save_item(NAME(m_timer[2].control)); + save_item(NAME(m_timer[2].maxA)); + save_item(NAME(m_timer[2].count)); + save_item(NAME(m_timer[2].time_timer_active)); + save_item(NAME(m_timer[2].last_time)); + save_item(NAME(m_dma[0].source)); + save_item(NAME(m_dma[0].dest)); + save_item(NAME(m_dma[0].count)); + save_item(NAME(m_dma[0].control)); + save_item(NAME(m_dma[1].source)); + save_item(NAME(m_dma[1].dest)); + save_item(NAME(m_dma[1].count)); + save_item(NAME(m_dma[1].control)); + save_item(NAME(m_intr.pending)); + save_item(NAME(m_intr.ack_mask)); + save_item(NAME(m_intr.priority_mask)); + save_item(NAME(m_intr.in_service)); + save_item(NAME(m_intr.request)); + save_item(NAME(m_intr.status)); + save_item(NAME(m_intr.poll_status)); + save_item(NAME(m_intr.timer)); + save_item(NAME(m_intr.dma)); + save_item(NAME(m_intr.ext)); + save_item(NAME(m_mem.lower)); + save_item(NAME(m_mem.upper)); + save_item(NAME(m_mem.middle)); + save_item(NAME(m_mem.middle_size)); + save_item(NAME(m_mem.peripheral)); + save_item(NAME(m_reloc)); + + m_timer[0].int_timer = timer_alloc(TIMER_INT0); + m_timer[1].int_timer = timer_alloc(TIMER_INT1); + m_timer[2].int_timer = timer_alloc(TIMER_INT2); + m_timer[0].time_timer = timer_alloc(TIMER_TIME0); + m_timer[1].time_timer = timer_alloc(TIMER_TIME1); + m_timer[2].time_timer = timer_alloc(TIMER_TIME2); + m_dma[0].finish_timer = timer_alloc(TIMER_DMA0); + m_dma[1].finish_timer = timer_alloc(TIMER_DMA1); + + m_out_tmrout0_func.resolve_safe(); + m_out_tmrout1_func.resolve_safe(); + m_read_slave_ack_func.resolve_safe(0); + m_out_chip_select_func.resolve_safe(); +} + +void i80186_cpu_device::device_reset() +{ + i8086_common_cpu_device::device_reset(); + /* reset the interrupt state */ + m_intr.priority_mask = 0x0007; + m_intr.timer = 0x000f; + m_intr.dma[0] = 0x000f; + m_intr.dma[1] = 0x000f; + m_intr.ext[0] = 0x000f; + m_intr.ext[1] = 0x000f; + m_intr.ext[2] = 0x000f; + m_intr.ext[3] = 0x000f; + m_intr.in_service = 0x0000; + + m_intr.pending = 0x0000; + m_intr.ack_mask = 0x0000; + m_intr.request = 0x0000; + m_intr.status = 0x0000; + m_intr.poll_status = 0x0000; + m_reloc = 0x20ff; + m_dma[0].drq_delay = false; + m_dma[1].drq_delay = false; + m_dma[0].drq_state = false; + m_dma[1].drq_state = false; + + set_irq_acknowledge_callback(device_irq_acknowledge_delegate(FUNC(i80186_cpu_device::int_callback),this)); +} + +UINT8 i80186_cpu_device::read_port_byte(UINT16 port) +{ + if(!(m_reloc & 0x1000) && (port >> 8) == (m_reloc & 0xff)) + { + UINT16 ret = internal_port_r(*m_io, (port >> 1) - ((m_reloc & 0xff) << 7), (port & 1) ? 0xff00 : 0x00ff); + return (port & 1) ? (ret >> 8) : (ret & 0xff); + } + return m_io->read_byte(port); +} + +UINT16 i80186_cpu_device::read_port_word(UINT16 port) +{ + if(!(m_reloc & 0x1000) && (port >> 8) == (m_reloc & 0xff)) + { + if(port & 1) + { + UINT8 low = read_port_byte(port); + return read_port_byte(port + 1) << 8 | low; + } + return internal_port_r(*m_io, (port >> 1) - ((m_reloc & 0xff) << 7)); + } + return m_io->read_word_unaligned(port); +} + +void i80186_cpu_device::write_port_byte(UINT16 port, UINT8 data) +{ + if(!(m_reloc & 0x1000) && (port >> 8) == (m_reloc & 0xff)) + internal_port_w(*m_io, (port >> 1) - ((m_reloc & 0xff) << 7), (port & 1) ? (data << 8) : data, (port & 1) ? 0xff00 : 0x00ff); + else + m_io->write_byte(port, data); +} + +void i80186_cpu_device::write_port_word(UINT16 port, UINT16 data) +{ + if(!(m_reloc & 0x1000) && (port >> 8) == (m_reloc & 0xff)) + { + if(port & 1) + { + write_port_byte(port, data & 0xff); + write_port_byte(port + 1, data >> 8); + } + else + internal_port_w(*m_io, (port >> 1) - ((m_reloc & 0xff) << 7), data); + } + else + m_io->write_word_unaligned(port, data); +} + +/************************************* + * + * 80186 interrupt controller + * + *************************************/ +IRQ_CALLBACK_MEMBER(i80186_cpu_device::int_callback) +{ + UINT8 vector; + UINT16 old; + UINT16 oldreq; + + if (LOG_INTERRUPTS) + logerror("(%f) **** Acknowledged interrupt vector %02X\n", machine().time().as_double(), m_intr.poll_status & 0x1f); + + /* clear the interrupt */ + set_input_line(0, CLEAR_LINE); + m_intr.pending = 0; + + oldreq=m_intr.request; + + /* clear the request and set the in-service bit */ +#if LATCH_INTS + m_intr.request &= ~m_intr.ack_mask; +#else + m_intr.request &= ~(m_intr.ack_mask & 0x0f); +#endif + + if((LOG_INTERRUPTS) && (m_intr.request!=oldreq)) + logerror("intr.request changed from %02X to %02X\n",oldreq,m_intr.request); + + old=m_intr.in_service; + + m_intr.in_service |= m_intr.ack_mask; + + if((LOG_INTERRUPTS) && (m_intr.in_service!=old)) + logerror("intr.in_service changed from %02X to %02X\n",old,m_intr.in_service); + + if (m_intr.ack_mask == 0x0001) + { + switch (m_intr.poll_status & 0x1f) + { + case 0x08: m_intr.status &= ~0x01; break; + case 0x12: m_intr.status &= ~0x02; break; + case 0x13: m_intr.status &= ~0x04; break; + } + } + m_intr.ack_mask = 0; + + /* a request no longer pending */ + m_intr.poll_status &= ~0x8000; + + /* return the vector */ + switch(m_intr.poll_status & 0x1F) + { + case 0x0C : vector=(m_intr.ext[0] & EXTINT_CTRL_CASCADE) ? m_read_slave_ack_func(0) : (m_intr.poll_status & 0x1f); break; + case 0x0D : vector=(m_intr.ext[1] & EXTINT_CTRL_CASCADE) ? m_read_slave_ack_func(1) : (m_intr.poll_status & 0x1f); break; + default : + vector=m_intr.poll_status & 0x1f; break; + } + + if (LOG_INTERRUPTS) + { + logerror("intr.ext[0]=%04X intr.ext[1]=%04X\n",m_intr.ext[0],m_intr.ext[1]); + logerror("Int %02X Calling vector %02X\n",m_intr.poll_status,vector); + } + + return vector; +} + + +void i80186_cpu_device::update_interrupt_state() +{ + int new_vector = 0; + int Priority; + int IntNo; + + if (LOG_INTERRUPTS) + logerror("update_interrupt_status: req=%04X stat=%04X serv=%04X priority_mask=%4X\n", m_intr.request, m_intr.status, m_intr.in_service, m_intr.priority_mask); + + /* loop over priorities */ + for (Priority = 0; Priority <= m_intr.priority_mask; Priority++) + { + /* note: by checking 4 bits, we also verify that the mask is off */ + if ((m_intr.timer & 0x0F) == Priority) + { + /* if we're already servicing something at this level, don't generate anything new */ + if (m_intr.in_service & 0x01) + return; + + /* if there's something pending, generate an interrupt */ + if (m_intr.status & 0x07) + { + if (m_intr.status & 1) + new_vector = 0x08; + else if (m_intr.status & 2) + new_vector = 0x12; + else if (m_intr.status & 4) + new_vector = 0x13; + else + logerror("Invalid timer interrupt!\n"); + + /* set the clear mask and generate the int */ + m_intr.ack_mask = 0x0001; + goto generate_int; + } + } + + /* check DMA interrupts */ + for (IntNo = 0; IntNo < 2; IntNo++) + if ((m_intr.dma[IntNo] & 0x0F) == Priority) + { + /* if we're already servicing something at this level, don't generate anything new */ + if (m_intr.in_service & (0x04 << IntNo)) + return; + + /* if there's something pending, generate an interrupt */ + if (m_intr.request & (0x04 << IntNo)) + { + new_vector = 0x0a + IntNo; + + /* set the clear mask and generate the int */ + m_intr.ack_mask = 0x0004 << IntNo; + goto generate_int; + } + } + + /* check external interrupts */ + for (IntNo = 0; IntNo < 4; IntNo++) + if ((m_intr.ext[IntNo] & 0x0F) == Priority) + { + if (LOG_INTERRUPTS) + logerror("Int%d priority=%d\n",IntNo,Priority); + + /* if we're already servicing something at this level, don't generate anything new */ + if (m_intr.in_service & (0x10 << IntNo)) + return; + + /* if there's something pending, generate an interrupt */ + if (m_intr.request & (0x10 << IntNo)) + { + /* otherwise, generate an interrupt for this request */ + new_vector = 0x0c + IntNo; + + /* set the clear mask and generate the int */ + m_intr.ack_mask = 0x0010 << IntNo; + goto generate_int; + } + } + } + return; + +generate_int: + /* generate the appropriate interrupt */ + m_intr.poll_status = 0x8000 | new_vector; + if (!m_intr.pending) + set_input_line(0, ASSERT_LINE); + m_intr.pending = 1; + machine().scheduler().trigger(CPU_RESUME_TRIGGER); + if (LOG_OPTIMIZATION) logerror(" - trigger due to interrupt pending\n"); + if (LOG_INTERRUPTS) logerror("(%f) **** Requesting interrupt vector %02X\n", machine().time().as_double(), new_vector); +} + + +void i80186_cpu_device::handle_eoi(int data) +{ + int Priority; + int IntNo; + int handled=0; + + /* specific case */ + if (!(data & 0x8000)) + { + /* turn off the appropriate in-service bit */ + switch (data & 0x1f) + { + case 0x08: m_intr.in_service &= ~0x01; break; + case 0x12: m_intr.in_service &= ~0x01; break; + case 0x13: m_intr.in_service &= ~0x01; break; + case 0x0a: m_intr.in_service &= ~0x04; break; + case 0x0b: m_intr.in_service &= ~0x08; break; + case 0x0c: m_intr.in_service &= ~0x10; break; + case 0x0d: m_intr.in_service &= ~0x20; break; + case 0x0e: m_intr.in_service &= ~0x40; break; + case 0x0f: m_intr.in_service &= ~0x80; break; + default: logerror("%05X:ERROR - 80186 EOI with unknown vector %02X\n", pc(), data & 0x1f); + } + if (LOG_INTERRUPTS) logerror("(%f) **** Got EOI for vector %02X\n", machine().time().as_double(), data & 0x1f); + } + + /* non-specific case */ + else + { + /* loop over priorities */ + for (Priority = 0; ((Priority <= 7) && !handled); Priority++) + { + /* check for in-service timers */ + if ((m_intr.timer & 0x07) == Priority && (m_intr.in_service & 0x01)) + { + m_intr.in_service &= ~0x01; + if (LOG_INTERRUPTS) logerror("(%f) **** Got EOI for timer\n", machine().time().as_double()); + handled=1; + } + + /* check for in-service DMA interrupts */ + for (IntNo = 0; ((IntNo < 2) && !handled) ; IntNo++) + if ((m_intr.dma[IntNo] & 0x07) == Priority && (m_intr.in_service & (0x04 << IntNo))) + { + m_intr.in_service &= ~(0x04 << IntNo); + if (LOG_INTERRUPTS) logerror("(%f) **** Got EOI for DMA%d\n", machine().time().as_double(), IntNo); + handled=1; + } + + /* check external interrupts */ + for (IntNo = 0; ((IntNo < 4) && !handled) ; IntNo++) + if ((m_intr.ext[IntNo] & 0x07) == Priority && (m_intr.in_service & (0x10 << IntNo))) + { + m_intr.in_service &= ~(0x10 << IntNo); + if (LOG_INTERRUPTS) logerror("(%f) **** Got EOI for INT%d\n", machine().time().as_double(), IntNo); + handled=1; + } + } + } +} + +/* Trigger an external interrupt, optionally supplying the vector to take */ +void i80186_cpu_device::external_int(UINT16 intno, int state, UINT8 vector) +{ + if (LOG_INTERRUPTS_EXT) logerror("generating external int %02X, vector %02X\n",intno,vector); + + if(!state) + return; + + // Turn on the requested request bit and handle interrupt + m_intr.request |= (0x010 << intno); + update_interrupt_state(); +} + +/************************************* + * + * 80186 internal timers + * + *************************************/ + +void i80186_cpu_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + switch(id) + { + case TIMER_INT0: + case TIMER_INT1: + case TIMER_INT2: + { + int which = param; + struct timer_state *t = &m_timer[which]; + + if (LOG_TIMER) logerror("Hit interrupt callback for timer %d\n", which); + + /* set the max count bit */ + t->control |= 0x0020; + + /* request an interrupt */ + if (t->control & 0x2000) + { + m_intr.status |= 0x01 << which; + update_interrupt_state(); + if (LOG_TIMER) logerror(" Generating timer interrupt\n"); + } + + if(which == 2) + { + if((m_dma[0].control & (TIMER_DRQ | ST_STOP)) == TIMER_DRQ) + drq_callback(0); + if((m_dma[1].control & (TIMER_DRQ | ST_STOP)) == TIMER_DRQ) + drq_callback(1); + if((m_timer[0].control & 0x800c) == 0x8008) + inc_timer(0); + if((m_timer[1].control & 0x800c) == 0x8008) + inc_timer(1); + } + else + { + if(!(t->control & 2)) + { + if(which) + m_out_tmrout1_func(1); + else + m_out_tmrout0_func(1); + } + else + { + if(which) + m_out_tmrout1_func(t->active_count); + else + m_out_tmrout0_func(t->active_count); + } + } + + /* if we're continuous, reset */ + if (t->control & 0x0001) + { + int count; + if((t->control & 2) && (which != 2)) + { + count = t->active_count ? t->maxA : t->maxB; + t->active_count = !t->active_count; + } + else + count = t->maxA; + + count = count ? count : 0x10000; + t->int_timer->adjust((attotime::from_hz(clock()/4) * count), which); + if (LOG_TIMER) logerror(" Repriming interrupt\n"); + } + else + t->int_timer->adjust(attotime::never, which); + break; + } + case TIMER_DMA0: + case TIMER_DMA1: + { + int which = param; + struct dma_state *d = &m_dma[which]; + + d->drq_delay = false; + if(d->drq_state); + drq_callback(which); + break; + } + case TIMER_TIME0: + case TIMER_TIME1: + case TIMER_TIME2: + default: + break; + } +} + + +void i80186_cpu_device::internal_timer_sync(int which) +{ + struct timer_state *t = &m_timer[which]; + + /* if we have a timing timer running, adjust the count */ + if (t->time_timer_active && !(t->control & 0x0c)) + { + t->last_time = t->time_timer->elapsed(); + } +} + +void i80186_cpu_device::inc_timer(int which) +{ + struct timer_state *t = &m_timer[which]; + + t->count++; + if(t->control & 2) + { + if(t->count == (t->active_count ? t->maxB : t->maxA)) + device_timer(*t->int_timer, which, which, NULL); + } + else if(t->count == t->maxA) + device_timer(*t->int_timer, which, which, NULL); +} + +void i80186_cpu_device::internal_timer_update(int which,int new_count,int new_maxA,int new_maxB,int new_control) +{ + struct timer_state *t = &m_timer[which]; + int update_int_timer = 0; + + if (LOG_TIMER) + logerror("internal_timer_update: %d, new_count=%d, new_maxA=%d, new_maxB=%d,new_control=%d\n",which,new_count,new_maxA,new_maxB,new_control); + + /* if we have a new count and we're on, update things */ + if (new_count != -1) + { + if (t->control & 0x8000) + { + internal_timer_sync(which); + update_int_timer = 1; + } + t->count = new_count; + } + + /* if we have a new max and we're on, update things */ + if (new_maxA != -1 && new_maxA != t->maxA) + { + if (t->control & 0x8000) + { + internal_timer_sync(which); + update_int_timer = 1; + } + t->maxA = new_maxA; + if (new_maxA == 0) + { + new_maxA = 0x10000; + } + } + + /* if we have a new max and we're on, update things */ + if (new_maxB != -1 && new_maxB != t->maxB) + { + if (t->control & 0x8000) + { + internal_timer_sync(which); + update_int_timer = 1; + } + + t->maxB = new_maxB; + + if (new_maxB == 0) + { + new_maxB = 0x10000; + } + } + + + /* handle control changes */ + if (new_control != -1) + { + int diff; + UINT16 resbits = (which == 2) ? 0x1fde : 0x1fc0; + + /* merge back in the bits we don't modify */ + new_control = (new_control & ~resbits) | (t->control & resbits); + + /* handle the /INH bit */ + if (!(new_control & 0x4000)) + new_control = (new_control & ~0x8000) | (t->control & 0x8000); + new_control &= ~0x4000; + + /* check for control bits we don't handle */ + diff = new_control ^ t->control; + if (diff & 0x0010) + logerror("%05X:ERROR! -unsupported timer mode %04X\n", pc(), new_control); + + /* if we have real changes, update things */ + if (diff != 0) + { + /* if we're going off, make sure our timers are gone */ + if ((diff & 0x8000) && !(new_control & 0x8000)) + { + /* compute the final count */ + internal_timer_sync(which); + + /* nuke the timer and force the interrupt timer to be recomputed */ + t->time_timer->adjust(attotime::never, which); + t->time_timer_active = 0; + update_int_timer = 1; + } + + /* if we're going on, start the timers running except with external clock or prescale */ + else if ((diff & 0x8000) && (new_control & 0x8000) && !(new_control & 0xc)) + { + /* start the timing */ + t->time_timer->adjust(attotime::never, which); + t->time_timer_active = 1; + update_int_timer = 1; + } + + /* if something about the interrupt timer changed, force an update */ + if (!(diff & 0x8000) && (diff & 0x2000)) + { + internal_timer_sync(which); + update_int_timer = 1; + } + } + + /* set the new control register */ + t->control = new_control; + } + + /* update the interrupt timer */ + if (update_int_timer) + { + t->active_count = 0; + if ((t->control & 0x8000) && !(t->control & 4)) + { + int diff = t->maxA - t->count; + if (diff <= 0) + diff += 0x10000; + t->int_timer->adjust(attotime::from_hz(clock()/4) * diff, which); + if (LOG_TIMER) logerror("Set interrupt timer for %d\n", which); + } + else + { + t->int_timer->adjust(attotime::never, which); + } + } +} + + + +/************************************* + * + * 80186 internal DMA + * + *************************************/ + +void i80186_cpu_device::update_dma_control(int which, int new_control) +{ + struct dma_state *d = &m_dma[which]; + int diff; + + /* handle the CHG bit */ + if (!(new_control & CHG_NOCHG)) + new_control = (new_control & ~ST_STOP) | (d->control & ST_STOP); + new_control &= ~CHG_NOCHG; + + /* check for control bits we don't handle */ + diff = new_control ^ d->control; + if ((LOG_DMA) && (diff & 0x6811)) + logerror("%05X:ERROR! - unsupported DMA mode %04X\n", pc(), new_control); + + if (LOG_DMA) logerror("Initiated DMA %d - count = %04X, source = %04X, dest = %04X\n", which, d->count, d->source, d->dest); + + /* set the new control register */ + d->control = new_control; +} + +void i80186_cpu_device::drq_callback(int which) +{ + struct dma_state *dma = &m_dma[which]; + + UINT16 dma_word; + UINT8 dma_byte; + UINT8 incdec_size; + + if(dma->drq_delay) + return; + + if (LOG_DMA>1) + logerror("Control=%04X, src=%05X, dest=%05X, count=%04X\n",dma->control,dma->source,dma->dest,dma->count); + + if(!(dma->control & ST_STOP)) + { + if(LOG_DMA) + logerror("%05X:ERROR! - drq%d with dma channel stopped\n", pc(), which); + return; + } + + address_space *dest_space = (dma->control & DEST_MIO) ? m_program : m_io; + address_space *src_space = (dma->control & SRC_MIO) ? m_program : m_io; + + // Do the transfer, 80188 is incapable of word transfers + if((dma->control & BYTE_WORD) && (m_program->data_width() == 16)) + { + dma_word=src_space->read_word(dma->source); + dest_space->write_word(dma->dest,dma_word); + incdec_size=2; + } + else + { + dma_byte=src_space->read_byte(dma->source); + dest_space->write_byte(dma->dest,dma_byte); + incdec_size=1; + } + + // Increment or Decrement destination and source pointers as needed + switch (dma->control & DEST_INCDEC_MASK) + { + case DEST_DECREMENT: + dma->dest -= incdec_size; + break; + case DEST_INCREMENT: + dma->dest += incdec_size; + break; + } + + switch (dma->control & SRC_INCDEC_MASK) + { + case SRC_DECREMENT: + dma->source -= incdec_size; + break; + case SRC_INCREMENT: + dma->source += incdec_size; + break; + } + + // decrement count + dma->count -= 1; + + // Terminate if count is zero, and terminate flag set + if((dma->control & TERMINATE_ON_ZERO) && (dma->count==0)) + { + dma->control &= ~ST_STOP; + if (LOG_DMA) logerror("DMA terminated\n"); + } + + // Interrupt if count is zero, and interrupt flag set + if((dma->control & INTERRUPT_ON_ZERO) && (dma->count==0)) + { + if (LOG_DMA>1) logerror("DMA%d - requesting interrupt: count = %04X, source = %04X\n", which, dma->count, dma->source); + m_intr.request |= 0x04 << which; + update_interrupt_state(); + } + +// dma->finish_timer->adjust(attotime::from_hz(clock()/8), 0); +// dma->drq_delay = true; +} + +READ16_MEMBER(i80186_cpu_device::internal_port_r) +{ + int temp, which; + + switch (offset) + { + case 0x11: + logerror("%05X:ERROR - read from 80186 EOI\n", pc()); + break; + + case 0x12: + if (LOG_PORTS) logerror("%05X:read 80186 interrupt poll\n", pc()); + if (m_intr.poll_status & 0x8000) + int_callback(*this, 0); + return m_intr.poll_status; + + case 0x13: + if (LOG_PORTS) logerror("%05X:read 80186 interrupt poll status\n", pc()); + return m_intr.poll_status; + + case 0x14: + if (LOG_PORTS) logerror("%05X:read 80186 interrupt mask\n", pc()); + temp = (m_intr.timer >> 3) & 0x01; + temp |= (m_intr.dma[0] >> 1) & 0x04; + temp |= (m_intr.dma[1] >> 0) & 0x08; + temp |= (m_intr.ext[0] << 1) & 0x10; + temp |= (m_intr.ext[1] << 2) & 0x20; + temp |= (m_intr.ext[2] << 3) & 0x40; + temp |= (m_intr.ext[3] << 4) & 0x80; + return temp; + + case 0x15: + if (LOG_PORTS) logerror("%05X:read 80186 interrupt priority mask\n", pc()); + return m_intr.priority_mask; + + case 0x16: + if (LOG_PORTS) logerror("%05X:read 80186 interrupt in-service\n", pc()); + return m_intr.in_service; + + case 0x17: + if (LOG_PORTS) logerror("%05X:read 80186 interrupt request\n", pc()); + temp = m_intr.request & ~0x0001; + if (m_intr.status & 0x0007) + temp |= 1; + return temp; + + case 0x18: + if (LOG_PORTS) logerror("%05X:read 80186 interrupt status\n", pc()); + return m_intr.status; + + case 0x19: + if (LOG_PORTS) logerror("%05X:read 80186 timer interrupt control\n", pc()); + return m_intr.timer; + + case 0x1a: + if (LOG_PORTS) logerror("%05X:read 80186 DMA 0 interrupt control\n", pc()); + return m_intr.dma[0]; + + case 0x1b: + if (LOG_PORTS) logerror("%05X:read 80186 DMA 1 interrupt control\n", pc()); + return m_intr.dma[1]; + + case 0x1c: + if (LOG_PORTS) logerror("%05X:read 80186 INT 0 interrupt control\n", pc()); + return m_intr.ext[0]; + + case 0x1d: + if (LOG_PORTS) logerror("%05X:read 80186 INT 1 interrupt control\n", pc()); + return m_intr.ext[1]; + + case 0x1e: + if (LOG_PORTS) logerror("%05X:read 80186 INT 2 interrupt control\n", pc()); + return m_intr.ext[2]; + + case 0x1f: + if (LOG_PORTS) logerror("%05X:read 80186 INT 3 interrupt control\n", pc()); + return m_intr.ext[3]; + + case 0x28: + case 0x2c: + case 0x30: + if (LOG_PORTS) logerror("%05X:read 80186 Timer %d count\n", pc(), (offset - 0x28) / 4); + which = (offset - 0x28) / 4; + if (!(offset & 1)) + internal_timer_sync(which); + return m_timer[which].count; + + case 0x29: + case 0x2d: + case 0x31: + if (LOG_PORTS) logerror("%05X:read 80186 Timer %d max A\n", pc(), (offset - 0x29) / 4); + which = (offset - 0x29) / 4; + return m_timer[which].maxA; + + case 0x2a: + case 0x2e: + logerror("%05X:read 80186 Timer %d max B\n", pc(), (offset - 0x2a) / 4); + which = (offset - 0x2a) / 4; + return m_timer[which].maxB; + + case 0x2b: + case 0x2f: + case 0x33: + if (LOG_PORTS) logerror("%05X:read 80186 Timer %d control\n", pc(), (offset - 0x2b) / 4); + which = (offset - 0x2b) / 4; + return m_timer[which].control; + + case 0x50: + if (LOG_PORTS) logerror("%05X:read 80186 upper chip select\n", pc()); + return m_mem.upper; + + case 0x51: + if (LOG_PORTS) logerror("%05X:read 80186 lower chip select\n", pc()); + return m_mem.lower; + + case 0x52: + if (LOG_PORTS) logerror("%05X:read 80186 peripheral chip select\n", pc()); + return m_mem.peripheral; + + case 0x53: + if (LOG_PORTS) logerror("%05X:read 80186 middle chip select\n", pc()); + return m_mem.middle; + + case 0x54: + if (LOG_PORTS) logerror("%05X:read 80186 middle P chip select\n", pc()); + return m_mem.middle_size; + + case 0x60: + case 0x68: + if (LOG_PORTS) logerror("%05X:read 80186 DMA%d lower source address\n", pc(), (offset - 0x60) / 8); + which = (offset - 0x60) / 8; + return m_dma[which].source; + + case 0x61: + case 0x69: + if (LOG_PORTS) logerror("%05X:read 80186 DMA%d upper source address\n", pc(), (offset - 0x61) / 8); + which = (offset - 0x61) / 8; + return m_dma[which].source >> 16; + + case 0x62: + case 0x6a: + if (LOG_PORTS) logerror("%05X:read 80186 DMA%d lower dest address\n", pc(), (offset - 0x62) / 8); + which = (offset - 0x62) / 8; + return m_dma[which].dest; + + case 0x63: + case 0x6b: + if (LOG_PORTS) logerror("%05X:read 80186 DMA%d upper dest address\n", pc(), (offset - 0x63) / 8); + which = (offset - 0x63) / 8; + return m_dma[which].dest >> 16; + + case 0x64: + case 0x6c: + if (LOG_PORTS) logerror("%05X:read 80186 DMA%d transfer count\n", pc(), (offset - 0x64) / 8); + which = (offset - 0x64) / 8; + return m_dma[which].count; + + case 0x65: + case 0x6d: + if (LOG_PORTS) logerror("%05X:read 80186 DMA%d control\n", pc(), (offset - 0x65) / 8); + which = (offset - 0x65) / 8; + return m_dma[which].control; + + case 0x7f: + return m_reloc; + + default: + logerror("%05X:read 80186 port %02X\n", pc(), offset); + break; + } + return 0x00; +} + +/************************************* + * + * 80186 internal I/O writes + * + *************************************/ + +WRITE16_MEMBER(i80186_cpu_device::internal_port_w) +{ + int which; + + switch (offset) + { + case 0x11: + if (LOG_PORTS) logerror("%05X:80186 EOI = %04X\n", pc(), data); + handle_eoi(0x8000); + update_interrupt_state(); + break; + + case 0x12: + logerror("%05X:ERROR - write to 80186 interrupt poll = %04X\n", pc(), data); + break; + + case 0x13: + logerror("%05X:ERROR - write to 80186 interrupt poll status = %04X\n", pc(), data); + break; + + case 0x14: + if (LOG_PORTS) logerror("%05X:80186 interrupt mask = %04X\n", pc(), data); + m_intr.timer = (m_intr.timer & ~0x08) | ((data << 3) & 0x08); + m_intr.dma[0] = (m_intr.dma[0] & ~0x08) | ((data << 1) & 0x08); + m_intr.dma[1] = (m_intr.dma[1] & ~0x08) | ((data << 0) & 0x08); + m_intr.ext[0] = (m_intr.ext[0] & ~0x08) | ((data >> 1) & 0x08); + m_intr.ext[1] = (m_intr.ext[1] & ~0x08) | ((data >> 2) & 0x08); + m_intr.ext[2] = (m_intr.ext[2] & ~0x08) | ((data >> 3) & 0x08); + m_intr.ext[3] = (m_intr.ext[3] & ~0x08) | ((data >> 4) & 0x08); + update_interrupt_state(); + break; + + case 0x15: + if (LOG_PORTS) logerror("%05X:80186 interrupt priority mask = %04X\n", pc(), data); + m_intr.priority_mask = data & 0x0007; + update_interrupt_state(); + break; + + case 0x16: + if (LOG_PORTS) logerror("%05X:80186 interrupt in-service = %04X\n", pc(), data); + m_intr.in_service = data & 0x00ff; + update_interrupt_state(); + break; + + case 0x17: + if (LOG_PORTS) logerror("%05X:80186 interrupt request = %04X\n", pc(), data); + m_intr.request = (m_intr.request & ~0x00c0) | (data & 0x00c0); + update_interrupt_state(); + break; + + case 0x18: + if (LOG_PORTS) logerror("%05X:WARNING - wrote to 80186 interrupt status = %04X\n", pc(), data); + m_intr.status = (m_intr.status & ~0x8007) | (data & 0x8007); + update_interrupt_state(); + break; + + case 0x19: + if (LOG_PORTS) logerror("%05X:80186 timer interrupt contol = %04X\n", pc(), data); + m_intr.timer = data & 0x000f; + break; + + case 0x1a: + if (LOG_PORTS) logerror("%05X:80186 DMA 0 interrupt control = %04X\n", pc(), data); + m_intr.dma[0] = data & 0x000f; + break; + + case 0x1b: + if (LOG_PORTS) logerror("%05X:80186 DMA 1 interrupt control = %04X\n", pc(), data); + m_intr.dma[1] = data & 0x000f; + break; + + case 0x1c: + if (LOG_PORTS) logerror("%05X:80186 INT 0 interrupt control = %04X\n", pc(), data); + m_intr.ext[0] = data & 0x007f; + break; + + case 0x1d: + if (LOG_PORTS) logerror("%05X:80186 INT 1 interrupt control = %04X\n", pc(), data); + m_intr.ext[1] = data & 0x007f; + break; + + case 0x1e: + if (LOG_PORTS) logerror("%05X:80186 INT 2 interrupt control = %04X\n", pc(), data); + m_intr.ext[2] = data & 0x001f; + break; + + case 0x1f: + if (LOG_PORTS) logerror("%05X:80186 INT 3 interrupt control = %04X\n", pc(), data); + m_intr.ext[3] = data & 0x001f; + break; + + case 0x28: + case 0x2c: + case 0x30: + if (LOG_PORTS) logerror("%05X:80186 Timer %d count = %04X\n", pc(), (offset - 0x28) / 4, data); + which = (offset - 0x28) / 4; + internal_timer_update(which, data, -1, -1, -1); + break; + + case 0x29: + case 0x2d: + case 0x31: + if (LOG_PORTS) logerror("%05X:80186 Timer %d max A = %04X\n", pc(), (offset - 0x29) / 4, data); + which = (offset - 0x29) / 4; + internal_timer_update(which, -1, data, -1, -1); + break; + + case 0x2a: + case 0x2e: + if (LOG_PORTS) logerror("%05X:80186 Timer %d max B = %04X\n", pc(), (offset - 0x2a) / 4, data); + which = (offset - 0x2a) / 4; + internal_timer_update(which, -1, -1, data, -1); + break; + + case 0x2b: + case 0x2f: + case 0x33: + if (LOG_PORTS) logerror("%05X:80186 Timer %d control = %04X\n", pc(), (offset - 0x2b) / 4, data); + which = (offset - 0x2b) / 4; + internal_timer_update(which, -1, -1, -1, data); + break; + + case 0x50: + if (LOG_PORTS) logerror("%05X:80186 upper chip select = %04X\n", pc(), data); + m_mem.upper = data | 0xc038; + m_out_chip_select_func(0, m_mem.upper, 0xffff); + break; + + case 0x51: + if (LOG_PORTS) logerror("%05X:80186 lower chip select = %04X\n", pc(), data); + m_mem.lower = (data & 0x3fff) | 0x0038; + m_out_chip_select_func(1, m_mem.lower, 0xffff); + break; + + case 0x52: + if (LOG_PORTS) logerror("%05X:80186 peripheral chip select = %04X\n", pc(), data); + m_mem.peripheral = data | 0x0038; + m_out_chip_select_func(2, m_mem.peripheral, 0xffff); + break; + + case 0x53: + if (LOG_PORTS) logerror("%05X:80186 middle chip select = %04X\n", pc(), data); + m_mem.middle = data | 0x01f8; + m_out_chip_select_func(3, m_mem.middle, 0xffff); + break; + + case 0x54: + if (LOG_PORTS) logerror("%05X:80186 middle P chip select = %04X\n", pc(), data); + m_mem.middle_size = data | 0x8038; + m_out_chip_select_func(4, m_mem.middle_size, 0xffff); + break; + + case 0x60: + case 0x68: + if (LOG_PORTS) logerror("%05X:80186 DMA%d lower source address = %04X\n", pc(), (offset - 0x60) / 8, data); + which = (offset - 0x60) / 8; + m_dma[which].source = (m_dma[which].source & ~0x0ffff) | (data & 0x0ffff); + break; + + case 0x61: + case 0x69: + if (LOG_PORTS) logerror("%05X:80186 DMA%d upper source address = %04X\n", pc(), (offset - 0x61) / 8, data); + which = (offset - 0x61) / 8; + m_dma[which].source = (m_dma[which].source & ~0xf0000) | ((data << 16) & 0xf0000); + break; + + case 0x62: + case 0x6a: + if (LOG_PORTS) logerror("%05X:80186 DMA%d lower dest address = %04X\n", pc(), (offset - 0x62) / 8, data); + which = (offset - 0x62) / 8; + m_dma[which].dest = (m_dma[which].dest & ~0x0ffff) | (data & 0x0ffff); + break; + + case 0x63: + case 0x6b: + if (LOG_PORTS) logerror("%05X:80186 DMA%d upper dest address = %04X\n", pc(), (offset - 0x63) / 8, data); + which = (offset - 0x63) / 8; + m_dma[which].dest = (m_dma[which].dest & ~0xf0000) | ((data << 16) & 0xf0000); + break; + + case 0x64: + case 0x6c: + if (LOG_PORTS) logerror("%05X:80186 DMA%d transfer count = %04X\n", pc(), (offset - 0x64) / 8, data); + which = (offset - 0x64) / 8; + m_dma[which].count = data; + break; + + case 0x65: + case 0x6d: + if (LOG_PORTS) logerror("%05X:80186 DMA%d control = %04X\n", pc(), (offset - 0x65) / 8, data); + which = (offset - 0x65) / 8; + update_dma_control(which, data); + break; + + case 0x7f: + if (LOG_PORTS) logerror("%05X:80186 relocation register = %04X\n", pc(), data); + if((data & 0x1fff) != (m_reloc & 0x1fff)) + { + UINT32 newmap = (data & 0xfff) << 8; + UINT32 oldmap = (m_reloc & 0xfff) << 8; + if(!(data & 0x1000) || ((data & 0x1000) && (m_reloc & 0x1000))) + m_program->unmap_readwrite(oldmap, oldmap + 0xff); + if(data & 0x1000) + m_program->install_readwrite_handler(newmap, newmap + 0xff, read16_delegate(FUNC(i80186_cpu_device::internal_port_r), this), write16_delegate(FUNC(i80186_cpu_device::internal_port_w), this)); + } + m_reloc = data; + + break; + + default: + logerror("%05X:80186 port %02X = %04X\n", pc(), offset, data); + break; + } +} diff --git a/src/emu/cpu/i86/i186.h b/src/emu/cpu/i86/i186.h new file mode 100644 index 00000000000..943df784508 --- /dev/null +++ b/src/emu/cpu/i86/i186.h @@ -0,0 +1,154 @@ +#ifndef I186_H__ +#define I186_H__ + +#include "emu.h" +#include "i86.h" + +extern const device_type I80186; +extern const device_type I80188; + +class i80186_cpu_device : public i8086_common_cpu_device +{ +public: + // construction/destruction + i80186_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + i80186_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source, int data_bus_size); + + template static devcb2_base &static_set_read_slave_ack_callback(device_t &device, _Object object) { return downcast(device).m_read_slave_ack_func.set_callback(object); } + template static devcb2_base &static_set_chip_select_callback(device_t &device, _Object object) { return downcast(device).m_out_chip_select_func.set_callback(object); } + template static devcb2_base &static_set_tmrout0_handler(device_t &device, _Object object) { return downcast(device).m_out_tmrout0_func.set_callback(object); } + template static devcb2_base &static_set_tmrout1_handler(device_t &device, _Object object) { return downcast(device).m_out_tmrout1_func.set_callback(object); } + + IRQ_CALLBACK_MEMBER(int_callback); + DECLARE_WRITE_LINE_MEMBER(drq0_w) { if(state) drq_callback(0); m_dma[0].drq_state = state; } + DECLARE_WRITE_LINE_MEMBER(drq1_w) { if(state) drq_callback(1); m_dma[1].drq_state = state; } + DECLARE_WRITE_LINE_MEMBER(tmrin0_w) { if(state && (m_timer[0].control & 0x8004) == 0x8004) { inc_timer(0); } } + DECLARE_WRITE_LINE_MEMBER(tmrin1_w) { if(state && (m_timer[1].control & 0x8004) == 0x8004) { inc_timer(1); } } + DECLARE_WRITE_LINE_MEMBER(int0_w) { external_int(0, state, 0); } + DECLARE_WRITE_LINE_MEMBER(int1_w) { external_int(1, state, 0); } + DECLARE_WRITE_LINE_MEMBER(int2_w) { external_int(2, state, 0); } + DECLARE_WRITE_LINE_MEMBER(int3_w) { external_int(3, state, 0); } + + // device_memory_interface overrides + virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_PROGRAM) ? &m_program_config : ( (spacenum == AS_IO) ? &m_io_config : NULL ); } + +protected: + virtual void execute_run(); + virtual void device_start(); + virtual void device_reset(); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + virtual UINT32 execute_input_lines() const { return 1; } + virtual UINT8 fetch_op(); + virtual UINT8 fetch(); + UINT32 pc() { return m_pc = (m_sregs[CS] << 4) + m_ip; } + + virtual UINT8 read_port_byte(UINT16 port); + virtual UINT16 read_port_word(UINT16 port); + virtual void write_port_byte(UINT16 port, UINT8 data); + virtual void write_port_word(UINT16 port, UINT16 data); + + static const UINT8 m_i80186_timing[200]; + +private: + void update_interrupt_state(); + void handle_eoi(int data); + void external_int(UINT16 intno, int state, UINT8 vector); + void internal_timer_sync(int which); + void internal_timer_update(int which,int new_count,int new_maxA,int new_maxB,int new_control); + void update_dma_control(int which, int new_control); + void drq_callback(int which); + void inc_timer(int which); + DECLARE_READ16_MEMBER(internal_port_r); + DECLARE_WRITE16_MEMBER(internal_port_w); + + struct mem_state + { + UINT16 lower; + UINT16 upper; + UINT16 middle; + UINT16 middle_size; + UINT16 peripheral; + }; + + struct timer_state + { + UINT16 control; + UINT16 maxA; + UINT16 maxB; + bool active_count; + UINT16 count; + emu_timer *int_timer; + emu_timer *time_timer; + UINT8 time_timer_active; + attotime last_time; + }; + + struct dma_state + { + bool drq_delay; + bool drq_state; + UINT32 source; + UINT32 dest; + UINT16 count; + UINT16 control; + emu_timer *finish_timer; + }; + + struct intr_state + { + UINT8 pending; + UINT16 ack_mask; + UINT16 priority_mask; + UINT16 in_service; + UINT16 request; + UINT16 status; + UINT16 poll_status; + UINT16 timer; + UINT16 dma[2]; + UINT16 ext[4]; + }; + + static const device_timer_id TIMER_INT0 = 0; + static const device_timer_id TIMER_INT1 = 1; + static const device_timer_id TIMER_INT2 = 2; + static const device_timer_id TIMER_TIME0 = 3; + static const device_timer_id TIMER_TIME1 = 4; + static const device_timer_id TIMER_TIME2 = 5; + static const device_timer_id TIMER_DMA0 = 6; + static const device_timer_id TIMER_DMA1 = 7; + + struct timer_state m_timer[3]; + struct dma_state m_dma[2]; + struct intr_state m_intr; + struct mem_state m_mem; + UINT16 m_reloc; + + address_space_config m_program_config; + address_space_config m_io_config; + + devcb2_read8 m_read_slave_ack_func; + devcb2_write16 m_out_chip_select_func; + devcb2_write_line m_out_tmrout0_func; + devcb2_write_line m_out_tmrout1_func; +}; + +class i80188_cpu_device : public i80186_cpu_device +{ +public: + // construction/destruction + i80188_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); +}; + +#define MCFG_80186_IRQ_SLAVE_ACK(_devcb) \ + devcb = &i80186_cpu_device::static_set_read_slave_ack_callback(*device, DEVCB2_##_devcb); + +#define MCFG_80186_CHIP_SELECT_CB(_devcb) \ + devcb = &i80186_cpu_device::static_set_chip_select_callback(*device, DEVCB2_##_devcb); + +#define MCFG_80186_TMROUT0_HANDLER(_devcb) \ + devcb = &i80186_cpu_device::static_set_tmrout0_handler(*device, DEVCB2_##_devcb); + +#define MCFG_80186_TMROUT1_HANDLER(_devcb) \ + devcb = &i80186_cpu_device::static_set_tmrout1_handler(*device, DEVCB2_##_devcb); + +#endif diff --git a/src/emu/cpu/i86/i86.c b/src/emu/cpu/i86/i86.c index 1ef7cbfa1ca..6d33c0e5d1e 100644 --- a/src/emu/cpu/i86/i86.c +++ b/src/emu/cpu/i86/i86.c @@ -77,78 +77,6 @@ const UINT8 i8086_cpu_device::m_i8086_timing[] = 18, 9,17, /* MOVS 8-bit */ 18, 9,17, /* MOVS 16-bit */ }; -/* these come from the Intel 80186 datasheet */ -const UINT8 i80186_cpu_device::m_i80186_timing[] = -{ - 45,28, /* exception, IRET */ - 0, 2, 4, 3, /* INTs */ - 2, /* segment overrides */ - 2, 2, 3, /* flag operations */ - 8, 7,19,15, /* arithmetic adjusts */ - 4, 4, /* decimal adjusts */ - 2, 4, /* sign extension */ - 2,18, 6, 2, 6,11, /* misc */ - - 14,14,14, /* direct JMPs */ - 11,17,26, /* indirect JMPs */ - 15,23, /* direct CALLs */ - 13,19,38, /* indirect CALLs */ - 16,22,18,25, /* returns */ - 4,13, 5,15, /* conditional JMPs */ - 6,16, 6,16, /* loops */ - - 10,10, 8, 8, /* port reads */ - 9, 9, 7, 7, /* port writes */ - - 2, 9,12, /* move, 8-bit */ - 3,12, /* move, 8-bit immediate */ - 2, 9,12, /* move, 16-bit */ - 4,13, /* move, 16-bit immediate */ - 8, 8, 9, 9, /* move, AL/AX memory */ - 2,11, 2,11, /* move, segment registers */ - 4,17, /* exchange, 8-bit */ - 4,17, 3, /* exchange, 16-bit */ - - 10,16, 9, 9, /* pushes */ - 10,20, 8, 8, /* pops */ - - 3,10,10, /* ALU ops, 8-bit */ - 4,16,10, /* ALU ops, 8-bit immediate */ - 3,10,10, /* ALU ops, 16-bit */ - 4,16,10, /* ALU ops, 16-bit immediate */ - 4,16,10, /* ALU ops, 16-bit w/8-bit immediate */ - 26,35,32,41, /* MUL */ - 25,34,31,40, /* IMUL */ - 29,38,35,44, /* DIV */ - 44,53,50,59, /* IDIV */ - 3, 3,15,15, /* INC/DEC */ - 3, 3,10,10, /* NEG/NOT */ - - 2, 5, 1, /* reg shift/rotate */ - 15,17, 1, /* m8 shift/rotate */ - 15,17, 1, /* m16 shift/rotate */ - - 22, 5,22, /* CMPS 8-bit */ - 22, 5,22, /* CMPS 16-bit */ - 15, 5,15, /* SCAS 8-bit */ - 15, 5,15, /* SCAS 16-bit */ - 12, 6,11, /* LODS 8-bit */ - 12, 6,11, /* LODS 16-bit */ - 10, 6, 9, /* STOS 8-bit */ - 10, 6, 9, /* STOS 16-bit */ - 14, 8, 8, /* MOVS 8-bit */ - 14, 8, 8, /* MOVS 16-bit */ - - 14, 8, 8, /* (80186) INS 8-bit */ - 14, 8, 8, /* (80186) INS 16-bit */ - 14, 8, 8, /* (80186) OUTS 8-bit */ - 14, 8, 8, /* (80186) OUTS 16-bit */ - 14,68,83, /* (80186) PUSH immediate, PUSHA/POPA */ - 22,29, /* (80186) IMUL immediate 8-bit */ - 25,32, /* (80186) IMUL immediate 16-bit */ - 15,25,4,16, 8, /* (80186) ENTER/LEAVE */ - 33, /* (80186) BOUND */ -}; /***************************************************************************/ /* cpu state */ @@ -159,405 +87,6 @@ const UINT8 i80186_cpu_device::m_i80186_timing[] = const device_type I8086 = &device_creator; const device_type I8088 = &device_creator; -const device_type I80186 = &device_creator; -const device_type I80188 = &device_creator; - -i80188_cpu_device::i80188_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : i80186_cpu_device(mconfig, I80188, "I80188", tag, owner, clock, "i80188", __FILE__, 8) -{ - memcpy(m_timing, m_i80186_timing, sizeof(m_i80186_timing)); - m_fetch_xor = 0; -} - -i80186_cpu_device::i80186_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : i8086_common_cpu_device(mconfig, I80186, "I80186", tag, owner, clock, "i80186", __FILE__) - , m_program_config("program", ENDIANNESS_LITTLE, 16, 20, 0) - , m_io_config("io", ENDIANNESS_LITTLE, 16, 16, 0) -{ - memcpy(m_timing, m_i80186_timing, sizeof(m_i80186_timing)); - m_fetch_xor = BYTE_XOR_LE(0); -} - -i80186_cpu_device::i80186_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source, int data_bus_size) - : i8086_common_cpu_device(mconfig, type, name, tag, owner, clock, shortname, source) - , m_program_config("program", ENDIANNESS_LITTLE, data_bus_size, 20, 0) - , m_io_config("io", ENDIANNESS_LITTLE, data_bus_size, 16, 0) -{ -} - -UINT8 i80186_cpu_device::fetch_op() -{ - UINT8 data; - data = m_direct->read_decrypted_byte(pc(), m_fetch_xor); - m_ip++; - return data; -} - -UINT8 i80186_cpu_device::fetch() -{ - UINT8 data; - data = m_direct->read_raw_byte(pc(), m_fetch_xor); - m_ip++; - return data; -} - -void i80186_cpu_device::execute_run() -{ - while(m_icount > 0 ) - { - if ( m_seg_prefix_next ) - { - m_seg_prefix = true; - m_seg_prefix_next = false; - } - else - { - m_prev_ip = m_ip; - m_seg_prefix = false; - - /* Dispatch IRQ */ - if ( m_pending_irq && m_no_interrupt == 0 ) - { - if ( m_pending_irq & NMI_IRQ ) - { - interrupt(I8086_NMI_INT_VECTOR); - m_pending_irq &= ~NMI_IRQ; - } - else if ( m_IF ) - { - /* the actual vector is retrieved after pushing flags */ - /* and clearing the IF */ - interrupt(-1); - } - } - - /* No interrupt allowed between last instruction and this one */ - if ( m_no_interrupt ) - { - m_no_interrupt--; - } - - /* trap should allow one instruction to be executed */ - if ( m_fire_trap ) - { - if ( m_fire_trap >= 2 ) - { - interrupt(1); - m_fire_trap = 0; - } - else - { - m_fire_trap++; - } - } - } - - debugger_instruction_hook( this, pc() ); - - UINT8 op = fetch_op(); - - switch(op) - { - case 0x60: // i_pusha - { - UINT32 tmp = m_regs.w[SP]; - - PUSH(m_regs.w[AX]); - PUSH(m_regs.w[CX]); - PUSH(m_regs.w[DX]); - PUSH(m_regs.w[BX]); - PUSH(tmp); - PUSH(m_regs.w[BP]); - PUSH(m_regs.w[SI]); - PUSH(m_regs.w[DI]); - CLK(PUSHA); - } - break; - - case 0x61: // i_popa - m_regs.w[DI] = POP(); - m_regs.w[SI] = POP(); - m_regs.w[BP] = POP(); - POP(); - m_regs.w[BX] = POP(); - m_regs.w[DX] = POP(); - m_regs.w[CX] = POP(); - m_regs.w[AX] = POP(); - CLK(POPA); - break; - - case 0x62: // i_bound - { - UINT32 low,high,tmp; - m_modrm = fetch(); - low = GetRMWord(); - high = GetnextRMWord(); - tmp = RegWord(); - if (tmphigh) - interrupt(5); - CLK(BOUND); - logerror("%s: %06x: bound %04x high %04x low %04x tmp\n", tag(), pc(), high, low, tmp); - } - break; - - case 0x68: // i_push_d16 - PUSH( fetch_word() ); - CLK(PUSH_IMM); - break; - - case 0x69: // i_imul_d16 - { - UINT32 tmp; - DEF_r16w(); - tmp = fetch_word(); - m_dst = (INT32)((INT16)m_src)*(INT32)((INT16)tmp); - m_CarryVal = m_OverVal = (((INT32)m_dst) >> 15 != 0) && (((INT32)m_dst) >> 15 != -1); - RegWord(m_dst); - CLKM(IMUL_RRI16, IMUL_RMI16); - } - break; - - case 0x6a: // i_push_d8 - PUSH( (UINT16)((INT16)((INT8)fetch())) ); - CLK(PUSH_IMM); - break; - - case 0x6b: // i_imul_d8 - { - UINT32 src2; - DEF_r16w(); - src2= (UINT16)((INT16)((INT8)fetch())); - m_dst = (INT32)((INT16)m_src)*(INT32)((INT16)src2); - m_CarryVal = m_OverVal = (((INT32)m_dst) >> 15 != 0) && (((INT32)m_dst) >> 15 != -1); - RegWord(m_dst); - CLKM(IMUL_RRI8, IMUL_RMI8); - } - break; - - case 0x6c: // i_insb - i_insb(); - break; - - case 0x6d: // i_insw - i_insw(); - break; - - case 0x6e: // i_outsb - i_outsb(); - break; - - case 0x6f: // i_outsw - i_outsw(); - break; - - case 0x8e: // i_mov_sregw - m_modrm = fetch(); - m_src = GetRMWord(); - CLKM(MOV_SR,MOV_SM); - switch (m_modrm & 0x38) - { - case 0x00: /* mov es,ew */ - m_sregs[ES] = m_src; - break; - case 0x10: /* mov ss,ew */ - m_sregs[SS] = m_src; - m_no_interrupt = 1; - break; - case 0x18: /* mov ds,ew */ - m_sregs[DS] = m_src; - break; - default: - logerror("%s: %06x: Mov Sreg - Invalid register\n", tag(), pc()); - interrupt(6); - } - break; - - case 0xc0: // i_rotshft_bd8 - { - UINT8 c; - m_modrm = fetch(); - m_src = GetRMByte(); - m_dst = m_src; - c = fetch() & 0x1f; - CLKM(ROT_REG_BASE,ROT_M8_BASE); - m_icount -= m_timing[ROT_REG_BIT] * c; - if (c) - { - switch ( m_modrm & 0x38 ) - { - case 0x00: do { ROL_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x08: do { ROR_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x10: do { ROLC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x18: do { RORC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x30: - case 0x20: SHL_BYTE(c); break; - case 0x28: SHR_BYTE(c); break; - case 0x38: SHRA_BYTE(c); break; - } - } - } - break; - - case 0xc1: // i_rotshft_wd8 - { - UINT8 c; - m_modrm = fetch(); - m_src = GetRMWord(); - m_dst = m_src; - c = fetch() & 0x1f; - CLKM(ROT_REG_BASE,ROT_M16_BASE); - m_icount -= m_timing[ROT_REG_BIT] * c; - if (c) - { - switch ( m_modrm & 0x38 ) - { - case 0x00: do { ROL_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x08: do { ROR_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x10: do { ROLC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x18: do { RORC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x30: - case 0x20: SHL_WORD(c); break; - case 0x28: SHR_WORD(c); break; - case 0x38: SHRA_WORD(c); break; - } - } - } - break; - - case 0xc8: // i_enter - { - UINT16 nb = fetch(); - UINT32 level; - - nb |= fetch() << 8; - level = fetch(); - CLK(!level ? ENTER0 : (level == 1) ? ENTER1 : ENTER_BASE); - if(level > 1) - m_icount -= level * m_timing[ENTER_COUNT]; - PUSH(m_regs.w[BP]); - m_regs.w[BP] = m_regs.w[SP]; - m_regs.w[SP] -= nb; - for (int i=1; i0); PutbackRMByte(m_dst); break; - case 0x08: do { ROR_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x10: do { ROLC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x18: do { RORC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x30: - case 0x20: SHL_BYTE(c); break; - case 0x28: SHR_BYTE(c); break; - case 0x38: SHRA_BYTE(c); break; - } - } - } - break; - - case 0xd3: // i_rotshft_wcl - { - UINT8 c; - - m_modrm = fetch(); - m_src = GetRMWord(); - m_dst = m_src; - c = m_regs.b[CL] & 0x1f; - CLKM(ROT_REG_BASE,ROT_M16_BASE); - m_icount -= m_timing[ROT_REG_BIT] * c; - if (c) - { - switch ( m_modrm & 0x38 ) - { - case 0x00: do { ROL_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x08: do { ROR_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x10: do { ROLC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x18: do { RORC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x30: - case 0x20: SHL_WORD(c); break; - case 0x28: SHR_WORD(c); break; - case 0x38: SHRA_WORD(c); break; - } - } - } - break; - - case 0xf2: // i_repne - case 0xf3: - { - bool pass = false; - UINT8 next = repx_op(); - UINT16 c = m_regs.w[CX]; - - switch (next) - { - case 0x6c: CLK(OVERRIDE); if (c) do { i_insb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0x6d: CLK(OVERRIDE); if (c) do { i_insw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0x6e: CLK(OVERRIDE); if (c) do { i_outsb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0x6f: CLK(OVERRIDE); if (c) do { i_outsw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - default: - // Decrement IP and pass on - m_ip -= 1 + (m_seg_prefix_next ? 1 : 0); - pass = true; - } - if(!pass) - { - if(c) - m_ip = m_prev_ip; - break; - } - } - - default: - if(!common_op(op)) - { - m_icount -= 10; // UD fault timing? - logerror("%s: %06x: Invalid Opcode %02x\n", tag(), pc(), op); - m_ip = m_prev_ip; - interrupt(6); // 80186 has #UD - break; - } - } - } -} - -void i80186_cpu_device::device_start() -{ - i8086_common_cpu_device::device_start(); - state_add( I8086_ES, "ES", m_sregs[ES] ).callimport().callexport().formatstr("%04X"); - state_add( I8086_CS, "CS", m_sregs[CS] ).callimport().callexport().formatstr("%04X"); - state_add( I8086_SS, "SS", m_sregs[SS] ).callimport().callexport().formatstr("%04X"); - state_add( I8086_DS, "DS", m_sregs[DS] ).callimport().callexport().formatstr("%04X"); - state_add( I8086_VECTOR, "V", m_int_vector).callimport().callexport().formatstr("%02X"); - - state_add(STATE_GENPC, "curpc", m_pc).callimport().callexport().formatstr("%05X"); -} i8088_cpu_device::i8088_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : i8086_cpu_device(mconfig, I8088, "I8088", tag, owner, clock, "i8088", __FILE__, 8) @@ -960,7 +489,6 @@ void i8086_common_cpu_device::execute_set_input( int inptnum, int state ) } } - offs_t i8086_common_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) { extern int i386_dasm_one(char *buffer, offs_t eip, const UINT8 *oprom, int mode); @@ -2262,6 +1790,11 @@ bool i8086_common_cpu_device::common_op(UINT8 op) case 0xd4: // i_aam { UINT8 base = fetch(); + if(!base) + { + interrupt(0); + break; + } m_regs.b[AH] = m_regs.b[AL] / base; m_regs.b[AL] %= base; set_SZPF_Word(m_regs.w[AX]); diff --git a/src/emu/cpu/i86/i86.h b/src/emu/cpu/i86/i86.h index c1f42886eeb..eea929a3a15 100644 --- a/src/emu/cpu/i86/i86.h +++ b/src/emu/cpu/i86/i86.h @@ -7,18 +7,10 @@ extern const device_type I8086; extern const device_type I8088; -extern const device_type I80186; -extern const device_type I80188; #define INPUT_LINE_INT0 INPUT_LINE_IRQ0 -#define INPUT_LINE_INT1 INPUT_LINE_IRQ1 -#define INPUT_LINE_INT2 INPUT_LINE_IRQ2 -#define INPUT_LINE_INT3 INPUT_LINE_IRQ3 #define INPUT_LINE_TEST 20 -#define INPUT_LINE_DRQ0 21 -#define INPUT_LINE_DRQ1 22 -#define INPUT_LINE_TMRIN0 23 -#define INPUT_LINE_TMRIN1 24 + enum { @@ -346,7 +338,7 @@ public: protected: virtual void execute_run(); virtual void device_start(); - virtual UINT32 execute_input_lines() const { return 2; } + virtual UINT32 execute_input_lines() const { return 1; } virtual UINT8 fetch_op(); virtual UINT8 fetch(); UINT32 pc() { return m_pc = (m_sregs[CS] << 4) + m_ip; } @@ -363,35 +355,5 @@ public: i8088_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); }; -class i80186_cpu_device : public i8086_common_cpu_device -{ -public: - // construction/destruction - i80186_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - i80186_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source, int data_bus_size); - - // device_memory_interface overrides - virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_PROGRAM) ? &m_program_config : ( (spacenum == AS_IO) ? &m_io_config : NULL ); } - -protected: - virtual void execute_run(); - virtual void device_start(); - virtual UINT32 execute_input_lines() const { return 9; } - virtual UINT8 fetch_op(); - virtual UINT8 fetch(); - UINT32 pc() { return m_pc = (m_sregs[CS] << 4) + m_ip; } - - address_space_config m_program_config; - address_space_config m_io_config; - static const UINT8 m_i80186_timing[200]; -}; - -class i80188_cpu_device : public i80186_cpu_device -{ -public: - // construction/destruction - i80188_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - #endif /* __I8086_H__ */ diff --git a/src/mame/audio/leland.c b/src/mame/audio/leland.c index 16773fe90a9..13b7634a261 100644 --- a/src/mame/audio/leland.c +++ b/src/mame/audio/leland.c @@ -78,227 +78,11 @@ ***************************************************************************/ #include "emu.h" -#include "cpu/i86/i86.h" #include "cpu/z80/z80.h" #include "includes/leland.h" -#include "sound/2151intf.h" -#include "sound/dac.h" -#include "devlegcy.h" - - -#define OUTPUT_RATE 50000 - -#define DAC_BUFFER_SIZE 1024 -#define DAC_BUFFER_SIZE_MASK (DAC_BUFFER_SIZE - 1) - -#define LOG_INTERRUPTS 0 -#define LOG_DMA 0 -#define LOG_SHORTAGES 0 -#define LOG_TIMER 0 -#define LOG_COMM 0 -#define LOG_PORTS 0 -#define LOG_DAC 0 -#define LOG_EXTERN 0 -#define LOG_PIT 0 - - -/* according to the Intel manual, external interrupts are not latched */ -/* however, I cannot get this system to work without latching them */ -#define LATCH_INTS 1 - -#define DAC_VOLUME_SCALE 4 - -struct mem_state -{ - UINT16 lower; - UINT16 upper; - UINT16 middle; - UINT16 middle_size; - UINT16 peripheral; -}; - -struct timer_state -{ - UINT16 control; - UINT16 maxA; - UINT16 maxB; - UINT16 count; - emu_timer *int_timer; - emu_timer *time_timer; - UINT8 time_timer_active; - attotime last_time; -}; - -struct dma_state -{ - UINT32 source; - UINT32 dest; - UINT16 count; - UINT16 control; - UINT8 finished; - emu_timer *finish_timer; -}; - -struct intr_state -{ - UINT8 pending; - UINT16 ack_mask; - UINT16 priority_mask; - UINT16 in_service; - UINT16 request; - UINT16 status; - UINT16 poll_status; - UINT16 timer; - UINT16 dma[2]; - UINT16 ext[4]; -}; - -struct i80186_state -{ - device_t *cpu; - struct timer_state timer[3]; - struct dma_state dma[2]; - struct intr_state intr; - struct mem_state mem; -}; - -struct dac_state -{ - INT16 value; - INT16 volume; - UINT32 frequency; - UINT32 step; - UINT32 fraction; - - INT16 buffer[DAC_BUFFER_SIZE]; - UINT32 bufin; - UINT32 bufout; - UINT32 buftarget; -}; - -struct counter_state -{ - emu_timer *timer; - INT32 count; - UINT8 mode; - UINT8 readbyte; - UINT8 writebyte; -}; - -struct leland_sound_state -{ - /* 1st gen */ - UINT8 *m_dac_buffer[2]; - UINT32 m_dac_bufin[2]; - UINT32 m_dac_bufout[2]; - sound_stream *m_dac_stream; - - /* 2nd+ gen */ - sound_stream *m_dma_stream; - sound_stream *m_nondma_stream; - sound_stream *m_extern_stream; - - UINT8 m_has_ym2151; - UINT8 m_is_redline; - - UINT8 m_last_control; - UINT8 m_clock_active; - UINT8 m_clock_tick; - - UINT16 m_sound_command; - UINT8 m_sound_response; - - UINT32 m_ext_start; - UINT32 m_ext_stop; - UINT8 m_ext_active; - UINT8 *m_ext_base; - - struct i80186_state m_i80186; - struct dac_state m_dac[8]; - struct counter_state m_counter[9]; -}; - - -/************************************* - * - * 1st generation sound - * - *************************************/ - -INLINE leland_sound_state *get_safe_token(device_t *device) -{ - assert(device != NULL); - assert(device->type() == LELAND || device->type() == LELAND_80186 || device->type() == REDLINE_80186); - - return (leland_sound_state *)downcast(device)->token(); -} - -static STREAM_UPDATE( leland_update ) -{ - leland_sound_state *state = get_safe_token(device); - stream_sample_t *buffer = outputs[0]; - int dacnum; - - /* reset the buffer */ - memset(buffer, 0, samples * sizeof(*buffer)); - for (dacnum = 0; dacnum < 2; dacnum++) - { - int bufout = state->m_dac_bufout[dacnum]; - int count = (state->m_dac_bufin[dacnum] - bufout) & DAC_BUFFER_SIZE_MASK; - - if (count > 300) - { - UINT8 *base = state->m_dac_buffer[dacnum]; - int i; - - for (i = 0; i < samples && count > 0; i++, count--) - { - buffer[i] += ((INT16)base[bufout] - 0x80) * 0x40; - bufout = (bufout + 1) & DAC_BUFFER_SIZE_MASK; - } - state->m_dac_bufout[dacnum] = bufout; - } - } -} - - -static DEVICE_START( leland_sound ) -{ - leland_sound_state *state = get_safe_token(device); - - /* reset globals */ - state->m_dac_buffer[0] = state->m_dac_buffer[1] = NULL; - state->m_dac_bufin[0] = state->m_dac_bufin[1] = 0; - state->m_dac_bufout[0] = state->m_dac_bufout[1] = 0; - - /* allocate the stream */ - state->m_dac_stream = device->machine().sound().stream_alloc(*device, 0, 1, 256*60, NULL, leland_update); - - /* allocate memory */ - state->m_dac_buffer[0] = auto_alloc_array(device->machine(), UINT8, DAC_BUFFER_SIZE); - state->m_dac_buffer[1] = auto_alloc_array(device->machine(), UINT8, DAC_BUFFER_SIZE); -} - - -void leland_dac_update(device_t *device, int dacnum, UINT8 sample) -{ - leland_sound_state *state = get_safe_token(device); - UINT8 *buffer = state->m_dac_buffer[dacnum]; - int bufin = state->m_dac_bufin[dacnum]; - - /* skip if nothing */ - if (!buffer) - return; - - /* copy data from VRAM */ - buffer[bufin] = sample; - bufin = (bufin + 1) & DAC_BUFFER_SIZE_MASK; - - /* update the buffer */ - state->m_dac_bufin[dacnum] = bufin; -} - +#define LOG_COMM 0 +#define LOG_EXTERN 0 /************************************* * @@ -306,208 +90,196 @@ void leland_dac_update(device_t *device, int dacnum, UINT8 sample) * *************************************/ -static void set_dac_frequency(leland_sound_state *state, int which, int frequency); - -static DECLARE_READ16_DEVICE_HANDLER( peripheral_r ); -static DECLARE_WRITE16_DEVICE_HANDLER( peripheral_w ); - - - -/************************************* - * - * Manual DAC sound generation - * - *************************************/ - -static STREAM_UPDATE( leland_80186_dac_update ) +WRITE_LINE_MEMBER(leland_80186_sound_device::pit0_2_w) { - leland_sound_state *state = get_safe_token(device); - stream_sample_t *buffer = outputs[0]; - int i, j, start, stop; - - if (LOG_SHORTAGES) logerror("----\n"); - - /* reset the buffer */ - memset(buffer, 0, samples * sizeof(*buffer)); - - /* if we're redline racer, we have more DACs */ - if (!state->m_is_redline) - start = 2, stop = 7; - else - start = 0, stop = 8; - - /* loop over manual DAC channels */ - for (i = start; i < stop; i++) - { - struct dac_state *d = &state->m_dac[i]; - int count = (d->bufin - d->bufout) & DAC_BUFFER_SIZE_MASK; - - /* if we have data, process it */ - if (count > 0) - { - INT16 *base = d->buffer; - int source = d->bufout; - int frac = d->fraction; - int step = d->step; - - /* sample-rate convert to the output frequency */ - for (j = 0; j < samples && count > 0; j++) - { - buffer[j] += base[source]; - frac += step; - source += frac >> 24; - count -= frac >> 24; - frac &= 0xffffff; - source &= DAC_BUFFER_SIZE_MASK; - } - - if (LOG_SHORTAGES && j < samples) - logerror("DAC #%d short by %d/%d samples\n", i, samples - j, samples); - - /* update the DAC state */ - d->fraction = frac; - d->bufout = source; - } - - /* update the clock status */ - if (count < d->buftarget) - state->m_clock_active |= 1 << i; - } + set_clock_line(2, state); } - - - -/************************************* - * - * DMA-based DAC sound generation - * - *************************************/ - -static STREAM_UPDATE( leland_80186_dma_update ) +WRITE_LINE_MEMBER(leland_80186_sound_device::pit1_0_w) { - leland_sound_state *state = get_safe_token(device); - address_space &dmaspace = *(address_space *)param; - stream_sample_t *buffer = outputs[0]; - int i, j; - - /* reset the buffer */ - memset(buffer, 0, samples * sizeof(*buffer)); - - /* loop over DMA buffers */ - for (i = 0; i < 2; i++) + set_clock_line(3, state); +} +WRITE_LINE_MEMBER(leland_80186_sound_device::pit1_1_w) +{ + set_clock_line(4, state); +} +WRITE_LINE_MEMBER(leland_80186_sound_device::pit1_2_w) +{ + set_clock_line(5, state); +} +WRITE_LINE_MEMBER(leland_80186_sound_device::pit2_0_w) +{ + set_clock_line(5, state); +} +WRITE_LINE_MEMBER(leland_80186_sound_device::i80186_tmr0_w) +{ + set_clock_line(6, state); +} +WRITE_LINE_MEMBER(leland_80186_sound_device::i80186_tmr1_w) +{ + if(state) { - struct dma_state *d = &state->m_i80186.dma[i]; - - /* check for enabled DMA */ - if (d->control & 0x0002) + if(m_ext_active && (m_ext_start < m_ext_stop)) { - /* make sure the parameters meet our expectations */ - if ((d->control & 0xfe00) != 0x1600) - { - logerror("Unexpected DMA control %02X\n", d->control); - } - else if (!state->m_is_redline && ((d->dest & 1) || (d->dest & 0x3f) > 0x0b)) - { - logerror("Unexpected DMA destination %02X\n", d->dest); - } - else if (state->m_is_redline && (d->dest & 0xf000) != 0x4000 && (d->dest & 0xf000) != 0x5000) - { - logerror("Unexpected DMA destination %02X\n", d->dest); - } - - /* otherwise, we're ready for liftoff */ - else - { - int source = d->source; - int count = d->count; - int which, frac, step, volume; - - /* adjust for redline racer */ - if (!state->m_is_redline) - which = (d->dest & 0x3f) / 2; - else - which = (d->dest >> 9) & 7; - - frac = state->m_dac[which].fraction; - step = state->m_dac[which].step; - volume = state->m_dac[which].volume; - - /* sample-rate convert to the output frequency */ - for (j = 0; j < samples && count > 0; j++) - { - buffer[j] += ((int)dmaspace.read_byte(source) - 0x80) * volume; - frac += step; - source += frac >> 24; - count -= frac >> 24; - frac &= 0xffffff; - } - - /* update the DMA state */ - if (count > 0) - { - d->source = source; - d->count = count; - } - else - { - /* let the timer callback actually mark the transfer finished */ - d->source = source + count - 1; - d->count = 1; - d->finished = 1; - } - - if (LOG_DMA) logerror("DMA Generated %d samples - new count = %04X, source = %04X\n", j, d->count, d->source); - - /* update the DAC state */ - state->m_dac[which].fraction = frac; - } + m_dac_sample[7] = (m_ext_base[m_ext_start] << 8) - 0x8000; + m_ext_start++; } } + set_clock_line(7, state); } - - - -/************************************* - * - * Externally-driven DAC sound generation - * - *************************************/ - -static STREAM_UPDATE( leland_80186_extern_update ) +const struct pit8253_interface leland_pit0_interface = { - leland_sound_state *state = get_safe_token(device); - stream_sample_t *buffer = outputs[0]; - struct dac_state *d = &state->m_dac[7]; - int count = state->m_ext_stop - state->m_ext_start; - int j; - - /* reset the buffer */ - memset(buffer, 0, samples * sizeof(*buffer)); - - /* if we have data, process it */ - if (count > 0 && state->m_ext_active) { - int source = state->m_ext_start; - int frac = d->fraction; - int step = d->step; - - /* sample-rate convert to the output frequency */ - for (j = 0; j < samples && count > 0; j++) { - buffer[j] += ((INT16)state->m_ext_base[source] - 0x80) * d->volume; - frac += step; - source += frac >> 24; - count -= frac >> 24; - frac &= 0xffffff; + 4000000, + DEVCB_NULL, + DEVCB_DEVICE_LINE_MEMBER(":audiocpu", i80186_cpu_device, drq0_w) + }, { + 4000000, + DEVCB_NULL, + DEVCB_DEVICE_LINE_MEMBER(":audiocpu", i80186_cpu_device, drq1_w) + }, { + 4000000, + DEVCB_NULL, + DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, leland_80186_sound_device, pit0_2_w) } - - /* update the DAC state */ - d->fraction = frac; - state->m_ext_start = source; } +}; + +const struct pit8253_interface leland_pit1_interface = +{ + { + { + 4000000, + DEVCB_NULL, + DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, leland_80186_sound_device, pit1_0_w) + }, { + 4000000, + DEVCB_NULL, + DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, leland_80186_sound_device, pit1_1_w) + }, { + 4000000, + DEVCB_NULL, + DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, leland_80186_sound_device, pit1_2_w) + } + } +}; + +const struct pit8253_interface redline_pit0_interface = +{ + { + { + 7000000, + DEVCB_NULL, + DEVCB_DEVICE_LINE_MEMBER(":audiocpu", i80186_cpu_device, drq0_w) + }, { + 7000000, + DEVCB_NULL, + DEVCB_DEVICE_LINE_MEMBER(":audiocpu", i80186_cpu_device, drq1_w) + }, { + 7000000, + DEVCB_NULL, + DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, leland_80186_sound_device, pit0_2_w) + } + } +}; + +const struct pit8253_interface redline_pit1_interface = +{ + { + { + 7000000, + DEVCB_NULL, + DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, leland_80186_sound_device, pit1_0_w) + }, { + 7000000, + DEVCB_NULL, + DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, leland_80186_sound_device, pit1_1_w) + }, { + 7000000, + DEVCB_NULL, + DEVCB_NULL + } + } +}; + +const struct pit8253_interface redline_pit2_interface = +{ + { + { + 7000000, + DEVCB_NULL, + DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, leland_80186_sound_device, pit2_0_w) + }, { + 7000000, + DEVCB_NULL, + DEVCB_NULL + }, { + 7000000, + DEVCB_NULL, + DEVCB_NULL + } + } +}; + +static MACHINE_CONFIG_FRAGMENT( leland_80186_sound ) + MCFG_SPEAKER_STANDARD_MONO("speaker") + MCFG_SOUND_ADD("dac", DAC, 0) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 1.00) + + MCFG_PIT8254_ADD("pit0", leland_pit0_interface) + MCFG_PIT8254_ADD("pit1", leland_pit1_interface) +MACHINE_CONFIG_END + +static MACHINE_CONFIG_FRAGMENT( redline_80186_sound ) + MCFG_SPEAKER_STANDARD_MONO("speaker") + MCFG_SOUND_ADD("dac", DAC, 0) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 1.00) + + MCFG_PIT8254_ADD("pit0", redline_pit0_interface) + MCFG_PIT8254_ADD("pit1", redline_pit1_interface) + MCFG_PIT8254_ADD("pit2", redline_pit2_interface) +MACHINE_CONFIG_END + +static MACHINE_CONFIG_FRAGMENT( ataxx_80186_sound ) + MCFG_SPEAKER_STANDARD_MONO("speaker") + MCFG_SOUND_ADD("dac", DAC, 0) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 1.00) + + MCFG_PIT8254_ADD("pit0", leland_pit0_interface) +MACHINE_CONFIG_END + +static MACHINE_CONFIG_FRAGMENT( wsf_80186_sound ) + MCFG_SPEAKER_STANDARD_MONO("speaker") + MCFG_SOUND_ADD("dac", DAC, 0) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 1.00) + + /* sound hardware */ + MCFG_YM2151_ADD("ymsnd", 4000000) + MCFG_SOUND_ROUTE(0, "speaker", 0.40) + MCFG_SOUND_ROUTE(1, "speaker", 0.40) + + MCFG_PIT8254_ADD("pit0", leland_pit0_interface) +MACHINE_CONFIG_END + +machine_config_constructor leland_80186_sound_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( leland_80186_sound ); } +machine_config_constructor redline_80186_sound_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( redline_80186_sound ); +} +machine_config_constructor ataxx_80186_sound_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( ataxx_80186_sound ); +} + +machine_config_constructor wsf_80186_sound_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( wsf_80186_sound ); +} /************************************* * @@ -515,1322 +287,128 @@ static STREAM_UPDATE( leland_80186_extern_update ) * *************************************/ -static TIMER_CALLBACK( internal_timer_int ); -static TIMER_CALLBACK( dma_timer_callback ); - -static DEVICE_START( common_sh_start ) +void leland_80186_sound_device::device_start() { - leland_sound_state *state = get_safe_token(device); - running_machine &machine = device->machine(); - address_space &dmaspace = machine.device("audiocpu")->memory().space(AS_PROGRAM); - int i; + m_audiocpu = downcast(machine().device("audiocpu")); /* determine which sound hardware is installed */ - state->m_has_ym2151 = (device->machine().device("ymsnd") != NULL); + if(m_type == TYPE_WSF) + m_ext_base = machine().root_device().memregion("dac")->base(); - /* allocate separate streams for the DMA and non-DMA DACs */ - state->m_dma_stream = device->machine().sound().stream_alloc(*device, 0, 1, OUTPUT_RATE, (void *)&dmaspace, leland_80186_dma_update); - state->m_nondma_stream = device->machine().sound().stream_alloc(*device, 0, 1, OUTPUT_RATE, NULL, leland_80186_dac_update); - - /* if we have a 2151, install an externally driven DAC stream */ - if (state->m_has_ym2151) - { - state->m_ext_base = machine.root_device().memregion("dac")->base(); - state->m_extern_stream = device->machine().sound().stream_alloc(*device, 0, 1, OUTPUT_RATE, NULL, leland_80186_extern_update); - } - - /* create timers here so they stick around */ - state->m_i80186.cpu = &dmaspace.device(); - state->m_i80186.timer[0].int_timer = machine.scheduler().timer_alloc(FUNC(internal_timer_int), device); - state->m_i80186.timer[1].int_timer = machine.scheduler().timer_alloc(FUNC(internal_timer_int), device); - state->m_i80186.timer[2].int_timer = machine.scheduler().timer_alloc(FUNC(internal_timer_int), device); - state->m_i80186.timer[0].time_timer = machine.scheduler().timer_alloc(FUNC_NULL); - state->m_i80186.timer[1].time_timer = machine.scheduler().timer_alloc(FUNC_NULL); - state->m_i80186.timer[2].time_timer = machine.scheduler().timer_alloc(FUNC_NULL); - state->m_i80186.dma[0].finish_timer = machine.scheduler().timer_alloc(FUNC(dma_timer_callback), device); - state->m_i80186.dma[1].finish_timer = machine.scheduler().timer_alloc(FUNC(dma_timer_callback), device); - - for (i = 0; i < 9; i++) - state->m_counter[i].timer = machine.scheduler().timer_alloc(FUNC_NULL); + m_dac_timer = timer_alloc(); } -static DEVICE_START( leland_80186_sound ) +void leland_80186_sound_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { - leland_sound_state *state = get_safe_token(device); - state->m_is_redline = 0; - DEVICE_START_CALL(common_sh_start); + INT32 out = 0; + for(int i = 0; i < 8; i++) + out += m_dac_sample[i] * m_dac_volume[i]; + m_dac->write(out>>10); } -static DEVICE_RESET( leland_80186_sound ); - -static DEVICE_START( redline_80186_sound ) +void leland_80186_sound_device::device_reset() { - leland_sound_state *state = get_safe_token(device); - state->m_is_redline = 1; - DEVICE_START_CALL(common_sh_start); + m_last_control = 0xf8; + m_clock_active = 0; + m_clock_tick = 0; + m_ext_start = 0; + m_ext_stop = 0; + m_ext_active = 0; + memset(m_dac_sample, 0, sizeof(m_dac_sample)); + memset(m_dac_volume, 0x80, sizeof(m_dac_volume)); + m_dac_timer->adjust(attotime::from_hz(48000), 0, attotime::from_hz(48000)); } - -const device_type LELAND = &device_creator; - -leland_sound_device::leland_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : device_t(mconfig, LELAND, "Leland DAC", tag, owner, clock, "leland_dac", __FILE__), - device_sound_interface(mconfig, *this) -{ - m_token = global_alloc_clear(leland_sound_state); -} - -leland_sound_device::leland_sound_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) - : device_t(mconfig, type, name, tag, owner, clock, shortname, source), - device_sound_interface(mconfig, *this) -{ - m_token = global_alloc_clear(leland_sound_state); -} - -//------------------------------------------------- -// device_config_complete - perform any -// operations now that the configuration is -// complete -//------------------------------------------------- - -void leland_sound_device::device_config_complete() -{ -} - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void leland_sound_device::device_start() -{ - DEVICE_START_NAME( leland_sound )(this); -} - -//------------------------------------------------- -// sound_stream_update - handle a stream update -//------------------------------------------------- - -void leland_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) -{ - // should never get here - fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); -} - - const device_type LELAND_80186 = &device_creator; leland_80186_sound_device::leland_80186_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : leland_sound_device(mconfig, LELAND_80186, "Leland 80186 DAC", tag, owner, clock, "leland_80186_sound", __FILE__) + : device_t(mconfig, LELAND_80186, "Leland 80186 DAC", tag, owner, clock, "leland_80186_sound", __FILE__), + m_dac(*this, "dac"), + m_pit0(*this, "pit0"), + m_pit1(*this, "pit1"), + m_pit2(*this, "pit2"), + m_ymsnd(*this, "ymsnd") { + m_type = TYPE_LELAND; } leland_80186_sound_device::leland_80186_sound_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) - : leland_sound_device(mconfig, type, name, tag, owner, clock, shortname, source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + m_dac(*this, "dac"), + m_pit0(*this, "pit0"), + m_pit1(*this, "pit1"), + m_pit2(*this, "pit2"), + m_ymsnd(*this, "ymsnd") { } - -//------------------------------------------------- -// device_config_complete - perform any -// operations now that the configuration is -// complete -//------------------------------------------------- - -void leland_80186_sound_device::device_config_complete() -{ -} - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void leland_80186_sound_device::device_start() -{ - DEVICE_START_NAME( leland_80186_sound )(this); -} - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void leland_80186_sound_device::device_reset() -{ - DEVICE_RESET_NAME( leland_80186_sound )(this); -} - -//------------------------------------------------- -// sound_stream_update - handle a stream update -//------------------------------------------------- - -void leland_80186_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) -{ - // should never get here - fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); -} - - const device_type REDLINE_80186 = &device_creator; redline_80186_sound_device::redline_80186_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : leland_80186_sound_device(mconfig, REDLINE_80186, "Redline Racer 80186 DAC", tag, owner, clock, "redline_80186_sound", __FILE__) { + m_type = TYPE_REDLINE; } -//------------------------------------------------- -// device_config_complete - perform any -// operations now that the configuration is -// complete -//------------------------------------------------- +const device_type ATAXX_80186 = &device_creator; -void redline_80186_sound_device::device_config_complete() +ataxx_80186_sound_device::ataxx_80186_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : leland_80186_sound_device(mconfig, REDLINE_80186, "Ataxx 80186 DAC", tag, owner, clock, "ataxx_80186_sound", __FILE__) { + m_type = TYPE_ATAXX; } -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- +const device_type WSF_80186 = &device_creator; -void redline_80186_sound_device::device_start() +wsf_80186_sound_device::wsf_80186_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : leland_80186_sound_device(mconfig, REDLINE_80186, "WSF 80186 DAC", tag, owner, clock, "wsf_80186_sound", __FILE__) { - DEVICE_START_NAME( redline_80186_sound )(this); + m_type = TYPE_WSF; } -//------------------------------------------------- -// sound_stream_update - handle a stream update -//------------------------------------------------- - -void redline_80186_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) +WRITE16_MEMBER(leland_80186_sound_device::peripheral_ctrl) { - // should never get here - fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); -} - - - - -static void leland_80186_reset(device_t *device) -{ - leland_sound_state *state = get_safe_token(device); - struct i80186_state oldstate = state->m_i80186; - emu_timer *counter_timer[9]; - int i; - - /* reset the i80186 state, but save the timers */ - memset(&state->m_i80186, 0, sizeof(state->m_i80186)); - state->m_i80186.cpu = oldstate.cpu; - state->m_i80186.timer[0].int_timer = oldstate.timer[0].int_timer; - state->m_i80186.timer[1].int_timer = oldstate.timer[1].int_timer; - state->m_i80186.timer[2].int_timer = oldstate.timer[2].int_timer; - state->m_i80186.timer[0].time_timer = oldstate.timer[0].time_timer; - state->m_i80186.timer[1].time_timer = oldstate.timer[1].time_timer; - state->m_i80186.timer[2].time_timer = oldstate.timer[2].time_timer; - state->m_i80186.dma[0].finish_timer = oldstate.dma[0].finish_timer; - state->m_i80186.dma[1].finish_timer = oldstate.dma[1].finish_timer; - - /* reset the interrupt state */ - state->m_i80186.intr.priority_mask = 0x0007; - state->m_i80186.intr.timer = 0x000f; - state->m_i80186.intr.dma[0] = 0x000f; - state->m_i80186.intr.dma[1] = 0x000f; - state->m_i80186.intr.ext[0] = 0x000f; - state->m_i80186.intr.ext[1] = 0x000f; - state->m_i80186.intr.ext[2] = 0x000f; - state->m_i80186.intr.ext[3] = 0x000f; - - /* reset the DAC and counter states as well */ - memset(&state->m_dac, 0, sizeof(state->m_dac)); - for (i = 0; i < 9; i++) - counter_timer[i] = state->m_counter[i].timer; - memset(&state->m_counter, 0, sizeof(state->m_counter)); - for (i = 0; i < 9; i++) - state->m_counter[i].timer = counter_timer[i]; -} - - -static DEVICE_RESET( leland_80186_sound ) -{ - leland_sound_state *state = get_safe_token(device); - - /* reset the 80186 registers */ - leland_80186_reset(device); - - /* reset our internal stuff */ - state->m_last_control = 0xf8; - state->m_clock_active = 0; - - /* reset the external DAC */ - state->m_ext_start = 0; - state->m_ext_stop = 0; - state->m_ext_active = 0; -} - - - -/************************************* - * - * 80186 interrupt controller - * - *************************************/ - -static IRQ_CALLBACK( int_callback ) -{ - leland_sound_state *state = get_safe_token(device->machine().device("custom")); - if (LOG_INTERRUPTS) logerror("(%f) **** Acknowledged interrupt vector %02X\n", device->machine().time().as_double(), state->m_i80186.intr.poll_status & 0x1f); - - /* clear the interrupt */ - state->m_i80186.cpu->execute().set_input_line(0, CLEAR_LINE); - state->m_i80186.intr.pending = 0; - - /* clear the request and set the in-service bit */ -#if LATCH_INTS - state->m_i80186.intr.request &= ~state->m_i80186.intr.ack_mask; -#else - state->m_i80186.intr.request &= ~(state->m_i80186.intr.ack_mask & 0x0f); -#endif - state->m_i80186.intr.in_service |= state->m_i80186.intr.ack_mask; - if (state->m_i80186.intr.ack_mask == 0x0001) + switch(offset) { - switch (state->m_i80186.intr.poll_status & 0x1f) + case 2: + m_peripheral = data; + break; + case 4: { - case 0x08: state->m_i80186.intr.status &= ~0x01; break; - case 0x12: state->m_i80186.intr.status &= ~0x02; break; - case 0x13: state->m_i80186.intr.status &= ~0x04; break; - } - } - state->m_i80186.intr.ack_mask = 0; - - /* a request no longer pending */ - state->m_i80186.intr.poll_status &= ~0x8000; - - /* return the vector */ - return state->m_i80186.intr.poll_status & 0x1f; -} - - -static void update_interrupt_state(device_t *device) -{ - leland_sound_state *state = get_safe_token(device); - running_machine &machine = device->machine(); - int i, j, new_vector = 0; - - if (LOG_INTERRUPTS) logerror("update_interrupt_status: req=%02X stat=%02X serv=%02X\n", state->m_i80186.intr.request, state->m_i80186.intr.status, state->m_i80186.intr.in_service); - - /* loop over priorities */ - for (i = 0; i <= state->m_i80186.intr.priority_mask; i++) - { - /* note: by checking 4 bits, we also verify that the mask is off */ - if ((state->m_i80186.intr.timer & 15) == i) - { - /* if we're already servicing something at this level, don't generate anything new */ - if (state->m_i80186.intr.in_service & 0x01) - return; - - /* if there's something pending, generate an interrupt */ - if (state->m_i80186.intr.status & 0x07) + UINT32 temp = (m_peripheral & 0xffc0) << 4; + if (data & 0x0040) { - if (state->m_i80186.intr.status & 1) - new_vector = 0x08; - else if (state->m_i80186.intr.status & 2) - new_vector = 0x12; - else if (state->m_i80186.intr.status & 4) - new_vector = 0x13; - else - popmessage("Invalid timer interrupt!"); - - /* set the clear mask and generate the int */ - state->m_i80186.intr.ack_mask = 0x0001; - goto generate_int; - } - } - - /* check DMA interrupts */ - for (j = 0; j < 2; j++) - if ((state->m_i80186.intr.dma[j] & 15) == i) - { - /* if we're already servicing something at this level, don't generate anything new */ - if (state->m_i80186.intr.in_service & (0x04 << j)) - return; - - /* if there's something pending, generate an interrupt */ - if (state->m_i80186.intr.request & (0x04 << j)) - { - new_vector = 0x0a + j; - - /* set the clear mask and generate the int */ - state->m_i80186.intr.ack_mask = 0x0004 << j; - goto generate_int; - } - } - - /* check external interrupts */ - for (j = 0; j < 4; j++) - if ((state->m_i80186.intr.ext[j] & 15) == i) - { - /* if we're already servicing something at this level, don't generate anything new */ - if (state->m_i80186.intr.in_service & (0x10 << j)) - return; - - /* if there's something pending, generate an interrupt */ - if (state->m_i80186.intr.request & (0x10 << j)) - { - /* otherwise, generate an interrupt for this request */ - new_vector = 0x0c + j; - - /* set the clear mask and generate the int */ - state->m_i80186.intr.ack_mask = 0x0010 << j; - goto generate_int; - } - } - } - return; - -generate_int: - /* generate the appropriate interrupt */ - state->m_i80186.intr.poll_status = 0x8000 | new_vector; - if (!state->m_i80186.intr.pending) - machine.device("audiocpu")->execute().set_input_line(0, ASSERT_LINE); - state->m_i80186.intr.pending = 1; - if (LOG_INTERRUPTS) logerror("(%f) **** Requesting interrupt vector %02X\n", machine.time().as_double(), new_vector); -} - - -static void handle_eoi(device_t *device, int data) -{ - leland_sound_state *state = get_safe_token(device); - running_machine &machine = device->machine(); - int i, j; - - /* specific case */ - if (!(data & 0x8000)) - { - /* turn off the appropriate in-service bit */ - switch (data & 0x1f) - { - case 0x08: state->m_i80186.intr.in_service &= ~0x01; break; - case 0x12: state->m_i80186.intr.in_service &= ~0x01; break; - case 0x13: state->m_i80186.intr.in_service &= ~0x01; break; - case 0x0a: state->m_i80186.intr.in_service &= ~0x04; break; - case 0x0b: state->m_i80186.intr.in_service &= ~0x08; break; - case 0x0c: state->m_i80186.intr.in_service &= ~0x10; break; - case 0x0d: state->m_i80186.intr.in_service &= ~0x20; break; - case 0x0e: state->m_i80186.intr.in_service &= ~0x40; break; - case 0x0f: state->m_i80186.intr.in_service &= ~0x80; break; - default: logerror("%s:ERROR - 80186 EOI with unknown vector %02X\n", machine.describe_context(), data & 0x1f); - } - if (LOG_INTERRUPTS) logerror("(%f) **** Got EOI for vector %02X\n", machine.time().as_double(), data & 0x1f); - } - - /* non-specific case */ - else - { - /* loop over priorities */ - for (i = 0; i <= 7; i++) - { - /* check for in-service timers */ - if ((state->m_i80186.intr.timer & 7) == i && (state->m_i80186.intr.in_service & 0x01)) - { - state->m_i80186.intr.in_service &= ~0x01; - if (LOG_INTERRUPTS) logerror("(%f) **** Got EOI for timer\n", machine.time().as_double()); - return; - } - - /* check for in-service DMA interrupts */ - for (j = 0; j < 2; j++) - if ((state->m_i80186.intr.dma[j] & 7) == i && (state->m_i80186.intr.in_service & (0x04 << j))) - { - state->m_i80186.intr.in_service &= ~(0x04 << j); - if (LOG_INTERRUPTS) logerror("(%f) **** Got EOI for DMA%d\n", machine.time().as_double(), j); - return; - } - - /* check external interrupts */ - for (j = 0; j < 4; j++) - if ((state->m_i80186.intr.ext[j] & 7) == i && (state->m_i80186.intr.in_service & (0x10 << j))) - { - state->m_i80186.intr.in_service &= ~(0x10 << j); - if (LOG_INTERRUPTS) logerror("(%f) **** Got EOI for INT%d\n", machine.time().as_double(), j); - return; - } - } - } -} - - - -/************************************* - * - * 80186 internal timers - * - *************************************/ - -static TIMER_CALLBACK( internal_timer_int ) -{ - device_t *device = (device_t *)ptr; - leland_sound_state *state = get_safe_token(device); - int which = param; - struct timer_state *t = &state->m_i80186.timer[which]; - - if (LOG_TIMER) logerror("Hit interrupt callback for timer %d\n", which); - - /* set the max count bit */ - t->control |= 0x0020; - - /* request an interrupt */ - if (t->control & 0x2000) - { - state->m_i80186.intr.status |= 0x01 << which; - update_interrupt_state(device); - if (LOG_TIMER) logerror(" Generating timer interrupt\n"); - } - - /* if we're continuous, reset */ - if (t->control & 0x0001) - { - int count = t->maxA ? t->maxA : 0x10000; - t->int_timer->adjust(attotime::from_hz(2000000) * count, which); - if (LOG_TIMER) logerror(" Repriming interrupt\n"); - } - else - t->int_timer->adjust(attotime::never, which); -} - - -static void internal_timer_sync(leland_sound_state *state, int which) -{ - struct timer_state *t = &state->m_i80186.timer[which]; - - /* if we have a timing timer running, adjust the count */ - if (t->time_timer_active) - { - attotime current_time = t->time_timer->elapsed(); - int net_clocks = ((current_time - t->last_time) * 2000000).as_double(); - t->last_time = current_time; - - /* set the max count bit if we passed the max */ - if ((int)t->count + net_clocks >= t->maxA) - t->control |= 0x0020; - - /* set the new count */ - if (t->maxA != 0) - t->count = (t->count + net_clocks) % t->maxA; - else - t->count = t->count + net_clocks; - } -} - - -static void internal_timer_update(leland_sound_state *state, int which, int new_count, int new_maxA, int new_maxB, int new_control) -{ - struct timer_state *t = &state->m_i80186.timer[which]; - int update_int_timer = 0; - - /* if we have a new count and we're on, update things */ - if (new_count != -1) - { - if (t->control & 0x8000) - { - internal_timer_sync(state, which); - update_int_timer = 1; - } - t->count = new_count; - } - - /* if we have a new max and we're on, update things */ - if (new_maxA != -1 && new_maxA != t->maxA) - { - if (t->control & 0x8000) - { - internal_timer_sync(state, which); - update_int_timer = 1; - } - t->maxA = new_maxA; - if (new_maxA == 0) new_maxA = 0x10000; - - /* redline racer controls nothing externally? */ - if (state->m_is_redline) - ; - - /* on the common board, timer 0 controls the 10-bit DAC frequency */ - else if (which == 0) - set_dac_frequency(state, 6, 2000000 / new_maxA); - - /* timer 1 controls the externally driven DAC on Indy Heat/WSF */ - else if (which == 1 && state->m_has_ym2151) - set_dac_frequency(state, 7, 2000000 / (new_maxA * 2)); - } - - /* if we have a new max and we're on, update things */ - if (new_maxB != -1 && new_maxB != t->maxB) - { - if (t->control & 0x8000) - { - internal_timer_sync(state, which); - update_int_timer = 1; - } - t->maxB = new_maxB; - if (new_maxB == 0) new_maxB = 0x10000; - - /* timer 1 controls the externally driven DAC on Indy Heat/WSF */ - /* they alternate the use of maxA and maxB in a way that makes no */ - /* sense according to the 80186 documentation! */ - if (which == 1 && state->m_has_ym2151) - set_dac_frequency(state, 7, 2000000 / (new_maxB * 2)); - } - - /* handle control changes */ - if (new_control != -1) - { - int diff; - - /* merge back in the bits we don't modify */ - new_control = (new_control & ~0x1fc0) | (t->control & 0x1fc0); - - /* handle the /INH bit */ - if (!(new_control & 0x4000)) - new_control = (new_control & ~0x8000) | (t->control & 0x8000); - new_control &= ~0x4000; - - /* check for control bits we don't handle */ - diff = new_control ^ t->control; - if (diff & 0x001c) - logerror("ERROR! - unsupported timer mode %04X\n", new_control); - - /* if we have real changes, update things */ - if (diff != 0) - { - /* if we're going off, make sure our timers are gone */ - if ((diff & 0x8000) && !(new_control & 0x8000)) - { - /* compute the final count */ - internal_timer_sync(state, which); - - /* nuke the timer and force the interrupt timer to be recomputed */ - t->time_timer->adjust(attotime::never, which); - t->time_timer_active = 0; - update_int_timer = 1; - } - - /* if we're going on, start the timers running */ - else if ((diff & 0x8000) && (new_control & 0x8000)) - { - /* start the timing */ - t->time_timer->adjust(attotime::never, which); - t->time_timer_active = 1; - update_int_timer = 1; - } - - /* if something about the interrupt timer changed, force an update */ - if (!(diff & 0x8000) && (diff & 0x2000)) - { - internal_timer_sync(state, which); - update_int_timer = 1; - } - } - - /* set the new control register */ - t->control = new_control; - } - - /* update the interrupt timer */ - - /* kludge: the YM2151 games sometimes crank timer 1 really high, and leave interrupts */ - /* enabled, even though the handler for timer 1 does nothing. To alleviate this, we */ - /* just ignore it */ - if (!state->m_has_ym2151 || which != 1) - if (update_int_timer) - { - if ((t->control & 0x8000) && (t->control & 0x2000)) - { - int diff = t->maxA - t->count; - if (diff <= 0) diff += 0x10000; - t->int_timer->adjust(attotime::from_hz(2000000) * diff, which); - if (LOG_TIMER) logerror("Set interrupt timer for %d\n", which); - } - else - t->int_timer->adjust(attotime::never, which); - } -} - - - -/************************************* - * - * 80186 internal DMA - * - *************************************/ - -static TIMER_CALLBACK( dma_timer_callback ) -{ - device_t *device = (device_t *)ptr; - leland_sound_state *state = get_safe_token(device); - int which = param; - struct dma_state *d = &state->m_i80186.dma[which]; - - /* force an update and see if we're really done */ - state->m_dma_stream->update(); - - /* complete the status update */ - d->control &= ~0x0002; - d->source += d->count; - d->count = 0; - - /* check for interrupt generation */ - if (d->control & 0x0100) - { - if (LOG_DMA) logerror("DMA%d timer callback - requesting interrupt: count = %04X, source = %04X\n", which, d->count, d->source); - state->m_i80186.intr.request |= 0x04 << which; - update_interrupt_state(device); - } -} - - -static void update_dma_control(leland_sound_state *state, int which, int new_control) -{ - struct dma_state *d = &state->m_i80186.dma[which]; - int diff; - - /* handle the CHG bit */ - if (!(new_control & 0x0004)) - new_control = (new_control & ~0x0002) | (d->control & 0x0002); - new_control &= ~0x0004; - - /* check for control bits we don't handle */ - diff = new_control ^ d->control; - if (diff & 0x6811) - logerror("ERROR! - unsupported DMA mode %04X\n", new_control); - - /* if we're going live, set a timer */ - if ((diff & 0x0002) && (new_control & 0x0002)) - { - /* make sure the parameters meet our expectations */ - if ((new_control & 0xfe00) != 0x1600) - { - logerror("Unexpected DMA control %02X\n", new_control); - } - else if (!state->m_is_redline && ((d->dest & 1) || (d->dest & 0x3f) > 0x0b)) - { - logerror("Unexpected DMA destination %02X\n", d->dest); - } - else if (state->m_is_redline && (d->dest & 0xf000) != 0x4000 && (d->dest & 0xf000) != 0x5000) - { - logerror("Unexpected DMA destination %02X\n", d->dest); - } - - /* otherwise, set a timer */ - else - { - int count = d->count; - int dacnum; - - /* adjust for redline racer */ - if (!state->m_is_redline) - dacnum = (d->dest & 0x3f) / 2; - else - { - dacnum = (d->dest >> 9) & 7; - state->m_dac[dacnum].volume = (d->dest & 0x1fe) / 2 / DAC_VOLUME_SCALE; - } - - if (LOG_DMA) logerror("Initiated DMA %d - count = %04X, source = %04X, dest = %04X\n", which, d->count, d->source, d->dest); - - d->finished = 0; - d->finish_timer->adjust(attotime::from_hz(state->m_dac[dacnum].frequency) * count, which); - } - } - - /* set the new control register */ - d->control = new_control; -} - - - -/************************************* - * - * 80186 internal I/O reads - * - *************************************/ - -static READ16_DEVICE_HANDLER( i80186_internal_port_r ) -{ - leland_sound_state *state = get_safe_token(device); - int temp, which; - - switch (offset) - { - case 0x22/2: - logerror("%05X:ERROR - read from 80186 EOI\n", state->m_i80186.cpu->safe_pc()); - break; - - case 0x24/2: - if (LOG_PORTS) logerror("%05X:read 80186 interrupt poll\n", state->m_i80186.cpu->safe_pc()); - if (state->m_i80186.intr.poll_status & 0x8000) - int_callback(state->m_i80186.cpu, 0); - return state->m_i80186.intr.poll_status; - - case 0x26/2: - if (LOG_PORTS) logerror("%05X:read 80186 interrupt poll status\n", state->m_i80186.cpu->safe_pc()); - return state->m_i80186.intr.poll_status; - - case 0x28/2: - if (LOG_PORTS) logerror("%05X:read 80186 interrupt mask\n", state->m_i80186.cpu->safe_pc()); - temp = (state->m_i80186.intr.timer >> 3) & 0x01; - temp |= (state->m_i80186.intr.dma[0] >> 1) & 0x04; - temp |= (state->m_i80186.intr.dma[1] >> 0) & 0x08; - temp |= (state->m_i80186.intr.ext[0] << 1) & 0x10; - temp |= (state->m_i80186.intr.ext[1] << 2) & 0x20; - temp |= (state->m_i80186.intr.ext[2] << 3) & 0x40; - temp |= (state->m_i80186.intr.ext[3] << 4) & 0x80; - return temp; - - case 0x2a/2: - if (LOG_PORTS) logerror("%05X:read 80186 interrupt priority mask\n", state->m_i80186.cpu->safe_pc()); - return state->m_i80186.intr.priority_mask; - - case 0x2c/2: - if (LOG_PORTS) logerror("%05X:read 80186 interrupt in-service\n", state->m_i80186.cpu->safe_pc()); - return state->m_i80186.intr.in_service; - - case 0x2e/2: - if (LOG_PORTS) logerror("%05X:read 80186 interrupt request\n", state->m_i80186.cpu->safe_pc()); - temp = state->m_i80186.intr.request & ~0x0001; - if (state->m_i80186.intr.status & 0x0007) - temp |= 1; - return temp; - - case 0x30/2: - if (LOG_PORTS) logerror("%05X:read 80186 interrupt status\n", state->m_i80186.cpu->safe_pc()); - return state->m_i80186.intr.status; - - case 0x32/2: - if (LOG_PORTS) logerror("%05X:read 80186 timer interrupt control\n", state->m_i80186.cpu->safe_pc()); - return state->m_i80186.intr.timer; - - case 0x34/2: - if (LOG_PORTS) logerror("%05X:read 80186 DMA 0 interrupt control\n", state->m_i80186.cpu->safe_pc()); - return state->m_i80186.intr.dma[0]; - - case 0x36/2: - if (LOG_PORTS) logerror("%05X:read 80186 DMA 1 interrupt control\n", state->m_i80186.cpu->safe_pc()); - return state->m_i80186.intr.dma[1]; - - case 0x38/2: - if (LOG_PORTS) logerror("%05X:read 80186 INT 0 interrupt control\n", state->m_i80186.cpu->safe_pc()); - return state->m_i80186.intr.ext[0]; - - case 0x3a/2: - if (LOG_PORTS) logerror("%05X:read 80186 INT 1 interrupt control\n", state->m_i80186.cpu->safe_pc()); - return state->m_i80186.intr.ext[1]; - - case 0x3c/2: - if (LOG_PORTS) logerror("%05X:read 80186 INT 2 interrupt control\n", state->m_i80186.cpu->safe_pc()); - return state->m_i80186.intr.ext[2]; - - case 0x3e/2: - if (LOG_PORTS) logerror("%05X:read 80186 INT 3 interrupt control\n", state->m_i80186.cpu->safe_pc()); - return state->m_i80186.intr.ext[3]; - - case 0x50/2: - case 0x58/2: - case 0x60/2: - if (LOG_PORTS) logerror("%05X:read 80186 Timer %d count\n", state->m_i80186.cpu->safe_pc(), (offset - 0x50/2) / 4); - which = (offset - 0x50/2) / 4; - if (ACCESSING_BITS_0_7) - internal_timer_sync(state, which); - return state->m_i80186.timer[which].count; - - case 0x52/2: - case 0x5a/2: - case 0x62/2: - if (LOG_PORTS) logerror("%05X:read 80186 Timer %d max A\n", state->m_i80186.cpu->safe_pc(), (offset - 0x50/2) / 4); - which = (offset - 0x50/2) / 4; - return state->m_i80186.timer[which].maxA; - - case 0x54/2: - case 0x5c/2: - logerror("%05X:read 80186 Timer %d max B\n", state->m_i80186.cpu->safe_pc(), (offset/2 - 0x50) / 4); - which = (offset - 0x50/2) / 4; - return state->m_i80186.timer[which].maxB; - - case 0x56/2: - case 0x5e/2: - case 0x66/2: - if (LOG_PORTS) logerror("%05X:read 80186 Timer %d control\n", state->m_i80186.cpu->safe_pc(), (offset - 0x50/2) / 4); - which = (offset - 0x50/2) / 4; - return state->m_i80186.timer[which].control; - - case 0xa0/2: - if (LOG_PORTS) logerror("%05X:read 80186 upper chip select\n", state->m_i80186.cpu->safe_pc()); - return state->m_i80186.mem.upper; - - case 0xa2/2: - if (LOG_PORTS) logerror("%05X:read 80186 lower chip select\n", state->m_i80186.cpu->safe_pc()); - return state->m_i80186.mem.lower; - - case 0xa4/2: - if (LOG_PORTS) logerror("%05X:read 80186 peripheral chip select\n", state->m_i80186.cpu->safe_pc()); - return state->m_i80186.mem.peripheral; - - case 0xa6/2: - if (LOG_PORTS) logerror("%05X:read 80186 middle chip select\n", state->m_i80186.cpu->safe_pc()); - return state->m_i80186.mem.middle; - - case 0xa8/2: - if (LOG_PORTS) logerror("%05X:read 80186 middle P chip select\n", state->m_i80186.cpu->safe_pc()); - return state->m_i80186.mem.middle_size; - - case 0xc0/2: - case 0xd0/2: - if (LOG_PORTS) logerror("%05X:read 80186 DMA%d lower source address\n", state->m_i80186.cpu->safe_pc(), (offset - 0xc0/2) / 8); - which = (offset - 0xc0/2) / 8; - state->m_dma_stream->update(); - return state->m_i80186.dma[which].source; - - case 0xc2/2: - case 0xd2/2: - if (LOG_PORTS) logerror("%05X:read 80186 DMA%d upper source address\n", state->m_i80186.cpu->safe_pc(), (offset - 0xc0/2) / 8); - which = (offset - 0xc0/2) / 8; - state->m_dma_stream->update(); - return state->m_i80186.dma[which].source >> 16; - - case 0xc4/2: - case 0xd4/2: - if (LOG_PORTS) logerror("%05X:read 80186 DMA%d lower dest address\n", state->m_i80186.cpu->safe_pc(), (offset - 0xc0/2) / 8); - which = (offset - 0xc0/2) / 8; - state->m_dma_stream->update(); - return state->m_i80186.dma[which].dest; - - case 0xc6/2: - case 0xd6/2: - if (LOG_PORTS) logerror("%05X:read 80186 DMA%d upper dest address\n", state->m_i80186.cpu->safe_pc(), (offset - 0xc0/2) / 8); - which = (offset - 0xc0/2) / 8; - state->m_dma_stream->update(); - return state->m_i80186.dma[which].dest >> 16; - - case 0xc8/2: - case 0xd8/2: - if (LOG_PORTS) logerror("%05X:read 80186 DMA%d transfer count\n", state->m_i80186.cpu->safe_pc(), (offset - 0xc0/2) / 8); - which = (offset - 0xc0/2) / 8; - state->m_dma_stream->update(); - return state->m_i80186.dma[which].count; - - case 0xca/2: - case 0xda/2: - if (LOG_PORTS) logerror("%05X:read 80186 DMA%d control\n", state->m_i80186.cpu->safe_pc(), (offset - 0xc0/2) / 8); - which = (offset - 0xc0/2) / 8; - state->m_dma_stream->update(); - return state->m_i80186.dma[which].control; - - default: - logerror("%05X:read 80186 port %02X\n", state->m_i80186.cpu->safe_pc(), offset*2); - break; - } - return 0x00; -} - - - -/************************************* - * - * 80186 internal I/O writes - * - *************************************/ - -static WRITE16_DEVICE_HANDLER( i80186_internal_port_w ) -{ - leland_sound_state *state = get_safe_token(device); - int temp, which; - - /* handle partials */ - if (!ACCESSING_BITS_8_15) - data = (i80186_internal_port_r(device, space, offset, 0xff00) & 0xff00) | (data & 0x00ff); - else if (!ACCESSING_BITS_0_7) - data = (i80186_internal_port_r(device, space, offset, 0x00ff) & 0x00ff) | (data & 0xff00); - - switch (offset) - { - case 0x22/2: - if (LOG_PORTS) logerror("%05X:80186 EOI = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - handle_eoi(device, 0x8000); - update_interrupt_state(device); - break; - - case 0x24/2: - logerror("%05X:ERROR - write to 80186 interrupt poll = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - break; - - case 0x26/2: - logerror("%05X:ERROR - write to 80186 interrupt poll status = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - break; - - case 0x28/2: - if (LOG_PORTS) logerror("%05X:80186 interrupt mask = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - state->m_i80186.intr.timer = (state->m_i80186.intr.timer & ~0x08) | ((data << 3) & 0x08); - state->m_i80186.intr.dma[0] = (state->m_i80186.intr.dma[0] & ~0x08) | ((data << 1) & 0x08); - state->m_i80186.intr.dma[1] = (state->m_i80186.intr.dma[1] & ~0x08) | ((data << 0) & 0x08); - state->m_i80186.intr.ext[0] = (state->m_i80186.intr.ext[0] & ~0x08) | ((data >> 1) & 0x08); - state->m_i80186.intr.ext[1] = (state->m_i80186.intr.ext[1] & ~0x08) | ((data >> 2) & 0x08); - state->m_i80186.intr.ext[2] = (state->m_i80186.intr.ext[2] & ~0x08) | ((data >> 3) & 0x08); - state->m_i80186.intr.ext[3] = (state->m_i80186.intr.ext[3] & ~0x08) | ((data >> 4) & 0x08); - update_interrupt_state(device); - break; - - case 0x2a/2: - if (LOG_PORTS) logerror("%05X:80186 interrupt priority mask = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - state->m_i80186.intr.priority_mask = data & 0x0007; - update_interrupt_state(device); - break; - - case 0x2c/2: - if (LOG_PORTS) logerror("%05X:80186 interrupt in-service = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - state->m_i80186.intr.in_service = data & 0x00ff; - update_interrupt_state(device); - break; - - case 0x2e/2: - if (LOG_PORTS) logerror("%05X:80186 interrupt request = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - state->m_i80186.intr.request = (state->m_i80186.intr.request & ~0x00c0) | (data & 0x00c0); - update_interrupt_state(device); - break; - - case 0x30/2: - if (LOG_PORTS) logerror("%05X:WARNING - wrote to 80186 interrupt status = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - state->m_i80186.intr.status = (state->m_i80186.intr.status & ~0x8000) | (data & 0x8000); - state->m_i80186.intr.status = (state->m_i80186.intr.status & ~0x0007) | (data & 0x0007); - update_interrupt_state(device); - break; - - case 0x32/2: - if (LOG_PORTS) logerror("%05X:80186 timer interrupt contol = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - state->m_i80186.intr.timer = data & 0x000f; - break; - - case 0x34/2: - if (LOG_PORTS) logerror("%05X:80186 DMA 0 interrupt control = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - state->m_i80186.intr.dma[0] = data & 0x000f; - break; - - case 0x36/2: - if (LOG_PORTS) logerror("%05X:80186 DMA 1 interrupt control = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - state->m_i80186.intr.dma[1] = data & 0x000f; - break; - - case 0x38/2: - if (LOG_PORTS) logerror("%05X:80186 INT 0 interrupt control = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - state->m_i80186.intr.ext[0] = data & 0x007f; - break; - - case 0x3a/2: - if (LOG_PORTS) logerror("%05X:80186 INT 1 interrupt control = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - state->m_i80186.intr.ext[1] = data & 0x007f; - break; - - case 0x3c/2: - if (LOG_PORTS) logerror("%05X:80186 INT 2 interrupt control = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - state->m_i80186.intr.ext[2] = data & 0x001f; - break; - - case 0x3e/2: - if (LOG_PORTS) logerror("%05X:80186 INT 3 interrupt control = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - state->m_i80186.intr.ext[3] = data & 0x001f; - break; - - case 0x50/2: - case 0x58/2: - case 0x60/2: - if (LOG_PORTS) logerror("%05X:80186 Timer %d count = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), (offset - 0x50/2) / 4, data, mem_mask); - which = (offset - 0x50/2) / 4; - internal_timer_update(state, which, data, -1, -1, -1); - break; - - case 0x52/2: - case 0x5a/2: - case 0x62/2: - if (LOG_PORTS) logerror("%05X:80186 Timer %d max A = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), (offset - 0x50/2) / 4, data, mem_mask); - which = (offset - 0x50/2) / 4; - internal_timer_update(state, which, -1, data, -1, -1); - break; - - case 0x54/2: - case 0x5c/2: - if (LOG_PORTS) logerror("%05X:80186 Timer %d max B = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), (offset - 0x50/2) / 4, data, mem_mask); - which = (offset - 0x50/2) / 4; - internal_timer_update(state, which, -1, -1, data, -1); - break; - - case 0x56/2: - case 0x5e/2: - case 0x66/2: - if (LOG_PORTS) logerror("%05X:80186 Timer %d control = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), (offset - 0x50/2) / 4, data, mem_mask); - which = (offset - 0x50/2) / 4; - internal_timer_update(state, which, -1, -1, -1, data); - break; - - case 0xa0/2: - if (LOG_PORTS) logerror("%05X:80186 upper chip select = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - state->m_i80186.mem.upper = data | 0xc038; - break; - - case 0xa2/2: - if (LOG_PORTS) logerror("%05X:80186 lower chip select = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - state->m_i80186.mem.lower = (data & 0x3fff) | 0x0038; - break; - - case 0xa4/2: - if (LOG_PORTS) logerror("%05X:80186 peripheral chip select = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - state->m_i80186.mem.peripheral = data | 0x0038; - break; - - case 0xa6/2: - if (LOG_PORTS) logerror("%05X:80186 middle chip select = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - state->m_i80186.mem.middle = data | 0x01f8; - break; - - case 0xa8/2: - if (LOG_PORTS) logerror("%05X:80186 middle P chip select = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - state->m_i80186.mem.middle_size = data | 0x8038; - - temp = (state->m_i80186.mem.peripheral & 0xffc0) << 4; - if (state->m_i80186.mem.middle_size & 0x0040) - { - state->m_i80186.cpu->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(*device, temp, temp + 0x2ff, FUNC(peripheral_r), FUNC(peripheral_w)); + m_audiocpu->device_t::memory().space(AS_PROGRAM).install_readwrite_handler(temp, temp + 0x2ff, read16_delegate(FUNC(leland_80186_sound_device::peripheral_r), this), write16_delegate(FUNC(leland_80186_sound_device::peripheral_w), this)); } else { temp &= 0xffff; - state->m_i80186.cpu->memory().space(AS_IO).install_legacy_readwrite_handler(*device, temp, temp + 0x2ff, FUNC(peripheral_r), FUNC(peripheral_w)); + m_audiocpu->device_t::memory().space(AS_IO).install_readwrite_handler(temp, temp + 0x2ff, read16_delegate(FUNC(leland_80186_sound_device::peripheral_r), this), write16_delegate(FUNC(leland_80186_sound_device::peripheral_w), this)); } - - /* we need to do this at a time when the 80186 context is swapped in */ - /* this register is generally set once at startup and never again, so it's a good */ - /* time to set it up */ - state->m_i80186.cpu->execute().set_irq_acknowledge_callback(int_callback); break; - - case 0xc0/2: - case 0xd0/2: - if (LOG_PORTS) logerror("%05X:80186 DMA%d lower source address = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), (offset - 0xc0/2) / 8, data, mem_mask); - which = (offset - 0xc0/2) / 8; - state->m_dma_stream->update(); - state->m_i80186.dma[which].source = (state->m_i80186.dma[which].source & ~0x0ffff) | (data & 0x0ffff); - break; - - case 0xc2/2: - case 0xd2/2: - if (LOG_PORTS) logerror("%05X:80186 DMA%d upper source address = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), (offset - 0xc0/2) / 8, data, mem_mask); - which = (offset - 0xc0/2) / 8; - state->m_dma_stream->update(); - state->m_i80186.dma[which].source = (state->m_i80186.dma[which].source & ~0xf0000) | ((data << 16) & 0xf0000); - break; - - case 0xc4/2: - case 0xd4/2: - if (LOG_PORTS) logerror("%05X:80186 DMA%d lower dest address = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), (offset - 0xc0/2) / 8, data, mem_mask); - which = (offset - 0xc0/2) / 8; - state->m_dma_stream->update(); - state->m_i80186.dma[which].dest = (state->m_i80186.dma[which].dest & ~0x0ffff) | (data & 0x0ffff); - break; - - case 0xc6/2: - case 0xd6/2: - if (LOG_PORTS) logerror("%05X:80186 DMA%d upper dest address = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), (offset - 0xc0/2) / 8, data, mem_mask); - which = (offset - 0xc0/2) / 8; - state->m_dma_stream->update(); - state->m_i80186.dma[which].dest = (state->m_i80186.dma[which].dest & ~0xf0000) | ((data << 16) & 0xf0000); - break; - - case 0xc8/2: - case 0xd8/2: - if (LOG_PORTS) logerror("%05X:80186 DMA%d transfer count = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), (offset - 0xc0/2) / 8, data, mem_mask); - which = (offset - 0xc0/2) / 8; - state->m_dma_stream->update(); - state->m_i80186.dma[which].count = data; - break; - - case 0xca/2: - case 0xda/2: - if (LOG_PORTS) logerror("%05X:80186 DMA%d control = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), (offset - 0xc0/2) / 8, data, mem_mask); - which = (offset - 0xc0/2) / 8; - state->m_dma_stream->update(); - update_dma_control(state, which, data); - break; - - case 0xfe/2: - if (LOG_PORTS) logerror("%05X:80186 relocation register = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), data, mem_mask); - - /* we assume here there that this doesn't happen too often */ - /* plus, we can't really remove the old memory range, so we also assume that it's */ - /* okay to leave us mapped where we were */ - temp = (data & 0x0fff) << 8; - if (data & 0x1000) - { - state->m_i80186.cpu->memory().space(AS_PROGRAM).install_legacy_readwrite_handler(*device, temp, temp + 0xff, FUNC(i80186_internal_port_r), FUNC(i80186_internal_port_w)); - } - else - { - temp &= 0xffff; - state->m_i80186.cpu->memory().space(AS_IO).install_legacy_readwrite_handler(*device, temp, temp + 0xff, FUNC(i80186_internal_port_r), FUNC(i80186_internal_port_w)); - } -/* popmessage("Sound CPU reset");*/ - break; - + } default: - logerror("%05X:80186 port %02X = %04X & %04X\n", state->m_i80186.cpu->safe_pc(), offset*2, data, mem_mask); break; } } - - -/************************************* - * - * 8254 PIT accesses - * - *************************************/ - -INLINE void counter_update_count(struct counter_state *ctr) -{ - /* only update if the timer is running */ - if (ctr->timer) - { - /* determine how many 2MHz cycles are remaining */ - int count = (ctr->timer->remaining() * 2000000).as_double(); - ctr->count = (count < 0) ? 0 : count; - } -} - - -static READ16_DEVICE_HANDLER( pit8254_r ) -{ - leland_sound_state *state = get_safe_token(device); - struct counter_state *ctr; - int which = offset / 0x40; - int reg = offset & 3; - - /* switch off the register */ - switch (reg) - { - case 0: - case 1: - case 2: - /* warning: assumes LSB/MSB addressing and no latching! */ - which = (which * 3) + reg; - ctr = &state->m_counter[which]; - - /* update the count */ - counter_update_count(ctr); - - /* return the LSB */ - if (ctr->readbyte == 0) - { - ctr->readbyte = 1; - return ctr->count & 0xff; - } - - /* write the MSB and reset the counter */ - else - { - ctr->readbyte = 0; - return (ctr->count >> 8) & 0xff; - } - break; - } - return 0; -} - - -static WRITE16_DEVICE_HANDLER( pit8254_w ) -{ - leland_sound_state *state = get_safe_token(device); - struct counter_state *ctr; - int which = offset / 0x40; - int reg = offset & 3; - - /* ignore odd offsets */ - if (!ACCESSING_BITS_0_7) - return; - data &= 0xff; - - /* switch off the register */ - switch (reg) - { - case 0: - case 1: - case 2: - /* warning: assumes LSB/MSB addressing and no latching! */ - which = (which * 3) + reg; - ctr = &state->m_counter[which]; - - /* write the LSB */ - if (ctr->writebyte == 0) - { - ctr->count = (ctr->count & 0xff00) | (data & 0x00ff); - ctr->writebyte = 1; - } - - /* write the MSB and reset the counter */ - else - { - ctr->count = (ctr->count & 0x00ff) | ((data << 8) & 0xff00); - ctr->writebyte = 0; - - /* treat 0 as $10000 */ - if (ctr->count == 0) ctr->count = 0x10000; - - /* reset/start the timer */ - ctr->timer->adjust(attotime::never); - - if (LOG_PIT) logerror("PIT counter %d set to %d (%d Hz)\n", which, ctr->count, 4000000 / ctr->count); - - /* set the frequency of the associated DAC */ - if (!state->m_is_redline) - set_dac_frequency(state, which, 4000000 / ctr->count); - else - { - if (which < 5) - set_dac_frequency(state, which, 7000000 / ctr->count); - else if (which == 6) - { - set_dac_frequency(state, 5, 7000000 / ctr->count); - set_dac_frequency(state, 6, 7000000 / ctr->count); - set_dac_frequency(state, 7, 7000000 / ctr->count); - } - } - } - break; - - case 3: - /* determine which counter */ - if ((data & 0xc0) == 0xc0) break; - which = (which * 3) + (data >> 6); - ctr = &state->m_counter[which]; - - /* set the mode */ - ctr->mode = (data >> 1) & 7; - break; - } -} - - - /************************************* * * External 80186 control * *************************************/ -WRITE8_DEVICE_HANDLER( leland_80186_control_w ) +WRITE8_MEMBER( leland_80186_sound_device::leland_80186_control_w ) { - leland_sound_state *state = get_safe_token(device); - /* see if anything changed */ - int diff = (state->m_last_control ^ data) & 0xf8; + int diff = (m_last_control ^ data) & 0xf8; if (!diff) return; - state->m_last_control = data; + m_last_control = data; if (LOG_COMM) { - logerror("%04X:80186 control = %02X", state->m_i80186.cpu->safe_pcbase(), data); + logerror("%04X:80186 control = %02X", m_audiocpu->device_t::safe_pcbase(), data); if (!(data & 0x80)) logerror(" /RESET"); if (!(data & 0x40)) logerror(" ZNMI"); if (!(data & 0x20)) logerror(" INT0"); @@ -1840,7 +418,8 @@ WRITE8_DEVICE_HANDLER( leland_80186_control_w ) } /* /RESET */ - space.machine().device("audiocpu")->execute().set_input_line(INPUT_LINE_RESET, data & 0x80 ? CLEAR_LINE : ASSERT_LINE); + m_audiocpu->device_t::execute().set_input_line(INPUT_LINE_RESET, data & 0x80 ? CLEAR_LINE : ASSERT_LINE); + m_audiocpu->device_t::execute().set_input_line(INPUT_LINE_TEST, data & 0x10 ? CLEAR_LINE : ASSERT_LINE); /* /NMI */ /* If the master CPU doesn't get a response by the time it's ready to send @@ -1850,30 +429,12 @@ WRITE8_DEVICE_HANDLER( leland_80186_control_w ) /* space.machine().device("audiocpu")->execute().set_input_line(INPUT_LINE_NMI, data & 0x40 ? CLEAR_LINE : ASSERT_LINE);*/ /* INT0 */ - if (data & 0x20) - { - if (!LATCH_INTS) state->m_i80186.intr.request &= ~0x10; - } - else if (state->m_i80186.intr.ext[0] & 0x10) - state->m_i80186.intr.request |= 0x10; - else if (diff & 0x20) - state->m_i80186.intr.request |= 0x10; - + m_audiocpu->int0_w(data & 0x20); /* INT1 */ - if (data & 0x08) - { - if (!LATCH_INTS) state->m_i80186.intr.request &= ~0x20; - } - else if (state->m_i80186.intr.ext[1] & 0x10) - state->m_i80186.intr.request |= 0x20; - else if (diff & 0x08) - state->m_i80186.intr.request |= 0x20; - + m_audiocpu->int1_w(data & 0x08); /* handle reset here */ if ((diff & 0x80) && (data & 0x80)) - leland_80186_reset(device); - - update_interrupt_state(device); + reset(); } @@ -1884,34 +445,30 @@ WRITE8_DEVICE_HANDLER( leland_80186_control_w ) * *************************************/ -static TIMER_CALLBACK( command_lo_sync ) +void leland_80186_sound_device::command_lo_sync(void *ptr, int param) { - device_t *device = (device_t *)ptr; - leland_sound_state *state = get_safe_token(device); - if (LOG_COMM) logerror("%s:Write sound command latch lo = %02X\n", machine.describe_context(), param); - state->m_sound_command = (state->m_sound_command & 0xff00) | param; + if (LOG_COMM) logerror("%s:Write sound command latch lo = %02X\n", machine().describe_context(), param); + m_sound_command = (m_sound_command & 0xff00) | param; } -WRITE8_DEVICE_HANDLER( leland_80186_command_lo_w ) +WRITE8_MEMBER( leland_80186_sound_device::leland_80186_command_lo_w ) { - space.machine().scheduler().synchronize(FUNC(command_lo_sync), data, device); + machine().scheduler().synchronize(timer_expired_delegate(FUNC(leland_80186_sound_device::command_lo_sync), this), data); } -WRITE8_DEVICE_HANDLER( leland_80186_command_hi_w ) +WRITE8_MEMBER( leland_80186_sound_device::leland_80186_command_hi_w ) { - leland_sound_state *state = get_safe_token(device); - if (LOG_COMM) logerror("%04X:Write sound command latch hi = %02X\n", state->m_i80186.cpu->safe_pcbase(), data); - state->m_sound_command = (state->m_sound_command & 0x00ff) | (data << 8); + if (LOG_COMM) logerror("%04X:Write sound command latch hi = %02X\n", m_audiocpu->device_t::safe_pcbase(), data); + m_sound_command = (m_sound_command & 0x00ff) | (data << 8); } -static READ16_DEVICE_HANDLER( main_to_sound_comm_r ) +READ16_MEMBER( leland_80186_sound_device::main_to_sound_comm_r ) { - leland_sound_state *state = get_safe_token(device); - if (LOG_COMM) logerror("%05X:Read sound command latch = %02X\n", state->m_i80186.cpu->safe_pc(), state->m_sound_command); - return state->m_sound_command; + if (LOG_COMM) logerror("%05X:Read sound command latch = %02X\n", m_audiocpu->device_t::safe_pc(), m_sound_command); + return m_sound_command; } @@ -1923,11 +480,9 @@ static READ16_DEVICE_HANDLER( main_to_sound_comm_r ) * *************************************/ -static TIMER_CALLBACK( delayed_response_r ) +void leland_80186_sound_device::delayed_response_r(void *ptr, int param) { - device_t *device = (device_t *)ptr; - leland_sound_state *state = get_safe_token(device); - cpu_device *master = machine.device("master"); + cpu_device *master = machine().device("master"); int checkpc = param; int pc = master->pc(); int oldaf = master->state_int(Z80_AF); @@ -1940,34 +495,32 @@ static TIMER_CALLBACK( delayed_response_r ) state and put the proper value into the A register. */ if (pc == checkpc) { - if (LOG_COMM) logerror("(Updated sound response latch to %02X)\n", state->m_sound_response); + if (LOG_COMM) logerror("(Updated sound response latch to %02X)\n", m_sound_response); - oldaf = (oldaf & 0x00ff) | (state->m_sound_response << 8); + oldaf = (oldaf & 0x00ff) | (m_sound_response << 8); master->set_state_int(Z80_AF, oldaf); } - else + else if(LOG_COMM) logerror("ERROR: delayed_response_r - current PC = %04X, checkPC = %04X\n", pc, checkpc); } -READ8_DEVICE_HANDLER( leland_80186_response_r ) +READ8_MEMBER( leland_80186_sound_device::leland_80186_response_r ) { - leland_sound_state *state = get_safe_token(device); - offs_t pc = state->m_i80186.cpu->safe_pcbase(); + offs_t pc = m_audiocpu->device_t::safe_pcbase(); - if (LOG_COMM) logerror("%04X:Read sound response latch = %02X\n", pc, state->m_sound_response); + if (LOG_COMM) logerror("%04X:Read sound response latch = %02X\n", pc, m_sound_response); /* synchronize the response */ - space.machine().scheduler().synchronize(FUNC(delayed_response_r), pc + 2, device); - return state->m_sound_response; + machine().scheduler().synchronize(timer_expired_delegate(FUNC(leland_80186_sound_device::delayed_response_r), this), pc + 2); + return m_sound_response; } -static WRITE16_DEVICE_HANDLER( sound_to_main_comm_w ) +WRITE16_MEMBER( leland_80186_sound_device::sound_to_main_comm_w ) { - leland_sound_state *state = get_safe_token(device); - if (LOG_COMM) logerror("%05X:Write sound response latch = %02X\n", state->m_i80186.cpu->safe_pc(), data); - state->m_sound_response = data; + if (LOG_COMM) logerror("%05X:Write sound response latch = %02X\n", m_audiocpu->device_t::safe_pc(), data); + m_sound_response = data; } @@ -1978,140 +531,31 @@ static WRITE16_DEVICE_HANDLER( sound_to_main_comm_w ) * *************************************/ -static void set_dac_frequency(leland_sound_state *state, int which, int frequency) +WRITE16_MEMBER( leland_80186_sound_device::dac_w ) { - struct dac_state *d = &state->m_dac[which]; - int count = (d->bufin - d->bufout) & DAC_BUFFER_SIZE_MASK; - - /* set the frequency of the associated DAC */ - d->frequency = frequency; - d->step = (int)((double)frequency * (double)(1 << 24) / (double)OUTPUT_RATE); - - /* also determine the target buffer size */ - d->buftarget = d->frequency / 60 + 50; - if (d->buftarget > DAC_BUFFER_SIZE - 1) - d->buftarget = DAC_BUFFER_SIZE - 1; - - /* reevaluate the count */ - if (count > d->buftarget) - state->m_clock_active &= ~(1 << which); - else if (count < d->buftarget) - state->m_clock_active |= 1 << which; - - if (LOG_DAC) logerror("DAC %d frequency = %d, step = %08X\n", which, d->frequency, d->step); -} - - -static WRITE16_DEVICE_HANDLER( dac_w ) -{ - leland_sound_state *state = get_safe_token(device); - int which = offset; - struct dac_state *d = &state->m_dac[which]; + int which = offset & 7; /* handle value changes */ if (ACCESSING_BITS_0_7) { - int count = (d->bufin - d->bufout) & DAC_BUFFER_SIZE_MASK; - - /* set the new value */ - d->value = (INT16)(UINT8)data - 0x80; - if (LOG_DAC) logerror("%05X:DAC %d value = %02X\n", state->m_i80186.cpu->safe_pc(), offset, (UINT8)data); - - /* if we haven't overflowed the buffer, add the value value to it */ - if (count < DAC_BUFFER_SIZE - 1) - { - /* if this is the first byte, sync the stream */ - if (count == 0) - state->m_nondma_stream->update(); - - /* prescale by the volume */ - d->buffer[d->bufin] = d->value * d->volume; - d->bufin = (d->bufin + 1) & DAC_BUFFER_SIZE_MASK; - - /* update the clock status */ - if (++count > d->buftarget) - state->m_clock_active &= ~(1 << which); - } + m_dac_sample[which] = (data << 8) - 0x8000; + m_clock_active &= ~(1<volume = ((data >> 8) ^ 0x00) / DAC_VOLUME_SCALE; - if (LOG_DAC) logerror("%05X:DAC %d volume = %02X\n", state->m_i80186.cpu->safe_pc(), offset, data); - } + m_dac_volume[which] = data >> 8; + } -static WRITE16_DEVICE_HANDLER( redline_dac_w ) +WRITE16_MEMBER( redline_80186_sound_device::redline_dac_w ) { - leland_sound_state *state = get_safe_token(device); - int which = offset / 0x100; - struct dac_state *d = &state->m_dac[which]; - int count = (d->bufin - d->bufout) & DAC_BUFFER_SIZE_MASK; - - /* set the new value */ - d->value = (INT16)(UINT8)data - 0x80; - - /* if we haven't overflowed the buffer, add the value value to it */ - if (count < DAC_BUFFER_SIZE - 1) - { - /* if this is the first byte, sync the stream */ - if (count == 0) - state->m_nondma_stream->update(); - - /* prescale by the volume */ - d->buffer[d->bufin] = d->value * d->volume; - d->bufin = (d->bufin + 1) & DAC_BUFFER_SIZE_MASK; - - /* update the clock status */ - if (++count > d->buftarget) - state->m_clock_active &= ~(1 << which); - } - - /* update the volume */ - d->volume = (offset & 0xff) / DAC_VOLUME_SCALE; - if (LOG_DAC) logerror("%05X:DAC %d value = %02X, volume = %02X\n", state->m_i80186.cpu->safe_pc(), which, data, (offset & 0x1fe) / 2); + dac_w(space, (offset >> 8) & 7, (data & 0xff) | (offset << 8), 0xffff); } - -static WRITE16_DEVICE_HANDLER( dac_10bit_w ) +WRITE16_MEMBER( leland_80186_sound_device::ataxx_dac_control ) { - leland_sound_state *state = get_safe_token(device); - struct dac_state *d = &state->m_dac[6]; - int count = (d->bufin - d->bufout) & DAC_BUFFER_SIZE_MASK; - int data16; - - /* warning: this assumes all port writes here are word-sized */ - assert(ACCESSING_BITS_0_7 && ACCESSING_BITS_8_15); - data16 = data; - - /* set the new value */ - d->value = (INT16)data16 - 0x200; - if (LOG_DAC) logerror("%05X:DAC 10-bit value = %02X\n", state->m_i80186.cpu->safe_pc(), data16); - - /* if we haven't overflowed the buffer, add the value value to it */ - if (count < DAC_BUFFER_SIZE - 1) - { - /* if this is the first byte, sync the stream */ - if (count == 0) - state->m_nondma_stream->update(); - - /* prescale by the volume */ - d->buffer[d->bufin] = d->value * (0xff / DAC_VOLUME_SCALE / 2); - d->bufin = (d->bufin + 1) & DAC_BUFFER_SIZE_MASK; - - /* update the clock status */ - if (++count > d->buftarget) - state->m_clock_active &= ~0x40; - } -} - - -static WRITE16_DEVICE_HANDLER( ataxx_dac_control ) -{ - leland_sound_state *state = get_safe_token(device); - /* handle common offsets */ switch (offset) { @@ -2119,52 +563,55 @@ static WRITE16_DEVICE_HANDLER( ataxx_dac_control ) case 0x01: case 0x02: if (ACCESSING_BITS_0_7) - dac_w(device, space, offset, data, 0x00ff); + dac_w(space, offset, data, 0x00ff); return; case 0x03: - dac_w(device, space, 0, ((data << 13) & 0xe000) | ((data << 10) & 0x1c00) | ((data << 7) & 0x0300), 0xff00); - dac_w(device, space, 2, ((data << 10) & 0xe000) | ((data << 7) & 0x1c00) | ((data << 4) & 0x0300), 0xff00); - dac_w(device, space, 4, ((data << 8) & 0xc000) | ((data << 6) & 0x3000) | ((data << 4) & 0x0c00) | ((data << 2) & 0x0300), 0xff00); + if(ACCESSING_BITS_0_7) + { + m_dac_volume[0] = ((data & 7) * 0x49) >> 1; + m_dac_volume[1] = (((data >> 3) & 7) * 0x49) >> 1; + m_dac_volume[2] = ((data >> 6) & 3) * 0x55; + } + return; + + case 0x21: + if (ACCESSING_BITS_0_7) + dac_w(space, 1, data, mem_mask); return; } /* if we have a YM2151 (and an external DAC), handle those offsets */ - if (state->m_has_ym2151) + if (m_type == TYPE_WSF) { - state->m_extern_stream->update(); switch (offset) { case 0x04: - state->m_ext_active = 1; + m_ext_active = 1; if (LOG_EXTERN) logerror("External DAC active\n"); return; case 0x05: - state->m_ext_active = 0; + m_ext_active = 0; if (LOG_EXTERN) logerror("External DAC inactive\n"); return; case 0x06: - state->m_ext_start >>= 4; - COMBINE_DATA(&state->m_ext_start); - state->m_ext_start <<= 4; - if (LOG_EXTERN) logerror("External DAC start = %05X\n", state->m_ext_start); + m_ext_start >>= 4; + COMBINE_DATA(&m_ext_start); + m_ext_start <<= 4; + if (LOG_EXTERN) logerror("External DAC start = %05X\n", m_ext_start); return; case 0x07: - state->m_ext_stop >>= 4; - COMBINE_DATA(&state->m_ext_stop); - state->m_ext_stop <<= 4; - if (LOG_EXTERN) logerror("External DAC stop = %05X\n", state->m_ext_stop); - return; - - case 0x21: - dac_w(device, space, offset - 0x21 + 7, data, mem_mask); + m_ext_stop >>= 4; + COMBINE_DATA(&m_ext_stop); + m_ext_stop <<= 4; + if (LOG_EXTERN) logerror("External DAC stop = %05X\n", m_ext_stop); return; } } - logerror("%05X:Unexpected peripheral write %d/%02X = %02X\n", state->m_i80186.cpu->safe_pc(), 5, offset, data); + logerror("%05X:Unexpected peripheral write %d/%02X = %02X\n", m_audiocpu->device_t::safe_pc(), 5, offset, data); } @@ -2175,9 +622,8 @@ static WRITE16_DEVICE_HANDLER( ataxx_dac_control ) * *************************************/ -static READ16_DEVICE_HANDLER( peripheral_r ) +READ16_MEMBER( leland_80186_sound_device::peripheral_r ) { - leland_sound_state *state = get_safe_token(device); int select = offset / 0x40; offset &= 0x3f; @@ -2185,79 +631,103 @@ static READ16_DEVICE_HANDLER( peripheral_r ) { case 0: /* we have to return 0 periodically so that they handle interrupts */ - if ((++state->m_clock_tick & 7) == 0) - return 0; + //if ((++m_clock_tick & 7) == 0) + // return 0; /* if we've filled up all the active channels, we can give this CPU a reset */ /* until the next interrupt */ - if (!state->m_is_redline) - return ((state->m_clock_active >> 1) & 0x3e); + if (m_type != TYPE_REDLINE) + return ((m_clock_active >> 1) & 0x3e); else - return ((state->m_clock_active << 1) & 0x7e); + return ((m_clock_active << 1) & 0x7e); case 1: - return main_to_sound_comm_r(device, space, offset, mem_mask); + return main_to_sound_comm_r(space, offset, mem_mask); case 2: - return pit8254_r(device, space, offset, mem_mask); + if(mem_mask == 0xff00) + return 0xffff; + return m_pit0->read(space, offset & 3); case 3: - if (!state->m_has_ym2151) - return pit8254_r(device, space, offset | 0x40, mem_mask); - else - return space.machine().device("ymsnd")->read(space, offset); + if (m_type <= TYPE_REDLINE) + { + if(mem_mask == 0xff00) + return 0xffff; + return m_pit1->read(space, offset & 3); + } + else if(m_type == TYPE_WSF) + return m_ymsnd->read(space, offset); + break; case 4: - if (state->m_is_redline) - return pit8254_r(device, space, offset | 0x80, mem_mask); + if (m_type == TYPE_REDLINE) + { + if(mem_mask == 0xff00) + return 0xffff; + return m_pit2->read(space, offset & 3); + } else - logerror("%05X:Unexpected peripheral read %d/%02X\n", state->m_i80186.cpu->safe_pc(), select, offset*2); + logerror("%05X:Unexpected peripheral read %d/%02X\n", m_audiocpu->device_t::safe_pc(), select, offset*2); break; default: - logerror("%05X:Unexpected peripheral read %d/%02X\n", state->m_i80186.cpu->safe_pc(), select, offset*2); + logerror("%05X:Unexpected peripheral read %d/%02X\n", m_audiocpu->device_t::safe_pc(), select, offset*2); break; } return 0xffff; } -static WRITE16_DEVICE_HANDLER( peripheral_w ) +WRITE16_MEMBER( leland_80186_sound_device::peripheral_w ) { - leland_sound_state *state = get_safe_token(device); int select = offset / 0x40; offset &= 0x3f; switch (select) { case 1: - sound_to_main_comm_w(device, space, offset, data, mem_mask); + sound_to_main_comm_w(space, offset, data, mem_mask); break; case 2: - pit8254_w(device, space, offset, data, mem_mask); + if(mem_mask == 0xff00) + return; + m_pit0->write(space, offset & 3, data); break; case 3: - if (!state->m_has_ym2151) - pit8254_w(device, space, offset | 0x40, data, mem_mask); - else - space.machine().device("ymsnd")->write(space, offset, data); + if (m_type <= TYPE_REDLINE) + { + if(mem_mask == 0xff00) + return; + m_pit1->write(space, offset & 3, data); + } + else if(m_type == TYPE_WSF) + m_ymsnd->write(space, offset, data); break; case 4: - if (state->m_is_redline) - pit8254_w(device, space, offset | 0x80, data, mem_mask); - else - dac_10bit_w(device, space, offset, data, mem_mask); + if (m_type == TYPE_REDLINE) + { + if(mem_mask == 0xff00) + return; + m_pit2->write(space, offset & 3, data); + } + else if(mem_mask == 0xffff) + { + m_dac_sample[6] = (data << 6) - 0x8000; + m_clock_active &= ~(1<<6); + } break; case 5: /* Ataxx/WSF/Indy Heat only */ - ataxx_dac_control(device, space, offset, data, mem_mask); + if(m_type > TYPE_REDLINE) + ataxx_dac_control(space, offset, data, mem_mask); break; default: - logerror("%05X:Unexpected peripheral write %d/%02X = %02X\n", state->m_i80186.cpu->safe_pc(), select, offset, data); + logerror("%05X:Unexpected peripheral write %d/%02X = %02X\n", m_audiocpu->device_t::safe_pc(), select, offset, data); break; } } @@ -2270,14 +740,14 @@ static WRITE16_DEVICE_HANDLER( peripheral_w ) * *************************************/ -WRITE8_DEVICE_HANDLER( ataxx_80186_control_w ) +WRITE8_MEMBER( leland_80186_sound_device::ataxx_80186_control_w ) { /* compute the bit-shuffled variants of the bits and then write them */ int modified = ((data & 0x01) << 7) | ((data & 0x02) << 5) | ((data & 0x04) << 3) | ((data & 0x08) << 1); - leland_80186_control_w(device, space, offset, modified); + leland_80186_control_w(space, offset, modified); } @@ -2293,23 +763,16 @@ ADDRESS_MAP_START( leland_80186_map_program, AS_PROGRAM, 16, driver_device ) AM_RANGE(0x20000, 0xfffff) AM_ROM ADDRESS_MAP_END - ADDRESS_MAP_START( ataxx_80186_map_io, AS_IO, 16, driver_device ) - AM_RANGE(0xff00, 0xffff) AM_DEVREADWRITE_LEGACY("custom", i80186_internal_port_r, i80186_internal_port_w) ADDRESS_MAP_END - ADDRESS_MAP_START( redline_80186_map_io, AS_IO, 16, driver_device ) - AM_RANGE(0x6000, 0x6fff) AM_DEVWRITE_LEGACY("custom", redline_dac_w) - AM_RANGE(0xff00, 0xffff) AM_DEVREADWRITE_LEGACY("custom", i80186_internal_port_r, i80186_internal_port_w) + AM_RANGE(0x0000, 0xffff) AM_DEVWRITE("custom", redline_80186_sound_device, redline_dac_w) ADDRESS_MAP_END ADDRESS_MAP_START( leland_80186_map_io, AS_IO, 16, driver_device ) - AM_RANGE(0x0000, 0x000b) AM_DEVWRITE_LEGACY("custom", dac_w) - AM_RANGE(0x0080, 0x008b) AM_DEVWRITE_LEGACY("custom", dac_w) - AM_RANGE(0x00c0, 0x00cb) AM_DEVWRITE_LEGACY("custom", dac_w) - AM_RANGE(0xff00, 0xffff) AM_DEVREADWRITE_LEGACY("custom", i80186_internal_port_r, i80186_internal_port_w) + AM_RANGE(0x0000, 0xffff) AM_DEVWRITE("custom", leland_80186_sound_device, dac_w) ADDRESS_MAP_END diff --git a/src/mame/drivers/ataxx.c b/src/mame/drivers/ataxx.c index b15ada30ca4..8a7cc242e80 100644 --- a/src/mame/drivers/ataxx.c +++ b/src/mame/drivers/ataxx.c @@ -26,12 +26,11 @@ #include "emu.h" -#include "cpu/i86/i86.h" +#include "cpu/i86/i186.h" #include "machine/eepromser.h" #include "machine/nvram.h" #include "cpu/z80/z80.h" #include "includes/leland.h" -#include "sound/2151intf.h" #define MASTER_CLOCK XTAL_28_63636MHz @@ -56,10 +55,10 @@ ADDRESS_MAP_END static ADDRESS_MAP_START( master_map_io, AS_IO, 8, leland_state ) ADDRESS_MAP_GLOBAL_MASK(0xff) - AM_RANGE(0x04, 0x04) AM_DEVREAD_LEGACY("custom", leland_80186_response_r) - AM_RANGE(0x05, 0x05) AM_DEVWRITE_LEGACY("custom", leland_80186_command_hi_w) - AM_RANGE(0x06, 0x06) AM_DEVWRITE_LEGACY("custom", leland_80186_command_lo_w) - AM_RANGE(0x0c, 0x0c) AM_DEVWRITE_LEGACY("custom", ataxx_80186_control_w) + AM_RANGE(0x04, 0x04) AM_DEVREAD("custom", leland_80186_sound_device, leland_80186_response_r) + AM_RANGE(0x05, 0x05) AM_DEVWRITE("custom", leland_80186_sound_device, leland_80186_command_hi_w) + AM_RANGE(0x06, 0x06) AM_DEVWRITE("custom", leland_80186_sound_device, leland_80186_command_lo_w) + AM_RANGE(0x0c, 0x0c) AM_DEVWRITE("custom", leland_80186_sound_device, ataxx_80186_control_w) AM_RANGE(0x20, 0x20) AM_READWRITE(ataxx_eeprom_r, ataxx_eeprom_w) AM_RANGE(0xd0, 0xef) AM_READWRITE(ataxx_mvram_port_r, ataxx_mvram_port_w) AM_RANGE(0xf0, 0xff) AM_READWRITE(ataxx_master_input_r, ataxx_master_output_w) @@ -301,9 +300,11 @@ static MACHINE_CONFIG_START( ataxx, leland_state ) MCFG_CPU_PROGRAM_MAP(slave_map_program) MCFG_CPU_IO_MAP(slave_map_io) - MCFG_CPU_ADD("audiocpu", I80186, XTAL_16MHz) + MCFG_CPU_ADD("audiocpu", I80186, XTAL_16MHz/2) MCFG_CPU_PROGRAM_MAP(leland_80186_map_program) MCFG_CPU_IO_MAP(ataxx_80186_map_io) + MCFG_80186_CHIP_SELECT_CB(DEVWRITE16("custom", leland_80186_sound_device, peripheral_ctrl)) + MCFG_80186_TMROUT0_HANDLER(DEVWRITELINE("custom", leland_80186_sound_device, i80186_tmr0_w)) MCFG_MACHINE_START_OVERRIDE(leland_state,ataxx) MCFG_MACHINE_RESET_OVERRIDE(leland_state,ataxx) @@ -317,21 +318,16 @@ static MACHINE_CONFIG_START( ataxx, leland_state ) MCFG_FRAGMENT_ADD(ataxx_video) /* sound hardware */ - MCFG_SPEAKER_STANDARD_MONO("mono") - - MCFG_SOUND_ADD("custom", LELAND_80186, 0) - MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0) + MCFG_DEVICE_ADD("custom", ATAXX_80186, 0) MACHINE_CONFIG_END static MACHINE_CONFIG_DERIVED( wsf, ataxx ) + MCFG_CPU_MODIFY("audiocpu") + MCFG_80186_TMROUT1_HANDLER(DEVWRITELINE("custom", leland_80186_sound_device, i80186_tmr1_w)) - /* basic machine hardware */ - - /* sound hardware */ - MCFG_YM2151_ADD("ymsnd", 4000000) - MCFG_SOUND_ROUTE(0, "mono", 0.40) - MCFG_SOUND_ROUTE(1, "mono", 0.40) + MCFG_DEVICE_REMOVE("custom") + MCFG_DEVICE_ADD("custom", WSF_80186, 0) MACHINE_CONFIG_END diff --git a/src/mame/drivers/bingo.c b/src/mame/drivers/bingo.c index 9814cef986a..4495cb4ef00 100644 --- a/src/mame/drivers/bingo.c +++ b/src/mame/drivers/bingo.c @@ -2,7 +2,7 @@ #include "emu.h" #include "cpu/s2650/s2650.h" #include "cpu/i8085/i8085.h" -#include "cpu/i86/i86.h" +#include "cpu/i86/i186.h" class bingo_state : public driver_device { diff --git a/src/mame/drivers/bingor.c b/src/mame/drivers/bingor.c index afbe9791977..0ff551408e3 100644 --- a/src/mame/drivers/bingor.c +++ b/src/mame/drivers/bingor.c @@ -438,7 +438,7 @@ ************************************************************************/ #include "emu.h" -#include "cpu/i86/i86.h" +#include "cpu/i86/i186.h" #include "cpu/pic16c5x/pic16c5x.h" #include "sound/saa1099.h" diff --git a/src/mame/drivers/gambl186.c b/src/mame/drivers/gambl186.c index 4266ad074fc..8b78434a196 100644 --- a/src/mame/drivers/gambl186.c +++ b/src/mame/drivers/gambl186.c @@ -28,7 +28,7 @@ code doesn't make much sense, wrong mapping? bad? #include "emu.h" -#include "cpu/i86/i86.h" +#include "cpu/i86/i186.h" class gambl186_state : public driver_device diff --git a/src/mame/drivers/highvdeo.c b/src/mame/drivers/highvdeo.c index b1a4eec7c16..2f455b595f4 100644 --- a/src/mame/drivers/highvdeo.c +++ b/src/mame/drivers/highvdeo.c @@ -96,7 +96,7 @@ Game is V30 based, with rom banking (2Mb) #include "emu.h" #include "cpu/nec/nec.h" -#include "cpu/i86/i86.h" +#include "cpu/i86/i186.h" #include "sound/okim6376.h" #include "machine/nvram.h" #include "fashion.lh" @@ -143,6 +143,7 @@ public: UINT32 screen_update_tourvisn(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); UINT32 screen_update_brasil(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); INTERRUPT_GEN_MEMBER(vblank_irq); + INTERRUPT_GEN_MEMBER(vblank_irq_80186); required_device m_maincpu; required_device m_okim6376; }; @@ -1063,6 +1064,11 @@ INTERRUPT_GEN_MEMBER(highvdeo_state::vblank_irq) device.execute().set_input_line_and_vector(0,HOLD_LINE,0x08/4); } +INTERRUPT_GEN_MEMBER(highvdeo_state::vblank_irq_80186) +{ + device.execute().set_input_line(INPUT_LINE_NMI, PULSE_LINE); +} + static MACHINE_CONFIG_START( tv_vcf, highvdeo_state ) MCFG_CPU_ADD("maincpu", V30, XTAL_12MHz/2 ) // ? MCFG_CPU_PROGRAM_MAP(tv_vcf_map) @@ -1134,14 +1140,14 @@ static MACHINE_CONFIG_DERIVED( ciclone, tv_tcf ) MCFG_CPU_ADD("maincpu", I80186, 20000000/2 ) // ? MCFG_CPU_PROGRAM_MAP(tv_tcf_map) MCFG_CPU_IO_MAP(tv_tcf_io) - MCFG_CPU_VBLANK_INT_DRIVER("screen", highvdeo_state, vblank_irq) + MCFG_CPU_VBLANK_INT_DRIVER("screen", highvdeo_state, vblank_irq_80186) MACHINE_CONFIG_END static MACHINE_CONFIG_START( brasil, highvdeo_state ) MCFG_CPU_ADD("maincpu", I80186, 20000000 ) // fashion doesn't like 20/2 Mhz MCFG_CPU_PROGRAM_MAP(brasil_map) MCFG_CPU_IO_MAP(brasil_io) - MCFG_CPU_VBLANK_INT_DRIVER("screen", highvdeo_state, vblank_irq) + MCFG_CPU_VBLANK_INT_DRIVER("screen", highvdeo_state, vblank_irq_80186) MCFG_NVRAM_ADD_0FILL("nvram") diff --git a/src/mame/drivers/leland.c b/src/mame/drivers/leland.c index 346c31c9d90..e66ed3afcb8 100644 --- a/src/mame/drivers/leland.c +++ b/src/mame/drivers/leland.c @@ -42,7 +42,7 @@ #include "emu.h" -#include "cpu/i86/i86.h" +#include "cpu/i86/i186.h" #include "machine/eepromser.h" #include "machine/nvram.h" #include "cpu/z80/z80.h" @@ -71,12 +71,16 @@ static ADDRESS_MAP_START( master_map_program, AS_PROGRAM, 8, leland_state ) AM_RANGE(0xf800, 0xf801) AM_WRITE(leland_master_video_addr_w) ADDRESS_MAP_END - static ADDRESS_MAP_START( master_map_io, AS_IO, 8, leland_state ) + ADDRESS_MAP_GLOBAL_MASK(0xff) + AM_RANGE(0xfd, 0xff) AM_READWRITE(leland_master_analog_key_r, leland_master_analog_key_w) +ADDRESS_MAP_END + +static ADDRESS_MAP_START( master_redline_map_io, AS_IO, 8, leland_state ) ADDRESS_MAP_GLOBAL_MASK(0xff) AM_RANGE(0xf0, 0xf0) AM_WRITE(leland_master_alt_bankswitch_w) - AM_RANGE(0xf2, 0xf2) AM_DEVREADWRITE_LEGACY("custom", leland_80186_response_r, leland_80186_command_lo_w) - AM_RANGE(0xf4, 0xf4) AM_DEVWRITE_LEGACY("custom", leland_80186_command_hi_w) + AM_RANGE(0xf2, 0xf2) AM_DEVREADWRITE("custom", leland_80186_sound_device, leland_80186_response_r, leland_80186_command_lo_w) + AM_RANGE(0xf4, 0xf4) AM_DEVWRITE("custom", leland_80186_sound_device, leland_80186_command_hi_w) AM_RANGE(0xfd, 0xff) AM_READWRITE(leland_master_analog_key_r, leland_master_analog_key_w) ADDRESS_MAP_END @@ -748,7 +752,6 @@ static MACHINE_CONFIG_START( leland, leland_state ) /* video hardware */ MCFG_FRAGMENT_ADD(leland_video) - /* sound hardware */ MCFG_SPEAKER_STANDARD_MONO("mono") @@ -760,42 +763,44 @@ static MACHINE_CONFIG_START( leland, leland_state ) MCFG_SOUND_CONFIG(ay8910_config) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) - MCFG_SOUND_ADD("custom", LELAND, 0) - MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50) + MCFG_SOUND_ADD("dac0", DAC, 0) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) + MCFG_SOUND_ADD("dac1", DAC, 0) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) MACHINE_CONFIG_END static MACHINE_CONFIG_DERIVED( redline, leland ) /* basic machine hardware */ + MCFG_CPU_MODIFY("master") + MCFG_CPU_IO_MAP(master_redline_map_io) - MCFG_CPU_ADD("audiocpu", I80186, MCU_CLOCK) + MCFG_CPU_ADD("audiocpu", I80186, MCU_CLOCK/2) MCFG_CPU_PROGRAM_MAP(leland_80186_map_program) MCFG_CPU_IO_MAP(redline_80186_map_io) + MCFG_80186_CHIP_SELECT_CB(DEVWRITE16("custom", leland_80186_sound_device, peripheral_ctrl)) /* sound hardware */ - MCFG_SOUND_REPLACE("custom", REDLINE_80186, 0) - MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0) + MCFG_DEVICE_ADD("custom", REDLINE_80186, 0) MACHINE_CONFIG_END static MACHINE_CONFIG_DERIVED( quarterb, redline ) /* basic machine hardware */ - MCFG_CPU_MODIFY("audiocpu") MCFG_CPU_IO_MAP(leland_80186_map_io) + MCFG_80186_TMROUT0_HANDLER(DEVWRITELINE("custom", leland_80186_sound_device, i80186_tmr0_w)) /* sound hardware */ - MCFG_SOUND_REPLACE("custom", LELAND_80186, 0) - MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0) + MCFG_DEVICE_REPLACE("custom", LELAND_80186, 0) MACHINE_CONFIG_END static MACHINE_CONFIG_DERIVED( lelandi, quarterb ) /* basic machine hardware */ - MCFG_CPU_MODIFY("slave") MCFG_CPU_PROGRAM_MAP(slave_large_map_program) MACHINE_CONFIG_END diff --git a/src/mame/drivers/neptunp2.c b/src/mame/drivers/neptunp2.c index 7a92952c930..8e0c5882c03 100644 --- a/src/mame/drivers/neptunp2.c +++ b/src/mame/drivers/neptunp2.c @@ -8,7 +8,7 @@ #include "emu.h" -#include "cpu/i86/i86.h" +#include "cpu/i86/i186.h" class neptunp2_state : public driver_device diff --git a/src/mame/drivers/subsino2.c b/src/mame/drivers/subsino2.c index 175b1ead79b..2ab46b60380 100644 --- a/src/mame/drivers/subsino2.c +++ b/src/mame/drivers/subsino2.c @@ -36,7 +36,7 @@ To do: #include "emu.h" #include "cpu/h83002/h8.h" -#include "cpu/i86/i86.h" +#include "cpu/i86/i186.h" #include "cpu/z180/z180.h" #include "sound/3812intf.h" #include "sound/okim6295.h" diff --git a/src/mame/drivers/timetrv.c b/src/mame/drivers/timetrv.c index 3a943e7fbeb..f581bd6e060 100644 --- a/src/mame/drivers/timetrv.c +++ b/src/mame/drivers/timetrv.c @@ -24,7 +24,7 @@ CPU is an Intel 80188 *************************************************************************************************/ #include "emu.h" -#include "cpu/i86/i86.h" +#include "cpu/i86/i186.h" class timetrv_state : public driver_device diff --git a/src/mame/includes/leland.h b/src/mame/includes/leland.h index 3d462096995..ae46ea64408 100644 --- a/src/mame/includes/leland.h +++ b/src/mame/includes/leland.h @@ -5,6 +5,10 @@ *************************************************************************/ #include "machine/eepromser.h" +#include "sound/2151intf.h" +#include "sound/dac.h" +#include "machine/pit8253.h" +#include "cpu/i86/i186.h" #define LELAND_BATTERY_RAM_SIZE 0x4000 #define ATAXX_EXTRA_TRAM_SIZE 0x800 @@ -16,7 +20,7 @@ struct vram_state_data UINT8 m_latch[2]; }; - +class leland_80186_sound_device; class leland_state : public driver_device { @@ -25,11 +29,17 @@ public: : driver_device(mconfig, type, tag), m_master(*this, "master"), m_slave(*this, "slave"), - m_eeprom(*this, "eeprom") { } + m_eeprom(*this, "eeprom"), + m_sound(*this, "custom"), + m_dac0(*this, "dac0"), + m_dac1(*this, "dac1") { } required_device m_master; required_device m_slave; required_device m_eeprom; + optional_device m_sound; + optional_device m_dac0; + optional_device m_dac1; UINT8 m_dac_control; UINT8 *m_alleymas_kludge_mem; @@ -146,6 +156,7 @@ public: DECLARE_MACHINE_START(leland); DECLARE_MACHINE_RESET(leland); DECLARE_VIDEO_START(leland); + DECLARE_VIDEO_START(leland2); DECLARE_VIDEO_START(ataxx); UINT32 screen_update_leland(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); UINT32 screen_update_ataxx(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); @@ -197,45 +208,72 @@ void leland_rotate_memory(running_machine &machine, const char *cpuname); /*----------- defined in audio/leland.c -----------*/ -class leland_sound_device : public device_t, - public device_sound_interface -{ -public: - leland_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - leland_sound_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); - ~leland_sound_device() { global_free(m_token); } - - // access to legacy token - void *token() const { assert(m_token != NULL); return m_token; } -protected: - // device-level overrides - virtual void device_config_complete(); - virtual void device_start(); - - // sound stream update overrides - virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); -private: - // internal state - void *m_token; -}; - -extern const device_type LELAND; - -class leland_80186_sound_device : public leland_sound_device +class leland_80186_sound_device : public device_t { public: leland_80186_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); leland_80186_sound_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); + virtual machine_config_constructor device_mconfig_additions() const; + + DECLARE_WRITE16_MEMBER(peripheral_ctrl); + DECLARE_WRITE8_MEMBER(leland_80186_control_w); + DECLARE_WRITE8_MEMBER(ataxx_80186_control_w); + DECLARE_READ16_MEMBER(peripheral_r); + DECLARE_WRITE16_MEMBER(peripheral_w); + DECLARE_WRITE8_MEMBER(leland_80186_command_lo_w); + DECLARE_WRITE8_MEMBER(leland_80186_command_hi_w); + DECLARE_READ16_MEMBER(main_to_sound_comm_r); + DECLARE_READ8_MEMBER(leland_80186_response_r); + DECLARE_WRITE16_MEMBER(sound_to_main_comm_w); + DECLARE_WRITE16_MEMBER(dac_w); + DECLARE_WRITE16_MEMBER(ataxx_dac_control); + DECLARE_WRITE_LINE_MEMBER(pit0_2_w); + DECLARE_WRITE_LINE_MEMBER(pit1_0_w); + DECLARE_WRITE_LINE_MEMBER(pit1_1_w); + DECLARE_WRITE_LINE_MEMBER(pit1_2_w); + DECLARE_WRITE_LINE_MEMBER(pit2_0_w); + DECLARE_WRITE_LINE_MEMBER(i80186_tmr0_w); + DECLARE_WRITE_LINE_MEMBER(i80186_tmr1_w); protected: // device-level overrides - virtual void device_config_complete(); virtual void device_start(); virtual void device_reset(); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + int m_type; + + enum { + TYPE_LELAND, + TYPE_REDLINE, + TYPE_ATAXX, + TYPE_WSF + }; + + required_device m_dac; - // sound stream update overrides - virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); private: + void command_lo_sync(void *ptr, int param); + void delayed_response_r(void *ptr, int param); + void set_clock_line(int which, bool state) { m_clock_active = state ? (m_clock_active | (1< m_pit0; + optional_device m_pit1; + optional_device m_pit2; + optional_device m_ymsnd; }; extern const device_type LELAND_80186; @@ -244,28 +282,29 @@ class redline_80186_sound_device : public leland_80186_sound_device { public: redline_80186_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -protected: - // device-level overrides - virtual void device_config_complete(); - virtual void device_start(); - - // sound stream update overrides - virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); -private: - // internal state + DECLARE_WRITE16_MEMBER(redline_dac_w); + virtual machine_config_constructor device_mconfig_additions() const; }; extern const device_type REDLINE_80186; +class ataxx_80186_sound_device : public leland_80186_sound_device +{ +public: + ataxx_80186_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual machine_config_constructor device_mconfig_additions() const; +}; -void leland_dac_update(device_t *device, int dacnum, UINT8 sample); +extern const device_type ATAXX_80186; -DECLARE_READ8_DEVICE_HANDLER( leland_80186_response_r ); +class wsf_80186_sound_device : public leland_80186_sound_device +{ +public: + wsf_80186_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual machine_config_constructor device_mconfig_additions() const; +}; -DECLARE_WRITE8_DEVICE_HANDLER( leland_80186_control_w ); -DECLARE_WRITE8_DEVICE_HANDLER( leland_80186_command_lo_w ); -DECLARE_WRITE8_DEVICE_HANDLER( leland_80186_command_hi_w ); -DECLARE_WRITE8_DEVICE_HANDLER( ataxx_80186_control_w ); +extern const device_type WSF_80186; ADDRESS_MAP_EXTERN(leland_80186_map_program, 16); ADDRESS_MAP_EXTERN(leland_80186_map_io, 16); diff --git a/src/mame/machine/leland.c b/src/mame/machine/leland.c index 708a09f5bec..8073360b034 100644 --- a/src/mame/machine/leland.c +++ b/src/mame/machine/leland.c @@ -467,7 +467,7 @@ WRITE8_MEMBER(leland_state::leland_master_alt_bankswitch_w) (this->*m_update_master_bank)(); /* sound control is in the rest */ - leland_80186_control_w(machine().device("custom"), space, offset, data); + m_sound->leland_80186_control_w(space, offset, data); } diff --git a/src/mame/video/leland.c b/src/mame/video/leland.c index 06276a5a9b3..09cc0da1c08 100644 --- a/src/mame/video/leland.c +++ b/src/mame/video/leland.c @@ -29,15 +29,14 @@ TIMER_CALLBACK_MEMBER(leland_state::scanline_callback) { - device_t *audio = machine().device("custom"); int scanline = param; /* update the DACs */ if (!(m_dac_control & 0x01)) - leland_dac_update(audio, 0, m_video_ram[(m_last_scanline) * 256 + 160]); + m_dac0->write_unsigned8(m_video_ram[(m_last_scanline) * 256 + 160]); if (!(m_dac_control & 0x02)) - leland_dac_update(audio, 1, m_video_ram[(m_last_scanline) * 256 + 161]); + m_dac1->write_unsigned8(m_video_ram[(m_last_scanline) * 256 + 161]); m_last_scanline = scanline; @@ -65,11 +64,10 @@ VIDEO_START_MEMBER(leland_state,leland) } - VIDEO_START_MEMBER(leland_state,ataxx) { /* first do the standard stuff */ - VIDEO_START_CALL_MEMBER(leland); + m_video_ram = auto_alloc_array_clear(machine(), UINT8, VRAM_SIZE); /* allocate memory */ m_ataxx_qram = auto_alloc_array_clear(machine(), UINT8, QRAM_SIZE); @@ -527,7 +525,6 @@ MACHINE_CONFIG_FRAGMENT( leland_video ) MCFG_SCREEN_UPDATE_DRIVER(leland_state, screen_update_leland) MACHINE_CONFIG_END - MACHINE_CONFIG_DERIVED( ataxx_video, leland_video ) MCFG_VIDEO_START_OVERRIDE(leland_state,ataxx) MCFG_SCREEN_MODIFY("screen") diff --git a/src/mess/drivers/compis.c b/src/mess/drivers/compis.c index fb2451df97f..93f954c6657 100644 --- a/src/mess/drivers/compis.c +++ b/src/mess/drivers/compis.c @@ -168,7 +168,6 @@ static ADDRESS_MAP_START( compis_io, AS_IO, 16, compis_state ) AM_RANGE( 0x0330, 0x0333) AM_DEVREADWRITE8("upd7220", upd7220_device, read, write, 0x00ff) /* GDC 82720 PCS6:6 */ AM_RANGE( 0x0340, 0x0343) AM_DEVICE8("i8272a", i8272a_device, map, 0x00ff) /* iSBX0 (J8) FDC 8272 */ AM_RANGE( 0x0350, 0x0351) AM_DEVREADWRITE8("i8272a", i8272a_device, mdma_r, mdma_w, 0x00ff) /* iSBX0 (J8) DMA ACK */ - AM_RANGE( 0xff00, 0xffff) AM_READWRITE( compis_i186_internal_port_r, compis_i186_internal_port_w)/* CPU 80186 */ //{ 0x0100, 0x017e, compis_null_r }, /* RTC */ //{ 0x0180, 0x01ff, compis_null_r }, /* PCS3? */ //{ 0x0200, 0x027f, compis_null_r }, /* Reserved */ @@ -372,7 +371,7 @@ static MACHINE_CONFIG_START( compis, compis_state ) /* Devices */ MCFG_PIT8253_ADD( "pit8253", compis_pit8253_config ) MCFG_PIT8254_ADD( "pit8254", compis_pit8254_config ) - MCFG_PIC8259_ADD( "pic8259_master", WRITELINE(compis_state, compis_pic8259_master_set_int_line), VCC, READ8(compis_state, get_slave_ack) ) + MCFG_PIC8259_ADD( "pic8259_master", DEVWRITELINE("maincpu", i80186_cpu_device, int2_w), VCC, READ8(compis_state, get_slave_ack) ) MCFG_PIC8259_ADD( "pic8259_slave", WRITELINE(compis_state, compis_pic8259_slave_set_int_line), GND, NULL ) MCFG_I8255_ADD( "ppi8255", compis_ppi_interface ) MCFG_UPD7220_ADD("upd7220", XTAL_4_433619MHz/2, hgdc_intf, upd7220_map) //unknown clock @@ -412,7 +411,7 @@ static MACHINE_CONFIG_START( compis2, compis_state ) /* Devices */ MCFG_PIT8253_ADD( "pit8253", compis_pit8253_config ) MCFG_PIT8254_ADD( "pit8254", compis_pit8254_config ) - MCFG_PIC8259_ADD( "pic8259_master", WRITELINE(compis_state, compis_pic8259_master_set_int_line), VCC, READ8(compis_state, get_slave_ack) ) + MCFG_PIC8259_ADD( "pic8259_master", DEVWRITELINE("maincpu", i80186_cpu_device, int2_w), VCC, READ8(compis_state, get_slave_ack) ) MCFG_PIC8259_ADD( "pic8259_slave", WRITELINE(compis_state, compis_pic8259_slave_set_int_line), GND, NULL ) MCFG_I8255_ADD( "ppi8255", compis_ppi_interface ) MCFG_UPD7220_ADD("upd7220", XTAL_4_433619MHz/2, hgdc_intf, upd7220_map) //unknown clock diff --git a/src/mess/drivers/rainbow.c b/src/mess/drivers/rainbow.c index fa9a5e40549..963d0c0a31b 100644 --- a/src/mess/drivers/rainbow.c +++ b/src/mess/drivers/rainbow.c @@ -336,7 +336,7 @@ WRITE8_MEMBER(rainbow_state::share_z80_w) READ8_MEMBER(rainbow_state::i8088_latch_r) { // printf("Read %02x from 8088 mailbox\n", m_8088_mailbox); - m_i8088->set_input_line(INPUT_LINE_INT1, CLEAR_LINE); + m_i8088->set_input_line(INPUT_LINE_INT0, CLEAR_LINE); return m_8088_mailbox; } @@ -357,7 +357,7 @@ READ8_MEMBER(rainbow_state::z80_latch_r) WRITE8_MEMBER(rainbow_state::z80_latch_w) { // printf("%02x to 8088 mailbox\n", data); - m_i8088->set_input_line_and_vector(INPUT_LINE_INT1, ASSERT_LINE, 0x27); + m_i8088->set_input_line_and_vector(INPUT_LINE_INT0, ASSERT_LINE, 0x27); m_8088_mailbox = data; } @@ -420,11 +420,11 @@ void rainbow_state::update_kbd_irq() { if ((m_kbd_rx_ready) || (m_kbd_tx_ready)) { - m_i8088->set_input_line_and_vector(INPUT_LINE_INT2, ASSERT_LINE, 0x26); + m_i8088->set_input_line_and_vector(INPUT_LINE_INT0, ASSERT_LINE, 0x26); } else { - m_i8088->set_input_line(INPUT_LINE_INT2, CLEAR_LINE); + m_i8088->set_input_line(INPUT_LINE_INT0, CLEAR_LINE); } } diff --git a/src/mess/drivers/rmnimbus.c b/src/mess/drivers/rmnimbus.c index 9b101fd4420..b33834b3a9d 100644 --- a/src/mess/drivers/rmnimbus.c +++ b/src/mess/drivers/rmnimbus.c @@ -8,7 +8,7 @@ */ #include "emu.h" -#include "cpu/i86/i86.h" +#include "cpu/i86/i186.h" #include "cpu/mcs51/mcs51.h" #include "imagedev/flopdrv.h" #include "machine/ram.h" @@ -110,7 +110,7 @@ static ADDRESS_MAP_START(nimbus_io, AS_IO, 16, rmnimbus_state ) AM_RANGE( 0x00f0, 0x00f7) AM_DEVREADWRITE8(Z80SIO_TAG, z80sio_device, read, write, 0x00ff) AM_RANGE( 0x0400, 0x041f) AM_READWRITE8(nimbus_disk_r, nimbus_disk_w, 0x00FF) AM_RANGE( 0x0480, 0x049f) AM_DEVREADWRITE8(VIA_TAG, via6522_device, read, write, 0x00FF) - AM_RANGE( 0xff00, 0xffff) AM_READWRITE(nimbus_i186_internal_port_r, nimbus_i186_internal_port_w)/* CPU 80186 */ + //AM_RANGE( 0xff00, 0xffff) AM_READWRITE(nimbus_i186_internal_port_r, nimbus_i186_internal_port_w)/* CPU 80186 */ ADDRESS_MAP_END static INPUT_PORTS_START( nimbus ) @@ -286,6 +286,7 @@ static MACHINE_CONFIG_START( nimbus, rmnimbus_state ) MCFG_CPU_ADD(MAINCPU_TAG, I80186, 10000000) MCFG_CPU_PROGRAM_MAP(nimbus_mem) MCFG_CPU_IO_MAP(nimbus_io) + MCFG_80186_IRQ_SLAVE_ACK(DEVREAD8(DEVICE_SELF_OWNER, rmnimbus_state, cascade_callback)) MCFG_CPU_ADD(IOCPU_TAG, I8031, 11059200) MCFG_CPU_PROGRAM_MAP(nimbus_iocpu_mem) diff --git a/src/mess/drivers/tandy2k.c b/src/mess/drivers/tandy2k.c index 45ad3079906..04e6bb7ac5c 100644 --- a/src/mess/drivers/tandy2k.c +++ b/src/mess/drivers/tandy2k.c @@ -121,10 +121,10 @@ WRITE8_MEMBER( tandy2k_state::enable_w ) m_fdc->reset(); // timer 0 enable - m_maincpu->set_input_line(INPUT_LINE_TMRIN0, BIT(data, 6)); + m_maincpu->tmrin0_w(BIT(data, 6)); // timer 1 enable - m_maincpu->set_input_line(INPUT_LINE_TMRIN1, BIT(data, 7)); + m_maincpu->tmrin1_w(BIT(data, 7)); } WRITE8_MEMBER( tandy2k_state::dma_mux_w ) @@ -705,8 +705,8 @@ static MACHINE_CONFIG_START( tandy2k, tandy2k_state ) MCFG_I8255A_ADD(I8255A_TAG, ppi_intf) MCFG_I8251_ADD(I8251A_TAG, usart_intf) MCFG_PIT8253_ADD(I8253_TAG, pit_intf) - MCFG_PIC8259_ADD(I8259A_0_TAG, INPUTLINE(I80186_TAG, INPUT_LINE_INT0), VCC, NULL) - MCFG_PIC8259_ADD(I8259A_1_TAG, INPUTLINE(I80186_TAG, INPUT_LINE_INT1), VCC, NULL) + MCFG_PIC8259_ADD(I8259A_0_TAG, DEVWRITELINE(I80186_TAG, i80186_cpu_device, int0_w), VCC, NULL) + MCFG_PIC8259_ADD(I8259A_1_TAG, DEVWRITELINE(I80186_TAG, i80186_cpu_device, int1_w), VCC, NULL) MCFG_I8272A_ADD(I8272A_TAG, true) MCFG_FLOPPY_DRIVE_ADD(I8272A_TAG ":0", tandy2k_floppies, "525qd", floppy_image_device::default_floppy_formats) MCFG_FLOPPY_DRIVE_ADD(I8272A_TAG ":1", tandy2k_floppies, "525qd", floppy_image_device::default_floppy_formats) diff --git a/src/mess/drivers/tek410x.c b/src/mess/drivers/tek410x.c index e3d1e993299..2aa8da3298a 100644 --- a/src/mess/drivers/tek410x.c +++ b/src/mess/drivers/tek410x.c @@ -16,7 +16,7 @@ #include "emu.h" -#include "cpu/i86/i86.h" +#include "cpu/i86/i186.h" #define I80188_TAG "i80188" #define SCREEN_TAG "screen" diff --git a/src/mess/includes/compis.h b/src/mess/includes/compis.h index 60533b40cb8..cc4f6a7b3ed 100644 --- a/src/mess/includes/compis.h +++ b/src/mess/includes/compis.h @@ -13,7 +13,7 @@ #define COMPIS_H_ #include "emu.h" -#include "cpu/i86/i86.h" +#include "cpu/i86/i186.h" #include "cpu/mcs48/mcs48.h" #include "video/upd7220.h" #include "machine/ctronics.h" @@ -155,8 +155,8 @@ public: required_device m_crtc; DECLARE_READ16_MEMBER(compis_usart_r); DECLARE_WRITE16_MEMBER(compis_usart_w); - DECLARE_READ16_MEMBER(compis_i186_internal_port_r); - DECLARE_WRITE16_MEMBER(compis_i186_internal_port_w); +// DECLARE_READ16_MEMBER(compis_i186_internal_port_r); +// DECLARE_WRITE16_MEMBER(compis_i186_internal_port_w); DECLARE_WRITE8_MEMBER(vram_w); DECLARE_READ8_MEMBER(compis_ppi_port_b_r); DECLARE_WRITE8_MEMBER(compis_ppi_port_c_w); @@ -166,13 +166,13 @@ public: DECLARE_WRITE_LINE_MEMBER(compis_pic8259_master_set_int_line); DECLARE_WRITE_LINE_MEMBER(compis_pic8259_slave_set_int_line); DECLARE_READ8_MEMBER(get_slave_ack); - i186_state m_i186; +// i186_state m_i186; TYP_COMPIS m_compis; UINT8 *m_p_videoram; - void update_dma_control(int which, int new_control); - void internal_timer_update(int which, int new_count, int new_maxA, int new_maxB, int new_control); - void internal_timer_sync(int which); - void handle_eoi(int data); +// void update_dma_control(int which, int new_control); +// void internal_timer_update(int which, int new_count, int new_maxA, int new_maxB, int new_control); +// void internal_timer_sync(int which); +// void handle_eoi(int data); void compis_fdc_tc(int state); void fdc_irq(bool state); @@ -185,10 +185,10 @@ public: virtual void palette_init(); UINT32 screen_update_compis2(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); INTERRUPT_GEN_MEMBER(compis_vblank_int); - TIMER_CALLBACK_MEMBER(internal_timer_int); - TIMER_CALLBACK_MEMBER(dma_timer_callback); - IRQ_CALLBACK_MEMBER(int_callback); - IRQ_CALLBACK_MEMBER(compis_irq_callback); +// TIMER_CALLBACK_MEMBER(internal_timer_int); +// TIMER_CALLBACK_MEMBER(dma_timer_callback); +// IRQ_CALLBACK_MEMBER(int_callback); +// IRQ_CALLBACK_MEMBER(compis_irq_callback); void compis_irq_set(UINT8 irq); void compis_keyb_update(); void compis_keyb_init(); diff --git a/src/mess/includes/rmnimbus.h b/src/mess/includes/rmnimbus.h index 2d109e5838e..1f27d8bb4a1 100644 --- a/src/mess/includes/rmnimbus.h +++ b/src/mess/includes/rmnimbus.h @@ -6,6 +6,7 @@ 2009-11-29. */ +#include "cpu/i86/i186.h" #include "machine/z80sio.h" #include "machine/wd17xx.h" #include "machine/scsicb.h" @@ -403,14 +404,14 @@ public: { } - required_device m_maincpu; + required_device m_maincpu; required_device m_msm; required_device m_ay8910; required_device m_scsibus; required_device m_ram; UINT32 m_debug_machine; - i186_state m_i186; +// i186_state m_i186; keyboard_t m_keyboard; nimbus_drives_t m_nimbus_drives; ipc_interface_t m_ipc_interface; @@ -427,8 +428,9 @@ public: UINT16 m_pixel_mask; UINT8 m_hs_count; UINT32 m_debug_video; - DECLARE_READ16_MEMBER(nimbus_i186_internal_port_r); - DECLARE_WRITE16_MEMBER(nimbus_i186_internal_port_w); + UINT8 m_vector; +// DECLARE_READ16_MEMBER(nimbus_i186_internal_port_r); +// DECLARE_WRITE16_MEMBER(nimbus_i186_internal_port_w); DECLARE_READ8_MEMBER(nimbus_mcu_r); DECLARE_WRITE8_MEMBER(nimbus_mcu_w); DECLARE_READ16_MEMBER(nimbus_io_r); @@ -459,8 +461,8 @@ public: virtual void palette_init(); UINT32 screen_update_nimbus(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); void screen_eof_nimbus(screen_device &screen, bool state); - TIMER_CALLBACK_MEMBER(internal_timer_int); - TIMER_CALLBACK_MEMBER(dma_timer_callback); +// TIMER_CALLBACK_MEMBER(internal_timer_int); +// TIMER_CALLBACK_MEMBER(dma_timer_callback); TIMER_CALLBACK_MEMBER(keyscan_callback); TIMER_CALLBACK_MEMBER(mouse_callback); DECLARE_WRITE_LINE_MEMBER(sio_interrupt); @@ -500,16 +502,17 @@ public: void write_reg_01E(); void write_reg_026(); void change_palette(UINT8 bank, UINT16 colours, UINT8 regno); - void update_interrupt_state(); - void handle_eoi(int data); +// void update_interrupt_state(); +// void handle_eoi(int data); void external_int(UINT16 intno, UINT8 vector); - void nimbus_recalculate_ints(); - void internal_timer_sync(int which); - void internal_timer_update(int which,int new_count,int new_maxA,int new_maxB,int new_control); - void update_dma_control(int which, int new_control); - void drq_callback(int which); - void nimbus_cpu_init(); - void nimbus_cpu_reset(); + DECLARE_READ8_MEMBER(cascade_callback); +// void nimbus_recalculate_ints(); +// void internal_timer_sync(int which); +// void internal_timer_update(int which,int new_count,int new_maxA,int new_maxB,int new_control); +// void update_dma_control(int which, int new_control); +// void drq_callback(int which); +// void nimbus_cpu_init(); +// void nimbus_cpu_reset(); void *get_dssi_ptr(address_space &space, UINT16 ds, UINT16 si); void nimbus_bank_memory(); void memory_reset(); diff --git a/src/mess/includes/tandy2k.h b/src/mess/includes/tandy2k.h index bb4f9f2a016..0d1f8fe30fa 100644 --- a/src/mess/includes/tandy2k.h +++ b/src/mess/includes/tandy2k.h @@ -3,7 +3,7 @@ #include "emu.h" -#include "cpu/i86/i86.h" +#include "cpu/i86/i186.h" #include "cpu/mcs48/mcs48.h" #include "imagedev/harddriv.h" #include "machine/ctronics.h" @@ -63,7 +63,7 @@ public: m_char_ram(*this, "char_ram") { } - required_device m_maincpu; + required_device m_maincpu; required_device m_uart; required_device m_pit; required_device m_fdc; diff --git a/src/mess/machine/compis.c b/src/mess/machine/compis.c index c3d973b204c..e9b5d91759c 100644 --- a/src/mess/machine/compis.c +++ b/src/mess/machine/compis.c @@ -339,6 +339,7 @@ WRITE16_MEMBER( compis_state::compis_usart_w ) } } +#if 0 /************************************* * * 80186 interrupt controller @@ -1226,7 +1227,7 @@ WRITE16_MEMBER( compis_state::compis_i186_internal_port_w ) break; } } - +#endif /*-------------------------------------------------------------------------*/ /* Name: compis */ /* Desc: CPU - Initialize the 80186 CPU */ @@ -1234,14 +1235,14 @@ WRITE16_MEMBER( compis_state::compis_i186_internal_port_w ) void compis_state::compis_cpu_init() { /* create timers here so they stick around */ - m_i186.timer[0].int_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(compis_state::internal_timer_int),this)); - m_i186.timer[1].int_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(compis_state::internal_timer_int),this)); - m_i186.timer[2].int_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(compis_state::internal_timer_int),this)); - m_i186.timer[0].time_timer = machine().scheduler().timer_alloc(FUNC_NULL); - m_i186.timer[1].time_timer = machine().scheduler().timer_alloc(FUNC_NULL); - m_i186.timer[2].time_timer = machine().scheduler().timer_alloc(FUNC_NULL); - m_i186.dma[0].finish_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(compis_state::dma_timer_callback),this)); - m_i186.dma[1].finish_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(compis_state::dma_timer_callback),this)); +// m_i186.timer[0].int_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(compis_state::internal_timer_int),this)); +// m_i186.timer[1].int_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(compis_state::internal_timer_int),this)); +// m_i186.timer[2].int_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(compis_state::internal_timer_int),this)); +// m_i186.timer[0].time_timer = machine().scheduler().timer_alloc(FUNC_NULL); +// m_i186.timer[1].time_timer = machine().scheduler().timer_alloc(FUNC_NULL); +// m_i186.timer[2].time_timer = machine().scheduler().timer_alloc(FUNC_NULL); +// m_i186.dma[0].finish_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(compis_state::dma_timer_callback),this)); +// m_i186.dma[1].finish_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(compis_state::dma_timer_callback),this)); } /*-------------------------------------------------------------------------*/ @@ -1257,7 +1258,7 @@ void compis_state::compis_cpu_init() WRITE_LINE_MEMBER( compis_state::compis_pic8259_master_set_int_line ) { - m_maincpu->set_input_line(0, state ? HOLD_LINE : CLEAR_LINE); +// m_maincpu->set_input_line(0, state ? HOLD_LINE : CLEAR_LINE); } WRITE_LINE_MEMBER( compis_state::compis_pic8259_slave_set_int_line ) @@ -1275,15 +1276,15 @@ READ8_MEMBER( compis_state::get_slave_ack ) } -IRQ_CALLBACK_MEMBER(compis_state::compis_irq_callback) -{ - return m_8259m->inta_r(); -} +//IRQ_CALLBACK_MEMBER(compis_state::compis_irq_callback) +//{ +// return m_8259m->inta_r(); +//} DRIVER_INIT_MEMBER(compis_state,compis) { - m_maincpu->set_irq_acknowledge_callback(device_irq_acknowledge_delegate(FUNC(compis_state::compis_irq_callback),this)); +// m_maincpu->set_irq_acknowledge_callback(device_irq_acknowledge_delegate(FUNC(compis_state::compis_irq_callback),this)); memset (&m_compis, 0, sizeof (m_compis) ); } @@ -1305,7 +1306,7 @@ void compis_state::machine_reset() compis_keyb_init(); /* OSP PIC 8259 */ - m_maincpu->set_irq_acknowledge_callback(device_irq_acknowledge_delegate(FUNC(compis_state::compis_irq_callback),this)); +// m_maincpu->set_irq_acknowledge_callback(device_irq_acknowledge_delegate(FUNC(compis_state::compis_irq_callback),this)); } /*-------------------------------------------------------------------------*/ diff --git a/src/mess/machine/rmnimbus.c b/src/mess/machine/rmnimbus.c index 290d574929a..b7ecc80259a 100644 --- a/src/mess/machine/rmnimbus.c +++ b/src/mess/machine/rmnimbus.c @@ -56,7 +56,7 @@ chdman createhd -o ST125N.chd -chs 407,4,26 -ss 512 #include "emu.h" #include "debugger.h" -#include "cpu/i86/i86.h" +#include "cpu/i86/i186.h" #include "debug/debugcpu.h" #include "debug/debugcon.h" #include "imagedev/flopdrv.h" @@ -152,7 +152,6 @@ static const UINT16 def_config[16] = static void execute_debug_irq(running_machine &machine, int ref, int params, const char *param[]); -static void execute_debug_intmasks(running_machine &machine, int ref, int params, const char *param[]); static void nimbus_debug(running_machine &machine, int ref, int params, const char *param[]); static int instruction_hook(device_t &device, offs_t curpc); @@ -166,7 +165,7 @@ static void decode_dssi_f_plonk_char(device_t *device,UINT16 ds, UINT16 si, UIN static void decode_dssi_f_rw_sectors(device_t *device,UINT16 ds, UINT16 si, UINT8 raw_flag); - +#if 0 /************************************* * * 80186 interrupt controller @@ -1199,11 +1198,39 @@ WRITE16_MEMBER(rmnimbus_state::nimbus_i186_internal_port_w) break; } } +#endif + +void rmnimbus_state::external_int(UINT16 intno, UINT8 vector) +{ + m_vector = vector; + switch(intno) + { + case 0: + m_maincpu->int0_w(1); + break; + case 1: + m_maincpu->int1_w(1); + break; + case 2: + m_maincpu->int2_w(1); + break; + case 3: + m_maincpu->int3_w(1); + break; + default: + return; + } +} + +READ8_MEMBER(rmnimbus_state::cascade_callback) +{ + return m_vector; +} void rmnimbus_state::machine_reset() { /* CPU */ - nimbus_cpu_reset(); +// nimbus_cpu_reset(); iou_reset(); fdc_reset(); hdc_reset(); @@ -1221,7 +1248,7 @@ DRIVER_INIT_MEMBER(rmnimbus_state,nimbus) void rmnimbus_state::machine_start() { /* init cpu */ - nimbus_cpu_init(); +// nimbus_cpu_init(); m_keyboard.keyscan_timer=machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(rmnimbus_state::keyscan_callback),this)); m_nimbus_mouse.m_mouse_timer=machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(rmnimbus_state::mouse_callback),this)); @@ -1230,7 +1257,6 @@ void rmnimbus_state::machine_start() if (machine().debug_flags & DEBUG_FLAG_ENABLED) { debug_console_register_command(machine(), "nimbus_irq", CMDFLAG_NONE, 0, 0, 2, execute_debug_irq); - debug_console_register_command(machine(), "nimbus_intmasks", CMDFLAG_NONE, 0, 0, 0, execute_debug_intmasks); debug_console_register_command(machine(), "nimbus_debug", CMDFLAG_NONE, 0, 0, 1, nimbus_debug); /* set up the instruction hook */ @@ -1260,23 +1286,6 @@ static void execute_debug_irq(running_machine &machine, int ref, int params, con } } - -static void execute_debug_intmasks(running_machine &machine, int ref, int params, const char *param[]) -{ - rmnimbus_state *state = machine.driver_data(); - int IntNo; - - debug_console_printf(machine,"i186.intr.priority_mask=%4X\n",state->m_i186.intr.priority_mask); - for(IntNo=0; IntNo<4; IntNo++) - { - debug_console_printf(machine,"extInt%d mask=%4X\n",IntNo,state->m_i186.intr.ext[IntNo]); - } - - debug_console_printf(machine,"i186.intr.request = %04X\n",state->m_i186.intr.request); - debug_console_printf(machine,"i186.intr.ack_mask = %04X\n",state->m_i186.intr.ack_mask); - debug_console_printf(machine,"i186.intr.in_service= %04X\n",state->m_i186.intr.in_service); -} - static void nimbus_debug(running_machine &machine, int ref, int params, const char *param[]) { rmnimbus_state *state = machine.driver_data(); @@ -2220,7 +2229,7 @@ WRITE_LINE_MEMBER(rmnimbus_state::nimbus_fdc_drq_w) logerror("nimbus_drives_drq_w(%d)\n", state); if(state && FDC_DRQ_ENABLED()) - drq_callback(1); + m_maincpu->drq1_w(state); } UINT8 rmnimbus_state::fdc_driveno(UINT8 drivesel) @@ -2406,7 +2415,7 @@ void rmnimbus_state::hdc_drq() { if(HDC_DRQ_ENABLED() && m_nimbus_drives.drq_ff) { - drq_callback(1); + m_maincpu->drq1_w(1); } }