summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
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
commit082617fa3d77788058f264a30af8f45b1df20b93 (patch)
tree2d288c31a2dfe776e8b947c1550475a8b8ad6f98
parent3a5518125cdc1b9903ae9dd543f34f56857fa7eb (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.cpp267
-rw-r--r--src/devices/cpu/tlcs870/tlcs870.h70
-rw-r--r--src/devices/cpu/tlcs870/tlcs870_ops.cpp10
-rw-r--r--src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp39
-rw-r--r--src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp10
-rw-r--r--src/devices/cpu/tlcs870/tlcs870_ops_src.cpp12
-rw-r--r--src/mame/drivers/hng64.cpp100
-rw-r--r--src/mame/includes/hng64.h20
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);