diff options
author | David Haywood <hazemamewip@hotmail.com> | 2018-07-31 18:52:15 +0100 |
---|---|---|
committer | ajrhacker <ajrhacker@users.noreply.github.com> | 2018-07-31 13:52:15 -0400 |
commit | 082617fa3d77788058f264a30af8f45b1df20b93 (patch) | |
tree | 2d288c31a2dfe776e8b947c1550475a8b8ad6f98 | |
parent | 3a5518125cdc1b9903ae9dd543f34f56857fa7eb (diff) |
tlcs870 - takes first interrupt (nw) (#3807)
* tlcs870 - takes first interrupt (nw)
still trying to work out exactly how I want this code to be formed, but this keeps pushing the program execution forward at least
* bit of port interface guessing to pass port based shared RAM check (nw)
* (nw)
* add analog ports, fix some tlcs870 exec issues (nw)
-rw-r--r-- | src/devices/cpu/tlcs870/tlcs870.cpp | 267 | ||||
-rw-r--r-- | src/devices/cpu/tlcs870/tlcs870.h | 70 | ||||
-rw-r--r-- | src/devices/cpu/tlcs870/tlcs870_ops.cpp | 10 | ||||
-rw-r--r-- | src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp | 39 | ||||
-rw-r--r-- | src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp | 10 | ||||
-rw-r--r-- | src/devices/cpu/tlcs870/tlcs870_ops_src.cpp | 12 | ||||
-rw-r--r-- | src/mame/drivers/hng64.cpp | 100 | ||||
-rw-r--r-- | src/mame/includes/hng64.h | 20 |
8 files changed, 460 insertions, 68 deletions
diff --git a/src/devices/cpu/tlcs870/tlcs870.cpp b/src/devices/cpu/tlcs870/tlcs870.cpp index a855697cfb7..8eb5a0662a3 100644 --- a/src/devices/cpu/tlcs870/tlcs870.cpp +++ b/src/devices/cpu/tlcs870/tlcs870.cpp @@ -36,9 +36,10 @@ void tlcs870_device::tmp87ph40an_mem(address_map &map) map(0x000b, 0x000b).w(FUNC(tlcs870_device::p1cr_w)); // Port 1 I/O control map(0x000c, 0x000c).w(FUNC(tlcs870_device::p6cr_w)); // Port 6 I/O control map(0x000d, 0x000d).w(FUNC(tlcs870_device::p7cr_w)); // Port 7 I/O control -#if 0 + map(0x000e, 0x000e).rw(FUNC(tlcs870_device::adccr_r), FUNC(tlcs870_device::adccr_w)); // A/D converter control map(0x000f, 0x000f).r(FUNC(tlcs870_device::adcdr_r)); // A/D converter result +#if 0 map(0x0010, 0x0010).w(FUNC(tlcs870_device::treg1a_l_w)); // Timer register 1A map(0x0011, 0x0011).w(FUNC(tlcs870_device::treg1a_h_w)); // @@ -82,16 +83,18 @@ void tlcs870_device::tmp87ph40an_mem(address_map &map) map(0x0035, 0x0035).w(FUNC(tlcs870_device::wdtcr2_w)); // map(0x0036, 0x0036).rw(FUNC(tlcs870_device::tbtcr_r), FUNC(tlcs870_device::tbtcr_w)); // TBT / TG / DVO control +#endif map(0x0037, 0x0037).rw(FUNC(tlcs870_device::eintcr_r), FUNC(tlcs870_device::eintcr_w)); // External interrupt control - +#if 0 map(0x0038, 0x0038).rw(FUNC(tlcs870_device::syscr1_r), FUNC(tlcs870_device::syscr1_w)); // System Control map(0x0039, 0x0039).rw(FUNC(tlcs870_device::syscr2_r), FUNC(tlcs870_device::syscr2_w)); // - +#endif map(0x003a, 0x003a).rw(FUNC(tlcs870_device::eir_l_r), FUNC(tlcs870_device::eir_l_w)); // Interrupt enable register map(0x003b, 0x003b).rw(FUNC(tlcs870_device::eir_h_r), FUNC(tlcs870_device::eir_h_w)); // map(0x003c, 0x003c).rw(FUNC(tlcs870_device::il_l_r), FUNC(tlcs870_device::il_l_w)); // Interrupt latch map(0x003d, 0x003d).rw(FUNC(tlcs870_device::il_h_r), FUNC(tlcs870_device::il_h_w)); // +#if 0 // 0x3e reserved map(0x003f, 0x003f).rw(FUNC(tlcs870_device::psw_r), FUNC(tlcs870_device::rbs_w)); // Program status word / Register bank selector #endif @@ -109,6 +112,7 @@ tlcs870_device::tlcs870_device(const machine_config &mconfig, device_type optype , m_intram(*this, "intram") , m_port_in_cb{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}} , m_port_out_cb{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}} + , m_port_analog_in_cb{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}} { } @@ -272,34 +276,261 @@ WRITE8_MEMBER(tlcs870_device::p7cr_w) m_port7_cr = data; } + + + +READ8_MEMBER(tlcs870_device::adcdr_r) +{ + logerror("adcdr_r\n"); + return m_ADCDR; +} + +/* + + ADCCR register bits + + es-apppp + + e = end flag (1 = done, data available in ADCDR, 0 = not requested / not finished) (r/o) + s = start flag (1 = request data be processed and put in ADCDR) + + a = analog input enable (won't function at all with this disabled?) + + p = analog port to use (upper bit is 'reserved', so 8 ports) + + current emulation assumes this is instant + + bits in P6CR (0x0c) should also be set to '1' to enable analog input on the port as the + same pins are otherwise used as a normal input port, not this multiplexed ADC + + */ + +READ8_MEMBER(tlcs870_device::adccr_r) +{ + return m_ADCCR | 0x80; // return with 'finished' bit set +} + +WRITE8_MEMBER(tlcs870_device::adccr_w) +{ + m_ADCCR = data; + + if (data & 0x40) + { + m_ADCDR = m_port_analog_in_cb[data&0x07](); + } +} + + +READ8_MEMBER(tlcs870_device::eintcr_r) +{ + return 0x00; +} + +WRITE8_MEMBER(tlcs870_device::eintcr_w) +{ + m_EINTCR = data; + + logerror("m_EINTCR (External Interrupt Control) bits set to\n"); + logerror("%d: INT1NC (Interrupt noise reject)\n", (m_EINTCR & 0x80) ? 1 : 0); + logerror("%d: INT0EN (Interrupt 0 enable)\n", (m_EINTCR & 0x40) ? 1 : 0); + logerror("%d: (invalid)\n", (m_EINTCR & 0x20) ? 1 : 0); + logerror("%d: INT4ES (edge select)\n", (m_EINTCR & 0x10) ? 1 : 0); + logerror("%d: INT3ES (edge select)\n", (m_EINTCR & 0x08) ? 1 : 0); + logerror("%d: INT2ES (edge select)\n", (m_EINTCR & 0x04) ? 1 : 0); + logerror("%d: INT1ES (edge select)\n", (m_EINTCR & 0x02) ? 1 : 0); + logerror("%d: (invalid)\n", (m_EINTCR & 0x01) ? 1 : 0); + + /* For edge select register 0 = rising edge, 1 = falling edge + + For INT0EN if 1 then Port 1 bit 0 is used for IRQ0, otherwise it is used for a port bit + if it is used as an IRQ pin then it should also be configured as an input in P1CR + */ +} + +READ8_MEMBER(tlcs870_device::eir_l_r) +{ + return m_EIR & 0xff; +} + +READ8_MEMBER(tlcs870_device::eir_h_r) +{ + return (m_EIR >> 8) & 0xff; +} + +WRITE8_MEMBER(tlcs870_device::eir_l_w) +{ + m_EIR = (m_EIR & 0xff00) | data; + + logerror("m_EIR(LSB) (Interrupt Enable) bits set to\n"); + logerror("%d: EF7 (External Interrupt 2)\n", (m_EIR & 0x0080) ? 1 : 0); + logerror("%d: EF6 (Time Base Timer Interrupt)\n", (m_EIR & 0x0040) ? 1 : 0); + logerror("%d: EF5 (External Interrupt 1)\n", (m_EIR & 0x0020) ? 1 : 0); + logerror("%d: EF4 (16-bit TC1 Interrupt)\n", (m_EIR & 0x0010) ? 1 : 0); + logerror("%d: (invalid)\n", (m_EIR & 0x0008) ? 1 : 0); // can't be External Int 0 (bit in different register is used) + logerror("%d: (invalid)\n", (m_EIR & 0x0004) ? 1 : 0); // can't be Watchdog interrupt (non-maskable) + logerror("%d: (invalid)\n", (m_EIR & 0x0002) ? 1 : 0); // can't be Software interrupt (non-maskable) + logerror("%d: IMF\n", (m_EIR & 0x0001) ? 1 : 0); // can't be Reset interrupt (non-maskable) +} + +WRITE8_MEMBER(tlcs870_device::eir_h_w) +{ + m_EIR = (m_EIR & 0x00ff) | (data << 8); + + logerror("m_EIR(MSB) (Interrupt Enable) bits set to\n"); + logerror("%d: EF15 (External Interrupt 5)\n", (m_EIR & 0x8000) ? 1 : 0); + logerror("%d: EF14 (16-bit TC2 Interrupt)\n", (m_EIR & 0x4000) ? 1 : 0); + logerror("%d: EF13 (Serial Interface 2 Interrupt)\n", (m_EIR & 0x2000) ? 1 : 0); + logerror("%d: EF12 (External Interrupt 4)\n", (m_EIR & 0x1000) ? 1 : 0); + logerror("%d: EF11 (External Interrupt 3)\n", (m_EIR & 0x0800) ? 1 : 0); + logerror("%d: EF10 (8-bit TC4 Interrupt)\n", (m_EIR & 0x0400) ? 1 : 0); + logerror("%d: EF9 (Serial Interface 1 Interrupt)\n", (m_EIR & 0x0200) ? 1 : 0); + logerror("%d: EF8 (8-bit TC3 Interrupt)\n", (m_EIR & 0x0100) ? 1 : 0); +} + +/* + the READ/WRITE/MODIFY operations cannot be used to clear interrupt latches + + also you can't set a latch by writing '1' to it, only clear a latch + by writing 0 to it + +*/ +READ8_MEMBER(tlcs870_device::il_l_r) +{ + return m_IL & 0xff; +} + +READ8_MEMBER(tlcs870_device::il_h_r) +{ + return (m_IL >> 8) & 0xff; +} + +WRITE8_MEMBER(tlcs870_device::il_l_w) +{ + // probably not this logic + m_IL = (m_IL & 0xff00) | data; +} + +WRITE8_MEMBER(tlcs870_device::il_h_w) +{ + // probably not this logic + m_IL = (m_EIR & 0x00ff) | (data << 8); +} + void tlcs870_device::execute_set_input(int inputnum, int state) { -#if 0 - switch (inputnum) { - case INPUT_LINE_NMI: - set_irq_line(INTNMI, state); + int32_t irqline = -1; + + switch (inputnum) + { + case INPUT_LINE_IRQ5: + irqline = 15; break; - case INPUT_LINE_IRQ0: - set_irq_line(INT0, state); + + case INPUT_LINE_IRQ4: + irqline = 12; break; - case INPUT_LINE_IRQ1: - set_irq_line(INT1, state); + + case INPUT_LINE_IRQ3: + irqline = 11; break; + case INPUT_LINE_IRQ2: - set_irq_line(INT2, state); + irqline = 7; + break; + + case INPUT_LINE_IRQ1: + irqline = 5; + break; + + case INPUT_LINE_IRQ0: + irqline = 3; break; } -#endif + + if (irqline != -1) + { + set_irq_line(irqline, state); + } +} + +void tlcs870_device::set_irq_line(int irqline, int state) +{ + //logerror("set_irq_line %d %d\n", irqline, state); + + if (!(m_irqstate & (1 << irqline))) + { + // rising edge + if (state) + { + m_irqstate |= 1<<irqline; + + // TODO: add checks to see if interrupt pin(s) are configured, and if they're in rising edge mode + m_IL |= 1<<irqline; + } + } + else + { + if (!state) + { + m_irqstate &= ~(1<<irqline); + } + } +} + +void tlcs870_device::check_interrupts() +{ + // priority 0-2 are non-maskable, and should have already been processed before we get here + for (int priority = 0; priority <= 15; priority++) + { + if (priority >= 3) // only priorities 0,1,2 are non-maskable + { + if (!(m_EIR & 1)) + { + // maskable interrupts are disabled, bail + continue; + } + + int is_latched = m_IL & (1<<priority); + + if (is_latched) + { + take_interrupt(priority); + return; + } + } + else + { + // TODO: handle non-maskable here + } + } +} + +void tlcs870_device::take_interrupt(int priority) +{ + m_IL &= ~(1<<priority); + m_EIR &= ~1; + logerror("taken interrupt %d\n", priority); + + uint16_t vector = RM16(0xffe0 + ((15-priority)*2)); + + WM16(m_sp.d - 1, get_PSW()); + WM16(m_sp.d - 2, m_addr); + m_sp.d -= 3; + + m_pc.d = vector; + logerror("setting PC to %04x\n", m_addr); + } void tlcs870_device::execute_run() { while (m_icount > 0) { + check_interrupts(); + m_prvpc.d = m_pc.d; debugger_instruction_hook(m_pc.d); - //check_interrupts(); m_addr = m_pc.d; m_tmppc = m_addr; // used for jumps etc. m_cycles = 0; @@ -323,6 +554,12 @@ void tlcs870_device::device_reset() { m_pc.d = RM16(0xfffe); m_RBS = 0; + m_EIR = 0; + m_IL = 0; + m_EINTCR = 0; + m_ADCCR = 0; + m_ADCDR = 0; + m_irqstate = 0; m_port_out_latch[0] = 0x00; m_port_out_latch[1] = 0x00; @@ -485,6 +722,8 @@ void tlcs870_device::device_start() cb.resolve_safe(0xff); for (auto &cb : m_port_out_cb) cb.resolve_safe(); + for (auto &cb : m_port_analog_in_cb) + cb.resolve_safe(0xff); } diff --git a/src/devices/cpu/tlcs870/tlcs870.h b/src/devices/cpu/tlcs870/tlcs870.h index 846cf818961..2d6c5f433d0 100644 --- a/src/devices/cpu/tlcs870/tlcs870.h +++ b/src/devices/cpu/tlcs870/tlcs870.h @@ -8,6 +8,7 @@ class tlcs870_device : public cpu_device { public: + auto p0_in_cb() { return m_port_in_cb[0].bind(); } auto p1_in_cb() { return m_port_in_cb[1].bind(); } auto p2_in_cb() { return m_port_in_cb[2].bind(); } @@ -26,6 +27,15 @@ public: auto p6_out_cb() { return m_port_out_cb[6].bind(); } auto p7_out_cb() { return m_port_out_cb[7].bind(); } + auto an0_in_cb() { return m_port_analog_in_cb[0].bind(); } + auto an1_in_cb() { return m_port_analog_in_cb[1].bind(); } + auto an2_in_cb() { return m_port_analog_in_cb[2].bind(); } + auto an3_in_cb() { return m_port_analog_in_cb[3].bind(); } + auto an4_in_cb() { return m_port_analog_in_cb[4].bind(); } + auto an5_in_cb() { return m_port_analog_in_cb[5].bind(); } + auto an6_in_cb() { return m_port_analog_in_cb[6].bind(); } + auto an7_in_cb() { return m_port_analog_in_cb[7].bind(); } + protected: // construction/destruction tlcs870_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor program_map); @@ -57,6 +67,26 @@ protected: uint32_t m_debugger_temp; + enum _tlcs870interrupts + { + TLCS870_IRQ_INT5, // FFE0 INT5 (External Interrupt 5) - priority 15 (lowest) + TLCS870_IRQ_INTTC2, // FFE2 INTTC2 (16-bit TC2 Interrupt) + TLCS870_IRQ_INTSIO2, // FFE4 INTSIO2 (Serial Interface 2 Interrupt) + TLCS870_IRQ_INT4, // FFE6 INT4 (External Interrupt 4) + TLCS870_IRQ_INT3, // FFE8 INT3 (External Interrupt 3) + TLCS870_IRQ_INTTC4, // FFEA INTTC4 (8-bit TC4 Interrupt) + TLCS870_IRQ_INTSIO1, // FFEC INTSIO1 (Serial Interface 1 Interrupt) + TLCS870_IRQ_INTTC3, // FFEE INTTC3 (8-bit TC3 Interrupt) + TLCS870_IRQ_INT2, // FFF0 INT2 (External Interrupt 2) + TLCS870_IRQ_INTTBT, // FFF2 INTTBT (Time Base Timer Interrupt) + TLCS870_IRQ_INT1, // FFF4 INT1 (External Interrupt 1) + TLCS870_IRQ_INTTC1, // FFF6 INTTC1 (16-bit TC1 Interrupt) + TLCS870_IRQ_INT0, // FFF8 INT0 (External Interrupt 0) + TLCS870_IRQ_INTWDT, // FFFA INTWDT (Watchdog Timer Interrupt) + TLCS870_IRQ_INTSW, // FFFC INTSW (Software Interrupt) + TLCS870_IRQ_RESET, // FFFE RESET (Reset Interrupt) - priority 0 (highest) + }; + private: enum _regs8 @@ -131,10 +161,12 @@ private: devcb_read8 m_port_in_cb[8]; devcb_write8 m_port_out_cb[8]; + devcb_read8 m_port_analog_in_cb[8]; + uint8_t m_port_out_latch[8]; int m_read_input_port; uint8_t m_port0_cr, m_port1_cr, m_port6_cr, m_port7_cr; - + DECLARE_READ8_MEMBER(port0_r); DECLARE_READ8_MEMBER(port1_r); DECLARE_READ8_MEMBER(port2_r); @@ -158,6 +190,25 @@ private: DECLARE_WRITE8_MEMBER(p6cr_w); DECLARE_WRITE8_MEMBER(p7cr_w); + DECLARE_READ8_MEMBER(eir_l_r); + DECLARE_READ8_MEMBER(eir_h_r); + DECLARE_READ8_MEMBER(il_l_r); + DECLARE_READ8_MEMBER(il_h_r); + + DECLARE_WRITE8_MEMBER(eir_l_w); + DECLARE_WRITE8_MEMBER(eir_h_w); + DECLARE_WRITE8_MEMBER(il_l_w); + DECLARE_WRITE8_MEMBER(il_h_w); + + DECLARE_READ8_MEMBER(eintcr_r); + + DECLARE_WRITE8_MEMBER(eintcr_w); + + DECLARE_READ8_MEMBER(adccr_r); + DECLARE_READ8_MEMBER(adcdr_r); + + DECLARE_WRITE8_MEMBER(adccr_w); + // Work registers uint8_t m_cycles; uint16_t m_tmppc; @@ -168,6 +219,18 @@ private: /* CPU registers */ uint8_t m_RBS; // register base (4-bits) + uint16_t m_IL; // 3D / 3C + uint16_t m_EIR; // 3B / 3A + uint8_t m_EINTCR; + uint8_t m_ADCCR; + uint8_t m_ADCDR; + + uint16_t m_irqstate; + + void set_irq_line(int irqline, int state); + void check_interrupts(); + void take_interrupt(int priority); + uint8_t RM8(const uint32_t a) { return m_program->read_byte(a); } uint16_t RM16(const uint32_t a) { return RM8(a) | (RM8((a + 1) & 0xffff) << 8); } @@ -371,8 +434,8 @@ private: void do_cmp_8bit(uint16_t param1, uint16_t param2); uint8_t do_alu_8bit(int op, uint16_t param1, uint16_t param2); - uint8_t do_add_16bit(uint32_t param1, uint32_t param2); - uint8_t do_sub_16bit(uint32_t param1, uint32_t param2); + uint16_t do_add_16bit(uint32_t param1, uint32_t param2); + uint16_t do_sub_16bit(uint32_t param1, uint32_t param2); void do_cmp_16bit(uint32_t param1, uint32_t param2); uint16_t do_alu_16bit(int op, uint32_t param1, uint32_t param2); @@ -386,7 +449,6 @@ private: uint8_t handle_DAA(uint8_t val); uint8_t handle_ROLC(uint8_t val); uint8_t handle_RORC(uint8_t val); - void handle_take_interrupt(int level); const bool check_jump_condition(int param1); diff --git a/src/devices/cpu/tlcs870/tlcs870_ops.cpp b/src/devices/cpu/tlcs870/tlcs870_ops.cpp index 2a79879c8fa..7c8dfca57b5 100644 --- a/src/devices/cpu/tlcs870/tlcs870_ops.cpp +++ b/src/devices/cpu/tlcs870/tlcs870_ops.cpp @@ -209,6 +209,9 @@ void tlcs870_device::do_RETI(const uint8_t opbyte0) m_sp.d += 3; m_addr = RM16(m_sp.d - 2); set_PSW(RM8(m_sp.d - 1)); + + // Interrupts always get reenabled after a RETI. The RETN behavior is different + m_EIR |= 1; } void tlcs870_device::do_RET(const uint8_t opbyte0) @@ -778,6 +781,7 @@ void tlcs870_device::do_SET_inxbit(const uint8_t opbyte0) const uint8_t srcaddr = READ8(); + m_read_input_port = 0; // reads output latch, not actual ports if accessing memory mapped ports uint8_t val = RM8(srcaddr); const uint8_t bitpos = opbyte0 & 0x7; @@ -811,6 +815,7 @@ void tlcs870_device::do_CLR_inxbit(const uint8_t opbyte0) const uint8_t srcaddr = READ8(); + m_read_input_port = 0; // not sure, might read uint8_t val = RM8(srcaddr); const uint8_t bitpos = opbyte0 & 0x7; @@ -1128,9 +1133,10 @@ void tlcs870_device::do_ff_opcode(const uint8_t opbyte0) OP (opbyte0) (immval0) (opbyte1) (immval1) (immval2) JF ZF CF HF cycles SWI 1111 1111 - - - - 9 (1 if already in NMI) */ - m_cycles = 9; // TODO: 1 if in NMI (acts as NOP?) + m_cycles = 9; // TODO: 1 if in NMI this acts as a NOP - handle_take_interrupt(0x0e); + // set interrupt latch + m_IL |= 1<<TLCS870_IRQ_INTSW; } /**********************************************************************************************************************/ diff --git a/src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp b/src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp index 8f494ba7475..e75799e554c 100644 --- a/src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp +++ b/src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp @@ -286,7 +286,7 @@ uint8_t tlcs870_device::do_add_8bit(uint16_t param1, uint16_t param2) return result; } -uint8_t tlcs870_device::do_add_16bit(uint32_t param1, uint32_t param2) +uint16_t tlcs870_device::do_add_16bit(uint32_t param1, uint32_t param2) { uint32_t result = param1 + param2; @@ -309,7 +309,7 @@ uint8_t tlcs870_device::do_add_16bit(uint32_t param1, uint32_t param2) } // unknown, manual says undefined, see note above - uint8_t temp = (param1 & 0xff) + (param2 & 0xff); + uint16_t temp = (param1 & 0xff) + (param2 & 0xff); if (temp & 0x100) { @@ -364,7 +364,7 @@ uint8_t tlcs870_device::do_sub_8bit(uint16_t param1, uint16_t param2) } -uint8_t tlcs870_device::do_sub_16bit(uint32_t param1, uint32_t param2) +uint16_t tlcs870_device::do_sub_16bit(uint32_t param1, uint32_t param2) { uint32_t result = param1 - param2; @@ -809,36 +809,3 @@ uint8_t tlcs870_device::handle_RORC(uint8_t val) return val; } - -/* - -(Priority Low - 15) -FFE0 INT5 (External Interrupt 5) -FFE2 INTTC2 (16-bit TC2 Interrupt) -FFE4 INTSIO2 (Serial Interface 2 Interrupt) -FFE6 INT4 (External Interrupt 4) -FFE8 INT3 (External Interrupt 3) -FFEA INTTC4 (8-bit TC4 Interrupt) -FFEC INTSIO1 (Serial Interface 1 Interrupt) -FFEE INTTC3 (8-bit TC3 Interrupt) -FFF0 INT2 (External Interrupt 2) -FFF2 INTTBT (Time Base Timer Interrupt) -FFF4 INT1 (External Interrupt 1) -FFF6 INTTC1 (16-bit TC1 Interrupt) -FFF8 INT0 (External Interrupt 0) -FFFA INTWDT (Watchdog Timer Interrupt) -FFFC INTSW (Software Interrupt) -FFFE RESET (Reset Vector) -(Priority High - 0) - -*/ - -void tlcs870_device::handle_take_interrupt(int level) -{ - WM8(m_sp.d - 1, get_PSW()); - WM16(m_sp.d - 2, m_addr); - m_sp.d -= 3; - - m_addr = RM16(0xffe0 + ((level &0xf)*2)); -} - diff --git a/src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp b/src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp index 484ce98fbb5..9a5177d5831 100644 --- a/src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp +++ b/src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp @@ -19,10 +19,10 @@ EF H (16-bit mode operations) - E8 invalid - E9 invalid - EA invalid - EB invalid + E8 WA + E9 BC + EA DE + EB HL EC WA ED BC EE DE @@ -497,6 +497,7 @@ void tlcs870_device::do_CLR_inppbit(const uint8_t opbyte0, const uint8_t opbyte1 const uint8_t bitpos = get_reg8(opbyte0 & 7) & 0x7; const uint8_t bitused = 1 << bitpos; const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL + m_read_input_port = 0; // reads output latch, not actual ports if accessing memory mapped ports uint8_t val = RM8(addr); if (val & bitused) // Zero flag gets set based on original value of bit? @@ -527,6 +528,7 @@ void tlcs870_device::do_CPL_inpp_indirectbit(const uint8_t opbyte0, const uint8_ const uint8_t bitpos = get_reg8(opbyte0 & 7) & 0x7; const uint8_t bitused = 1 << bitpos; const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL + m_read_input_port = 0; // reads output latch, not actual ports if accessing memory mapped ports uint8_t val = RM8(addr); uint8_t bit = val & bitused; diff --git a/src/devices/cpu/tlcs870/tlcs870_ops_src.cpp b/src/devices/cpu/tlcs870/tlcs870_ops_src.cpp index 0d1a5ae6205..6295d9c06b3 100644 --- a/src/devices/cpu/tlcs870/tlcs870_ops_src.cpp +++ b/src/devices/cpu/tlcs870/tlcs870_ops_src.cpp @@ -416,6 +416,7 @@ void tlcs870_device::do_XCH_r_insrc(const uint8_t opbyte0, const uint8_t opbyte1 */ m_cycles += 4; + m_read_input_port = 0; // reads output latch, not actual ports if accessing memory mapped ports const uint8_t val = RM8(srcaddr); const uint8_t temp = get_reg8(opbyte1 & 0x7); @@ -520,7 +521,10 @@ void tlcs870_device::do_ALUOP_insrc_inHL(const uint8_t opbyte0, const uint8_t op m_cycles += 6; const int aluop = (opbyte1 & 0x7); + if (aluop != 0x07) + m_read_input_port = 0; // reads output latch, not actual ports if accessing memory mapped ports const uint8_t val = RM8(srcaddr); + m_read_input_port = 1; const uint16_t HL = get_reg16(REG_HL); @@ -616,6 +620,10 @@ void tlcs870_device::do_ALUOP_insrc_n(const uint8_t opbyte0, const uint8_t opbyt const uint8_t n = READ8(); const int aluop = (opbyte1 & 0x7); + + if (aluop != 0x07) + m_read_input_port = 0; // reads output latch, not actual ports if accessing memory mapped ports + const uint8_t val = RM8(srcaddr); const uint8_t result = do_alu_8bit(aluop, val, n); @@ -848,6 +856,7 @@ void tlcs870_device::do_LD_insrcbit_CF(const uint8_t opbyte0, const uint8_t opby */ m_cycles += 4; + m_read_input_port = 0; // reads output latch, not actual ports if accessing memory mapped ports uint8_t val = RM8(srcaddr); const uint8_t bitpos = opbyte1 & 0x7; @@ -885,6 +894,7 @@ void tlcs870_device::do_CPL_insrcbit(const uint8_t opbyte0, const uint8_t opbyte */ m_cycles += 4; + m_read_input_port = 0; // reads output latch, not actual ports if accessing memory mapped ports uint8_t val = RM8(srcaddr); const uint8_t bitpos = opbyte1 & 0x7; @@ -956,6 +966,7 @@ void tlcs870_device::do_SET_insrcbit(const uint8_t opbyte0, const uint8_t opbyte */ m_cycles += 4; + m_read_input_port = 0; // reads output latch, not actual ports if accessing memory mapped ports uint8_t val = RM8(srcaddr); const uint8_t bitpos = opbyte1 & 0x7; @@ -994,6 +1005,7 @@ void tlcs870_device::do_CLR_insrcbit(const uint8_t opbyte0, const uint8_t opbyte */ m_cycles += 4; + m_read_input_port = 0; // reads output latch, not actual ports if accessing memory mapped ports uint8_t val = RM8(srcaddr); const uint8_t bitpos = opbyte1 & 0x7; diff --git a/src/mame/drivers/hng64.cpp b/src/mame/drivers/hng64.cpp index 19f68c69c3d..38e73787959 100644 --- a/src/mame/drivers/hng64.cpp +++ b/src/mame/drivers/hng64.cpp @@ -1520,6 +1520,8 @@ void hng64_state::machine_start() } m_3dfifo_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(hng64_state::hng64_3dfifo_processed), this)); + + init_io(); } void hng64_state::machine_reset() @@ -1532,11 +1534,14 @@ void hng64_state::machine_reset() reset_sound(); } -// used +// used (shard ram access at least) READ8_MEMBER(hng64_state::ioport0_r) { - logerror("%s: ioport0_r\n", machine().describe_context()); - return 0x03; // expects 0x03 after writing it to port 0 earlier + uint16_t addr = (m_ex_ramaddr | (m_ex_ramaddr_upper<<9)) & 0x7ff; + uint8_t ret = m_ioram[addr]; + + logerror("%s: ioport0_r %02x (from address %04x)\n", machine().describe_context(), ret, addr); + return ret; // expects 0x03 after writing it to port 0 earlier } // used @@ -1546,10 +1551,13 @@ READ8_MEMBER(hng64_state::ioport1_r) return 0xff; } -// used +// used (shard ram access at least) WRITE8_MEMBER(hng64_state::ioport0_w) { - logerror("%s: ioport0_w %02x\n", machine().describe_context(), data); + uint16_t addr = (m_ex_ramaddr | (m_ex_ramaddr_upper<<9)) & 0x7ff; + m_ioram[addr] = data; + + logerror("%s: ioport0_w %02x (to address %04x)\n", machine().describe_context(), data, addr); } // used @@ -1564,10 +1572,41 @@ WRITE8_MEMBER(hng64_state::ioport3_w) logerror("%s: ioport3_w %02x\n", machine().describe_context(), data); } -// used +// used (shared ram access control for port 0 at least) WRITE8_MEMBER(hng64_state::ioport7_w) { - logerror("%s: ioport7_w %02x\n", machine().describe_context(), data); + /* Port bits + + -?xR Aacr + + a = 0x200 of address bit to external RAM (direct?) + A = 0x400 of address bit to external RAM (direct?) + R = read / write mode? (if 1, write, if 0, read?) + + r = counter reset? ( 1->0 ?) + c = clock address? ( 1->0 ?) + + x = written with clock bits, might be latch related? + ? = written before some operations + + */ + + //logerror("%s: ioport7_w %02x\n", machine().describe_context(), data); + + m_ex_ramaddr_upper = (data & 0x0c) >> 2; + + if ((!(data & 0x01)) && (m_port7 & 0x01)) + { + m_ex_ramaddr = 0; + } + + if ((!(data & 0x02)) && (m_port7 & 0x02)) + { + m_ex_ramaddr++; + m_ex_ramaddr &= 0x1ff; + } + + m_port7 = data; } // check if these are used @@ -1583,6 +1622,44 @@ WRITE8_MEMBER(hng64_state::ioport4_w) { logerror("%s: ioport4_w %02x\n", machine WRITE8_MEMBER(hng64_state::ioport5_w) { logerror("%s: ioport5_w %02x\n", machine().describe_context(), data); } WRITE8_MEMBER(hng64_state::ioport6_w) { logerror("%s: ioport6_w %02x\n", machine().describe_context(), data); } +READ8_MEMBER(hng64_state::anport0_r) { logerror("%s: anport0_r\n", machine().describe_context()); return 0xff; } +READ8_MEMBER(hng64_state::anport1_r) { logerror("%s: anport1_r\n", machine().describe_context()); return 0xff; } +READ8_MEMBER(hng64_state::anport2_r) { logerror("%s: anport2_r\n", machine().describe_context()); return 0xff; } +READ8_MEMBER(hng64_state::anport3_r) { logerror("%s: anport3_r\n", machine().describe_context()); return 0xff; } +READ8_MEMBER(hng64_state::anport4_r) { logerror("%s: anport4_r\n", machine().describe_context()); return 0xff; } +READ8_MEMBER(hng64_state::anport5_r) { logerror("%s: anport5_r\n", machine().describe_context()); return 0xff; } +READ8_MEMBER(hng64_state::anport6_r) { logerror("%s: anport6_r\n", machine().describe_context()); return 0xff; } +READ8_MEMBER(hng64_state::anport7_r) { logerror("%s: anport7_r\n", machine().describe_context()); return 0xff; } + + +TIMER_CALLBACK_MEMBER(hng64_state::tempio_irqon_callback) +{ + logerror("timer_hack_on\n"); + m_iomcu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE ); + m_tempio_irqoff_timer->adjust(m_maincpu->cycles_to_attotime(1000)); +} + +TIMER_CALLBACK_MEMBER(hng64_state::tempio_irqoff_callback) +{ + logerror("timer_hack_off\n"); + m_iomcu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE ); +} + +void hng64_state::init_io() +{ + m_tempio_irqon_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(hng64_state::tempio_irqon_callback), this)); + m_tempio_irqoff_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(hng64_state::tempio_irqoff_callback), this)); + + m_tempio_irqon_timer->adjust(m_maincpu->cycles_to_attotime(100000000)); // just ensure an IRQ gets turned on to move the program forward, real source currently unknown + m_port7 = 0; + m_ex_ramaddr = 0; + m_ex_ramaddr_upper = 0; + + m_ioram = std::make_unique<uint8_t[]>(0x800); // in realty this is 'm_dualport' but as the hookup is incomplete the program fights with the simulation at the moment + save_pointer(&m_ioram[0], "m_ioram", 0x800); + +} + MACHINE_CONFIG_START(hng64_state::hng64) /* basic machine hardware */ MCFG_DEVICE_ADD("maincpu", VR4300BE, HNG64_MASTER_CLOCK) // actually R4300 @@ -1625,7 +1702,14 @@ MACHINE_CONFIG_START(hng64_state::hng64) iomcu.p5_out_cb().set(FUNC(hng64_state::ioport5_w)); iomcu.p6_out_cb().set(FUNC(hng64_state::ioport6_w)); iomcu.p7_out_cb().set(FUNC(hng64_state::ioport7_w)); - + iomcu.an0_in_cb().set(FUNC(hng64_state::anport0_r)); + iomcu.an1_in_cb().set(FUNC(hng64_state::anport1_r)); + iomcu.an2_in_cb().set(FUNC(hng64_state::anport2_r)); + iomcu.an3_in_cb().set(FUNC(hng64_state::anport3_r)); + iomcu.an4_in_cb().set(FUNC(hng64_state::anport4_r)); + iomcu.an5_in_cb().set(FUNC(hng64_state::anport5_r)); + iomcu.an6_in_cb().set(FUNC(hng64_state::anport6_r)); + iomcu.an7_in_cb().set(FUNC(hng64_state::anport7_r)); MACHINE_CONFIG_END diff --git a/src/mame/includes/hng64.h b/src/mame/includes/hng64.h index 0e8ccfb1df7..68b81a9f238 100644 --- a/src/mame/includes/hng64.h +++ b/src/mame/includes/hng64.h @@ -323,6 +323,26 @@ private: DECLARE_WRITE8_MEMBER(ioport6_w); DECLARE_WRITE8_MEMBER(ioport7_w); + DECLARE_READ8_MEMBER(anport0_r); + DECLARE_READ8_MEMBER(anport1_r); + DECLARE_READ8_MEMBER(anport2_r); + DECLARE_READ8_MEMBER(anport3_r); + DECLARE_READ8_MEMBER(anport4_r); + DECLARE_READ8_MEMBER(anport5_r); + DECLARE_READ8_MEMBER(anport6_r); + DECLARE_READ8_MEMBER(anport7_r); + + uint8_t m_port7; + int m_ex_ramaddr; + int m_ex_ramaddr_upper; + std::unique_ptr<uint8_t[]> m_ioram; + + TIMER_CALLBACK_MEMBER(tempio_irqon_callback); + TIMER_CALLBACK_MEMBER(tempio_irqoff_callback); + emu_timer *m_tempio_irqon_timer; + emu_timer *m_tempio_irqoff_timer; + void init_io(); + void init_hng64_reorder_gfx(); void set_irq(uint32_t irq_vector); |