From baeadecbaf56e3e5bde7ffce6a46569a88830700 Mon Sep 17 00:00:00 2001 From: qufb <93520295+qufb@users.noreply.github.com> Date: Sat, 30 Nov 2024 01:51:08 +0000 Subject: [PATCH] cpu/hcd62121,casio/pickytlk.cpp: Add support for more Picky Talk models (#13015) --- src/devices/cpu/hcd62121/hcd62121.cpp | 380 +++++++++++----------- src/devices/cpu/hcd62121/hcd62121.h | 9 + src/devices/cpu/hcd62121/hcd62121d.cpp | 16 +- src/mame/casio/pickytlk.cpp | 432 ++++++++++++++++++------- src/mame/mame.lst | 8 +- 5 files changed, 542 insertions(+), 303 deletions(-) diff --git a/src/devices/cpu/hcd62121/hcd62121.cpp b/src/devices/cpu/hcd62121/hcd62121.cpp index 641ea096fe3..08b1707da15 100644 --- a/src/devices/cpu/hcd62121/hcd62121.cpp +++ b/src/devices/cpu/hcd62121/hcd62121.cpp @@ -66,9 +66,14 @@ hcd62121_cpu_device::hcd62121_cpu_device(const machine_config &mconfig, const ch , m_f(0) , m_time(0) , m_time_op(0) + , m_unk_f5(0) , m_cycles_until_timeout(0) , m_is_timer_started(false) + , m_is_timer_irq_enabled(false) + , m_is_timer_irq_asserted(false) + , m_is_timer_wait_elapsed(true) , m_is_infinite_timeout(false) + , m_timer_cycles(0) , m_lar(0) , m_opt(0) , m_port(0) @@ -145,12 +150,12 @@ void hcd62121_cpu_device::write_reg(int size, u8 op1) if (op1 & 0x80) { for (int i = 0; i < size; i++) - m_reg[(op1 - i) & 0x7f] = m_temp1[i]; + set_reg((op1 - i) & 0x7f, m_temp1[i]); } else { for (int i = 0; i < size; i++) - m_reg[(op1 + i) & 0x7f] = m_temp1[i]; + set_reg((op1 + i) & 0x7f, m_temp1[i]); } } @@ -219,13 +224,13 @@ void hcd62121_cpu_device::write_regreg(int size, u8 arg1, u8 arg2) { /* store in arg1 */ for (int i = 0; i < size; i++) - m_reg[(arg1 + i) & 0x7f] = m_temp1[i]; + set_reg((arg1 + i) & 0x7f, m_temp1[i]); } else { /* store in arg2 */ for (int i = 0; i < size; i++) - m_reg[(arg2 + i) & 0x7f] = m_temp1[i]; + set_reg((arg2 + i) & 0x7f, m_temp1[i]); } } @@ -286,7 +291,7 @@ void hcd62121_cpu_device::write_iregreg(int size, u8 op1, u8 op2) { /* store in reg2 */ for (int i = 0; i < size; i++) - m_reg[(op2 + i) & 0x7f] = m_temp1[i]; + set_reg((op2 + i) & 0x7f, m_temp1[i]); } } @@ -297,7 +302,7 @@ void hcd62121_cpu_device::write_iregreg2(int size, u8 op1, u8 op2) { /* store in reg2 */ for (int i = 0; i < size; i++) - m_reg[(op2 + i) & 0x7f] = m_temp2[i]; + set_reg((op2 + i) & 0x7f, m_temp2[i]); } else { @@ -574,17 +579,22 @@ void hcd62121_cpu_device::device_reset() { m_sp = 0x0000; m_ip = 0x0000; + m_dsize = 0; m_cseg = 0; m_dseg = 0; m_sseg = 0; - m_lar = 0; m_f = 0; m_time = 0; m_time_op = 0; + m_unk_f5 = 0; m_cycles_until_timeout = 0; m_is_timer_started = false; + m_is_timer_irq_enabled = false; + m_is_timer_irq_asserted = false; + m_is_timer_wait_elapsed = true; m_is_infinite_timeout = false; - m_dsize = 0; + m_timer_cycles = 0; + m_lar = 0; m_opt = 0; m_port = 0; @@ -869,15 +879,29 @@ inline void hcd62121_cpu_device::op_sub(int size) } +inline void hcd62121_cpu_device::op_pushb(u8 source) +{ + m_program->write_byte((m_sseg << 16) | m_sp, source); + m_sp--; +} + + inline void hcd62121_cpu_device::op_pushw(u16 source) { - m_program->write_byte(( m_sseg << 16) | m_sp, source & 0xff); + m_program->write_byte((m_sseg << 16) | m_sp, source & 0xff); m_sp--; - m_program->write_byte(( m_sseg << 16) | m_sp, source >> 8); + m_program->write_byte((m_sseg << 16) | m_sp, source >> 8); m_sp--; } +inline u8 hcd62121_cpu_device::op_popb() +{ + m_sp++; + return m_program->read_byte((m_sseg << 16) | m_sp); +} + + inline u16 hcd62121_cpu_device::op_popw() { m_sp++; @@ -888,14 +912,29 @@ inline u16 hcd62121_cpu_device::op_popw() return res; } +void hcd62121_cpu_device::timer_elapsed() +{ + m_is_timer_wait_elapsed = true; + + if (m_is_timer_irq_enabled) + { + m_is_timer_irq_asserted = true; + + // Call timer interrupt vector. + op_pushb(m_cseg); + op_pushw(m_ip); + m_cseg = 0x00; + m_ip = 0x0008; + } +} void hcd62121_cpu_device::execute_run() { do { - if (m_ki_cb() != 0) + if (m_ki_cb() != 0 && m_input_flag_cb() == 0) { - m_cycles_until_timeout = 0; + m_is_timer_wait_elapsed = true; m_is_infinite_timeout = false; } @@ -904,15 +943,26 @@ void hcd62121_cpu_device::execute_run() set_input_flag(false); } - if (m_is_infinite_timeout) + if (m_is_infinite_timeout && !m_is_timer_wait_elapsed) { m_icount = 0; } - else if (m_cycles_until_timeout > 0) + else if (m_cycles_until_timeout > 0 && !m_is_timer_irq_asserted) { int cycles_to_consume = std::min(m_cycles_until_timeout, m_icount); m_cycles_until_timeout -= cycles_to_consume; - m_icount -= cycles_to_consume; + + if (!m_is_timer_wait_elapsed) + { + // It's a blocking wait, consume as much as possible in this quantum. + m_icount -= cycles_to_consume; + } + + if (m_cycles_until_timeout <= 0) + { + m_cycles_until_timeout += m_timer_cycles; + timer_elapsed(); + } } if (m_icount <= 0) { @@ -1656,7 +1706,22 @@ void hcd62121_cpu_device::execute_run() break; case 0x8E: /* unk_8E */ - logerror("%02x:%04x: unimplemented instruction %02x encountered\n", m_cseg, m_ip-1, op); + { + logerror("%02x:%04x: unimplemented instruction %02x encountered\n", m_cseg, m_ip-1, op); + if (m_unk_f5 == 0xd0) + { + /* + FIXME: Needs to be validated with hardware tests. + + Instruction 0x8E is called before reading and testing inputs in some cases. + While the timer is also configured, there's no blocking wait for it to expire. + Instead, there's a busy wait on 2 bytes at register R76 that aren't updated directly by + program code. So far only seen when instruction 0xF5 is executed with operand 0xD0, but + maybe irrelevant, see JD-364 @ 21:b65f. + */ + m_is_timer_irq_enabled = true; + } + } break; case 0x90: /* retzh */ @@ -1685,6 +1750,12 @@ void hcd62121_cpu_device::execute_run() } break; + case 0x9E: /* reti */ + m_ip = op_popw(); + m_cseg = op_popb(); + m_is_timer_irq_asserted = false; + break; + case 0x9F: /* ret */ m_ip = op_popw(); break; @@ -1738,7 +1809,72 @@ void hcd62121_cpu_device::execute_run() { u8 arg = read_op(); + /* + When timer control is set with operand 0xC0, the CPU periodically reads + from external RAM (address range 0x7c00..0x7fff) at an interval of + 832 clock cycles, with the reads themselves taking another 64 clock cycles. + This needs to be explicitly setup, involving writes to unknown segments + 0x11 and 0xE1 (see cfx9850.bin @ 00:00fe), otherwise there's only activity + on address lines without any reads. + + The total sum of these state reads can be approximated to the closest + power of two to define timeout values. Multiple samples were averaged, + as the state read interval can start at a distinct point in time from + the timer wait execution. + */ + const u64 TIMER_STATE_READ_CYCLES = 832 + 64; + m_is_infinite_timeout = false; + m_is_timer_wait_elapsed = true; + m_cycles_until_timeout = m_timer_cycles = 0; m_time_op = arg; + switch (m_time_op) + { + case 0x01: case 0x03: + // Likely only timeouts on KO enabled input. + m_is_infinite_timeout = true; + break; + case 0x11: case 0x13: case 0x15: case 0x17: case 0x19: case 0x1b: case 0x1d: case 0x1f: + case 0x31: case 0x33: case 0x35: case 0x37: case 0x39: case 0x3b: case 0x3d: case 0x3f: + case 0x51: case 0x53: case 0x55: case 0x57: case 0x59: case 0x5b: case 0x5d: case 0x5f: + case 0x71: case 0x73: case 0x75: case 0x77: case 0x79: case 0x7b: case 0x7d: case 0x7f: + case 0x91: case 0x93: case 0x95: case 0x97: case 0x99: case 0x9b: case 0x9d: case 0x9f: + case 0xb1: case 0xb3: case 0xb5: case 0xb7: case 0xb9: case 0xbb: case 0xbd: case 0xbf: + case 0xd1: case 0xd3: case 0xd5: case 0xd7: case 0xd9: case 0xdb: case 0xdd: case 0xdf: + // Approximately 814.32us + m_timer_cycles = 0x4 * TIMER_STATE_READ_CYCLES; + break; + case 0x21: case 0x23: case 0x25: case 0x27: case 0x29: case 0x2b: case 0x2d: case 0x2f: + case 0x61: case 0x63: case 0x65: case 0x67: case 0x69: case 0x6b: case 0x6d: case 0x6f: + case 0xa1: case 0xa3: case 0xa5: case 0xa7: case 0xa9: case 0xab: case 0xad: case 0xaf: + // Approximately 1.63ms + m_timer_cycles = 0x8 * TIMER_STATE_READ_CYCLES; + break; + case 0x05: case 0x07: case 0x0d: case 0x0f: + case 0x45: case 0x47: case 0x4d: case 0x4f: + case 0xc5: case 0xc7: case 0xcd: case 0xcf: + // Approximately 209.34ms + m_timer_cycles = 0x400 * TIMER_STATE_READ_CYCLES; + break; + case 0x09: case 0x0b: + case 0x49: case 0x4b: + case 0xc9: case 0xcb: + // Approximately 837.61ms + m_timer_cycles = 0x1000 * TIMER_STATE_READ_CYCLES; + break; + case 0x41: case 0x43: + case 0xc1: case 0xc3: + // Approximately 1.68s + m_timer_cycles = 0x2000 * TIMER_STATE_READ_CYCLES; + break; + case 0x81: case 0x83: + // Approximately 100.58s + m_timer_cycles = 0x7a800 * TIMER_STATE_READ_CYCLES; + break; + default: + logerror("%02x:%04x: unimplemented timer value %02x encountered\n", m_cseg, m_ip-1, m_time_op); + break; + } + m_cycles_until_timeout = m_timer_cycles; m_is_timer_started = true; } break; @@ -1804,7 +1940,7 @@ void hcd62121_cpu_device::execute_run() for (int i = 0; i < size; i++) { - m_reg[(reg + i) & 0x7f] = read_op(); + set_reg((reg + i) & 0x7f, read_op()); } } break; @@ -1848,7 +1984,18 @@ void hcd62121_cpu_device::execute_run() m_lar += pre_inc; if (arg1 & 0x80) { + /* + FIXME: Needs to be validated with hardware tests. + + JD-368 @ 20:047a must write value 0x7f @ 40:1819, despite 0x7f7f being + expected @ 20:3492. This routine is used to clear RAM, and will overflow + if 40:1818 = 0xff7f7f, since it will loop beyond the expected 0x8000 size + to clear. + + Does this instruction zero-extend immediate values? + */ m_program->write_byte((m_dseg << 16) | m_lar, arg2); + arg2 = 0; } else { @@ -1863,7 +2010,7 @@ void hcd62121_cpu_device::execute_run() for (int i = 0; i < size; i++) { m_lar += pre_inc; - m_reg[(arg2 + i) & 0x7f] = m_program->read_byte((m_dseg << 16) | m_lar); + set_reg((arg2 + i) & 0x7f, m_program->read_byte((m_dseg << 16) | m_lar)); m_lar += post_inc; } } @@ -1970,16 +2117,16 @@ void hcd62121_cpu_device::execute_run() logerror("%06x: in0 read\n", (m_cseg << 16) | m_ip); u8 reg1 = read_op(); - m_reg[reg1 & 0x7f] = m_in0_cb(); + set_reg(reg1 & 0x7f, m_in0_cb()); } break; case 0xE1: /* movb reg,OPT */ - m_reg[read_op() & 0x7f] = m_opt; + set_reg(read_op() & 0x7f, m_opt); break; case 0xE2: /* in kb, reg */ - m_reg[read_op() & 0x7f] = m_ki_cb(); + set_reg(read_op() & 0x7f, m_ki_cb()); break; case 0xE3: /* movb reg,dsize */ @@ -1987,7 +2134,7 @@ void hcd62121_cpu_device::execute_run() u8 reg = read_op(); if (reg & 0x80) fatalerror("%02x:%04x: unimplemented instruction %02x encountered with (arg & 0x80) != 0\n", m_cseg, m_ip-1, op); - m_reg[reg & 0x7f] = m_dsize; + set_reg(reg & 0x7f, m_dsize); } break; @@ -1996,24 +2143,24 @@ void hcd62121_cpu_device::execute_run() u8 reg = read_op(); if (reg & 0x80) fatalerror("%02x:%04x: unimplemented instruction %02x encountered with (arg & 0x80) != 0\n", m_cseg, m_ip-1, op); - m_reg[reg & 0x7f] = m_f; + set_reg(reg & 0x7f, m_f); } break; case 0xE5: /* movb reg,TIME */ - m_reg[read_op() & 0x7f] = m_time; + set_reg(read_op() & 0x7f, m_time); break; case 0xE6: /* movb reg,PORT */ - m_reg[read_op() & 0x7f] = m_port; + set_reg(read_op() & 0x7f, m_port); break; case 0xE8: /* movw r1,lar */ { u8 reg1 = read_op(); - m_reg[reg1 & 0x7f] = m_lar & 0xff; - m_reg[(reg1 + 1) & 0x7f] = m_lar >> 8; + set_reg(reg1 & 0x7f, m_lar & 0xff); + set_reg((reg1 + 1) & 0x7f, m_lar >> 8); } break; @@ -2021,8 +2168,8 @@ void hcd62121_cpu_device::execute_run() { u8 reg1 = read_op(); - m_reg[reg1 & 0x7f] = m_ip & 0xff; - m_reg[(reg1 + 1) & 0x7f] = m_ip >> 8; + set_reg(reg1 & 0x7f, m_ip & 0xff); + set_reg((reg1 + 1) & 0x7f, m_ip >> 8); } break; @@ -2030,21 +2177,21 @@ void hcd62121_cpu_device::execute_run() { u8 reg1 = read_op(); - m_reg[reg1 & 0x7f] = m_sp & 0xff; - m_reg[(reg1 + 1) & 0x7f] = m_sp >> 8; + set_reg(reg1 & 0x7f, m_sp & 0xff); + set_reg((reg1 + 1) & 0x7f, m_sp >> 8); } break; case 0xED: /* movb reg,ds */ - m_reg[read_op() & 0x7f] = m_dseg; + set_reg(read_op() & 0x7f, m_dseg); break; case 0xEE: /* movb reg,cs */ - m_reg[read_op() & 0x7f] = m_cseg; + set_reg(read_op() & 0x7f, m_cseg); break; case 0xEF: /* movb reg,ss */ - m_reg[read_op() & 0x7f] = m_sseg; + set_reg(read_op() & 0x7f, m_sseg); break; case 0xF0: /* movb OPT,reg */ @@ -2057,170 +2204,33 @@ void hcd62121_cpu_device::execute_run() m_port_cb(m_port); break; + case 0xF5: /* unk_F5 reg/i8 (out?) */ + logerror("%02x:%04x: unimplemented instruction %02x encountered\n", m_cseg, m_ip-1, op); + m_unk_f5 = read_op(); + break; + case 0xF1: /* unk_F1 reg/i8 (out?) */ case 0xF3: /* unk_F3 reg/i8 (out?) */ - case 0xF5: /* unk_F5 reg/i8 (out?) */ case 0xF6: /* unk_F6 reg/i8 (out?) */ case 0xF7: /* timer_ctrl i8 */ + case 0xF8: /* unk_F8 reg/i8 (out?) */ logerror("%02x:%04x: unimplemented instruction %02x encountered\n", m_cseg, m_ip-1, op); read_op(); break; - case 0xFC: /* unk_FC - disable interrupts/stop timer?? */ - logerror("%02x:%04x: unimplemented instruction %02x encountered\n", m_cseg, m_ip-1, op); + case 0xFC: /* timer_clear */ + // FIXME: Needs to be validated with hardware tests. + m_cycles_until_timeout = m_timer_cycles = 0; + m_is_timer_irq_enabled = false; + m_is_timer_irq_asserted = false; + m_is_timer_wait_elapsed = true; break; case 0xFD: /* timer_wait_low (no X1 clock, address or data bus activity) */ case 0xFE: /* timer_wait */ - if (m_time_op & 0x01) + if (BIT(m_time_op, 0)) { - /* - When timer control is set with operand 0xC0, the CPU periodically reads - from external RAM (address range 0x7c00..0x7fff) at an interval of - 832 clock cycles, with the reads themselves taking another 64 clock cycles. - This needs to be explicitly setup, involving writes to unknown segments - 0x11 and 0xE1 (see cfx9850.bin @ 00:00fe), otherwise there's only activity - on address lines without any reads. - - The total sum of these state reads can be approximated to the closest - power of two to define timeout values. Multiple samples were averaged, - as the state read interval can start at a distinct point in time from - the timer wait execution. - */ - const u64 TIMER_STATE_READ_CYCLES = 832 + 64; - switch (m_time_op) - { - case 0x01: - case 0x03: - // Likely only timeouts on KO enabled input. - m_is_infinite_timeout = true; - break; - case 0x11: - case 0x13: - case 0x15: - case 0x17: - case 0x19: - case 0x1b: - case 0x1d: - case 0x1f: - case 0x31: - case 0x33: - case 0x35: - case 0x37: - case 0x39: - case 0x3b: - case 0x3d: - case 0x3f: - case 0x51: - case 0x53: - case 0x55: - case 0x57: - case 0x59: - case 0x5b: - case 0x5d: - case 0x5f: - case 0x71: - case 0x73: - case 0x75: - case 0x77: - case 0x79: - case 0x7b: - case 0x7d: - case 0x7f: - case 0x91: - case 0x93: - case 0x95: - case 0x97: - case 0x99: - case 0x9b: - case 0x9d: - case 0x9f: - case 0xb1: - case 0xb3: - case 0xb5: - case 0xb7: - case 0xb9: - case 0xbb: - case 0xbd: - case 0xbf: - case 0xd1: - case 0xd3: - case 0xd5: - case 0xd7: - case 0xd9: - case 0xdb: - case 0xdd: - case 0xdf: - // Approximately 814.32us - m_cycles_until_timeout = 0x4 * TIMER_STATE_READ_CYCLES; - break; - case 0x21: - case 0x23: - case 0x25: - case 0x27: - case 0x29: - case 0x2b: - case 0x2d: - case 0x2f: - case 0x61: - case 0x63: - case 0x65: - case 0x67: - case 0x69: - case 0x6b: - case 0x6d: - case 0x6f: - case 0xa1: - case 0xa3: - case 0xa5: - case 0xa7: - case 0xa9: - case 0xab: - case 0xad: - case 0xaf: - // Approximately 1.63ms - m_cycles_until_timeout = 0x8 * TIMER_STATE_READ_CYCLES; - break; - case 0x05: - case 0x07: - case 0x0d: - case 0x0f: - case 0x45: - case 0x47: - case 0x4d: - case 0x4f: - case 0xc5: - case 0xc7: - case 0xcd: - case 0xcf: - // Approximately 209.34ms - m_cycles_until_timeout = 0x400 * TIMER_STATE_READ_CYCLES; - break; - case 0x09: - case 0x0b: - case 0x49: - case 0x4b: - case 0xc9: - case 0xcb: - // Approximately 837.61ms - m_cycles_until_timeout = 0x1000 * TIMER_STATE_READ_CYCLES; - break; - case 0x41: - case 0x43: - case 0xc1: - case 0xc3: - // Approximately 1.68s - m_cycles_until_timeout = 0x2000 * TIMER_STATE_READ_CYCLES; - break; - case 0x81: - case 0x83: - // Approximately 100.58s - m_cycles_until_timeout = 0x7a800 * TIMER_STATE_READ_CYCLES; - break; - default: - logerror("%02x:%04x: unimplemented timer value %02x encountered\n", m_cseg, m_ip-1, m_time_op); - break; - } + m_is_timer_wait_elapsed = false; } else { diff --git a/src/devices/cpu/hcd62121/hcd62121.h b/src/devices/cpu/hcd62121/hcd62121.h index 51404f95318..98d6e23ad7f 100644 --- a/src/devices/cpu/hcd62121/hcd62121.h +++ b/src/devices/cpu/hcd62121/hcd62121.h @@ -83,8 +83,12 @@ class hcd62121_cpu_device : public cpu_device void op_addb(int size); void op_subb(int size); void op_sub(int size); + void op_pushb(u8 source); void op_pushw(u16 source); + u8 op_popb(); u16 op_popw(); + void set_reg(u8 i, u8 val) { m_reg[i] = val; /*logerror("R%02X = %02x @ %06X\n", i, val, (m_cseg << 16) | m_ip);*/ } + void timer_elapsed(); address_space_config m_program_config; @@ -98,9 +102,14 @@ class hcd62121_cpu_device : public cpu_device u8 m_f; u8 m_time; u8 m_time_op; + u8 m_unk_f5; s32 m_cycles_until_timeout; bool m_is_timer_started; + bool m_is_timer_irq_enabled; + bool m_is_timer_irq_asserted; + bool m_is_timer_wait_elapsed; bool m_is_infinite_timeout; + s32 m_timer_cycles; emu_timer *m_timer; u16 m_lar; u8 m_reg[0x80]; diff --git a/src/devices/cpu/hcd62121/hcd62121d.cpp b/src/devices/cpu/hcd62121/hcd62121d.cpp index 661d40b1701..86109e67287 100644 --- a/src/devices/cpu/hcd62121/hcd62121d.cpp +++ b/src/devices/cpu/hcd62121/hcd62121d.cpp @@ -157,14 +157,14 @@ const hcd62121_disassembler::dasm hcd62121_disassembler::ops[256] = { "movb", ARG_REG, ARG_CS }, { "movb", ARG_REG, ARG_SS }, /* 0xf0 */ - { "movb", ARG_OPT, ARG_REG }, { "unF1?", ARG_I8, ARG_NONE }, - { "movb", ARG_PORT, ARG_REG }, { "unF3?", ARG_I8, ARG_NONE }, - { "unF4?", ARG_I8, ARG_NONE }, { "unF5?", ARG_I8, ARG_NONE }, - { "unF6?", ARG_I8, ARG_NONE }, { "timer_ctrl", ARG_I8, ARG_NONE }, - { "unF8?", ARG_NONE, ARG_NONE }, { "unF9?", ARG_NONE, ARG_NONE }, - { "unFA?", ARG_NONE, ARG_NONE }, { "unFb?", ARG_NONE, ARG_NONE }, - { "unFC?", ARG_NONE, ARG_NONE }, { "timer_wait_low", ARG_NONE, ARG_NONE }, - { "timer_wait", ARG_NONE, ARG_NONE }, { "nop", ARG_NONE, ARG_NONE } + { "movb", ARG_OPT, ARG_REG }, { "unF1?", ARG_I8, ARG_NONE }, + { "movb", ARG_PORT, ARG_REG }, { "unF3?", ARG_I8, ARG_NONE }, + { "unF4?", ARG_I8, ARG_NONE }, { "unF5?", ARG_I8, ARG_NONE }, + { "unF6?", ARG_I8, ARG_NONE }, { "timer_ctrl", ARG_I8, ARG_NONE }, + { "unF8?", ARG_I8, ARG_NONE }, { "unF9?", ARG_NONE, ARG_NONE }, + { "unFA?", ARG_NONE, ARG_NONE }, { "unFb?", ARG_NONE, ARG_NONE }, + { "timer_clear", ARG_NONE, ARG_NONE }, { "timer_wait_low", ARG_NONE, ARG_NONE }, + { "timer_wait", ARG_NONE, ARG_NONE }, { "nop", ARG_NONE, ARG_NONE } }; u32 hcd62121_disassembler::opcode_alignment() const diff --git a/src/mame/casio/pickytlk.cpp b/src/mame/casio/pickytlk.cpp index e1fed5cc5d1..bced0df7fb0 100644 --- a/src/mame/casio/pickytlk.cpp +++ b/src/mame/casio/pickytlk.cpp @@ -2,19 +2,16 @@ // copyright-holders:QUFB /*************************************************************************** - Driver for Casio Picky Talk + Driver for Casio Picky Talk and Casio Plet's TODO: - Communication port; - Panel active buttons display; - Review PORT/OPT callbacks copied from CFX9850G; - - Some points of interest can be accessed under the debugger: - - 1. bpset 0x200328 - 2. ip=3fe (clock screen) - 3. ip=410 (main screen) + - Fix unk_F8 loop when viewing calendar in JD-363/JD-364 models; + - Fix busy loop @ 20:2981 in Plet's models; + - Keyboard input for Plet's models; Hardware -------- @@ -26,6 +23,25 @@ - LSI3 (Static RAM): NEC D441000LGZ (1M-bit, 128K-word by 8-bit) - LSI5 (Mask ROM): NEC D23C8000XGX-C64 (8M-bit, 1M-word by 8-bit, pin compatible with AMD AM29F800B) + Plet's (MK-300): + + - PCB revision: A141252-1 Z836-1 + - LSI1 (CPU): Unknown (instruction set compatible with Hitachi HCD62121) + - LSI3 (Static RAM): Toshiba TC551001BFL-10V (1M-bit, 128K-word by 8-bit) + - LSI5 (Mask ROM): NEC D23C8000XGX-C77 (8M-bit, 1M-word by 8-bit, pin compatible with AMD AM29F800B) + + Plet's (MK-350): + + - PCB revision: A141252-1 Z836-1 + - LSI1 (CPU): Unknown (instruction set compatible with Hitachi HCD62121) + - LSI3 (Static RAM): NEC D441000LGW-B85X + - LSI5 (Mask ROM): Oki M538032E-48 + + Hidden Features + --------------- + + [JD-370] On the debugger, run "bpset 20adb2,,{ ip=20ad27; g; }" to access an unused test program. + ***************************************************************************/ #include "emu.h" @@ -46,10 +62,10 @@ namespace { -class pickytlk_state : public driver_device +class pickytlk_base_state : public driver_device { public: - pickytlk_state(const machine_config &mconfig, device_type type, const char *tag) + pickytlk_base_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) , m_display_ram(*this, "display_ram") , m_maincpu(*this, "maincpu") @@ -68,7 +84,7 @@ class pickytlk_state : public driver_device ioport_value pen_y_rescale_r(); ioport_value pen_target_r(); -private: +protected: enum pen_target : u8 { PEN_TARGET_LCD = 0, @@ -96,11 +112,11 @@ class pickytlk_state : public driver_device TIMER_CALLBACK_MEMBER(io_timer_tick); u8 io_pen_x_read(); u8 io_pen_y_read(); - u8 tablet_read(offs_t offset); + virtual u8 tablet_read(offs_t offset); void tablet_write(offs_t offset, u8 data); + virtual void pickytlk_layout(machine_config &config); void update_crosshair(screen_device &screen); - void pickytlk_palette(palette_device &palette) const; u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); void pickytlk_mem(address_map &map) ATTR_COLD; @@ -128,19 +144,19 @@ class pickytlk_state : public driver_device u8 m_pen_target; }; -void pickytlk_state::machine_start() +void pickytlk_base_state::machine_start() { save_item(NAME(m_ko)); save_item(NAME(m_port)); save_item(NAME(m_opt)); m_io_tablet_regs = make_unique_clear(0x100); save_pointer(NAME(m_io_tablet_regs), 0x100); - m_io_timer = timer_alloc(FUNC(pickytlk_state::io_timer_tick), this); + m_io_timer = timer_alloc(FUNC(pickytlk_base_state::io_timer_tick), this); save_item(NAME(m_pen_state)); save_item(NAME(m_pen_target)); } -void pickytlk_state::machine_reset() +void pickytlk_base_state::machine_reset() { memset(m_io_tablet_regs.get(), 0, 0x100); m_io_timer->reset(attotime::never); @@ -148,14 +164,14 @@ void pickytlk_state::machine_reset() m_pen_target = PEN_TARGET_LCD; } -CROSSHAIR_MAPPER_MEMBER(pickytlk_state::pen_y_mapper) +CROSSHAIR_MAPPER_MEMBER(pickytlk_base_state::pen_y_mapper) { // Parameter `linear_value` is ignored, since we will read the input port directly // for adjustments, just need to return that value in the expected range [0.0f..1.0f]. return (float) pen_y_rescale_r() / 0xff; } -ioport_value pickytlk_state::pen_y_rescale_r() +ioport_value pickytlk_base_state::pen_y_rescale_r() { /* There are two distinct areas that can be interacted with the pen: @@ -182,25 +198,12 @@ ioport_value pickytlk_state::pen_y_rescale_r() return adjusted_value; } -ioport_value pickytlk_state::pen_target_r() +ioport_value pickytlk_base_state::pen_target_r() { return m_pen_target; } -void pickytlk_state::pickytlk_mem(address_map &map) -{ - map(0x000000, 0x007fff).mirror(0x008000).rom(); - map(0x080000, 0x0807ff).ram(); - map(0x080300, 0x08030f).rw(FUNC(pickytlk_state::tablet_read), FUNC(pickytlk_state::tablet_write)); -// map(0x100000, 0x10ffff) // some memory mapped i/o??? -// map(0x110000, 0x11ffff) // some memory mapped i/o??? - map(0x200000, 0x2fffff).rom().region("mask_rom", 0); - map(0x400000, 0x4007ff).ram().share("display_ram"); - map(0x400800, 0x41ffff).ram(); -// map(0xe10000, 0xe1ffff) // some memory mapped i/o??? -} - -TIMER_CALLBACK_MEMBER(pickytlk_state::io_timer_tick) +TIMER_CALLBACK_MEMBER(pickytlk_base_state::io_timer_tick) { if (m_pen_state == PEN_PRESS) { @@ -208,7 +211,7 @@ TIMER_CALLBACK_MEMBER(pickytlk_state::io_timer_tick) } } -u8 pickytlk_state::io_pen_x_read() +u8 pickytlk_base_state::io_pen_x_read() { // Pen callibration tests seem to check coordinates relative to the center of the LCD screen, // and those offsets also align with the LCD position relative to the full tablet surface. @@ -218,7 +221,7 @@ u8 pickytlk_state::io_pen_x_read() return rescale(io_pen_x_pos, io_pen_x_min, io_pen_x_max, 0x20, 0xdf); } -u8 pickytlk_state::io_pen_y_read() +u8 pickytlk_base_state::io_pen_y_read() { s16 io_pen_y_min = m_io_pen_y->field(0xff)->minval(); s16 io_pen_y_max = m_io_pen_y->field(0xff)->maxval(); @@ -228,77 +231,43 @@ u8 pickytlk_state::io_pen_y_read() : rescale(io_pen_y_pos, io_pen_y_min, io_pen_y_max, 0xa0, 0xf0); } -u8 pickytlk_state::tablet_read(offs_t offset) +u8 pickytlk_base_state::tablet_read(offs_t offset) { - /* - Pen coordinates can return a mirrored value when bit 4 is not set. - Both pairs of values , are approximated from these tests: - - General case: - - x1 + x2 > 0xc8 - - y1 + y2 > 0xc8 - - Reset screen with "OK" prompt: - - x1 > 0x7d - - y1 > 0x7d - - Pen callibration: - - x1 < 0x72 - - x2 < 0x72 - - y1 < 0x64 - - y1 > 0x68 - */ - LOGMASKED(LOG_TABLET, "%s: tablet_read [%02x] = %02x\n", machine().describe_context(), offset, m_io_tablet_regs[offset]); - switch (offset) - { - case 0: - { - u8 y = BIT(m_ko, 7) ? io_pen_y_read() : 0; - LOGMASKED(LOG_TABLET, "%s: pen y = %02x\n", machine().describe_context(), y); - return BIT(m_ko, 4) ? y : (0xff - y); - } - case 1: - { - u8 x = BIT(m_ko, 6) ? io_pen_x_read() : 0; - LOGMASKED(LOG_TABLET, "%s: pen x = %02x\n", machine().describe_context(), x); - return BIT(m_ko, 4) ? x : (0xff - x); - } - case 4: - // Can return 0 if other values are not stable/ready? - return 0x80; - default: - return m_io_tablet_regs[offset]; - } + // Default (overriden by each system) + return 0; } -void pickytlk_state::tablet_write(offs_t offset, u8 data) +void pickytlk_base_state::tablet_write(offs_t offset, u8 data) { LOGMASKED(LOG_TABLET, "%s: tablet_write [%02x] = %02x\n", machine().describe_context(), offset, data); m_io_tablet_regs[offset] = data; } -void pickytlk_state::kol_w(u8 data) +void pickytlk_base_state::kol_w(u8 data) { m_ko = (m_ko & 0xff00) | data; LOGMASKED(LOG_IO, "%s: KO = %04x\n", machine().describe_context(), m_ko); } -void pickytlk_state::koh_w(u8 data) +void pickytlk_base_state::koh_w(u8 data) { m_ko = (m_ko & 0x00ff) | (u16(data) << 8); LOGMASKED(LOG_IO, "%s: KO = %04x\n", machine().describe_context(), m_ko); } -void pickytlk_state::port_w(u8 data) +void pickytlk_base_state::port_w(u8 data) { m_port = data; LOGMASKED(LOG_IO, "%s: PORT = %02x\n", machine().describe_context(), m_port); } -void pickytlk_state::opt_w(u8 data) +void pickytlk_base_state::opt_w(u8 data) { m_opt = data; LOGMASKED(LOG_IO, "%s: OPT = %02x\n", machine().describe_context(), m_opt); } -u8 pickytlk_state::ki_r() +u8 pickytlk_base_state::ki_r() { if (BIT(m_io_buttons->read(), 6)) { @@ -308,7 +277,7 @@ u8 pickytlk_state::ki_r() // FIXME: Adjust delay when more accurate instruction timings are implemented. // Program code waits for input flag to be stable by executing `mov DSIZE,0xff` // then `movq R00,R00` 15 times (see pickytlk ROM @ 2015f6). - m_io_timer->adjust(attotime::from_msec(1), 0, attotime::never); + m_io_timer->adjust(attotime::from_msec(20), 0, attotime::never); } } else @@ -320,7 +289,7 @@ u8 pickytlk_state::ki_r() return m_pen_state == PEN_PRESS ? 0x80 : 0; } -u8 pickytlk_state::in0_r() +u8 pickytlk_base_state::in0_r() { // battery level? // bit4 -> if reset CPU keeps restarting (several unknown instructions before jumping to 0) @@ -332,26 +301,23 @@ u8 pickytlk_state::in0_r() return 0x30 & ~0x00; } -u8 pickytlk_state::input_flag_read() +u8 pickytlk_base_state::input_flag_read() { - return m_pen_state == PEN_HOLD ? 0 : 1; + return m_pen_state == PEN_PRESS || m_pen_state == PEN_HOLD ? 0 : 1; } -void pickytlk_state::update_crosshair(screen_device &screen) +void pickytlk_base_state::pickytlk_layout(machine_config &config) { - // Either screen crosshair or layout view's cursor should be visible at a time. - machine().crosshair().get_crosshair(0).set_screen(m_pen_target ? CROSSHAIR_SCREEN_NONE : &screen); + // Nothing (overriden by each system) } -void pickytlk_state::pickytlk_palette(palette_device &palette) const +void pickytlk_base_state::update_crosshair(screen_device &screen) { - palette.set_pen_color(0, 0xee, 0xee, 0xcc); - palette.set_pen_color(1, 0x11, 0x33, 0x99); - palette.set_pen_color(2, 0x33, 0xcc, 0x77); - palette.set_pen_color(3, 0xee, 0x77, 0x33); + // Either screen crosshair or layout view's cursor should be visible at a time. + machine().crosshair().get_crosshair(0).set_screen(m_pen_target ? CROSSHAIR_SCREEN_NONE : &screen); } -u32 pickytlk_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +u32 pickytlk_base_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { update_crosshair(screen); @@ -388,55 +354,303 @@ static INPUT_PORTS_START(pickytlk) // TODO: On/Off/Reset PORT_START("BUTTONS") PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("Pen Down") - PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(FUNC(pickytlk_state::pen_target_r)) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(FUNC(pickytlk_base_state::pen_target_r)) PORT_START("PEN_X") PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(30) PORT_KEYDELTA(10) PORT_MINMAX(0, 255) PORT_PLAYER(1) PORT_NAME("Pen X") PORT_START("PEN_Y") - PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(30) PORT_KEYDELTA(10) PORT_MINMAX(0, 255) PORT_PLAYER(1) PORT_NAME("Pen Y") PORT_CROSSHAIR_MAPPER_MEMBER(FUNC(pickytlk_state::pen_y_mapper)) + PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(30) PORT_KEYDELTA(10) PORT_MINMAX(0, 255) PORT_PLAYER(1) PORT_NAME("Pen Y") PORT_CROSSHAIR_MAPPER_MEMBER(FUNC(pickytlk_base_state::pen_y_mapper)) PORT_START("PEN_Y_RESCALE") - PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(FUNC(pickytlk_state::pen_y_rescale_r)) + PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(FUNC(pickytlk_base_state::pen_y_rescale_r)) INPUT_PORTS_END -void pickytlk_state::pickytlk(machine_config &config) +void pickytlk_base_state::pickytlk(machine_config &config) { HCD62121(config, m_maincpu, 4300000); /* X1 - 4.3 MHz */ - m_maincpu->set_addrmap(AS_PROGRAM, &pickytlk_state::pickytlk_mem); - m_maincpu->kol_cb().set(FUNC(pickytlk_state::kol_w)); - m_maincpu->koh_cb().set(FUNC(pickytlk_state::koh_w)); - m_maincpu->port_cb().set(FUNC(pickytlk_state::port_w)); - m_maincpu->opt_cb().set(FUNC(pickytlk_state::opt_w)); - m_maincpu->ki_cb().set(FUNC(pickytlk_state::ki_r)); - m_maincpu->in0_cb().set(FUNC(pickytlk_state::in0_r)); - m_maincpu->input_flag_cb().set(FUNC(pickytlk_state::input_flag_read)); + m_maincpu->kol_cb().set(FUNC(pickytlk_base_state::kol_w)); + m_maincpu->koh_cb().set(FUNC(pickytlk_base_state::koh_w)); + m_maincpu->port_cb().set(FUNC(pickytlk_base_state::port_w)); + m_maincpu->opt_cb().set(FUNC(pickytlk_base_state::opt_w)); + m_maincpu->ki_cb().set(FUNC(pickytlk_base_state::ki_r)); + m_maincpu->in0_cb().set(FUNC(pickytlk_base_state::in0_r)); + m_maincpu->input_flag_cb().set(FUNC(pickytlk_base_state::input_flag_read)); screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD)); screen.set_refresh_hz(60); screen.set_size(127, 64); screen.set_visarea(0, 126, 0, 63); - screen.set_screen_update(FUNC(pickytlk_state::screen_update)); + screen.set_screen_update(FUNC(pickytlk_base_state::screen_update)); screen.set_palette("palette"); - // TODO: Verify amount of colors and palette. Colors can be changed by changing the contrast. - PALETTE(config, "palette", FUNC(pickytlk_state::pickytlk_palette), 4); + pickytlk_layout(config); +} + + +class pickytlk_monocolor_state : public pickytlk_base_state +{ +public: + pickytlk_monocolor_state(const machine_config &mconfig, device_type type, const char *tag) + : pickytlk_base_state(mconfig, type, tag) + { } + + void pickytlk_monocolor(machine_config &config); +private: + virtual u8 tablet_read(offs_t offset) override; + virtual void pickytlk_layout(machine_config &config) override; + void pickytlk_mem(address_map &map); + void pickytlk_palette(palette_device &palette) const; +}; + +void pickytlk_monocolor_state::pickytlk_layout(machine_config &config) +{ config.set_default_layout(layout_pickytlk); } +u8 pickytlk_monocolor_state::tablet_read(offs_t offset) +{ + LOGMASKED(LOG_TABLET, "%s: tablet_read [%02x] = %02x\n", machine().describe_context(), offset, m_io_tablet_regs[offset]); -ROM_START(pickytlk) - ROM_REGION(0x8000, "maincpu", 0) + if (BIT(offset, 0)) + { + u8 y = BIT(m_ko, 3) ? io_pen_y_read() : 0; + LOGMASKED(LOG_TABLET, "%s: pen y = %02x\n", machine().describe_context(), y); + return BIT(m_ko, 0) ? y : (0xff - y); + } + else + { + u8 x = BIT(m_ko, 2) ? io_pen_x_read() : 0; + LOGMASKED(LOG_TABLET, "%s: pen x = %02x\n", machine().describe_context(), x); + return BIT(m_ko, 0) ? x : (0xff - x); + } +} + +void pickytlk_monocolor_state::pickytlk_mem(address_map &map) +{ + map(0x000000, 0x00bfff).rom(); +// map(0x040000, 0x04ffff) // Unknown + map(0x080000, 0x0807ff).ram(); +// map(0x100000, 0x10ffff) // Unknown + map(0x200000, 0x2fffff).rom().region("mask_rom", 0); + map(0x400000, 0x4007ff).ram().share("display_ram"); + map(0x400800, 0x41ffff).ram(); + // Read after pen callibration + map(0x800030, 0x80003f).rw(FUNC(pickytlk_monocolor_state::tablet_read), FUNC(pickytlk_monocolor_state::tablet_write)); + // Read before pen callibration + map(0x800040, 0x80004f).rw(FUNC(pickytlk_monocolor_state::tablet_read), FUNC(pickytlk_monocolor_state::tablet_write)); +// map(0xe00000, 0xe0ffff) // LCD I/O +} + +void pickytlk_monocolor_state::pickytlk_palette(palette_device &palette) const +{ + palette.set_pen_color(0, 0xee, 0xee, 0xcc); + palette.set_pen_color(1, 0x11, 0x11, 0x11); + palette.set_pen_color(2, 0x11, 0x11, 0x11); + palette.set_pen_color(3, 0x11, 0x11, 0x11); +} + +void pickytlk_monocolor_state::pickytlk_monocolor(machine_config &config) +{ + pickytlk_base_state::pickytlk(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &pickytlk_monocolor_state::pickytlk_mem); + + // TODO: Verify palette. Colors can be changed by changing the contrast. + PALETTE(config, "palette", FUNC(pickytlk_monocolor_state::pickytlk_palette), 4); +} + + +class pickytlk_multicolor_state : public pickytlk_base_state +{ +public: + pickytlk_multicolor_state(const machine_config &mconfig, device_type type, const char *tag) + : pickytlk_base_state(mconfig, type, tag) + { } + + void pickytlk_multicolor(machine_config &config); + +private: + virtual u8 tablet_read(offs_t offset) override; + virtual void pickytlk_layout(machine_config &config) override; + void pickytlk_mem(address_map &map); + void pickytlk_palette(palette_device &palette) const; +}; + +void pickytlk_multicolor_state::pickytlk_layout(machine_config &config) +{ + config.set_default_layout(layout_pickytlk); +} + +u8 pickytlk_multicolor_state::tablet_read(offs_t offset) +{ + /* + Pen coordinates can return a mirrored value when bit 4 is not set. + Both pairs of values , are approximated from these tests: + - General case: + - x1 + x2 > 0xc8 + - y1 + y2 > 0xc8 + - Reset screen with "OK" prompt: + - x1 > 0x7d + - y1 > 0x7d + - Pen callibration: + - x1 < 0x72 + - x2 < 0x72 + - y1 < 0x64 + - y1 > 0x68 + */ + LOGMASKED(LOG_TABLET, "%s: tablet_read [%02x] = %02x\n", machine().describe_context(), offset, m_io_tablet_regs[offset]); + switch (offset) + { + case 0: + { + u8 y = BIT(m_ko, 7) ? io_pen_y_read() : 0; + LOGMASKED(LOG_TABLET, "%s: pen y = %02x\n", machine().describe_context(), y); + return BIT(m_ko, 4) ? y : (0xff - y); + } + case 1: + { + u8 x = BIT(m_ko, 6) ? io_pen_x_read() : 0; + LOGMASKED(LOG_TABLET, "%s: pen x = %02x\n", machine().describe_context(), x); + return BIT(m_ko, 4) ? x : (0xff - x); + } + case 4: + // Can return 0 if other values are not stable/ready? + return 0x80; + default: + return m_io_tablet_regs[offset]; + } +} + +void pickytlk_multicolor_state::pickytlk_mem(address_map &map) +{ + map(0x000000, 0x007fff).rom(); + map(0x080000, 0x0807ff).ram(); + map(0x080300, 0x08030f).rw(FUNC(pickytlk_multicolor_state::tablet_read), FUNC(pickytlk_multicolor_state::tablet_write)); +// map(0x100000, 0x10ffff) // Unknown +// map(0x110000, 0x11ffff) // LCD I/O + map(0x200000, 0x2fffff).rom().region("mask_rom", 0); + map(0x400000, 0x4007ff).ram().share("display_ram"); + map(0x400800, 0x41ffff).ram(); +// map(0xe10000, 0xe1ffff) // LCD I/O +} + +void pickytlk_multicolor_state::pickytlk_palette(palette_device &palette) const +{ + palette.set_pen_color(0, 0xee, 0xee, 0xcc); + palette.set_pen_color(1, 0x11, 0x33, 0x99); + palette.set_pen_color(2, 0x33, 0xcc, 0x77); + palette.set_pen_color(3, 0xee, 0x77, 0x33); +} + +void pickytlk_multicolor_state::pickytlk_multicolor(machine_config &config) +{ + pickytlk_base_state::pickytlk(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &pickytlk_multicolor_state::pickytlk_mem); + + // TODO: Verify palette. Colors can be changed by changing the contrast. + PALETTE(config, "palette", FUNC(pickytlk_multicolor_state::pickytlk_palette), 4); +} + + +class plets_state : public pickytlk_multicolor_state +{ +public: + plets_state(const machine_config &mconfig, device_type type, const char *tag) + : pickytlk_multicolor_state(mconfig, type, tag) + { } + +private: + virtual void pickytlk_layout(machine_config &config) override; +}; + +void plets_state::pickytlk_layout(machine_config &config) +{ + // Nothing +} + + +#define CPU_ROM_MONOCOLOR \ + ROM_REGION(0xc000, "maincpu", 0) \ + ROM_LOAD("cpu.lsi1", 0x0000, 0xc000, CRC(67c76253) SHA1(2f7d368e584608d0ed3135159c36f35f02cdd8c4)) + +#define CPU_ROM_MULTICOLOR \ + ROM_REGION(0x8000, "maincpu", 0) \ ROM_LOAD("cpu.lsi1", 0x0000, 0x8000, CRC(d58efff9) SHA1(a8d2c2a331d79c5299274e2f2d180deda60a5aed)) + +ROM_START(jd363) + CPU_ROM_MONOCOLOR + + ROM_REGION(0x100000, "mask_rom", 0) + ROM_LOAD("d23c8000lwgx-c11.lsi5", 0x00000, 0x100000, CRC(d4c6e7d2) SHA1(ef199725f04da977cd47293dba8086011f156baf)) +ROM_END + +ROM_START(pickydis) + CPU_ROM_MONOCOLOR + + ROM_REGION(0x100000, "mask_rom", 0) + ROM_LOAD("d23c8000lwgx-c14.lsi5", 0x00000, 0x100000, CRC(1a6273c7) SHA1(f0601873503272d9a620789b5c9798f6e1baf4e7)) +ROM_END + +ROM_START(jd364) + CPU_ROM_MULTICOLOR + + ROM_REGION(0x100000, "mask_rom", 0) + ROM_LOAD("d23c8000lwgx-c12.lsi5", 0x00000, 0x100000, CRC(c023b709) SHA1(0c081a62f00d0fbee496a5c9067fb145cb79c8cd)) +ROM_END + +ROM_START(jd368) + CPU_ROM_MULTICOLOR + + ROM_REGION(0x100000, "mask_rom", 0) + ROM_LOAD("d23c8000xgx-c42.lsi5", 0x00000, 0x100000, CRC(c396bafb) SHA1(0d5610d288ab2474017c05ed54fc816d2e82525f)) +ROM_END + +ROM_START(pickytlk) + CPU_ROM_MULTICOLOR + ROM_REGION(0x100000, "mask_rom", 0) ROM_LOAD("d23c8000xgx-c64.lsi5", 0x00000, 0x100000, CRC(6ed6feae) SHA1(f9a63db3d048da0954cab052690deb01ec384b22)) ROM_END +ROM_START(mk300) + CPU_ROM_MULTICOLOR + + ROM_REGION(0x100000, "mask_rom", 0) + ROM_LOAD("d23c8000xgx-c77.lsi5", 0x00000, 0x100000, CRC(50ecb853) SHA1(5f2564ccb6ff7e0e5a21064ca32626f35dc81506)) +ROM_END + +ROM_START(mk350) + CPU_ROM_MULTICOLOR + + ROM_REGION(0x100000, "mask_rom", 0) + ROM_LOAD("m538032e-48.lsi5", 0x00000, 0x100000, CRC(42068a99) SHA1(24f8dc15a51a391d4c35cce7332d55f1fa4d8160)) +ROM_END + } // anonymous namespace -// "CASIO スーパーピッキートーク「グルタンの森」はやわかりビデオ" has copyright dates 1997,1998,1999 -COMP(1997, pickytlk, 0, 0, pickytlk, pickytlk, pickytlk_state, empty_init, "Casio", "Super Picky Talk - Forest of Gurutan", MACHINE_NO_SOUND | MACHINE_NOT_WORKING) +// Release date 1995-09 from "Casio Game Perfect Catalogue" +COMP(1995, jd363, 0, 0, pickytlk_monocolor, pickytlk, pickytlk_monocolor_state, empty_init, "Casio", "Picky Talk - Super Denshi Techou", MACHINE_NO_SOUND | MACHINE_NOT_WORKING) + +// ROM date 9539K7001 +COMP(1995?, pickydis, 0, 0, pickytlk_monocolor, pickytlk, pickytlk_monocolor_state, empty_init, "Tsukuda Original", "Disney Characters - Tegaki Electronic Note", MACHINE_NO_SOUND | MACHINE_NOT_WORKING) + +// Release date 1995-10 from "Casio Game Perfect Catalogue" +COMP(1995, jd364, 0, 0, pickytlk_multicolor, pickytlk, pickytlk_multicolor_state, empty_init, "Casio", "Color Picky Talk - Super Denshi Techou", MACHINE_NO_SOUND | MACHINE_NOT_WORKING) + +// ROM date 9737K7041 +COMP(1997?, jd368, 0, 0, pickytlk_multicolor, pickytlk, pickytlk_multicolor_state, empty_init, "Casio", "Super Picky Talk - Access Pet", MACHINE_NO_SOUND | MACHINE_NOT_WORKING) + +// Release date 1998-07 from "Casio Game Perfect Catalogue" +COMP(1998, pickytlk, 0, 0, pickytlk_multicolor, pickytlk, pickytlk_multicolor_state, empty_init, "Casio", "Super Picky Talk - Forest of Gurutan", MACHINE_NO_SOUND | MACHINE_NOT_WORKING) + +// Release date 1999-09 from "Casio Game Perfect Catalogue" +COMP(1999, mk300, 0, 0, pickytlk_multicolor, pickytlk, plets_state, empty_init, "Casio", "Plet's (MK-300)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING) + +// ROM date 0019K7001 +COMP(2000?, mk350, 0, 0, pickytlk_multicolor, pickytlk, plets_state, empty_init, "Casio", "Plet's (MK-350)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING) diff --git a/src/mame/mame.lst b/src/mame/mame.lst index e3f664b91f3..72b021f7f6e 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -16138,7 +16138,13 @@ pb1000 // Casio PB-1000 pb2000c // Casio PB-2000C @source:casio/pickytlk.cpp -pickytlk // Casio Picky Talk +jd363 // Casio Picky Talk - Super Denshi Techou +jd364 // Casio Color Picky Talk - Super Denshi Techou +jd368 // Casio Super Picky Talk - Access Pet +mk300 // Casio Plet's (MK-300) +mk350 // Casio Plet's (MK-350) +pickydis // Tsukuda Original Disney Characters - Tegaki Electronic Note +pickytlk // Casio Super Picky Talk - Forest of Gurutan @source:casio/pv1000.cpp pv1000 // Casio PV-1000