From 0a18e664630af3aa977c93c0a8504939b68e3552 Mon Sep 17 00:00:00 2001 From: Paul-Arnold <98924583+Paul-Arnold@users.noreply.github.com> Date: Thu, 18 Aug 2022 14:41:08 +0100 Subject: misc/magicard.cpp: Added required devices and default NVRAM contents. (#9970) * cpu/pic16c5x: Expose driven lines to I/O handlers in mask. * machine/ds1207.cpp: Added DS1207 Time Key device. * machine/msm6242.cpp: Fixed interrupt output pulse duration. * machine/scc66470.cpp: Added Philips SCC66470 Video and System controller device. Machines promoted to working ------------------------------- Puzzle Me! Lucky 7 (Impera) V04/91a Clones promoted to working ------------------------------- Magic Card Export 94 (V2.11a, set 3) Magic Card - Wien (Sicherheitsversion 1.2) unknown Poker 'TE06' --- scripts/src/machine.lua | 23 + src/devices/cpu/pic16c5x/pic16c5x.cpp | 14 +- src/devices/machine/ds1207.cpp | 646 ++++++++++++++++ src/devices/machine/ds1207.h | 122 +++ src/devices/machine/msm6242.cpp | 27 +- src/devices/machine/msm6242.h | 2 + src/devices/machine/scc66470.cpp | 901 ++++++++++++++++++++++ src/devices/machine/scc66470.h | 115 +++ src/devices/machine/scc68070.cpp | 629 ++++++++++++++- src/devices/machine/scc68070.h | 129 +--- src/mame/misc/magicard.cpp | 1370 +++++++++++++++++++++------------ src/mame/philips/cdicdic.cpp | 4 +- 12 files changed, 3386 insertions(+), 596 deletions(-) create mode 100644 src/devices/machine/ds1207.cpp create mode 100644 src/devices/machine/ds1207.h create mode 100644 src/devices/machine/scc66470.cpp create mode 100644 src/devices/machine/scc66470.h diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 6c564876d8b..0fb0e109de5 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -1179,6 +1179,18 @@ if (MACHINES["DS1205"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/ds1207.h,MACHINES["DS1207"] = true +--------------------------------------------------- + +if (MACHINES["DS1207"]~=null) then + files { + MAME_DIR .. "src/devices/machine/ds1207.cpp", + MAME_DIR .. "src/devices/machine/ds1207.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/ds1302.h,MACHINES["DS1302"] = true @@ -3105,6 +3117,17 @@ if (MACHINES["SAA1043"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/scc66470.h,MACHINES["SCC66470"] = true +--------------------------------------------------- +if (MACHINES["SCC66470"]~=null) then + files { + MAME_DIR .. "src/devices/machine/scc66470.cpp", + MAME_DIR .. "src/devices/machine/scc66470.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/scc68070.h,MACHINES["SCC68070"] = true diff --git a/src/devices/cpu/pic16c5x/pic16c5x.cpp b/src/devices/cpu/pic16c5x/pic16c5x.cpp index e6284b1412c..ee1dcabc4fd 100644 --- a/src/devices/cpu/pic16c5x/pic16c5x.cpp +++ b/src/devices/cpu/pic16c5x/pic16c5x.cpp @@ -51,6 +51,8 @@ * hap (12-Feb-2017) Ver 1.16 * * - Added basic support for the old GI PIC1650 and PIC1655. * * - Made RTCC(aka T0CKI) pin an inputline handler. * + * pa (12-Jun-2022) Ver 1.17 * + * - Port callback functions pass tristate value in mem_mask. * * * * * * **** Notes: **** * @@ -449,7 +451,7 @@ void pic16c5x_device::STORE_REGFILE(offs_t addr, uint8_t data) /* Write to in } else if (m_picmodel != 0x1655) { /* A is input-only on 1655 */ data &= 0x0f; /* 4-bit port (only lower 4 bits used) */ - m_write_a(PIC16C5x_PORTA, data & (uint8_t)(~m_TRISA), 0xff); + m_write_a(PIC16C5x_PORTA, data & (uint8_t)(~m_TRISA) & 0x0f, (uint8_t)(~m_TRISA) & 0x0f); } PORTA = data; break; @@ -458,7 +460,7 @@ void pic16c5x_device::STORE_REGFILE(offs_t addr, uint8_t data) /* Write to in m_write_b(PIC16C5x_PORTB, data, 0xff); } else { - m_write_b(PIC16C5x_PORTB, data & (uint8_t)(~m_TRISB), 0xff); + m_write_b(PIC16C5x_PORTB, data & (uint8_t)(~m_TRISB), (uint8_t)(~m_TRISB)); } PORTB = data; break; @@ -467,7 +469,7 @@ void pic16c5x_device::STORE_REGFILE(offs_t addr, uint8_t data) /* Write to in m_write_c(PIC16C5x_PORTC, data, 0xff); } else if ((m_picmodel == 0x16C55) || (m_picmodel == 0x16C57)) { - m_write_c(PIC16C5x_PORTC, data & (uint8_t)(~m_TRISC), 0xff); + m_write_c(PIC16C5x_PORTC, data & (uint8_t)(~m_TRISC), (uint8_t)(~m_TRISC)); } PORTC = data; /* also writes to RAM */ break; @@ -756,12 +758,12 @@ void pic16c5x_device::tris() switch(m_opcode.b.l & 0x7) { case 5: if (m_TRISA == m_W) break; - else { m_TRISA = m_W | 0xf0; m_write_a(PIC16C5x_PORTA, PORTA & (uint8_t)(~m_TRISA) & 0x0f, 0xff); break; } + else { m_TRISA = m_W | 0xf0; m_write_a(PIC16C5x_PORTA, PORTA & (uint8_t)(~m_TRISA) & 0x0f, (uint8_t)(~m_TRISA) & 0x0f); break; } case 6: if (m_TRISB == m_W) break; - else { m_TRISB = m_W; m_write_b(PIC16C5x_PORTB, PORTB & (uint8_t)(~m_TRISB), 0xff); break; } + else { m_TRISB = m_W; m_write_b(PIC16C5x_PORTB, PORTB & (uint8_t)(~m_TRISB), (uint8_t)(~m_TRISB)); break; } case 7: if ((m_picmodel == 0x16C55) || (m_picmodel == 0x16C57)) { if (m_TRISC == m_W) break; - else { m_TRISC = m_W; m_write_c(PIC16C5x_PORTC, PORTC & (uint8_t)(~m_TRISC), 0xff); break; } + else { m_TRISC = m_W; m_write_c(PIC16C5x_PORTC, PORTC & (uint8_t)(~m_TRISC), (uint8_t)(~m_TRISC)); break; } } else { illegal(); break; diff --git a/src/devices/machine/ds1207.cpp b/src/devices/machine/ds1207.cpp new file mode 100644 index 00000000000..50597ec113c --- /dev/null +++ b/src/devices/machine/ds1207.cpp @@ -0,0 +1,646 @@ +// license:BSD-3-Clause +// copyright-holders:Paul-Arnold +/* + * ds1207.c + * + * Time Key + * + * Based on ds1204 by smf. + * + * File format is as follows: + * 00-01 unique command pattern + * 02-09 identification pattern + * 0a-11 security match + * 12-41 secure memory data + * 42-43 days left + * 44-4b start time (from time_t) + * 4c control + * + * Control bits: + * bit 0 - OSC ENABLED + * bit 1 - OSC RUNNING + * bit 2 - DAYS LOCKED + * bit 3 - DAYS EXPIRED + * + * The unique command pattern can be user specific but a number of off the shelf devices exist. + * For these devices the pattern should be as follows: + * DS1207-G01 0x00 0xb0 + * DS1207-G02 0x04 0xb0 + * DS1207-G03 0x08 0xb0 + * DS1207-G04 0x0c 0xb0 + * DS1207-G05 0x10 0xb0 + */ +#include "emu.h" +#include "ds1207.h" + +#define LOG_LINES (1U << 1) +#define LOG_STATE (1U << 2) +#define LOG_DATA (1U << 3) + +//#define VERBOSE (LOG_LINES | LOG_STATE | LOG_DATA) +#include "logmacro.h" + +#define LOGLINES(...) LOGMASKED(LOG_LINES, __VA_ARGS__) +#define LOGSTATE(...) LOGMASKED(LOG_STATE, __VA_ARGS__) +#define LOGDATA(...) LOGMASKED(LOG_DATA, __VA_ARGS__) + +// device type definition +DEFINE_DEVICE_TYPE(DS1207, ds1207_device, "ds1207", "DS1207 Time Key") + +ds1207_device::ds1207_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, DS1207, tag, owner, clock), + device_nvram_interface(mconfig, *this), + device_rtc_interface(mconfig, *this), + m_region(*this, DEVICE_SELF), + m_rst(0), + m_clk(0), + m_dqw(0), m_dqr(0), m_state(0), m_bit(0) +{ +} + +void ds1207_device::device_reset() +{ + adjust_days_left(); // compensate for time machine has been turned off +} + +void ds1207_device::device_start() +{ + new_state(STATE_STOP); + m_dqr = DQ_HIGH_IMPEDANCE; + + std::fill_n(m_command, std::size(m_command), 0); + std::fill_n(m_compare_register, std::size(m_compare_register), 0); + m_last_update_time = 0; + m_startup_time = 0; + std::fill_n(m_day_clock, std::size(m_day_clock), 0); + + save_item(NAME(m_rst)); + save_item(NAME(m_clk)); + save_item(NAME(m_dqw)); + save_item(NAME(m_dqr)); + save_item(NAME(m_state)); + save_item(NAME(m_bit)); + save_item(NAME(m_command)); + save_item(NAME(m_compare_register)); + save_item(NAME(m_unique_pattern)); + save_item(NAME(m_identification)); + save_item(NAME(m_security_match)); + save_item(NAME(m_secure_memory)); + save_item(NAME(m_day_clock)); + save_item(NAME(m_days_left)); + save_item(NAME(m_start_time)); + save_item(NAME(m_device_state)); + save_item(NAME(m_startup_time)); + save_item(NAME(m_last_update_time)); +} + +void ds1207_device::nvram_default() +{ + std::fill_n(m_unique_pattern, std::size(m_unique_pattern), 0); + std::fill_n(m_identification, std::size(m_identification), 0); + std::fill_n(m_security_match, std::size(m_security_match), 0); + std::fill_n(m_secure_memory, std::size(m_secure_memory), 0); + std::fill_n(m_days_left, std::size(m_days_left), 0); + std::fill_n(m_start_time, std::size(m_start_time), 0); + m_device_state = 0; + + int expected_bytes = sizeof(m_unique_pattern) + sizeof(m_identification) + sizeof(m_security_match) + sizeof(m_secure_memory) + + sizeof(m_days_left) + sizeof(m_start_time) + sizeof(m_device_state);; + + if(!m_region.found()) + { + logerror("ds1207(%s) region not found\n", tag()); + } + else if(m_region->bytes() != expected_bytes) + { + logerror("ds1207(%s) region length 0x%x expected 0x%x\n", tag(), m_region->bytes(), expected_bytes); + } + else + { + uint8_t *region = m_region->base(); + + memcpy(m_unique_pattern, region, sizeof(m_unique_pattern)); + region += sizeof(m_unique_pattern); + memcpy(m_identification, region, sizeof(m_identification)); + region += sizeof(m_identification); + memcpy(m_security_match, region, sizeof(m_security_match)); + region += sizeof(m_security_match); + memcpy(m_secure_memory, region, sizeof(m_secure_memory)); + region += sizeof(m_secure_memory); + memcpy(m_days_left, region, sizeof(m_days_left)); + region += sizeof(m_days_left); + memcpy(m_start_time, region, sizeof(m_start_time)); + region += sizeof(m_start_time); + memcpy(&m_device_state, region, sizeof(m_device_state)); + region += sizeof(m_device_state); + } +} + +bool ds1207_device::nvram_read(util::read_stream &file) +{ + size_t actual; + bool result = !file.read(m_unique_pattern, sizeof(m_unique_pattern), actual) && actual == sizeof(m_unique_pattern); + result = result && !file.read(m_identification, sizeof(m_identification), actual) && actual == sizeof(m_identification); + result = result && !file.read(m_security_match, sizeof(m_security_match), actual) && actual == sizeof(m_security_match); + result = result && !file.read(m_secure_memory, sizeof(m_secure_memory), actual) && actual == sizeof(m_secure_memory); + result = result && !file.read(m_days_left, sizeof(m_days_left), actual) && actual == sizeof(m_days_left); + result = result && !file.read(m_start_time, sizeof(m_start_time), actual) && actual == sizeof(m_start_time); + result = result && !file.read(&m_device_state, sizeof(m_device_state), actual) && actual == sizeof(m_device_state); + return result; +} + +bool ds1207_device::nvram_write(util::write_stream &file) +{ + size_t actual; + bool result = !file.write(m_unique_pattern, sizeof(m_unique_pattern), actual) && actual == sizeof(m_unique_pattern); + result = result && !file.write(m_identification, sizeof(m_identification), actual) && actual == sizeof(m_identification); + result = result && !file.write(m_security_match, sizeof(m_security_match), actual) && actual == sizeof(m_security_match); + result = result && !file.write(m_secure_memory, sizeof(m_secure_memory), actual) && actual == sizeof(m_secure_memory); + result = result && !file.write(m_days_left, sizeof(m_days_left), actual) && actual == sizeof(m_days_left); + result = result && !file.write(m_start_time, sizeof(m_start_time), actual) && actual == sizeof(m_start_time); + result = result && !file.write(&m_device_state, sizeof(m_device_state), actual) && actual == sizeof(m_device_state); + return result; +} + +void ds1207_device::new_state(uint8_t state) +{ + m_state = state; + m_bit = 0; +} + +void ds1207_device::writebit(uint8_t *buffer) +{ + if(m_clk) + { + uint16_t index = m_bit / 8; + uint8_t mask = 1 << (m_bit % 8); + + if(m_dqw) + { + buffer[ index ] |= mask; + } + else + { + buffer[ index ] &= ~mask; + } + + m_bit++; + } +} + +void ds1207_device::readbit(uint8_t *buffer) +{ + if(!m_clk) + { + uint16_t index = m_bit / 8; + uint8_t mask = 1 << (m_bit % 8); + + if(buffer[ index ] & mask) + { + m_dqr = 1; + } + else + { + m_dqr = 0; + } + } + else + { + m_bit++; + } +} + +WRITE_LINE_MEMBER(ds1207_device::write_rst) +{ + const uint8_t this_state = state ? 1 : 0; + if(m_rst != this_state) + { + m_rst = this_state; + LOGLINES("%s: DS1270 rst=%d\n", machine().describe_context(), m_rst); + + if(m_rst) + { + new_state(STATE_PROTOCOL); + } + else + { + switch(m_state) + { + case STATE_WRITE_IDENTIFICATION: + LOGSTATE("%s: DS1270 reset during write identification (bit=%u)\n", machine().describe_context(), m_bit); + break; + + case STATE_WRITE_SECURITY_MATCH: + LOGSTATE("%s: DS1270 reset during write security match (bit=%u)\n", machine().describe_context(), m_bit); + break; + + case STATE_WRITE_SECURE_MEMORY: + LOGSTATE("%s: DS1270 reset during write secure memory (bit=%u)\n", machine().describe_context(), m_bit); + break; + } + + new_state(STATE_STOP); + m_dqr = DQ_HIGH_IMPEDANCE; + } + } +} + +WRITE_LINE_MEMBER(ds1207_device::write_clk) +{ + const uint8_t this_state = state ? 1 : 0; + if(m_clk != this_state) + { + m_clk = this_state; + LOGLINES("%s: DS1270 clk=%d (bit=%u)\n", machine().describe_context(), m_clk, m_bit); + + if(m_clk) + { + m_dqr = DQ_HIGH_IMPEDANCE; + } + + switch(m_state) + { + case STATE_PROTOCOL: + writebit(m_command); + + if(m_bit == 24) + { + LOGDATA("%s: DS1270 -> command %02x %02x %02x (%02x %02x)\n", machine().describe_context(), + m_command[ 0 ], m_command[ 1 ], m_command[ 2 ], m_unique_pattern[ 0 ], m_unique_pattern[ 1 ]); + + if(m_command[ 2 ] == m_unique_pattern[ 1 ] && (m_command[ 1 ] & ~3) == m_unique_pattern[ 0 ]) + { + set_start_time(); + adjust_time_into_day(); + + if(m_command[ 0 ] == COMMAND_READ && (m_command[ 1 ] & 3) == CYCLE_NORMAL) + { + new_state(STATE_READ_IDENTIFICATION); + } + else if(m_command[ 0 ] == COMMAND_READ_DAY_CLOCK && (m_command[ 1 ] & 3) == CYCLE_PROGRAM) + { + new_state(STATE_READ_DAY_CLOCK); + } + else if(m_command[ 0 ] == COMMAND_READ_DAYS_REMAINING && (m_command[ 1 ] & 3) == CYCLE_PROGRAM) + { + new_state(STATE_READ_DAYS_REMAINING); + } + else if(!(m_device_state & DAYS_EXPIRED)) + { + if(m_command[ 0 ] == COMMAND_WRITE && (m_command[ 1 ] & 3) == CYCLE_NORMAL) + { + new_state(STATE_READ_IDENTIFICATION); + } + else if((m_command[ 1 ] & 3) == CYCLE_PROGRAM) + { + if(m_command[ 0 ] == COMMAND_WRITE) + { + new_state(STATE_WRITE_IDENTIFICATION); + } + else if(m_command[ 0 ] == COMMAND_WRITE_DAYS_REMAINING) + { + if(!(m_device_state & DAYS_LOCKED)) + { + new_state(STATE_WRITE_DAYS_REMAINING); + } + else + { + new_state(STATE_STOP); + } + } + else if(m_command[ 0 ] == COMMAND_LOCK_DAYS_COUNT) + { + m_device_state |= DAYS_LOCKED; + + new_state(STATE_STOP); + } + else if(m_command[ 0 ] == COMMAND_STOP_OSCILLATOR) + { + if(!(m_device_state & DAYS_LOCKED)) + { + m_device_state &= ~(OSC_ENABLED | OSC_RUNNING); + } + + new_state(STATE_STOP); + } + else if(m_command[ 0 ] == COMMAND_ARM_OSCILLATOR) + { + m_device_state |= OSC_ENABLED; + } + else + { + new_state(STATE_STOP); + } + } + else + { + new_state(STATE_STOP); + } + } + else + { + new_state(STATE_STOP); + } + } + else + { + new_state(STATE_STOP); + } + } + break; + + case STATE_READ_IDENTIFICATION: + readbit(m_identification); + + if(m_bit == 64) + { + LOGDATA("%s: DS1270 <- identification %02x %02x %02x %02x %02x %02x %02x %02x\n", machine().describe_context(), + m_identification[ 0 ], m_identification[ 1 ], m_identification[ 2 ], m_identification[ 3 ], + m_identification[ 4 ], m_identification[ 5 ], m_identification[ 6 ], m_identification[ 7 ]); + + new_state(STATE_WRITE_COMPARE_REGISTER); + } + break; + + case STATE_WRITE_COMPARE_REGISTER: + writebit(m_compare_register); + + if(m_bit == 64) + { + LOGDATA("%s: DS1207 -> compare register %02x %02x %02x %02x %02x %02x %02x %02x (%02x %02x %02x %02x %02x %02x %02x %02x)\n", machine().describe_context(), + m_compare_register[ 0 ], m_compare_register[ 1 ], m_compare_register[ 2 ], m_compare_register[ 3 ], + m_compare_register[ 4 ], m_compare_register[ 5 ], m_compare_register[ 6 ], m_compare_register[ 7 ], + m_security_match[ 0 ], m_security_match[ 1 ], m_security_match[ 2 ], m_security_match[ 3 ], + m_security_match[ 4 ], m_security_match[ 5 ], m_security_match[ 6 ], m_security_match[ 7 ]); + + if(memcmp(m_compare_register, m_security_match, sizeof(m_compare_register)) == 0) + { + if(m_command[ 0 ] == COMMAND_READ) + { + new_state(STATE_READ_SECURE_MEMORY); + } + else + { + new_state(STATE_WRITE_SECURE_MEMORY); + } + } + else + { + new_state(STATE_OUTPUT_GARBLED_DATA); + } + } + break; + + case STATE_READ_SECURE_MEMORY: + readbit(m_secure_memory); + + if(m_bit == 384) + { + new_state(STATE_STOP); + } + break; + + case STATE_WRITE_SECURE_MEMORY: + writebit(m_secure_memory); + + if(m_bit == 384) + { + new_state(STATE_STOP); + } + break; + + case STATE_WRITE_IDENTIFICATION: + writebit(m_identification); + + if(m_bit == 64) + { + LOGDATA("%s: DS1207 -> identification %02x %02x %02x %02x %02x %02x %02x %02x\n", machine().describe_context(), + m_identification[ 0 ], m_identification[ 1 ], m_identification[ 2 ], m_identification[ 3 ], + m_identification[ 4 ], m_identification[ 5 ], m_identification[ 6 ], m_identification[ 7 ]); + + new_state(STATE_WRITE_SECURITY_MATCH); + } + break; + + case STATE_WRITE_SECURITY_MATCH: + writebit(m_security_match); + + if(m_bit == 64) + { + LOGDATA("%s: DS1207 >- security match %02x %02x %02x %02x %02x %02x %02x %02x\n", machine().describe_context(), + m_security_match[ 0 ], m_security_match[ 1 ], m_security_match[ 2 ], m_security_match[ 3 ], + m_security_match[ 4 ], m_security_match[ 5 ], m_security_match[ 6 ], m_security_match[ 7 ]); + + new_state(STATE_STOP); + } + break; + + case STATE_OUTPUT_GARBLED_DATA: + if(!m_clk && m_command[ 0 ] == COMMAND_READ) + { + m_dqr = machine().rand() & 1; + m_bit++; + } + else if(m_clk && m_command[ 0 ] == COMMAND_WRITE) + { + m_bit++; + } + + if(m_bit == 64) + { + if(m_command[ 0 ] == COMMAND_READ) + { + LOGDATA("%s: DS1207 <- random\n", machine().describe_context()); + } + else + { + LOGDATA("%s: DS1207 -> ignore\n", machine().describe_context()); + } + + new_state(STATE_STOP); + } + break; + + case STATE_READ_DAY_CLOCK: + readbit(m_day_clock); + + if(m_bit == 20) + { + new_state(STATE_STOP); + } + break; + + case STATE_READ_DAYS_REMAINING: + readbit(m_days_left); + + if(m_bit == 9) + { + new_state(STATE_STOP); + } + break; + + case STATE_WRITE_DAYS_REMAINING: + writebit(m_days_left); + + if(m_bit == 9) + { + new_state(STATE_STOP); + } + break; + } + } +} + +WRITE_LINE_MEMBER(ds1207_device::write_dq) +{ + const uint8_t this_state = state ? 1 : 0; + if(m_dqw != this_state) + { + m_dqw = this_state; + + LOGLINES("%s: DS1270 dqw=%u\n", machine().describe_context(), m_dqw); + } +} + +READ_LINE_MEMBER(ds1207_device::read_dq) +{ + if(m_dqr == DQ_HIGH_IMPEDANCE) + { + LOGLINES("%s: DS1270 dqr=high impedance\n", machine().describe_context()); + return 0; + } + + LOGLINES("%s: DS1270 dqr=%d (bit=%u)\n", machine().describe_context(), m_dqr, m_bit); + return m_dqr; +} + +void ds1207_device::adjust_time_into_day() +{ + if(!(m_device_state & DAYS_EXPIRED) && (m_device_state & OSC_ENABLED) && (m_device_state & OSC_RUNNING)) + { + uint64_t day_clock = ((uint64_t)m_day_clock[ 0 ]) | (((uint64_t)m_day_clock[ 1 ]) << 8) | (((uint64_t)m_day_clock[ 2 ]) << 16); + + const uint64_t cur_time = machine().time().as_ticks(32768) / 2700; + const uint64_t diff_time = cur_time - m_last_update_time; + m_last_update_time = cur_time; + + day_clock += diff_time; + + m_day_clock[ 0 ] = day_clock & 0xff; + m_day_clock[ 1 ] = (day_clock >> 8) & 0xff; + m_day_clock[ 2 ] = (day_clock >> 16) & 0xff; + + if(day_clock >= 1048576) + { + adjust_days_left(); + } + } +} + +void ds1207_device::adjust_days_left() +{ + if(!(m_device_state & DAYS_EXPIRED) && (m_device_state & OSC_ENABLED) && (m_device_state & OSC_RUNNING)) + { + const uint64_t current_time = m_startup_time + machine().time().as_ticks(1); + + uint64_t start_time = 0; + + for(int i = 0; i < 8 ; i++) + { + start_time <<= 8; + start_time |= m_start_time[ 7 - i ]; + } + + if(current_time > start_time) + { + uint64_t time_diff = current_time - start_time; + + const uint16_t days_elapsed = time_diff / (24*60*60); + + time_diff %= (24*60*60);// seconds into day + + const uint32_t day_clock = (time_diff * 32768)/2700;// time into day + + m_day_clock[ 0 ] = day_clock & 0xff; + m_day_clock[ 1 ] = (day_clock >> 8) & 0xff; + m_day_clock[ 2 ] = (day_clock >> 16) & 0xff; + + if(days_elapsed > 0) + { + uint16_t days_left = m_days_left[ 0 ] | (m_days_left[ 1 ] << 8); + + if(days_elapsed > days_left) + { + days_left = 0xffff; + m_device_state |= DAYS_EXPIRED; + } + else + { + days_left -= days_elapsed; + } + + m_days_left[ 0 ] = days_left & 0xff; + m_days_left[ 1 ] = (days_left >> 8) & 0x1; + + start_time += days_elapsed * 24 * 60 * 60; + + for(int i = 0; i < 8 ; i++) + { + m_start_time[ i ] = (start_time >> (i * 8)) & 0xff; + } + } + } + } +} + +void ds1207_device::set_start_time() +{ + if(!(m_device_state & DAYS_EXPIRED) && m_device_state & OSC_ENABLED && !(m_device_state & OSC_RUNNING)) + { + const uint64_t current_time = m_startup_time + machine().time().as_ticks(1); + + for(int i = 0; i < 8 ; i++) + { + m_start_time[ i ] = (current_time >> (i * 8)) & 0xff; + } + m_day_clock [ 0 ] = m_day_clock[ 1 ] = m_day_clock[ 2 ] = 0; + + m_device_state |= OSC_RUNNING; + } +} + +void ds1207_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) +{ + const int month_to_day_conversion[ 12 ] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + + // put the seconds + uint64_t m_startup_time = second; + + // put the minutes + m_startup_time += minute * 60; + + // put the hours + m_startup_time += hour * 60 * 60; + + // put the days (note -1) */ + m_startup_time += (day - 1) * 60 * 60 * 24; + + // take the months - despite popular beliefs, leap years aren't just evenly divisible by 4 */ + if(((((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0)) && month > 2) + { + m_startup_time += (month_to_day_conversion[ month - 1 ] + 1) * 60 * 60 * 24; + } + else + { + m_startup_time += (month_to_day_conversion[ month - 1 ]) * 60 * 60 * 24; + } + + // put the years + int year_count = (year - 1969); + + for(int i = 0; i < year_count - 1 ; i++) + { + m_startup_time += (((((i+1970) % 4) == 0) && (((i+1970) % 100) != 0)) || (((i+1970) % 400) == 0)) ? 60*60*24*366 : 60*60*24*365; + } +} + diff --git a/src/devices/machine/ds1207.h b/src/devices/machine/ds1207.h new file mode 100644 index 00000000000..d93af480b1b --- /dev/null +++ b/src/devices/machine/ds1207.h @@ -0,0 +1,122 @@ +// license:BSD-3-Clause +// copyright-holders:Paul-Arnold +/* + * ds1207.h + * + * Time Key + * + */ + +#ifndef MAME_MACHINE_DS1207_H +#define MAME_MACHINE_DS1207_H + +#pragma once + +#include "dirtc.h" + +class ds1207_device : public device_t, public device_nvram_interface, public device_rtc_interface +{ +public: + // construction/destruction + ds1207_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + + DECLARE_WRITE_LINE_MEMBER(write_rst); + DECLARE_WRITE_LINE_MEMBER(write_clk); + DECLARE_WRITE_LINE_MEMBER(write_dq); + DECLARE_READ_LINE_MEMBER(read_dq); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // device_nvram_interface overrides + virtual void nvram_default() override; + virtual bool nvram_read(util::read_stream &file) override; + virtual bool nvram_write(util::write_stream &file) override; + + // device_rtc_interface overrides + virtual bool rtc_feature_y2k() const override { return true; } + virtual bool rtc_feature_leap_year() const override { return true; } + virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) override; + +private: + void new_state(uint8_t state); + void writebit(uint8_t *buffer); + void readbit(uint8_t *buffer); + void set_start_time(); + void adjust_days_left(); + void adjust_time_into_day(); + + enum state_t + { + STATE_STOP, + STATE_PROTOCOL, + STATE_READ_IDENTIFICATION, + STATE_WRITE_IDENTIFICATION, + STATE_WRITE_COMPARE_REGISTER, + STATE_WRITE_SECURITY_MATCH, + STATE_READ_SECURE_MEMORY, + STATE_WRITE_SECURE_MEMORY, + STATE_OUTPUT_GARBLED_DATA, + STATE_READ_DAY_CLOCK, + STATE_READ_DAYS_REMAINING, + STATE_WRITE_DAYS_REMAINING + }; + + enum command_t + { + COMMAND_READ = 0x62, + COMMAND_WRITE = 0x9d, + COMMAND_READ_DAY_CLOCK = 0xf1, + COMMAND_WRITE_DAYS_REMAINING = 0xf2, + COMMAND_READ_DAYS_REMAINING = 0xf3, + COMMAND_STOP_OSCILLATOR = 0xf4, + COMMAND_ARM_OSCILLATOR = 0xf5, + COMMAND_LOCK_DAYS_COUNT = 0xf6 + }; + + enum cycle_t + { + CYCLE_NORMAL = 1, + CYCLE_PROGRAM = 2, + CYCLE_MASK = 3 + }; + + enum device_state_t + { + OSC_ENABLED = 1, + OSC_RUNNING = 2, + DAYS_LOCKED = 4, + DAYS_EXPIRED = 8 + }; + + static const int8_t DQ_HIGH_IMPEDANCE = -1; + + optional_memory_region m_region; + + uint8_t m_rst; + uint8_t m_clk; + uint8_t m_dqw; + int8_t m_dqr; + uint8_t m_state; + uint16_t m_bit; + uint64_t m_startup_time; + uint64_t m_last_update_time; + uint8_t m_command[3]; + uint8_t m_day_clock[3]; + uint8_t m_compare_register[8]; + uint8_t m_unique_pattern[2]; + uint8_t m_identification[8]; + uint8_t m_security_match[8]; + uint8_t m_secure_memory[48]; + uint8_t m_days_left[2]; + uint8_t m_start_time[8]; + uint8_t m_device_state; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(DS1207, ds1207_device) + +#endif // MAME_MACHINE_DS1207_H diff --git a/src/devices/machine/msm6242.cpp b/src/devices/machine/msm6242.cpp index c7beb22694a..187d70e6902 100644 --- a/src/devices/machine/msm6242.cpp +++ b/src/devices/machine/msm6242.cpp @@ -53,7 +53,6 @@ enum MSM6242_REG_CF }; -#define TIMER_RTC_CALLBACK 1 @@ -102,6 +101,8 @@ void msm6242_device::device_start() // let's call the timer callback every tick m_timer = timer_alloc(FUNC(msm6242_device::rtc_timer_callback), this); m_timer->adjust(attotime::zero); + m_timer_irq_clear = timer_alloc(FUNC(msm6242_device::rtc_irq_pulse_timer_callback), this); + m_timer_irq_clear->adjust(attotime::zero); // set up registers m_tick = 0; @@ -176,6 +177,14 @@ void msm6242_device::set_irq(bool active) if (!m_out_int_handler.isnull()) m_out_int_handler(active ? ASSERT_LINE : CLEAR_LINE); + + if (active) + { + if (!BIT(m_reg[1], 1)) // irq is pulsed + { + m_timer_irq_clear->adjust(attotime::from_nsec(7812500)); + } + } } @@ -262,7 +271,7 @@ void msm6242_device::update_rtc_registers() return; // ticks - if ((m_tick % 200) != int((delta + m_tick) % 0x200)) + if ((m_tick / 0x200) != int((delta + m_tick) / 0x200)) irq(IRQ_64THSECOND); delta = bump(RTC_TICKS, delta, 0, 0x8000); if (delta == 0) @@ -369,6 +378,17 @@ TIMER_CALLBACK_MEMBER(msm6242_device::rtc_timer_callback) +//------------------------------------------------- +// rtc_irq_pulse_timer_callback +//------------------------------------------------- + +TIMER_CALLBACK_MEMBER(msm6242_device::rtc_irq_pulse_timer_callback) +{ + set_irq(false); +} + + + //------------------------------------------------- // get_clock_nibble //------------------------------------------------- @@ -519,6 +539,7 @@ void msm6242_device::write(offs_t offset, u8 data) { LOGIRQENABLE("%s: MSM6242 acknowledging irq\n", machine().describe_context()); set_irq(false); + m_timer_irq_clear->adjust(attotime::zero); } m_reg[0] = (data & 0x09) | (m_reg[0] & 0x06); break; @@ -528,7 +549,7 @@ void msm6242_device::write(offs_t offset, u8 data) // --x- STD // ---x MASK m_reg[1] = data & 0x0f; - if((data & 3) == 0) // MASK & STD = 0 + if((data & 1) == 0) // MASK = 0 { m_irq_flag = 1; m_irq_type = (data & 0xc) >> 2; diff --git a/src/devices/machine/msm6242.h b/src/devices/machine/msm6242.h index 427a2337d24..216c66fc5b5 100644 --- a/src/devices/machine/msm6242.h +++ b/src/devices/machine/msm6242.h @@ -83,10 +83,12 @@ private: // incidentals devcb_write_line m_out_int_handler; emu_timer * m_timer; + emu_timer * m_timer_irq_clear; u64 m_last_update_time; // last update time, in clock cycles // methods TIMER_CALLBACK_MEMBER(rtc_timer_callback); + TIMER_CALLBACK_MEMBER(rtc_irq_pulse_timer_callback); u64 current_time(); void set_irq(bool active); void irq(u8 irq_type); diff --git a/src/devices/machine/scc66470.cpp b/src/devices/machine/scc66470.cpp new file mode 100644 index 00000000000..ca8a11e228c --- /dev/null +++ b/src/devices/machine/scc66470.cpp @@ -0,0 +1,901 @@ +// license:BSD-3-Clause +// copyright-holders:Paul Arnold +/*************************************************************************** + Philips SCC66470 Video and System controller. + + This does not render the image to the display. It is up to the user + to provide their own screen_update function. Pixel (palette offset) data + can be obtained by calling line( line number ) for each line. + Some boards have multiple video sources, the source being displayed being + selected based on pixel value...is there a nice way of doing this other + than leaving it to the board driver ? + + Todo: + Add support for mosaic and RLE screens. + Add remaining pixac operations. Only BCOLOUR1/BCOLOUR2 are supported. + Add interlaced support. + Add bep ? + Verify number of cycles for each access. +***************************************************************************/ + +#include "emu.h" +#include "scc66470.h" +#include "screen.h" + +#define CSR_REG (m_csr) +#define DCR_REG (m_dcr) +#define DCR2_REG (m_dcr2) + +#define DCR_DE 15 +#define DCR_CF1 14 +#define DCR_CF2 13 +#define DCR_FD 12 +#define DCR_SM 11 +#define DCR_SS 10 +#define DCR_LS 9 +#define DCR_CM 8 +#define DCR_FG 7 +#define DCR_DF 6 +#define DCR_IC 5 +#define DCR_DC 4 + +#define CSR_DI1 15 +#define CSR_DI2 14 +#define CSR_EW 10 +#define CSR_DD1 9 +#define CSR_DD2 8 +#define CSR_DM1 7 +#define CSR_DM2 6 +#define CSR_TD 5 +#define CSR_CG 4 +#define CSR_DD 3 +#define CSR_ED 2 +#define CSR_ST 1 +#define CSR_BE 0 + +#define DCR2_OM1 14 +#define DCR2_OM2 13 +#define DCR2_ID 12 +#define DCR2_MF1 11 +#define DCR2_MF2 10 +#define DCR2_FT1 9 +#define DCR2_FT2 8 + +#define CSR_R_DA 0x80 +#define CSR_R_PA 0x20 +#define CSR_R_IT2 0x04 +#define CSR_R_IT1 0x02 + +#define SCC_INS_STOP ( 0 << 12 ) +#define SCC_INS_NOP ( 1 << 12 ) +#define SCC_INS_LOAD_DCP ( 2 << 12 ) +#define SCC_INS_LOAD_DCP_STOP ( 3 << 12 ) +#define SCC_INS_LOAD_VSR ( 4 << 12 ) +#define SCC_INS_LOAD_VSR_STOP ( 5 << 12 ) +#define SCC_INS_INTERRUPT ( 6 << 12 ) +#define SCC_INS_LOAD_BORDER ( 14 << 11 ) +#define SCC_INS_LOAD_BORDER_DSP ( 15 << 11 ) +#define SCC_INS_BEP_CONTROL ( 1 << 15 ) + +#define PIXAC_4N 15 +#define PIXAC_COL 14 +#define PIXAC_EXC 13 +#define PIXAC_CPY 12 +#define PIXAC_CMP 11 +#define PIXAC_RTL 10 +#define PIXAC_SHK 9 +#define PIXAC_ZOM 8 +#define PIXAC_INV 3 +#define PIXAC_BIT 2 +#define PIXAC_TT 1 +#define PIXAC_NI 0 + +struct horizontal_settings +{ + uint32_t pixels; + uint32_t border; +}; + +static const horizontal_settings h_table[] = +{ + //cf1 cf2 ss st + { 512, 64 }, // 0 0 0 0 + { 512, 64 }, // 0 0 0 1 + { 512, 0 }, // 0 0 1 0 + { 512, 0 }, // 0 0 1 1 + + { 640, 128 }, // 0 1 0 0 + { 640, 128 }, // 0 1 0 1 + { 640, 0 }, // 0 1 1 0 + { 640, 0 }, // 0 1 1 1 + + { 720, 80 }, // 1 0 0 0 + { 720, 80 }, // 1 0 0 1 + + { 720, 0 }, // 1 0 1 0 + { 720, 0 }, // 1 0 1 1 + + { 768, 128 }, // 1 1 0 0 + { 720, 80 }, // 1 1 0 1 + + { 768, 0 }, // 1 1 1 0 + + { 768, 48 }, // 1 1 1 1 +}; + +// device type definition +DEFINE_DEVICE_TYPE(SCC66470, scc66470_device, "scc66470", "Philips SCC66470") + +//------------------------------------------------- +// scc66470_device - constructor +//------------------------------------------------- + +scc66470_device::scc66470_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, SCC66470, tag, owner, clock), + device_memory_interface(mconfig, *this), + device_video_interface(mconfig, *this), + m_irqcallback(*this), + m_space_config("videoram", ENDIANNESS_BIG, 16, 21, 0, address_map_constructor(FUNC(scc66470_device::scc66470_vram), this)) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void scc66470_device::device_start() +{ + m_irqcallback.resolve_safe(); + + m_ica_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(scc66470_device::process_ica), this)); + + m_dca_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(scc66470_device::process_dca), this)); + + save_item(NAME(m_csr)); + save_item(NAME(m_dcr)); + save_item(NAME(m_vsr)); + save_item(NAME(m_bcr)); + save_item(NAME(m_dcr2)); + save_item(NAME(m_dcp)); + save_item(NAME(m_swm)); + save_item(NAME(m_stm)); + save_item(NAME(m_reg_a)); + save_item(NAME(m_reg_b)); + save_item(NAME(m_pcr)); + save_item(NAME(m_mask)); + save_item(NAME(m_shift)); + save_item(NAME(m_index)); + save_item(NAME(m_fc)); + save_item(NAME(m_bc)); + save_item(NAME(m_tc)); + save_item(NAME(m_csr_r)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void scc66470_device::device_reset() +{ + m_working_dcp = 0; + + m_csr = 0; + m_dcr = 0; + m_vsr = 0; + m_bcr = 0; + m_dcr2 = 0; + m_dcp = 0; + m_swm = 0; + m_stm = 0; + m_reg_a = 0; + m_reg_b = 0; + m_pcr = 0; + m_mask = 0; + m_shift = 0; + m_index = 0; + m_fc = 0; + m_bc = 0; + m_tc = 0; + m_csr_r = 0; + + m_ica_timer->adjust(screen().time_until_pos(0, 0)); + m_dca_timer->adjust(screen().time_until_pos(32, 784)); +} + +// default address map +void scc66470_device::scc66470_vram(address_map &map) +{ + if(!has_configured_map(0)) + { + map(0x00000000, 0x0017ffff).ram(); + } +} + +device_memory_interface::space_config_vector scc66470_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(0, &m_space_config) + }; +} + + +void scc66470_device::set_vectors(uint16_t *src) +{ + for(int i = 0 ; i < 4 ; i++) + { + dram_w(i, *src++, 0xffff); + } +} + + +void scc66470_device::dram_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + space().write_word(offset<<1, data, mem_mask); +} + +uint16_t scc66470_device::dram_r(offs_t offset, uint16_t mem_mask) +{ + return space().read_word(offset<<1, mem_mask); +} + +inline uint8_t scc66470_device::dram_byte_r(offs_t offset) +{ + return space().read_byte(offset); +} + +void scc66470_device::csr_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&m_csr); +} + +void scc66470_device::dcr_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&m_dcr); +} + +void scc66470_device::vsr_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&m_vsr); +} + +void scc66470_device::bcr_w(offs_t offset, uint8_t data) +{ + m_bcr = data; +} + +void scc66470_device::dcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&m_dcr2); +} + +void scc66470_device::dcp_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&m_dcp); +} + +void scc66470_device::swm_w(offs_t offset, uint8_t data) +{ + m_swm = data | data << 8; +} + +void scc66470_device::stm_w(offs_t offset, uint8_t data) +{ + m_stm = data; +} + +void scc66470_device::reg_a_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&m_reg_a); +} + +void scc66470_device::reg_b_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&m_reg_b); + perform_pixac_op(); +} + +void scc66470_device::pcr_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&m_pcr); + + if(!BIT(m_pcr, PIXAC_COL) || !BIT(m_pcr, PIXAC_4N) || !BIT(m_pcr, PIXAC_BIT)) + { + logerror("unsuppported pixac %x\n", m_pcr); + } +} + +void scc66470_device::mask_w(offs_t offset, uint8_t data) +{ + m_mask = data; +} + +void scc66470_device::shift_w(offs_t offset, uint8_t data) +{ + m_shift = data; +} + +void scc66470_device::index_w(offs_t offset, uint8_t data) +{ + m_index = data; +} + +void scc66470_device::fc_w(offs_t offset, uint8_t data) +{ + m_fc = data; +} + +void scc66470_device::bc_w(offs_t offset, uint8_t data) +{ + m_bc = data; +} + +void scc66470_device::tc_w(offs_t offset, uint8_t data) +{ + m_tc = data; +} + +uint8_t scc66470_device::csr_r(offs_t offset) +{ + uint8_t val = m_csr_r; + + if(!machine().side_effects_disabled()) + { + m_csr_r &= ~(CSR_R_IT1 | CSR_R_IT2); + + if(!m_irqcallback.isnull()) + { + m_irqcallback(CLEAR_LINE); + } + } + + int scanline = screen().vpos(); + + if(scanline >= total_height() - height()) + { + val |= CSR_R_DA; + } + + return val; +} + +uint16_t scc66470_device::reg_b_r(offs_t offset, uint16_t mem_mask) +{ + return m_reg_b & mem_mask; +} + +int scc66470_device::dram_dtack_cycles() +{ + const int slot_cycle = (int)(machine().time().as_ticks(clock()) & 0xf); + + if(slot_cycle == 9) + { + return 2; + } + else if(slot_cycle < 9) + { + return 2 + 9 - slot_cycle; + } + else + { + return 2 + 9 + 16 - slot_cycle; + } +} + +void scc66470_device::map(address_map &map) +{ + map(0x000000, 0x17ffff).rw(FUNC(scc66470_device::dram_r), FUNC(scc66470_device::dram_w)); + map(0x1fffe0, 0x1fffe1).w(FUNC(scc66470_device::csr_w)); + map(0x1fffe1, 0x1fffe1).r(FUNC(scc66470_device::csr_r)); + map(0x1fffe2, 0x1fffe3).w(FUNC(scc66470_device::dcr_w)); + map(0x1fffe4, 0x1fffe5).w(FUNC(scc66470_device::vsr_w)); + map(0x1fffe7, 0x1fffe7).w(FUNC(scc66470_device::bcr_w)); + map(0x1fffe8, 0x1fffe9).w(FUNC(scc66470_device::dcr2_w)); + map(0x1fffea, 0x1fffeb).w(FUNC(scc66470_device::dcp_w)); + map(0x1fffec, 0x1fffec).w(FUNC(scc66470_device::swm_w)); + map(0x1fffef, 0x1fffef).w(FUNC(scc66470_device::stm_w)); + map(0x1ffff0, 0x1ffff1).w(FUNC(scc66470_device::reg_a_w)); + map(0x1ffff2, 0x1ffff3).rw(FUNC(scc66470_device::reg_b_r), FUNC(scc66470_device::reg_b_w)); + map(0x1ffff4, 0x1ffff5).w(FUNC(scc66470_device::pcr_w)); + map(0x1ffff7, 0x1ffff7).w(FUNC(scc66470_device::mask_w)); + map(0x1ffff8, 0x1ffff8).w(FUNC(scc66470_device::shift_w)); + map(0x1ffffb, 0x1ffffb).w(FUNC(scc66470_device::index_w)); + map(0x1ffffc, 0x1ffffc).w(FUNC(scc66470_device::fc_w)); + map(0x1ffffd, 0x1ffffd).w(FUNC(scc66470_device::bc_w)); + map(0x1ffffe, 0x1ffffe).w(FUNC(scc66470_device::tc_w)); +} + +int scc66470_device::pixac_trigger() +{ + if(BIT(m_pcr, PIXAC_COL)) + { + return 1; + } + else if(BIT(m_pcr, PIXAC_CPY) && !BIT(m_pcr, PIXAC_TT)) + { + return 1; + } + else + { + return 0; + } +} + +void scc66470_device::perform_pixac_op() +{ + if(BIT(m_pcr, PIXAC_COL) && BIT(m_pcr, PIXAC_BIT)) + { + if(BIT(m_pcr, PIXAC_4N)) + { + uint16_t result = m_reg_b; + m_index &= 0xf; + + if(BIT(m_reg_a, 15 - m_index)) + { + result = (result & 0xff) | m_fc << 8; + } + else if(!BIT(m_pcr, PIXAC_TT)) + { + result = (result & 0xff) | m_bc << 8; + } + + m_index++; + + m_index &= 0xf; + + if(BIT(m_reg_a, 15 - m_index)) + { + result = (result & 0xff00) | m_fc; + } + else if(!BIT(m_pcr, PIXAC_TT)) + { + result = (result & 0xff00) | m_bc; + } + + m_index++; + + m_reg_b = (m_reg_b & ~m_swm) | (result & m_swm); + } + } +} + + +uint16_t scc66470_device::ipa_r(offs_t offset, uint16_t mem_mask) +{ + if(offset < 0x180000 / 2) + { + if(pixac_trigger()) + { + reg_b_w(0, dram_r(offset, 0xffff), 0xffff); + } + } + + return 0; +} + +void scc66470_device::ipa_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if(offset < 0x180000 / 2) + { + if(pixac_trigger()) + { + dram_w(offset, m_reg_b, 0xffff); + } + } +} + +bool scc66470_device::display_enabled() +{ + if(BIT(DCR_REG, DCR_DE)) + { + return true; + } + else + { + return false; + } +} + +void scc66470_device::set_vsr(uint32_t vsr) +{ + m_dcr = (m_dcr & 0xfff0) | ((vsr >> 16) & 0x0f); + m_vsr = vsr; +} + +uint32_t scc66470_device::get_vsr() +{ + return ((m_dcr & 0xf) << 16) | m_vsr; +} + +uint32_t scc66470_device::get_dcp() +{ + return ((m_dcr2 & 0x0f) << 16) | m_dcp; +} + +void scc66470_device::set_dcp(uint32_t dcp) +{ + m_dcr2 = (m_dcr2 & 0xfff0) | (dcp & 0x0f); + m_dcp = dcp; +} + +void scc66470_device::line(int line, uint8_t *line_buffer, unsigned line_buffer_size) +{ + if(line_buffer_size == width()) + { + if(display_enabled() && line >= (total_height() - height())) + { + uint8_t bc = m_bcr; + + if(BIT(DCR_REG, DCR_CM)) //4 bits/pixel + { + bc = bc >> 4; + } + + line -= total_height() - height(); + + if(line < border_height() || line >= (height() - border_height())) + { + std::fill_n(line_buffer, width(), bc); + + if(line == height() - 1) + { + set_vsr(0); + } + } + else + { + unsigned vsr = get_vsr() & 0xfffff; + + if(vsr) + { + line_buffer = std::fill_n(line_buffer, border_width(), bc); + + if(BIT(DCR_REG, DCR_CM)) //4 bits/pixel + { + if(!BIT(DCR2_REG, DCR2_FT1)) + { + for(int i = 0 ; i < width() - (border_width() * 2) ; i += 2) + { + uint8_t pixels = dram_byte_r(vsr++); + *line_buffer++ = (pixels >> 4) & 0x0f; + *line_buffer++ = (pixels) & 0x0f; + vsr &= 0xfffff; + } + } + } + else + { + if(!BIT(DCR2_REG, DCR2_FT1)) + { + for(int i = 0 ; i < width() - (border_width() * 2) ; i += 2) + { + const uint8_t pixel = dram_byte_r(vsr++); + *line_buffer++ = pixel; + *line_buffer++ = pixel; + vsr &= 0xfffff; + } + } + } + + std::fill_n(line_buffer, border_width(), bc); + + if(BIT(DCR_REG, DCR_LS)) + { + vsr = get_vsr() + 512; + + if(BIT(DCR_REG, DCR_IC)) + { + m_working_dcp = vsr - 64; + } + else + { + m_working_dcp = vsr - 16; + } + } + else + { + if(!BIT(DCR2_REG, DCR2_ID)) + { + if(BIT(DCR_REG, DCR_DC)) + { + m_working_dcp = vsr; + + if(BIT(DCR_REG, DCR_IC)) + { + vsr += 64; + } + else + { + vsr += 16; + } + } + } + } + + set_vsr(vsr); + } + else + { + std::fill_n(line_buffer, line_buffer_size, 0); + } + } + } + else + { + std::fill_n(line_buffer, line_buffer_size, 0); + } + } + else + { + std::fill_n(line_buffer, line_buffer_size, 0); + } +} + +TIMER_CALLBACK_MEMBER(scc66470_device::process_ica) +{ + uint32_t ctrl = 0x400 / 2; + + if((BIT(DCR_REG, DCR_IC) || BIT(DCR_REG, DCR_DC)) && dram_r(ctrl, 0xffff) != 0) + { + bool stop = false; + while(!stop) + { + uint16_t cmd = dram_r(ctrl++, 0xffff); + uint16_t data = dram_r(ctrl++, 0xffff); + + ctrl &= 0xffffe; + + switch(cmd & 0xff00) + { + case SCC_INS_STOP: + set_vsr((ctrl - 2) * 2); + stop = true; + break; + + case SCC_INS_NOP: + break; + + case SCC_INS_LOAD_DCP: + set_dcp(((cmd & 0xf) << 16) | (data & 0xfc)); + break; + + case SCC_INS_LOAD_DCP_STOP: + set_dcp(((cmd & 0xf) << 16) | (data & 0xfc)); + stop = true; + break; + + case SCC_INS_LOAD_VSR: + ctrl = (((cmd & 0xf) << 16) | data) / 2; + ctrl &= 0xffffe; + break; + + case SCC_INS_LOAD_VSR_STOP: + ctrl = ((cmd & 0xf) << 16) | data; + ctrl &= 0xffffe; + set_vsr(ctrl); + stop = true; + break; + + case SCC_INS_INTERRUPT: + m_csr_r |= CSR_R_IT1; + + if(!BIT(CSR_REG, CSR_DI1)) + { + if(!m_irqcallback.isnull()) + { + m_irqcallback(ASSERT_LINE); + } + } + + break; + + default: + if((cmd & 0xf800) == SCC_INS_LOAD_BORDER) + { + m_bcr = cmd & 0xff; + } + else if((cmd & 0xf800) == SCC_INS_LOAD_BORDER_DSP) + { + m_bcr = cmd & 0xff; + m_dcr2 = (m_dcr2 & 0x90ff) | (data & 0x6f) << 8; + m_dcr = (m_dcr & 0xfaff) | (data & 0x0500); + } + else if(cmd & SCC_INS_BEP_CONTROL) + { + //need to implement ? + } + else + { + logerror("Unknown ica/dca instruction %x %x %x\n",cmd,data,ctrl); + } + } + } + } + + m_working_dcp = 0; + + if(BIT(DCR_REG, DCR_DC) && BIT(DCR2_REG, DCR2_ID)) + { + m_working_dcp = get_dcp(); + } + + m_ica_timer->adjust(screen().time_until_pos(0, 0)); +} + +TIMER_CALLBACK_MEMBER(scc66470_device::process_dca) +{ + uint32_t ctrl = (m_working_dcp / 2) & 0xffffe; + + if(BIT(DCR_REG, DCR_DC) && ctrl) + { + bool stop = false; + bool new_dcp = false; + uint32_t count; + + if(!BIT(DCR_REG, DCR_IC)) + { + count = 16; + } + else + { + count = 64; + } + + while(!stop && count) + { + uint16_t cmd = dram_r(ctrl++, 0xffff); + uint16_t data = dram_r(ctrl++, 0xffff); + + ctrl &= 0xffffe; + + count -= 4; + + switch(cmd & 0xff00) + { + case SCC_INS_STOP: + stop = true; + break; + + case SCC_INS_NOP: + break; + + case SCC_INS_LOAD_DCP: + m_working_dcp = ((cmd & 0xf) << 16) | (data & 0xfc); + set_dcp(m_working_dcp); + ctrl = m_working_dcp / 2; + ctrl &= 0xffffe; + break; + + case SCC_INS_LOAD_DCP_STOP: + m_working_dcp = ((cmd & 0xf) << 16) | (data & 0xfc); + set_dcp(m_working_dcp); + stop = true; + new_dcp = true; + break; + + case SCC_INS_LOAD_VSR: + set_vsr(((cmd & 0xf) << 16) | data); + break; + + case SCC_INS_LOAD_VSR_STOP: + set_vsr(((cmd & 0xf) << 16) | data); + stop = true; + break; + + case SCC_INS_INTERRUPT: + m_csr_r |= CSR_R_IT1; + + if(!BIT(CSR_REG, CSR_DI1)) + { + if(!m_irqcallback.isnull()) + { + m_irqcallback(ASSERT_LINE); + } + } + + break; + + default: + if((cmd & 0xf800) == SCC_INS_LOAD_BORDER) + { + m_bcr = cmd & 0xff; + } + else if((cmd & 0xf800) == SCC_INS_LOAD_BORDER_DSP) + { + m_bcr = cmd & 0xff; + m_dcr2 = (m_dcr2 & 0x90ff) | (data & 0x6f) << 8; + m_dcr = (m_dcr & 0xfaff) | (data & 0x0500); + } + else if(cmd & SCC_INS_BEP_CONTROL) + { + //need to implement ? + } + else + { + logerror("Unknown ica instruction %x %x %x\n",cmd,data,ctrl); + } + } + } + + ctrl *= 2; + + if(!new_dcp) + { + ctrl += count; + } + + if(BIT(DCR_REG, DCR_DC) && BIT(DCR2_REG, DCR2_ID)) + { + m_working_dcp = ctrl; + } + else + { + m_working_dcp = 0; + } + } + + int scanline = screen().vpos(); + + if(scanline == total_height() - border_height() - 1) + { + m_csr_r ^= CSR_R_PA; + + m_dca_timer->adjust(screen().time_until_pos(total_height() - height() + border_height(), 784)); + } + else + { + m_dca_timer->adjust(screen().time_until_pos(scanline + 1, 784)); + } +} + +unsigned scc66470_device::border_width() +{ + const unsigned hoffset = (BIT(DCR_REG, DCR_CF1) << 3) | (BIT(DCR_REG, DCR_CF2) << 2) | (BIT(DCR_REG, DCR_SS) << 1) | BIT(CSR_REG, CSR_ST); + return h_table[ hoffset ].border / 2; +} + +int scc66470_device::border_height() +{ + int height = 0; + + if(!BIT(DCR_REG, DCR_FD) && BIT(CSR_REG, CSR_ST)) + { + height = 20; + } + + if(!BIT(DCR_REG, DCR_SS)) + { + height += 15; + } + + return height; +} + +unsigned scc66470_device::width() +{ + const unsigned hoffset = (BIT(DCR_REG, DCR_CF1) << 3) | (BIT(DCR_REG, DCR_CF2) << 2) | (BIT(DCR_REG, DCR_SS) << 1) | BIT(CSR_REG, CSR_ST); + return h_table[ hoffset ].pixels; +} + +unsigned scc66470_device::height() +{ + if(BIT(DCR_REG, DCR_FD)) + { + return 240; + } + else + { + return 280; + } +} + +unsigned scc66470_device::total_height() +{ + if(BIT(DCR_REG, DCR_FD)) + { + return 262; + } + else + { + return 312; + } +} diff --git a/src/devices/machine/scc66470.h b/src/devices/machine/scc66470.h new file mode 100644 index 00000000000..d5a5700b304 --- /dev/null +++ b/src/devices/machine/scc66470.h @@ -0,0 +1,115 @@ +// license:BSD-3-Clause +// copyright-holders:Paul Arnold +/*************************************************************************** + + scc66470.h + +***************************************************************************/ + +#ifndef MAME_VIDEO_SCC66470_H +#define MAME_VIDEO_SCC66470_H + +#pragma once + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + + +// ======================> scc66470_device + +class scc66470_device : public device_t, public device_memory_interface, public device_video_interface +{ +public: + auto irq() + { + return m_irqcallback.bind(); + } + + // construction/destruction + scc66470_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + uint16_t ipa_r(offs_t offset, uint16_t mem_mask = ~0); + void ipa_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + bool display_enabled(); + void line(int line, uint8_t *line_buffer, unsigned line_buffer_size); + unsigned width(); + unsigned height(); + unsigned total_height(); + int dram_dtack_cycles(); + void dram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t dram_r(offs_t offset, uint16_t mem_mask = ~0); + void map(address_map &map); + void set_vectors(uint16_t *src); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + virtual space_config_vector memory_space_config() const override; + + devcb_write_line m_irqcallback; + + uint32_t m_working_dcp; + + uint16_t m_csr; + uint16_t m_dcr; + uint16_t m_vsr; + uint8_t m_bcr; + uint16_t m_dcr2; + uint16_t m_dcp; + uint16_t m_swm; + uint8_t m_stm; + uint16_t m_reg_a; + uint16_t m_reg_b; + uint16_t m_pcr; + uint8_t m_mask; + uint8_t m_shift; + uint8_t m_index; + uint8_t m_fc; + uint8_t m_bc; + uint8_t m_tc; + uint8_t m_csr_r; + +private: + void scc66470_vram(address_map &map); + void set_vsr(uint32_t vsr); + void set_dcp(uint32_t dcp); + uint32_t get_vsr(); + uint32_t get_dcp(); + unsigned border_width(); + int border_height(); + void csr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + void dcr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + void vsr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + void bcr_w(offs_t offset, uint8_t data); + void dcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + void dcp_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + void swm_w(offs_t offset, uint8_t data); + void stm_w(offs_t offset, uint8_t data); + void reg_a_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + void reg_b_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + void pcr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + void mask_w(offs_t offset, uint8_t data); + void shift_w(offs_t offset, uint8_t data); + void index_w(offs_t offset, uint8_t data); + void fc_w(offs_t offset, uint8_t data); + void bc_w(offs_t offset, uint8_t data); + void tc_w(offs_t offset, uint8_t data); + uint8_t csr_r(offs_t offset); + uint16_t reg_b_r(offs_t offset, uint16_t mem_mask = ~0); + int pixac_trigger(); + void perform_pixac_op(); + inline uint8_t dram_byte_r(offs_t offset); + + TIMER_CALLBACK_MEMBER(process_ica); + TIMER_CALLBACK_MEMBER(process_dca); + emu_timer *m_ica_timer; + emu_timer *m_dca_timer; + + const address_space_config m_space_config; +}; + +// device type definition +DECLARE_DEVICE_TYPE(SCC66470, scc66470_device) + +#endif // MAME_VIDEO_SCC66470_H diff --git a/src/devices/machine/scc68070.cpp b/src/devices/machine/scc68070.cpp index 63c7dc01dce..e7bfaceeb72 100644 --- a/src/devices/machine/scc68070.cpp +++ b/src/devices/machine/scc68070.cpp @@ -13,11 +13,12 @@ STATUS: -- Skeleton. Just enough for the CD-i to run. +- Skeleton. Just enough for the CD-i and Magicard to run. TODO: - Proper handling of the 68070's internal devices (UART, DMA, Timers, etc.) +- I2C could do with re-visiting. *******************************************************************************/ @@ -41,6 +42,165 @@ TODO: #define ENABLE_UART_PRINTING (0) +//************************************************************************** +// Register defines +//************************************************************************** +enum isr_bits +{ + ISR_MST = 0x80, // Master + ISR_TRX = 0x40, // Transmitter + ISR_BB = 0x20, // Busy + ISR_PIN = 0x10, // No Pending Interrupt + ISR_AL = 0x08, // Arbitration Lost + ISR_AAS = 0x04, // Addressed As Slave + ISR_AD0 = 0x02, // Address Zero + ISR_LRB = 0x01, // Last Received Bit + ISR_SSR_MASK = (ISR_MST | ISR_TRX | ISR_BB),// Mask for detecting start/stop/restart + ISR_START = (ISR_MST | ISR_TRX | ISR_BB),// Start bit request + ISR_STOP = (ISR_MST | ISR_TRX) // Stop bit request +}; + +enum umr_bits +{ + UMR_OM = 0xc0, + UMR_OM_NORMAL = 0x00, + UMR_OM_ECHO = 0x40, + UMR_OM_LOOPBACK = 0x80, + UMR_OM_RLOOP = 0xc0, + UMR_TXC = 0x10, + UMR_PC = 0x08, + UMR_P = 0x04, + UMR_SB = 0x02, + UMR_CL = 0x01 +}; + +enum usr_bits +{ + USR_RB = 0x80, + USR_FE = 0x40, + USR_PE = 0x20, + USR_OE = 0x10, + USR_TXEMT = 0x08, + USR_TXRDY = 0x04, + USR_RXRDY = 0x01 +}; + +enum tsr_bits +{ + TSR_OV0 = 0x80, + TSR_MA1 = 0x40, + TSR_CAP1 = 0x20, + TSR_OV1 = 0x10, + TSR_MA2 = 0x08, + TSR_CAP2 = 0x04, + TSR_OV2 = 0x02 +}; + +enum tcr_bits +{ + TCR_E1 = 0xc0, + TCR_E1_NONE = 0x00, + TCR_E1_RISING = 0x40, + TCR_E1_FALLING = 0x80, + TCR_E1_BOTH = 0xc0, + TCR_M1 = 0x30, + TCR_M1_NONE = 0x00, + TCR_M1_MATCH = 0x10, + TCR_M1_CAPTURE = 0x20, + TCR_M1_COUNT = 0x30, + TCR_E2 = 0x0c, + TCR_E2_NONE = 0x00, + TCR_E2_RISING = 0x04, + TCR_E2_FALLING = 0x08, + TCR_E2_BOTH = 0x0c, + TCR_M2 = 0x03, + TCR_M2_NONE = 0x00, + TCR_M2_MATCH = 0x01, + TCR_M2_CAPTURE = 0x02, + TCR_M2_COUNT = 0x03 +}; + +enum csr_bits +{ + CSR_COC = 0x80, + CSR_NDT = 0x20, + CSR_ERR = 0x10, + CSR_CA = 0x08 +}; + +enum cer_bits +{ + CER_EC = 0x1f, + CER_NONE = 0x00, + CER_TIMING = 0x02, + CER_BUSERR_MEM = 0x09, + CER_BUSERR_DEV = 0x0a, + CER_SOFT_ABORT = 0x11 +}; + +enum dcr1_bits +{ + DCR1_ERM = 0x80, + DCR1_DT = 0x30 +}; + +enum dcr2_bits +{ + DCR2_ERM = 0x80, + DCR2_DT = 0x30, + DCR2_DS = 0x08 +}; + + +enum scr2_bits +{ + SCR2_MAC = 0x0c, + SCR2_MAC_NONE = 0x00, + SCR2_MAC_INC = 0x04, + SCR2_DAC = 0x03, + SCR2_DAC_NONE = 0x00, + SCR2_DAC_INC = 0x01 +}; + +enum ccr_bits +{ + CCR_SO = 0x80, + CCR_SA = 0x10, + CCR_INE = 0x08, + CCR_IPL = 0x07 +}; + +enum icr_bits +{ + ICR_SEL = 0x40, + ICR_ESO = 0x08, + ICR_ACK = 0x04 +}; + +enum i2c_states +{ + I2C_IDLE = 0, + I2C_TX_IN_PROGRESS, + I2C_RX_IN_PROGRESS, + I2C_RX_COMPLETE, + I2C_GET_ACK, + I2C_SEND_ACK, + I2C_SEND_ACK_AND_RX, + I2C_SEND_ACK_AND_STOP, + I2C_SEND_STOP, + I2C_CHANGED_TO_RX, + I2C_SEND_RESTART +}; + +enum i2c_clock_states +{ + I2C_SCL_IDLE = 0, + I2C_SCL_SET_0, + I2C_SCL_SET_1, + I2C_SCL_WAIT_1, +}; + + // device type definition DEFINE_DEVICE_TYPE(SCC68070, scc68070_device, "scc68070", "Philips SCC68070") @@ -86,6 +246,9 @@ scc68070_device::scc68070_device(const machine_config &mconfig, const char *tag, , m_iack7_callback(*this) , m_uart_tx_callback(*this) , m_uart_rtsn_callback(*this) + , m_i2c_scl_callback(*this) + , m_i2c_sdaw_callback(*this) + , m_i2c_sdar_callback(*this) , m_ipl(0) , m_in2_line(CLEAR_LINE) , m_in4_line(CLEAR_LINE) @@ -113,6 +276,9 @@ void scc68070_device::device_resolve_objects() m_iack7_callback.resolve_safe(autovector(7)); m_uart_tx_callback.resolve_safe(); m_uart_rtsn_callback.resolve_safe(); + m_i2c_scl_callback.resolve_safe(); + m_i2c_sdaw_callback.resolve_safe(); + m_i2c_sdar_callback.resolve_safe(0); } //------------------------------------------------- @@ -146,6 +312,16 @@ void scc68070_device::device_start() save_item(NAME(m_i2c.status_register)); save_item(NAME(m_i2c.control_register)); save_item(NAME(m_i2c.clock_control_register)); + save_item(NAME(m_i2c.scl_out_state)); + save_item(NAME(m_i2c.scl_in_state)); + save_item(NAME(m_i2c.sda_out_state)); + save_item(NAME(m_i2c.sda_in_state)); + save_item(NAME(m_i2c.state)); + save_item(NAME(m_i2c.counter)); + save_item(NAME(m_i2c.clock_change_state)); + save_item(NAME(m_i2c.clocks)); + save_item(NAME(m_i2c.first_byte)); + save_item(NAME(m_i2c.ack_or_nak_sent)); save_item(NAME(m_uart.mode_register)); save_item(NAME(m_uart.status_register)); @@ -191,6 +367,9 @@ void scc68070_device::device_start() m_uart.tx_timer = timer_alloc(FUNC(scc68070_device::tx_callback), this); m_uart.tx_timer->adjust(attotime::never); + + m_i2c.timer = timer_alloc(FUNC(scc68070_device::i2c_callback), this); + m_i2c.timer->adjust(attotime::never); } //------------------------------------------------- @@ -212,9 +391,15 @@ void scc68070_device::device_reset() m_i2c.data_register = 0; m_i2c.address_register = 0; - m_i2c.status_register = 0; + m_i2c.status_register = ISR_PIN; m_i2c.control_register = 0; m_i2c.clock_control_register = 0; + m_i2c.scl_out_state = true; + m_i2c.scl_in_state = true; + m_i2c.sda_out_state = true; + m_i2c.state = I2C_IDLE; + m_i2c.clock_change_state = I2C_SCL_IDLE; + m_i2c.clocks = 0; m_uart.mode_register = 0; m_uart.status_register = USR_TXRDY; @@ -260,7 +445,7 @@ void scc68070_device::device_reset() m_uart.rx_timer->adjust(attotime::never); m_uart.tx_timer->adjust(attotime::never); - m_timers.timer0_timer->adjust(attotime::never); + set_timer_callback(0); } void scc68070_device::m68k_reset_peripherals() @@ -274,9 +459,15 @@ void scc68070_device::m68k_reset_peripherals() m_uart_rx_int = false; m_uart_tx_int = false; - m_i2c.status_register = 0; + m_i2c.status_register = ISR_PIN; m_i2c.control_register = 0; m_i2c.clock_control_register = 0; + m_i2c.scl_out_state = true; + m_i2c.scl_in_state = true; + m_i2c.sda_out_state = true; + m_i2c.state = I2C_IDLE; + m_i2c.clock_change_state = I2C_SCL_IDLE; + m_i2c.clocks = 0; m_uart.command_register = 0; m_uart.receive_pointer = -1; m_uart.transmit_pointer = -1; @@ -291,6 +482,7 @@ void scc68070_device::m68k_reset_peripherals() m_uart.rx_timer->adjust(attotime::never); m_uart.tx_timer->adjust(attotime::never); m_timers.timer0_timer->adjust(attotime::never); + m_i2c.timer->adjust(attotime::never); update_ipl(); } @@ -370,7 +562,7 @@ WRITE_LINE_MEMBER(scc68070_device::int2_w) update_ipl(); } - m_int1_line = state; + m_int2_line = state; } } @@ -558,13 +750,41 @@ TIMER_CALLBACK_MEMBER(scc68070_device::tx_callback) uint8_t scc68070_device::lir_r() { // LIR priority level: 80001001 - return m_lir; + return m_lir & 0x77; } void scc68070_device::lir_w(uint8_t data) { LOGMASKED(LOG_IRQS, "%s: LIR Write: %02x\n", machine().describe_context(), data); - m_lir = data; + + switch (data & 0x88) + { + case 0x08: + if (m_lir & 0x08) + { + m_lir &= 0xf7; + update_ipl(); + } + break; + + case 0x80: + if (data & 0x80) + { + m_lir &= 0x7f; + update_ipl(); + } + break; + + case 0x88: + if (data & 0x88) + { + m_lir &= 0x77; + update_ipl(); + } + break; + } + + m_lir = (m_lir & 0x88) | (data & 0x77); } uint8_t scc68070_device::picr1_r() @@ -654,6 +874,35 @@ uint8_t scc68070_device::idr_r() // I2C data register: 80002001 if (!machine().side_effects_disabled()) LOGMASKED(LOG_I2C, "%s: I2C Data Register Read: %02x\n", machine().describe_context(), m_i2c.data_register); + + m_i2c.counter = 0; + m_i2c.status_register |= ISR_PIN; + m_i2c_int = false; + update_ipl(); + + if (m_i2c.state != I2C_RX_COMPLETE) + { + } + else + { + m_i2c.sda_out_state = (m_i2c.control_register & ICR_ACK) ? false : true; + m_i2c_sdaw_callback(m_i2c.sda_out_state); + + if (m_i2c.control_register & ICR_ACK) + { + m_i2c.state = I2C_SEND_ACK_AND_RX; + m_i2c.clocks = 9; + } + else + { + m_i2c.state = I2C_SEND_ACK; + m_i2c.clocks = 1; + } + m_i2c.ack_or_nak_sent = true; + m_i2c.clock_change_state = I2C_SCL_SET_1; + set_i2c_timer(); + + } return m_i2c.data_register; } @@ -661,6 +910,18 @@ void scc68070_device::idr_w(uint8_t data) { LOGMASKED(LOG_I2C, "%s: I2C Data Register Write: %02x\n", machine().describe_context(), data); m_i2c.data_register = data; + if (m_i2c.status_register & ISR_MST && m_i2c.status_register & ISR_TRX && m_i2c.status_register & ISR_BB) + { + m_i2c.status_register |= ISR_PIN; + m_i2c_int = false; + update_ipl(); + m_i2c.counter = 0; + m_i2c.state = I2C_TX_IN_PROGRESS; + m_i2c.clocks = 9; + i2c_process_falling_scl(); + m_i2c.clock_change_state = I2C_SCL_SET_1; + set_i2c_timer(); + } } uint8_t scc68070_device::iar_r() @@ -682,13 +943,154 @@ uint8_t scc68070_device::isr_r() // I2C status register: 80002005 if (!machine().side_effects_disabled()) LOGMASKED(LOG_I2C, "%s: I2C Status Register Read: %02x\n", machine().describe_context(), m_i2c.status_register); - return m_i2c.status_register & 0xef; // hack for magicard + return m_i2c.status_register; } void scc68070_device::isr_w(uint8_t data) { LOGMASKED(LOG_I2C, "%s: I2C Status Register Write: %02x\n", machine().describe_context(), data); - m_i2c.status_register = data; + if (data & ISR_MST) + { + if ((data & ISR_SSR_MASK) == ISR_START) + { + if ((m_i2c.status_register & ISR_SSR_MASK) == ISR_STOP || (m_i2c.status_register & ISR_SSR_MASK) == 0) + { + if (m_i2c_sdar_callback() && m_i2c.state == I2C_IDLE) + { + m_i2c.status_register = data; + if (data & ISR_PIN) + { + m_i2c_int = false; + update_ipl(); + } + m_i2c.sda_out_state = false; + m_i2c_sdaw_callback(false); + m_i2c.clock_change_state = I2C_SCL_SET_0; + m_i2c.clocks = 10; + m_i2c.state = I2C_TX_IN_PROGRESS; + m_i2c.first_byte = true; + m_i2c.ack_or_nak_sent = false; + set_i2c_timer(); + m_i2c.counter = 0; + } + else + { + m_i2c.status_register |= ISR_AL; + m_i2c.status_register &= ~ISR_PIN; + m_i2c_int = true; + update_ipl(); + } + } + else if ((m_i2c.status_register & ISR_SSR_MASK) == ISR_MST) + { + m_i2c.status_register = data; + if (data & ISR_PIN) + { + m_i2c_int = false; + update_ipl(); + } + m_i2c.sda_out_state = true; + m_i2c_sdaw_callback(true); + m_i2c.clock_change_state = I2C_SCL_SET_1; + m_i2c.clocks = 10; + m_i2c.state = I2C_SEND_RESTART; + m_i2c.first_byte = true; + m_i2c.ack_or_nak_sent = false; + set_i2c_timer(); + m_i2c.counter = 0; + } + } + else if ((data & ISR_SSR_MASK) == ISR_STOP && m_i2c.status_register & ISR_BB) + { + // we should send STOP here, however, unkte06 in magicard appears to expect + // NAK followed by STOP when in read mode. + + if (data & ISR_PIN) + { + m_i2c_int = false; + update_ipl(); + } + + if (m_i2c.ack_or_nak_sent || (m_i2c.status_register & ISR_TRX)) + { + m_i2c.state = I2C_SEND_STOP; + m_i2c.sda_out_state = false; + m_i2c_sdaw_callback(false); + } + else + { + m_i2c.ack_or_nak_sent = true; + m_i2c.sda_out_state = (m_i2c.control_register&ICR_ACK) ? false : true; + m_i2c_sdaw_callback(m_i2c.sda_out_state); + m_i2c.state = I2C_SEND_ACK_AND_STOP; + m_i2c.clocks = 2; + } + m_i2c.status_register = data | ISR_BB; + m_i2c.clock_change_state = I2C_SCL_SET_1; + set_i2c_timer(); + } + else if ((data & ISR_SSR_MASK) == ISR_MST) + { + m_i2c.status_register = data; + if (data & ISR_PIN) + { + m_i2c_int = false; + update_ipl(); + } + } + else + { + if (data & ISR_PIN && !(m_i2c.status_register & ISR_PIN)) + { + if (m_i2c.state == I2C_CHANGED_TO_RX) + { + m_i2c.state = I2C_RX_IN_PROGRESS; + m_i2c.clock_change_state = I2C_SCL_SET_1; + m_i2c.status_register = data; + m_i2c_int = false; + update_ipl(); + m_i2c.counter = 0; + m_i2c.clocks = 8; + set_i2c_timer(); + } + else + { + m_i2c.ack_or_nak_sent = true; + m_i2c.sda_out_state = (m_i2c.control_register&ICR_ACK) ? false : true; + m_i2c_sdaw_callback(m_i2c.sda_out_state); + m_i2c.status_register = data; + m_i2c_int = false; + update_ipl(); + m_i2c.state = I2C_SEND_ACK; + m_i2c.clock_change_state = I2C_SCL_SET_1; + m_i2c.clocks = 1; + set_i2c_timer(); + } + } + else + { + m_i2c.status_register = data; + if (data & ISR_PIN) + { + m_i2c_int = false; + update_ipl(); + } + } + } + } + else + { + m_i2c.status_register = data; + m_i2c_int = false; + update_ipl(); + m_i2c.timer->adjust(attotime::never); + m_i2c_scl_callback(1); + m_i2c_sdaw_callback(1); + m_i2c.scl_out_state = true; + m_i2c.scl_in_state = true; + m_i2c.sda_out_state = true; + m_i2c.state = I2C_IDLE; + } } uint8_t scc68070_device::icr_r() @@ -703,6 +1105,17 @@ void scc68070_device::icr_w(uint8_t data) { LOGMASKED(LOG_I2C, "%s: I2C Control Register Write: %02x\n", machine().describe_context(), data); m_i2c.control_register = data; + + if (!(data & ICR_ESO)) + { + m_i2c.timer->adjust(attotime::never); + m_i2c_scl_callback(1); + m_i2c_sdaw_callback(1); + m_i2c.scl_out_state = true; + m_i2c.scl_in_state = true; + m_i2c.sda_out_state = true; + m_i2c.state = I2C_IDLE; + } } uint8_t scc68070_device::iccr_r() @@ -719,6 +1132,200 @@ void scc68070_device::iccr_w(uint8_t data) m_i2c.clock_control_register = data & 0x1f; } + +void scc68070_device::i2c_process_falling_scl() +{ + switch (m_i2c.state) + { + case I2C_TX_IN_PROGRESS: + if (m_i2c.counter<8) + { + m_i2c.sda_out_state = BIT(m_i2c.data_register, 7 - m_i2c.counter); + m_i2c_sdaw_callback(m_i2c.sda_out_state); + m_i2c.counter++; + } + else + { + m_i2c.sda_out_state = true; + m_i2c_sdaw_callback(true); + m_i2c.state = I2C_GET_ACK; + } + break; + + case I2C_GET_ACK: + m_i2c.status_register &= ~ISR_PIN; + m_i2c_int = true; + update_ipl(); + m_i2c.state = I2C_IDLE; + if (m_i2c.first_byte) + { + m_i2c.first_byte = false; + if (BIT(m_i2c.data_register, 0)) + { + m_i2c.status_register &= ~ISR_TRX; + if (!(m_i2c.status_register & ISR_LRB)) + { + m_i2c.state = I2C_CHANGED_TO_RX; + } + } + } + break; + + case I2C_RX_IN_PROGRESS: + if (m_i2c.counter >= 8) + { + m_i2c.status_register &= ~ISR_PIN; + m_i2c_int = true; + update_ipl(); + m_i2c.state = I2C_RX_COMPLETE; + } + break; + + case I2C_SEND_ACK_AND_RX: + m_i2c.sda_out_state = true; + m_i2c_sdaw_callback(true); + m_i2c.state = I2C_RX_IN_PROGRESS; + m_i2c.counter = 0; + break; + + case I2C_SEND_ACK_AND_STOP: + m_i2c.sda_out_state = false; + m_i2c_sdaw_callback(false); + m_i2c.state = I2C_SEND_STOP; + break; + + case I2C_SEND_ACK: + m_i2c.state = I2C_IDLE; + m_i2c.status_register &= ~ISR_PIN; + m_i2c_int = true; + update_ipl(); + break; + } +} + +void scc68070_device::i2c_process_rising_scl() +{ + switch (m_i2c.state) + { + case I2C_GET_ACK: + if (m_i2c_sdar_callback()) + { + m_i2c.status_register |= ISR_LRB; + } + else + { + m_i2c.status_register &= ~ISR_LRB; + } + break; + + case I2C_SEND_STOP: + case I2C_SEND_RESTART: + m_i2c.timer->adjust(attotime::from_nsec(5000)); + break; + + case I2C_RX_IN_PROGRESS: + if (m_i2c.counter < 8) + { + m_i2c.data_register <<= 1; + m_i2c.data_register |= m_i2c_sdar_callback(); + m_i2c.counter++; + } + break; + } +} + +WRITE_LINE_MEMBER(scc68070_device::write_scl) +{ + if (m_i2c.status_register & ISR_MST) + { + if (m_i2c.scl_in_state != state && state) + { + i2c_process_rising_scl(); + i2c_next_state(); + } + } + m_i2c.scl_in_state = state; +} + +TIMER_CALLBACK_MEMBER(scc68070_device::i2c_callback) +{ + i2c_next_state(); +} + +void scc68070_device::i2c_next_state() +{ + switch (m_i2c.clock_change_state) + { + case I2C_SCL_SET_0: + if (m_i2c.state == I2C_SEND_STOP) + { + if (!m_i2c.sda_out_state) + { + m_i2c.sda_out_state = true; + m_i2c_sdaw_callback(true); + set_i2c_timer(); + } + else + { + m_i2c.state = I2C_IDLE; + m_i2c.status_register &= ~(ISR_PIN | ISR_BB); + m_i2c_int = true; + update_ipl(); + m_i2c.clock_change_state = I2C_SCL_IDLE; + } + } + else if (m_i2c.state == I2C_SEND_RESTART) + { + m_i2c.sda_out_state = false; + m_i2c_sdaw_callback(false); + set_i2c_timer(); + m_i2c.clock_change_state = I2C_SCL_SET_0; + m_i2c.state = I2C_TX_IN_PROGRESS; + } + else + { + m_i2c.scl_out_state = false; + m_i2c_scl_callback(false); + if (m_i2c.clocks) + { + m_i2c.clocks--; + } + if (m_i2c.clocks == 0) + { + m_i2c.clock_change_state = I2C_SCL_IDLE; + } + else + { + set_i2c_timer(); + m_i2c.clock_change_state = I2C_SCL_SET_1; + } + i2c_process_falling_scl(); + } + break; + + case I2C_SCL_SET_1: + m_i2c.clock_change_state = I2C_SCL_WAIT_1; + m_i2c.scl_out_state = true; + m_i2c_scl_callback(true); + break; + + case I2C_SCL_WAIT_1: + set_i2c_timer(); + m_i2c.clock_change_state = I2C_SCL_SET_0; + break; + } +} + +void scc68070_device::set_i2c_timer() +{ + // divider offset 0 entry is illegal + static constexpr int divider[]={ 1, 78, 90, 102, 126, 150, 174, 198, + 246, 294, 342, 390, 486, 582, 678, 774, + 996, 1158, 1350, 1542, 1926, 2310, 2694, 3078, + 3846, 4614, 5382, 6150, 7686, 9222, 10758, 12294 }; + m_i2c.timer->adjust(cycles_to_attotime(divider[m_i2c.clock_control_register])); +} + uint8_t scc68070_device::umr_r() { // UART mode register: 80002011 @@ -870,7 +1477,8 @@ uint16_t scc68070_device::timer_r(offs_t offset, uint16_t mem_mask) case 0x4/2: if (!machine().side_effects_disabled()) LOGMASKED(LOG_TIMERS, "%s: Timer 0 Read: %04x & %04x\n", machine().describe_context(), m_timers.timer0, mem_mask); - return m_timers.timer0; + return 0x10000 - (attotime_to_cycles(m_timers.timer0_timer->remaining()) / 96); + case 0x6/2: if (!machine().side_effects_disabled()) LOGMASKED(LOG_TIMERS, "%s: Timer 1 Read: %04x & %04x\n", machine().describe_context(), m_timers.timer1, mem_mask); @@ -908,6 +1516,7 @@ void scc68070_device::timer_w(offs_t offset, uint16_t data, uint16_t mem_mask) case 0x2/2: LOGMASKED(LOG_TIMERS, "%s: Timer Reload Register Write: %04x & %04x\n", machine().describe_context(), data, mem_mask); COMBINE_DATA(&m_timers.reload_register); + set_timer_callback(0); break; case 0x4/2: LOGMASKED(LOG_TIMERS, "%s: Timer 0 Write: %04x & %04x\n", machine().describe_context(), data, mem_mask); diff --git a/src/devices/machine/scc68070.h b/src/devices/machine/scc68070.h index 5fe621abd64..d6a26fab8b3 100644 --- a/src/devices/machine/scc68070.h +++ b/src/devices/machine/scc68070.h @@ -28,105 +28,18 @@ TODO: #include "cpu/m68000/m68000.h" - -#define ISR_MST 0x80 // Master -#define ISR_TRX 0x40 // Transmitter -#define ISR_BB 0x20 // Busy -#define ISR_PIN 0x10 // No Pending Interrupt -#define ISR_AL 0x08 // Arbitration Lost -#define ISR_AAS 0x04 // Addressed As Slave -#define ISR_AD0 0x02 // Address Zero -#define ISR_LRB 0x01 // Last Received Bit - -#define UMR_OM 0xc0 -#define UMR_OM_NORMAL 0x00 -#define UMR_OM_ECHO 0x40 -#define UMR_OM_LOOPBACK 0x80 -#define UMR_OM_RLOOP 0xc0 -#define UMR_TXC 0x10 -#define UMR_PC 0x08 -#define UMR_P 0x04 -#define UMR_SB 0x02 -#define UMR_CL 0x01 - -#define USR_RB 0x80 -#define USR_FE 0x40 -#define USR_PE 0x20 -#define USR_OE 0x10 -#define USR_TXEMT 0x08 -#define USR_TXRDY 0x04 -#define USR_RXRDY 0x01 - -#define TSR_OV0 0x80 -#define TSR_MA1 0x40 -#define TSR_CAP1 0x20 -#define TSR_OV1 0x10 -#define TSR_MA2 0x08 -#define TSR_CAP2 0x04 -#define TSR_OV2 0x02 - -#define TCR_E1 0xc0 -#define TCR_E1_NONE 0x00 -#define TCR_E1_RISING 0x40 -#define TCR_E1_FALLING 0x80 -#define TCR_E1_BOTH 0xc0 -#define TCR_M1 0x30 -#define TCR_M1_NONE 0x00 -#define TCR_M1_MATCH 0x10 -#define TCR_M1_CAPTURE 0x20 -#define TCR_M1_COUNT 0x30 -#define TCR_E2 0x0c -#define TCR_E2_NONE 0x00 -#define TCR_E2_RISING 0x04 -#define TCR_E2_FALLING 0x08 -#define TCR_E2_BOTH 0x0c -#define TCR_M2 0x03 -#define TCR_M2_NONE 0x00 -#define TCR_M2_MATCH 0x01 -#define TCR_M2_CAPTURE 0x02 -#define TCR_M2_COUNT 0x03 - -#define CSR_COC 0x80 -#define CSR_NDT 0x20 -#define CSR_ERR 0x10 -#define CSR_CA 0x08 - -#define CER_EC 0x1f -#define CER_NONE 0x00 -#define CER_TIMING 0x02 -#define CER_BUSERR_MEM 0x09 -#define CER_BUSERR_DEV 0x0a -#define CER_SOFT_ABORT 0x11 - -#define DCR1_ERM 0x80 -#define DCR1_DT 0x30 - -#define DCR2_ERM 0x80 -#define DCR2_DT 0x30 -#define DCR2_DS 0x08 - -#define OCR_D 0x80 -#define OCR_D_M2D 0x00 -#define OCR_D_D2M 0x80 -#define OCR_OS 0x30 -#define OCR_OS_BYTE 0x00 -#define OCR_OS_WORD 0x10 - -#define SCR2_MAC 0x0c -#define SCR2_MAC_NONE 0x00 -#define SCR2_MAC_INC 0x04 -#define SCR2_DAC 0x03 -#define SCR2_DAC_NONE 0x00 -#define SCR2_DAC_INC 0x01 - -#define CCR_SO 0x80 -#define CCR_SA 0x10 -#define CCR_INE 0x08 -#define CCR_IPL 0x07 - //************************************************************************** // TYPE DEFINITIONS //************************************************************************** +enum scc68070_ocr_bits +{ + SCC68070_OCR_D = 0x80, + SCC68070_OCR_D_M2D = 0x00, + SCC68070_OCR_D_D2M = 0x80, + SCC68070_OCR_OS = 0x30, + SCC68070_OCR_OS_BYTE = 0x00, + SCC68070_OCR_OS_WORD = 0x10 +}; // ======================> scc68070_device @@ -141,6 +54,9 @@ public: auto iack7_callback() { return m_iack7_callback.bind(); } auto uart_tx_callback() { return m_uart_tx_callback.bind(); } auto uart_rtsn_callback() { return m_uart_rtsn_callback.bind(); } + auto i2c_scl_w() { return m_i2c_scl_callback.bind(); } + auto i2c_sda_w() { return m_i2c_sdaw_callback.bind(); } + auto i2c_sda_r() { return m_i2c_sdar_callback.bind(); } DECLARE_WRITE_LINE_MEMBER(in2_w); DECLARE_WRITE_LINE_MEMBER(in4_w); @@ -149,9 +65,12 @@ public: DECLARE_WRITE_LINE_MEMBER(int1_w); DECLARE_WRITE_LINE_MEMBER(int2_w); + DECLARE_WRITE_LINE_MEMBER(write_scl); + TIMER_CALLBACK_MEMBER(timer0_callback); TIMER_CALLBACK_MEMBER(rx_callback); TIMER_CALLBACK_MEMBER(tx_callback); + TIMER_CALLBACK_MEMBER(i2c_callback); // external callbacks void uart_rx(uint8_t data); @@ -170,6 +89,17 @@ public: uint8_t control_register; uint8_t reserved; uint8_t clock_control_register; + emu_timer* timer; + bool scl_out_state; + bool scl_in_state; + bool sda_out_state; + bool sda_in_state; + uint8_t clock_change_state; + uint8_t clocks; + uint8_t state; + uint8_t counter; + bool first_byte; + bool ack_or_nak_sent; }; struct uart_regs_t @@ -298,6 +228,10 @@ private: void icr_w(uint8_t data); uint8_t iccr_r(); void iccr_w(uint8_t data); + void set_i2c_timer(); + void i2c_process_falling_scl(); + void i2c_process_rising_scl(); + void i2c_next_state(); // UART interface uint8_t umr_r(); @@ -336,6 +270,9 @@ private: devcb_read8 m_iack7_callback; devcb_write8 m_uart_tx_callback; devcb_write_line m_uart_rtsn_callback; + devcb_write_line m_i2c_scl_callback; + devcb_write_line m_i2c_sdaw_callback; + devcb_read8 m_i2c_sdar_callback; // internal state uint8_t m_ipl; diff --git a/src/mame/misc/magicard.cpp b/src/mame/misc/magicard.cpp index c38986c2b1e..24e270a61f7 100644 --- a/src/mame/misc/magicard.cpp +++ b/src/mame/misc/magicard.cpp @@ -10,22 +10,16 @@ TODO: - driver based off raw guesses (we don't have relevant key docs); - - Device-ize 66470 - Handles video and CRTC, has annoying blitter ops (magicard text on - playfield at very least, most likely service mode too); - Verify RAM config on PCBs; - I/Os; - UART; - - magicardj & magicle: hook-up PIC; - - magicardj: expects GFX pitch width to be 320 rather than 336 for - title screen to draw correctly; + - hook-up pic16f84 when emulation available - hotslots, quingo: sets up 68070 timer chs 1 & 2, currently unsupported; - - magicardj: keeps reading timer 0 low byte, expects a live change? - - bigdeal0: punts with an address error PC=0x60ea3a A2=$c71c38e3; - - lucky7i, unkte06, magicardw: loops on i2c accesses; - - Is int1_w unconnected? Doesn't seem to be enabled by games so far; - - puzzleme: confirm it has a ssg (mapping matches hotslots); - + - bigdeal0: locks with 68070 continually executing address error exception + - determine what drives int1_w. (It's rtc on boards with rtc) (Not all games use this) + - Correct memory map - at the moment rom is mapped to several address spaces for + all games. This is probably wrong. + - dallaspk produces white noise after some sounds. Games running on this hardware: @@ -43,7 +37,7 @@ * Bel Slots Export (5.01), Impera, 1999. * Big Deal Belgien (5.04), Impera, 2001. * Puzzle Me!, Impera, 199?. - * unknown 'TE06', Impera, 199?. + * unknown 'TE06', Impera, 1994. * Lucky 7 (Impera), Impera, 199?. * unknown Poker 'W', unknown, 1993. * Dallas Poker, unknown, 1993. @@ -81,6 +75,48 @@ so... they ported the game to Impera/Funworld 8bits boards, losing part of graphics and sound/music quality. The new product was named "Magic Card II". + On first power up many games appear to lock with an error due to nvr not being + initialised. The following procedures fix this... + + magicard shows STATIC MEMORY ERROR. + Press OWNER BOOK KEEPING button and game will continue and finally show + OUT OF RANGE ERROR. Press OWNER BOOK KEEPING again and game shows test menu + with "!PRESS HOLD4 for 5sec TO INIT MACHINE!". Press HOLD 4 for 5 secs and + after this game should start without error. + + magicarda/b/w/unkte06/unkpkr_w show !!ERROR!! CALL SERVICEMAN 4 + Press OWNER BOOK KEEPING. Game enters test Press HOLD3 for next test. + Select PREFERENCES I and then RAM RESET. + magicarda/b/unkpkr_w lock with TURN OFF! + Quit and restart game. + + magicarde/ea/f + Show STATIC MEMORY ERROR. + Press OWNER BOOK KEEPING to get past this and again when error appears later. + Use HOLD3 to enter menu and CLEAR to get hidden test. Press HOLD5 for 5 secs + will initialise machine. + + magicarde/ea alarm when credit is added and credit is then cleared so can't be played. + Needs further investigation. + + Lucky7i shows !! FEHLER !! BITTE TECHNIKER RUFEN 4 + Press OWNER BOOK Keeping. Game enters test. Press HOLD 3 (Einstellungen) + and then HOLD 5 (RAM RESET). + Machine shows "GERAET JETZT AUS. UND WIEDER EINSTECKEN!!! + + magicardeb fails on OUT OF RANGE ERROR.. + magicardec/j fail on ERROR IN SETTINGS + + kajotcrd gets stuck during initialisation. Possible eeprom contents issue ? + dallaspk requires protection device (serial port ?) + + magicle/hotslots/quingo/belslots fail on I2C BUS ERROR - protection device missing. + + puzzleme - appears to work. Amount of credit for each coin input is set by values + in the eeprom but there doesn't appear to be any tests to set these. + Is something missing on this game ? + + magicardf, magicardw, unkte06 and lucky7i appear to work (but are they right?) ******************************************************************************* @@ -105,10 +141,57 @@ For PCB layouts and extra info see the ROM Load of each game below. +******************************************************************************* + + The information below is purely to aid development and should be removed + when complete. + There are some mysteries - eg. magicardf appears to address an I2C address where + there is no device but the game seems to work without ? + +******************************************************************************* + + DS2401 DS1207 EP PROTECT PROT AVAIL ELO TOUCH + magicard NO YES[3] 24c02 YES NO + magicarda NO YES[3] 24c02 YES NO + magicardb NO YES[2] 24c02? YES NO + magicarde YES YES[1] 24c02 16C54 YES + magicardea YES YES[1] 24c02 16C54 YES + magicardeb YES YES[1] 24c02? YES NO + magicardec YES NO 24c02? YES NO + magicardf YES NO 24c02 ?? *1 + magicardj YES NO ? 24c02 16F84 YES* + magicardw NO ? YES[2] 24c02? 16C54 YES + magicle ? ? 24c04 16F84 YES* YES + hotslots ? ? 24c02 YES NO + quingo ? ? 24c04 YES NO YES + belslots ? ? 24c04 YES NO YES + bigdeal0 ? ? 24c04 ? + puzzleme NO NO 24c02 16C54 YES + unkte06 NO YES[2] 24c02 16C56 YES + lucky7i YES[3] 24c02 NO + unkpkr_w NO YES[2] 24c02 YES NO + dallaspk NO YES[4] 24c02 YES NO protection via serial port ? + kajotcrd YES ?? 24c02 YES NO + + PIC16F84 emulation not available + + [1] Use same signature + [2] Use same signature + [3] Use unique signature + [4] Use unique signature, 8 byte identification value isn't validated by the game. + + *1 Accesses I2C device 0x48 but fails. Game works anyway. *******************************************************************************/ #include "emu.h" +#include "cpu/pic16c5x/pic16c5x.h" +#include "machine/ds1207.h" +#include "machine/ds2401.h" +#include "machine/i2cmem.h" +#include "machine/msm6242.h" +#include "machine/nvram.h" +#include "machine/scc66470.h" #include "machine/scc68070.h" #include "machine/timer.h" #include "sound/ay8910.h" @@ -118,386 +201,315 @@ #include "screen.h" #include "speaker.h" - #define CLOCK_A XTAL(30'000'000) #define CLOCK_B XTAL(8'000'000) #define CLOCK_C XTAL(19'660'800) +enum +{ + I2C_CPU = 0, + I2C_PIC, + i2C_MEM +}; -class magicard_state : public driver_device +class magicard_base_state : public driver_device { public: - magicard_state(const machine_config &mconfig, device_type type, const char *tag) + magicard_base_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) - , m_magicram(*this, "magicram") - , m_magicramb(*this, "magicramb") - , m_pcab_vregs(*this, "pcab_vregs") , m_maincpu(*this, "maincpu") , m_screen(*this, "screen") , m_palette(*this, "palette") + , m_scc66470(*this,"scc66470") + , m_i2cmem(*this, "sereeprom") { } - void magicard(machine_config &config); - void hotslots(machine_config &config); + void magicard_base(machine_config &config); - void init_magicard(); + void dram_w(offs_t offset, uint16_t data, uint16_t mem_mask); + uint16_t dram_r(offs_t offset, uint16_t mem_mask); + void mcu_dram_w(offs_t offset, uint16_t data, uint16_t mem_mask); + uint16_t mcu_dram_r(offs_t offset, uint16_t mem_mask); + uint8_t pic_portb_r(); + void pic_portb_w(offs_t offset, uint8_t data, uint8_t mask); + void output_w(offs_t offset, uint16_t data); -private: - //u16 m_vector; - required_shared_ptr m_magicram; - required_shared_ptr m_magicramb; - required_shared_ptr m_pcab_vregs; - uint16_t test_r(); - uint16_t philips_66470_r(offs_t offset); - void philips_66470_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + DECLARE_WRITE_LINE_MEMBER(cpu_int1); + +protected: + virtual void machine_start() override; virtual void machine_reset() override; - virtual void video_start() override; uint32_t screen_update_magicard(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - TIMER_DEVICE_CALLBACK_MEMBER(magicard_scanline_cb); required_device m_maincpu; required_device m_screen; required_device m_palette; - void hotslots_map(address_map &map); - void magicard_map(address_map &map); - void ramdac_map(address_map &map); -}; + required_device m_scc66470; + required_device m_i2cmem; + uint8_t m_sda_state; + uint8_t m_scl_state; -/********************************************* -* Video Hardware * -*********************************************/ + void ramdac_map(address_map &map); -/* -66470 -video and system controller -19901219/wjvg -*/ -/* -TODO: check this register,doesn't seem to be 100% correct. -1fffe0 csr = control and status register - w 00...... ........ DM = slow timing speed, normal dram mode - w 01...... ........ DM = fast timing speed, page dram mode - w 10...... ........ DM = fast timing speed, nibble dram mode - w 11...... ........ DM = slow timing speed, dual-port vram mode - w ..1..... ........ TD = 256/64 k dram's - w ...1.... ........ CG = enable character generator - w ....1... ........ DD = rom data acknowledge delay - w .....1.. ........ ED = early dtack - w ......0. ........ not used - w .......1 ........ BE = enable bus error (watchdog timer) - r ........ 1....... DA = vertical display active - r ........ .1...... FG = set during frame grabbing (if fg in dcr set) - r ........ ..xxx... not used - r ........ .....1.. IT2 = intn active - r ........ ......1. IT1 = pixac free and intn active - r ........ .......1 BE = bus error generated by watchdog timer -*/ + DECLARE_WRITE_LINE_MEMBER(scc66470_irq); + DECLARE_WRITE_LINE_MEMBER(cpu_i2c_scl); + DECLARE_WRITE_LINE_MEMBER(cpu_i2c_sda_write); + DECLARE_READ_LINE_MEMBER(cpu_i2c_sda_read); -// 63 at post test, 6d all the time. -#define SCC_CSR_VREG (m_pcab_vregs[0x00/2] & 0xffff) -#define SCC_CG_VREG ((SCC_CSR_VREG & 0x10)>>4) + void update_sda(uint8_t device, uint8_t state); + void update_scl(uint8_t device, uint8_t state); -/* -1fffe2 dcr = display command register - w 1....... ........ DE = enable display - w .00..... ........ CF = 20 MHz (or 19.6608 MHz) - w .01..... ........ CF = 24 MHz - w .10..... ........ CF = 28.5 MHz - w .11..... ........ CF = 30 MHz - w ...1.... ........ FD = 60/50 Hz frame duration - w ....00.. ........ SM/SS = non-interlaced scan mode - w ....01.. ........ SM/SS = double frequency scan mode - w ....10.. ........ SM/SS = interlaced scan mode - w ....11.. ........ SM/SS = interlaced field repeat scan mode - w ......1. ........ LS = full screen/border - w .......1 ........ CM = logical/physical screen - w ........ 1....... FG = 4/8 bits per pixel - w ........ .1...... DF = enable frame grabbing - w ........ ..00.... IC/DC = ICA and DCA inactive - w ........ ..01.... IC/DC = ICA active, reduced DCA mode (DCA sz=16 byts) - w ........ ..10.... IC/DC = ICA active, DCA inactive - w ........ ..11.... IC/DC = ICA active, DCA active (DCA size=64 bytes) - w ........ ....aaaa VSR:H = video start address (MSB's) -*/ +private: + void scc66470_map(address_map &map); + std::unique_ptrm_dram; -#define SCC_DCR_VREG (m_pcab_vregs[0x02/2] & 0xffff) -#define SCC_DE_VREG ((SCC_DCR_VREG & 0x8000)>>15) -#define SCC_FG_VREG ((SCC_DCR_VREG & 0x0080)>>7) -#define SCC_VSR_VREG_H ((SCC_DCR_VREG & 0xf)>>0) +}; -/* -1fffe4 vsr = video start register - w aaaaaaaa aaaaaaaa VSR:L = video start address (LSB's) -*/ +class magicard_state : public magicard_base_state +{ +public: + magicard_state(const machine_config &mconfig, device_type type, const char *tag) + : magicard_base_state(mconfig, type, tag) + , m_nvram(*this, "nvram") + , m_ds1207(*this, "ds1207") + { } -#define SCC_VSR_VREG_L (m_pcab_vregs[0x04/2] & 0xffff) -#define SCC_VSR_VREG ((SCC_VSR_VREG_H)<<16) | (SCC_VSR_VREG_L) + void magicard_pic54(machine_config &config); + void magicard(machine_config &config); + void unkte06(machine_config &config); -/* -1fffe6 bcr = border colour register - w ........ nnnnnnnn in 8 bit mode - w ........ nnnn.... in 4 bit mode -*/ -/* -(Note: not present on the original vreg listing) -1fffe8 dcr2 = display command register 2 - w x....... ........ not used - w .nn..... ........ OM = lower port of the video mode (with CM) - w ...1.... ........ ID = Indipendent DCA bit - w ....nn.. ........ MF = Mosaic Factor (2,4,8,16) - w ......nn ........ FT = File Type (0/1 = bitmap, 2 = RLE, 3 = Mosaic) - w ........ xxxx.... not used - w ........ ....aaaa "data" (dunno the purpose...) -*/ -#define SCC_DCR2_VREG (m_pcab_vregs[0x08/2] & 0xffff) +protected: + virtual void machine_start() override; -/* -(Note: not present on the original vreg listing) -1fffea dcp = ??? - w aaaaaaaa aaaaaa-- "data" (dunno the purpose...) - w -------- ------xx not used -*/ +private: + required_device m_nvram; + required_device m_ds1207; -/* -1fffec swm = selective write mask register - w nnnnnnnn ........ mask -*/ -/* -1fffee stm = selective mask register - w ........ nnnnnnnn mask -*/ -/* -1ffff0 a = source register a - w nnnnnnnn nnnnnnnn source -*/ -#define SCC_SRCA_VREG (m_pcab_vregs[0x10/2] & 0xffff) + std::unique_ptr m_nvram8; -/* -1ffff2 b = destination register b - rw nnnnnnnn nnnnnnnn destination -*/ + void magicard_map(address_map &map); + uint8_t nvram_r(offs_t offset); + void nvram_w(offs_t offset, uint8_t data); + uint8_t read_ds1207(offs_t offset); + void write_ds1207(offs_t offset, uint8_t data); +}; -#define SCC_DSTB_VREG (m_pcab_vregs[0x12/2] & 0xffff) +class hotslots_state : public magicard_base_state +{ +public: + hotslots_state(const machine_config &mconfig, device_type type, const char *tag) + : magicard_base_state(mconfig, type, tag) + , m_ds2401(*this, "serial_id") + , m_ds1207(*this, "ds1207") + , m_rtc(*this, "rtc") + { } -/* -1ffff4 pcr = pixac command register - w 1....... ........ 4N = 8/4 bits per pixel - w .1....00 ....x00. COL = enable colour2 function - w .1....00 .....01. COL = enable colour1 function - w .1...0.. .....10. COL = enable bcolour2 function - w .1...0.. .....11. COL = enable bcolour1 function - w ..1..000 ....x00. EXC = enable exchange function - w ..1..000 .....01. EXC = enable swap function - w ..1..000 .....10. EXC = enable inverted exchange function - w ..1..000 .....11. EXC = enable inverted swap function - w ...1..0. ....x00. CPY = enable copy type b function - w ...1...0 ....x10. CPY = enable copy type a function - w ...1..0. .....01. CPY = enable patch type b function - w ...1...0 .....11. CPY = enable patch type a function - w ....1000 .....00. CMP = enable compare function - w ....1000 .....10. CMP = enable compact function - w .....1.. ........ RTL = manipulate right to left - w ......1. ........ SHK = shrink picture by factor 2 - w .......1 ........ ZOM = zoom picture by factor 2 - w ........ nnnn.... LGF = logical function - w ........ 0000.... LGF = d=r - w ........ 0001.... LGF = d=~r - w ........ 0010.... LGF = d=0 - w ........ 0011.... LGF = d=1 - w ........ 0100.... LGF = d=~(d^r) - w ........ 0101.... LGF = d=d^r - w ........ 0110.... LGF = d=d&r - w ........ 0111.... LGF = d=~d&r - w ........ 1000.... LGF = d=~d&~r - w ........ 1001.... LGF = d=d&~r - w ........ 1010.... LGF = d=~d|r - w ........ 1011.... LGF = d=d|r - w ........ 1100.... LGF = d=d|~r - w ........ 1101.... LGF = d=~d|~r - w ........ 1110.... LGF = d=d - w ........ 1111.... LGF = d=~d - w ........ ....1... INV = invert transparancy state of source bits - w ........ .....1.. BIT = copy: enable copy type a - w ........ .....1.. BIT = colour: enable bcolour/colour - w ........ .....1.. BIT = compare: compact/compare - w ........ ......1. TT = perform transparancy test - w ........ .......0 -*/ + void hotslots_base(machine_config &config); + void hotslots(machine_config &config); + void hotslots_pic54(machine_config &config); + void magicle(machine_config &config); + void puzzleme(machine_config &config); -#define SCC_PCR_VREG (m_pcab_vregs[0x14/2] & 0xffff) +private: + optional_device m_ds2401; + optional_device m_ds1207; + required_device m_rtc; -/* -1ffff6 mask = mask register - w ........ ....nnnn mask nibbles/0 -*/ -/* -1ffff8 shift = shift register - w ......nn ........ shift by .. during source alignment -*/ -/* -1ffffa index = index register - w ........ ......nn bcolour: use bit .. in the source word - w ........ ......nn compact: nibble .. will hold the result -*/ -/* -1ffffc fc/bc = foreground/background colour register - w nnnnnnnn ........ FC = foreground colour - w ........ nnnnnnnn BC = background colour -*/ -/* -1ffffe tc = transparent colour register - w nnnnnnnn ........ transparent colour -*/ + void hotslots_map_base(address_map &map); + void hotslots_map(address_map &map); + void puzzleme_map(address_map &map); + uint8_t read_ds1207_ds2401(offs_t offset); + void write_ds1207_ds2401(offs_t offset, uint8_t data); + void output_w(offs_t offset, uint16_t data); -void magicard_state::video_start() + DECLARE_WRITE_LINE_MEMBER(cpu_int1); +}; + +void magicard_base_state::machine_start() { + m_dram = make_unique_clear(0x80000/2); + save_pointer(NAME(m_dram), 0x80000/2); + save_item(NAME(m_sda_state)); + save_item(NAME(m_scl_state)); } -uint32_t magicard_state::screen_update_magicard(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +void magicard_state::machine_start() { - // TODO: border & genlock - bitmap.fill(m_palette->black_pen(), cliprect); + magicard_base_state::machine_start(); + m_nvram8 = std::make_unique(16384); + m_nvram->set_base(m_nvram8.get(),16384); +} - // punt if display enable is off - if(!(SCC_DE_VREG)) - return 0; +void magicard_state::nvram_w(offs_t offset, uint8_t data) +{ + m_nvram8[ offset ] = data; +} - uint32_t count = ((SCC_VSR_VREG) / 2); +uint8_t magicard_state::nvram_r(offs_t offset) +{ + return m_nvram8[ offset ]; +} - if(SCC_FG_VREG) // 4bpp gfx +void magicard_base_state::mcu_dram_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if(!machine().side_effects_disabled()) { - for(int y = 0; y < 300; y++) - { - for(int x = 0; x < 84; x++) - { - uint32_t color; - - color = ((m_magicram[count]) & 0x000f) >> 0; - - if(cliprect.contains((x * 4) + 3, y)) - bitmap.pix(y, (x * 4) + 3) = m_palette->pen(color); - - color = ((m_magicram[count]) & 0x00f0) >> 4; - - if(cliprect.contains((x * 4) + 2, y)) - bitmap.pix(y, (x * 4) + 2) = m_palette->pen(color); - - color = ((m_magicram[count]) & 0x0f00) >> 8; - - if(cliprect.contains((x * 4) + 1, y)) - bitmap.pix(y, (x * 4) + 1) = m_palette->pen(color); - - color = ((m_magicram[count]) & 0xf000) >> 12; - - if(cliprect.contains((x * 4) + 0, y)) - bitmap.pix(y, (x * 4) + 0) = m_palette->pen(color); - - count++; - } - } + m_maincpu->eat_cycles(m_maincpu->attotime_to_cycles(attotime::from_ticks(m_scc66470->dram_dtack_cycles(), m_scc66470->clock()))); } - else // 8bpp gfx + m_scc66470->dram_w(offset, data, mem_mask); +} + +uint16_t magicard_base_state::mcu_dram_r(offs_t offset, uint16_t mem_mask) +{ + if(!machine().side_effects_disabled()) { - for(int y = 0; y < 300; y++) - { - for(int x = 0; x < 168; x++) - { - uint32_t color; + m_maincpu->eat_cycles(m_maincpu->attotime_to_cycles(attotime::from_ticks(m_scc66470->dram_dtack_cycles(), m_scc66470->clock()))); + } + return m_scc66470->dram_r(offset); +} - color = ((m_magicram[count]) & 0x00ff) >> 0; +void magicard_base_state::dram_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&m_dram[offset]); +} - if(cliprect.contains((x * 2) + 1, y)) - bitmap.pix(y, (x * 2) + 1) = m_palette->pen(color); +uint16_t magicard_base_state::dram_r(offs_t offset, uint16_t mem_mask) +{ + return m_dram[ offset ] & mem_mask; +} - color = ((m_magicram[count]) & 0xff00) >> 8; +void magicard_base_state::scc66470_map(address_map &map) +{ + map(0x00000, 0x7ffff).rw(FUNC(magicard_base_state::dram_r), FUNC(magicard_base_state::dram_w)); +} - if(cliprect.contains((x * 2) + 0, y)) - bitmap.pix(y, (x * 2) + 0) = m_palette->pen(color); +uint32_t magicard_base_state::screen_update_magicard(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + if(cliprect.min_y == cliprect.max_y) + { + uint8_t buffer[768]; + m_scc66470->line(cliprect.min_y, buffer, sizeof(buffer)); + uint32_t *dest = &bitmap.pix(cliprect.min_y); - count++; - } + for(int x = cliprect.min_x ; x <= cliprect.max_x ; x++) + { + *dest++ = m_palette->pen(buffer[ x ]); } } - return 0; } +/************************* +* R/W Handlers * +*************************/ -/********************************************* -* R/W Handlers * -*********************************************/ +uint8_t magicard_state::read_ds1207(offs_t offset) +{ + return m_ds1207->read_dq() ? 0x08 : 0x00; +} -uint16_t magicard_state::test_r() +void magicard_state::write_ds1207(offs_t offset, uint8_t data) { - return machine().rand(); + m_ds1207->write_rst(BIT(data,0)); + m_ds1207->write_clk(BIT(data,1)); + m_ds1207->write_dq(BIT(data,3)); } -uint16_t magicard_state::philips_66470_r(offs_t offset) +void magicard_base_state::output_w(offs_t offset, uint16_t data) { - switch(offset) - { - case 0/2: - { - uint8_t vdisp; - vdisp = m_screen->vpos() < 256; + // bit 0 - counter out + // bit 1 - ?? + // bit 2 - ?? + // bit 3 - counter jackpot + // bit 4 - counter checkout + // bit 5 - ?? + // bit 6 - ?? + // bit 7 - hold 3 lamp + // bit 8 - start lamp + // bit 9 - hold 1 lamp + // bit 10 - hold 5 lamp + // bit 11 - hold 2 lamp + // bit 12 - hold 4 lamp + // bit 13 - clear lamp + // bit 14 - hopper drive + // bit 15 - counter in +} - // TODO: other bits - return (m_pcab_vregs[offset] & 0xff7f) | vdisp << 7; - } - } - return m_pcab_vregs[offset]; +uint8_t hotslots_state::read_ds1207_ds2401(offs_t offset) +{ + m_ds2401->write(true); + return (m_ds2401->read() ? 0x10 : 0x00) | (m_ds1207->read_dq() ? 0x08 : 0x00); } -void magicard_state::philips_66470_w(offs_t offset, uint16_t data, uint16_t mem_mask) +void hotslots_state::write_ds1207_ds2401(offs_t offset, uint8_t data) { - COMBINE_DATA(&m_pcab_vregs[offset]); + m_ds2401->write(BIT(data,4)); + m_ds1207->write_rst(BIT(data,0)); + m_ds1207->write_clk(BIT(data,1)); + m_ds1207->write_dq(BIT(data,3)); +} -// if(offset == 0x10/2) -// { - //printf("%04x %04x %04x\n",data,m_pcab_vregs[0x12/2],m_pcab_vregs[0x14/2]); - //m_pcab_vregs[0x12/2] = m_pcab_vregs[0x10/2]; -// } +void hotslots_state::output_w(offs_t offset, uint16_t data) +{ + // bit 0 - counter out + // bit 1 - counter key switch + // bit 2 - ?? + // bit 3 - counter hopper refill + // bit 4 - counter cashbox + // bit 5 - ?? + // bit 6 - ?? + // bit 7 - hold 3 lamp + // bit 8 - ?? + // bit 9 - hold 1 lamp + // bit 10 - hold 5 lamp + // bit 11 - hold 2 lamp + // bit 12 - hold 4 lamp + // bit 13 - clear lamp + // bit 14 - hopper drive + // bit 15 - counter in } -/********************************************* -* Memory Map Information * -*********************************************/ +/************************* +* Memory Maps * +*************************/ void magicard_state::magicard_map(address_map &map) { -// map.global_mask(0x1fffff); - map(0x00000000, 0x001ffbff).mirror(0x00200000).ram().share("magicram"); - map(0x00600000, 0x007ffbff).ram().share("magicramb"); - // 001ffc00-001ffdff System I/O - map(0x001ffc00, 0x001ffc01).mirror(0x7fe00000).portr("SYSTEM"); - map(0x001ffc40, 0x001ffc41).mirror(0x7fe00000).r(FUNC(magicard_state::test_r)); - map(0x001ffd01, 0x001ffd01).mirror(0x7fe00000).w("ramdac", FUNC(ramdac_device::index_w)); - map(0x001ffd03, 0x001ffd03).mirror(0x7fe00000).w("ramdac", FUNC(ramdac_device::pal_w)); - map(0x001ffd05, 0x001ffd05).mirror(0x7fe00000).w("ramdac", FUNC(ramdac_device::mask_w)); - map(0x001ffd40, 0x001ffd43).mirror(0x7fe00000).w("saa", FUNC(saa1099_device::write)).umask16(0x00ff); - map(0x001ffd80, 0x001ffd81).mirror(0x7fe00000).r(FUNC(magicard_state::test_r)); - map(0x001ffd80, 0x001ffd81).mirror(0x7fe00000).nopw(); - map(0x001fff80, 0x001fffbf).mirror(0x7fe00000).ram(); // DRAM I/O, not accessed by this game, CD buffer? - map(0x001fffe0, 0x001fffff).mirror(0x7fe00000).rw(FUNC(magicard_state::philips_66470_r), FUNC(magicard_state::philips_66470_w)).share("pcab_vregs"); + map(0x00000000, 0x001fffff).m(m_scc66470, FUNC(scc66470_device::map)); + map(0x00000000, 0x0017ffff).rw(FUNC(magicard_base_state::mcu_dram_r), FUNC(magicard_base_state::mcu_dram_w)); + map(0x00180000, 0x001dffff).rom().region("maincpu", 0); // boot vectors point here + map(0x001e0000, 0x001e7fff).rw(FUNC(magicard_state::nvram_r), FUNC(magicard_state::nvram_w)).umask16(0x00ff); + map(0x00200000, 0x003fffff).rw(m_scc66470, FUNC(scc66470_device::ipa_r), FUNC(scc66470_device::ipa_w)); + /* 001ffc00-001ffdff System I/O */ + map(0x001ffc00, 0x001ffc01).portr("SW0"); + map(0x001ffc40, 0x001ffc41).portr("SW1"); + map(0x001ffc80, 0x001ffc81).w( FUNC(magicard_base_state::output_w)); + map(0x001ffd01, 0x001ffd01).w("ramdac", FUNC(ramdac_device::index_w)); + map(0x001ffd03, 0x001ffd03).w("ramdac", FUNC(ramdac_device::pal_w)); + map(0x001ffd05, 0x001ffd05).w("ramdac", FUNC(ramdac_device::mask_w)); + map(0x001ffd40, 0x001ffd43).w("saa", FUNC(saa1099_device::write)).umask16(0x00ff); + map(0x001ffd80, 0x001ffd81).rw(FUNC(magicard_state::read_ds1207), FUNC(magicard_state::write_ds1207)).umask16(0x00ff); + map(0x001fff80, 0x001fffbf).ram(); //DRAM I/O, not accessed by this game, CD buffer? } // Different PAL mapping? -void magicard_state::hotslots_map(address_map &map) +void hotslots_state::hotslots_map_base(address_map &map) { -// map.global_mask(0x1fffff); - // puzzleme sets $0080000a as default reset vector, magicardf sets $00800078 - // latter also will address error if we mirror with bank A by logic (i.e. .mirror(0x00a00000)) - // we currently map it to B bank for now - map(0x00000000, 0x001ffbff).mirror(0x00200000).ram().share("magicram"); - map(0x00600000, 0x007ffbff).ram().share("magicramb"); - map(0x00800000, 0x009ffbff).ram().share("magicramb"); - map(0x001fff80, 0x001fffbf).mirror(0x7fe00000).ram(); // DRAM I/O, not accessed by this game, CD buffer? - map(0x001fffe0, 0x001fffff).mirror(0x7fe00000).rw(FUNC(magicard_state::philips_66470_r), FUNC(magicard_state::philips_66470_w)).share("pcab_vregs"); - map(0x00400000, 0x00403fff).ram(); // ? bigdeal0, magicardj accesses this as scratchram - map(0x00411000, 0x00411001).portr("SYSTEM"); + map(0x00000000, 0x001fffff).m(m_scc66470, FUNC(scc66470_device::map)); + map(0x00000000, 0x0017ffff).rw(FUNC(magicard_base_state::mcu_dram_r), FUNC(magicard_base_state::mcu_dram_w)); + map(0x00180000, 0x001ffbff).rom().region("maincpu", 0); // boot vectors point here + map(0x00200000, 0x003fffff).rw(m_scc66470, FUNC(scc66470_device::ipa_r), FUNC(scc66470_device::ipa_w)); + map(0x00600000, 0x0067fbff).rom().region("maincpu", 0); // boot vectors point here + map(0x00680000, 0x006ffbff).rom().region("maincpu", 0); // boot vectors point here + map(0x00800000, 0x0087fbff).rom().region("maincpu", 0); // boot vectors point here + map(0x001fff80, 0x001fffbf).ram(); //DRAM I/O, not accessed by this game, CD buffer? + map(0x00400000, 0x0040ffff).ram().share("nvram"); + map(0x00411000, 0x00411001).portr("SW0"); + map(0x00412346, 0x00412347).portr("SW1"); + map(0x00413000, 0x00413001).w( FUNC(hotslots_state::output_w)); map(0x00414001, 0x00414001).w("ramdac", FUNC(ramdac_device::index_w)); map(0x00414003, 0x00414003).w("ramdac", FUNC(ramdac_device::pal_w)); map(0x00414005, 0x00414005).w("ramdac", FUNC(ramdac_device::mask_w)); @@ -505,158 +517,472 @@ void magicard_state::hotslots_map(address_map &map) map(0x00415003, 0x00415003).r("ramdac", FUNC(ramdac_device::pal_r)); map(0x00416001, 0x00416001).w("ssg", FUNC(ymz284_device::data_w)); map(0x00417001, 0x00417001).w("ssg", FUNC(ymz284_device::address_w)); + map(0x00418000, 0x00418020).rw("rtc", FUNC(rtc72421_device::read), FUNC(rtc72421_device::write)).umask16(0x00ff); } +void hotslots_state::hotslots_map(address_map &map) +{ + hotslots_map_base(map); + map(0x00419566, 0x00419567).rw(FUNC(hotslots_state::read_ds1207_ds2401), FUNC(hotslots_state::write_ds1207_ds2401)).umask16(0x00ff); +} + +void hotslots_state::puzzleme_map(address_map &map) +{ + hotslots_map_base(map); +} -/********************************************* -* Input Ports * -*********************************************/ +/************************* +* Input ports * +*************************/ static INPUT_PORTS_START( magicard ) - PORT_START("SYSTEM") - PORT_DIPNAME( 0x01, 0x01, "SYSTEM0" ) - PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) + PORT_START("SW0") + + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) + + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN3 ) PORT_NAME("Remote 2") + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN4 ) PORT_NAME("Remote 1") + + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN2 ) + + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_POKER_HOLD1 ) PORT_NAME("Hold 1") + + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Bet/Clear/Collect") + + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_POKER_HOLD5 ) PORT_NAME("Hold 5") + + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START1 ) + + PORT_BIT( 0x100, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) PORT_NAME("Rental Book Keeping") PORT_TOGGLE + PORT_BIT( 0x200, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_NAME("Owner Book Keeping") + + PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_POKER_HOLD4 ) PORT_NAME("Hold 4") + PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_POKER_HOLD2 ) PORT_NAME("Hold 2") + PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_POKER_HOLD3 ) PORT_NAME("Hold 3") + + PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) PORT_NAME("Pay Out") + PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Hopper Count") PORT_CODE(KEYCODE_W) + PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_SERVICE3 ) PORT_NAME("Accounting 3") PORT_TOGGLE + + PORT_START("SW1") + PORT_DIPNAME( 0x80, 0x80, "Hopper" ) PORT_DIPLOCATION("DIP 1:1") + PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) + PORT_DIPNAME( 0x40, 0x40, "Hopper" ) PORT_DIPLOCATION("DIP 1:2") + PORT_DIPSETTING( 0x40, "Coin B" ) + PORT_DIPSETTING( 0x00, "Coin A" ) + + PORT_DIPNAME( 0x38, 0x38, "Setting" ) PORT_DIPLOCATION("DIP 1:5,4,3") + PORT_DIPSETTING( 0x38, "Austria 1" ) + PORT_DIPSETTING( 0x30, "Austria 2" ) + PORT_DIPSETTING( 0x18, "Tschech 1" ) + PORT_DIPSETTING( 0x10, "Tschech 2" ) + PORT_DIPSETTING( 0x28, "Germany 1" ) + PORT_DIPSETTING( 0x20, "Germany 2" ) + PORT_DIPSETTING( 0x08, "Hungary 1" ) + PORT_DIPSETTING( 0x00, "Hungary 2" ) + + PORT_DIPNAME( 0x04, 0x04, "Swap Coin Inputs" ) PORT_DIPLOCATION("DIP 1:6") + PORT_DIPSETTING( 0x04, DEF_STR( No ) ) + PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) + PORT_DIPNAME( 0x02, 0x02, "Remote/Keyboard" ) PORT_DIPLOCATION("DIP 1:7") + PORT_DIPSETTING( 0x02, "Remote Switch" ) + PORT_DIPSETTING( 0x00, "Keyboard" ) + PORT_DIPNAME( 0x01, 0x01, "Keyboard Test" ) PORT_DIPLOCATION("DIP 1:8") + PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) + + PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Hopper Full") PORT_CODE(KEYCODE_A) PORT_TOGGLE + PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_UNUSED ) // PORT_NAME("Reserve In 9") + PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_UNUSED ) // PORT_NAME("Reserve In 8") + PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_UNUSED ) // PORT_NAME("Reserve In 7") + PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_UNUSED ) // PORT_NAME("Reserve In 6") + PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_UNUSED ) // PORT_NAME("Reserve In 5") + PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_GAMBLE_DOOR ) PORT_NAME("Door Switch") PORT_TOGGLE + PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Clear Credit") PORT_CODE(KEYCODE_J) + +INPUT_PORTS_END + +static INPUT_PORTS_START( magicarde ) + PORT_INCLUDE( magicard ) + + PORT_MODIFY("SW1") + PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_NAME("Alarm") PORT_CODE(KEYCODE_S) + PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("Counter Control") PORT_CODE(KEYCODE_D) + PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_UNUSED ) // PORT_NAME("N/C 1") + PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_UNUSED ) // PORT_NAME("N/C 2") + PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("Clear coinCard") PORT_CODE(KEYCODE_H) + +INPUT_PORTS_END + +static INPUT_PORTS_START( puzzleme ) + PORT_START("SW0") + + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_COIN1 ) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_COIN3 ) PORT_NAME("Remote") + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON1 ) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_COIN2 ) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_MEMORY_RESET ) PORT_NAME("Clear") + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_SERVICE3 ) PORT_NAME("Show All Book Keeping") + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START1 ) + PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) PORT_NAME("Rental Book Keeping") + PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_NAME("Owner Book Keeping") + PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) + PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) + PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) + PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("SW1") + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_CONFNAME( 0x1800, 0x1800, DEF_STR( Difficulty ) ) + PORT_CONFSETTING( 0x1800, DEF_STR( Normal ) ) + PORT_CONFSETTING( 0x0000, DEF_STR( Easy ) ) + PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_UNUSED ) + +INPUT_PORTS_END + +static INPUT_PORTS_START( lucky7i ) + PORT_INCLUDE( magicard ) + + PORT_MODIFY("SW0") + + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Win Plan Scroll/Collect") + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_GAMBLE_BET ) PORT_NAME("Einsatz") + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START1 ) PORT_NAME("Start/Gamble") + PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) PORT_NAME("Rental Book Keeping") + + PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_MODIFY("SW1") + PORT_DIPNAME( 0x80, 0x80, "Hopper" ) PORT_DIPLOCATION("DIP 1:1") + PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) + + PORT_DIPNAME( 0x40, 0x40, "Hopper-Wert" ) PORT_DIPLOCATION("DIP 1:2") + PORT_DIPSETTING( 0x40, "10" ) + PORT_DIPSETTING( 0x00, "5" ) + + PORT_DIPNAME( 0x08, 0x08, "Munzer1" ) PORT_DIPLOCATION("DIP 1:5") + PORT_DIPSETTING( 0x08, "10" ) + PORT_DIPSETTING( 0x00, "5" ) + + PORT_DIPNAME( 0x04, 0x04, "Munzer2" ) PORT_DIPLOCATION("DIP 1:6") + PORT_DIPSETTING( 0x04, "10" ) + PORT_DIPSETTING( 0x00, "5" ) + + PORT_DIPNAME( 0x02, 0x02, "Remote 1" ) PORT_DIPLOCATION("DIP 1:7") + PORT_DIPSETTING( 0x02, "100" ) + PORT_DIPSETTING( 0x00, "10" ) + + PORT_DIPNAME( 0x20, 0x20, "Remote 2" ) PORT_DIPLOCATION("DIP 1:3") + PORT_DIPSETTING( 0x20, "100" ) + PORT_DIPSETTING( 0x00, "50" ) + + PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DIP 1:4") PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) + + PORT_DIPNAME( 0x01, 0x01, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DIP 1:8") + PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) + + PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) PORT_NAME("Attendant Collect") PORT_CODE(KEYCODE_A) + +INPUT_PORTS_END + +static INPUT_PORTS_START( dallaspk ) + PORT_INCLUDE( magicard ) + + PORT_MODIFY("SW1") + PORT_DIPNAME( 0x80, 0x80, "Hopper" ) PORT_DIPLOCATION("DIP 1:1") PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x0100, 0x0100, "SYSTEM1" ) - PORT_DIPSETTING( 0x0100, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - // Used by magicard to enter into gameplay - PORT_DIPNAME( 0x0200, 0x0200, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0200, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0400, 0x0400, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0400, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0800, 0x0800, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0800, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x1000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x2000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x4000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - // coin sound in magicard (but no GFX is updated?) - PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x8000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x40, "Hopper-Wert" ) PORT_DIPLOCATION("DIP 1:2") + PORT_DIPSETTING( 0x40, "10" ) + PORT_DIPSETTING( 0x00, "5" ) + + PORT_DIPNAME( 0x08, 0x08, "Munzer1" ) PORT_DIPLOCATION("DIP 1:5") + PORT_DIPSETTING( 0x08, "10" ) + PORT_DIPSETTING( 0x00, "5" ) + + PORT_DIPNAME( 0x04, 0x04, "Munzer2" ) PORT_DIPLOCATION("DIP 1:6") + PORT_DIPSETTING( 0x04, "10" ) + PORT_DIPSETTING( 0x00, "5" ) + + PORT_DIPNAME( 0x02, 0x02, "Remote 1" ) PORT_DIPLOCATION("DIP 1:7") + PORT_DIPSETTING( 0x02, "100" ) + PORT_DIPSETTING( 0x00, "10" ) + + PORT_DIPNAME( 0x20, 0x20, "Remote 2" ) PORT_DIPLOCATION("DIP 1:3") + PORT_DIPSETTING( 0x20, "100" ) + PORT_DIPSETTING( 0x00, "50" ) + + PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DIP 1:4") + PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + + PORT_DIPNAME( 0x01, 0x01, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DIP 1:8") + PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + INPUT_PORTS_END +static INPUT_PORTS_START( hotslots ) + PORT_INCLUDE( magicard ) -/****************************************** -* Machine Start & Reset * -******************************************/ + PORT_MODIFY("SW1") + PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("Alarm") PORT_CODE(KEYCODE_S) + PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("Counter Control") PORT_CODE(KEYCODE_D) + PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_NAME("Clear coinCard") PORT_CODE(KEYCODE_H) -void magicard_state::machine_reset() +INPUT_PORTS_END + +void magicard_base_state::machine_reset() { - // TODO: confirm reset state - uint16_t *src = (uint16_t*)memregion("maincpu")->base(); - uint16_t *dst = m_magicram; - memcpy (dst, src, 0x80000); - memcpy (dst + 0x40000 * 1, src, 0x80000); - memcpy (dst + 0x40000 * 2, src, 0x80000); - memcpy (dst + 0x40000 * 3, src, 0x7fc00); - dst = m_magicramb; - memcpy (dst, src, 0x80000); - memcpy (dst + 0x40000 * 1, src, 0x80000); - memcpy (dst + 0x40000 * 2, src, 0x80000); - memcpy (dst + 0x40000 * 3, src, 0x7fc00); + uint16_t *src = (uint16_t*)memregion("maincpu")->base(); + m_scc66470->set_vectors( src ); + + m_sda_state = 0; + m_scl_state = 0; } -/********************************************* -* Machine Drivers * -*********************************************/ +/************************* +* Machine Drivers * +*************************/ -TIMER_DEVICE_CALLBACK_MEMBER(magicard_state::magicard_scanline_cb) +WRITE_LINE_MEMBER(magicard_base_state::scc66470_irq) { - int scanline = param; + m_maincpu->int2_w(state); +} + +WRITE_LINE_MEMBER(magicard_base_state::cpu_int1) +{ + // todo: is this used by games on magicard hardware ? + m_maincpu->int1_w(1); + m_maincpu->int1_w(0); +} + +WRITE_LINE_MEMBER(hotslots_state::cpu_int1) +{ + m_maincpu->int1_w(state); +} - // hotslots and quingo definitely wants two irqs per frame, - // reading vdisp as branch dispatch and setting a specific flag in RAM - if (scanline == 256 || scanline == 0) +void magicard_base_state::ramdac_map(address_map &map) +{ + map(0x0000, 0x03ff).rw("ramdac", FUNC(ramdac_device::ramdac_pal_r), FUNC(ramdac_device::ramdac_rgb666_w)); +} + +void magicard_base_state::update_scl(uint8_t device, uint8_t state) +{ + if(state) { - m_maincpu->int2_w(1); - m_maincpu->int2_w(0); + m_scl_state &= ~(1<write_scl(m_scl_state ? 0 : 1); + m_maincpu->write_scl(m_scl_state ? 0 : 1); } -void magicard_state::ramdac_map(address_map &map) +void magicard_base_state::update_sda(uint8_t device, uint8_t state) { - map(0x0000, 0x03ff).rw("ramdac", FUNC(ramdac_device::ramdac_pal_r), FUNC(ramdac_device::ramdac_rgb666_w)); + if(state) + { + m_sda_state &= ~(1<write_sda(m_sda_state ? 0 : 1); +} + +WRITE_LINE_MEMBER(magicard_base_state::cpu_i2c_scl) +{ + update_scl(I2C_CPU, state); } +WRITE_LINE_MEMBER(magicard_base_state::cpu_i2c_sda_write) +{ + update_sda(I2C_CPU, state); +} -void magicard_state::magicard(machine_config &config) +READ_LINE_MEMBER(magicard_base_state::cpu_i2c_sda_read) { - SCC68070(config, m_maincpu, CLOCK_A); // SCC-68070 CCA84 - m_maincpu->set_addrmap(AS_PROGRAM, &magicard_state::magicard_map); - TIMER(config, "scantimer").configure_scanline(FUNC(magicard_state::magicard_scanline_cb), "screen", 0, 1); + return (m_sda_state ? 0 : 1) & (m_i2cmem->read_sda() ? 1 : 0); +} + +void magicard_base_state::magicard_base(machine_config &config) +{ + SCC68070(config, m_maincpu, CLOCK_C); /* SCC-68070 CCA84 */ + m_maincpu->i2c_scl_w().set(FUNC(magicard_base_state::cpu_i2c_scl)); + m_maincpu->i2c_sda_w().set(FUNC(magicard_base_state::cpu_i2c_sda_write)); + m_maincpu->i2c_sda_r().set(FUNC(magicard_base_state::cpu_i2c_sda_read)); SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - // TODO: has dynamic resolution, fill defaults and convert to set_raw - m_screen->set_refresh_hz(50); - m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0)); - m_screen->set_size(400, 300); - m_screen->set_visarea(0, 320-1, 0, 256-1); -// m_screen->screen_vblank().set(m_maincpu, FUNC(scc68070_device::int2_w)); - m_screen->set_screen_update(FUNC(magicard_state::screen_update_magicard)); + m_screen->set_raw( CLOCK_A/2, 960, 0, 768, 312, 32, 312); + m_screen->set_video_attributes(VIDEO_UPDATE_SCANLINE); + m_screen->set_screen_update(FUNC(magicard_base_state::screen_update_magicard)); + + SCC66470(config,m_scc66470,CLOCK_A); + m_scc66470->set_addrmap(0, &magicard_base_state::scc66470_map); + m_scc66470->set_screen("screen"); + m_scc66470->irq().set(FUNC(magicard_base_state::scc66470_irq)); PALETTE(config, m_palette).set_entries(0x100); ramdac_device &ramdac(RAMDAC(config, "ramdac", 0, m_palette)); ramdac.set_addrmap(0, &magicard_state::ramdac_map); SPEAKER(config, "mono").front_center(); + + NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); +} + +void magicard_state::magicard(machine_config &config) +{ + magicard_base(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &magicard_state::magicard_map); + + m_screen->screen_vblank().set(FUNC(magicard_base_state::cpu_int1)); + SAA1099(config, "saa", CLOCK_B).add_route(ALL_OUTPUTS, "mono", 1.0); + + I2C_24C02(config, m_i2cmem).set_e0(1); + + DS1207(config, "ds1207"); } -void magicard_state::hotslots(machine_config &config) +void magicard_state::magicard_pic54(machine_config &config) { magicard(config); - m_maincpu->set_addrmap(AS_PROGRAM, &magicard_state::hotslots_map); - config.device_remove("saa"); + pic16c54_device &pic(PIC16C54(config, "pic16c54", 3686400)); // correct? + pic.read_b().set(FUNC(magicard_base_state::pic_portb_r)); + pic.write_b().set(FUNC(magicard_base_state::pic_portb_w)); +} + +void magicard_state::unkte06(machine_config &config) +{ + magicard(config); + + pic16c56_device &pic(PIC16C56(config, "pic16c56", 3686400)); // correct? + pic.read_b().set(FUNC(magicard_base_state::pic_portb_r)); + pic.write_b().set(FUNC(magicard_base_state::pic_portb_w)); +} + +uint8_t magicard_base_state::pic_portb_r() +{ + return (m_sda_state ? 0 : 0x80) | (m_scl_state ? 0 : 0x40); +} + +void magicard_base_state::pic_portb_w(offs_t offset, uint8_t data, uint8_t mask) +{ + update_scl(I2C_PIC,((data & mask) | (~mask & 0x40)) & 0x40); + update_sda(I2C_PIC,((data & mask) | (~mask & 0x80)) & 0x80); +} + +void hotslots_state::hotslots_base(machine_config &config) +{ + magicard_base(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &hotslots_state::hotslots_map); + YMZ284(config, "ssg", 4000000).add_route(ALL_OUTPUTS, "mono", 1.0); + + RTC72421(config, m_rtc, XTAL(32'768)).out_int_handler().set(FUNC(hotslots_state::cpu_int1)); + + DS2401(config, "serial_id"); + + DS1207(config, "ds1207"); +} + +void hotslots_state::hotslots(machine_config &config) +{ + hotslots_base(config); + + I2C_24C02(config, m_i2cmem).set_e0(1); } +void hotslots_state::hotslots_pic54(machine_config &config) +{ + hotslots(config); -/********************************************* -* Rom Load * -*********************************************/ + pic16c54_device &pic(PIC16C54(config, "pic16c54", 3686400)); // correct? + pic.read_b().set(FUNC(magicard_base_state::pic_portb_r)); + pic.write_b().set(FUNC(magicard_base_state::pic_portb_w)); +} +void hotslots_state::magicle(machine_config &config) +{ + hotslots_base(config); + + I2C_24C04(config, m_i2cmem).set_e0(1); +} + +void hotslots_state::puzzleme(machine_config &config) +{ + hotslots_base(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &hotslots_state::puzzleme_map); + + pic16c54_device &pic(PIC16C54(config, "pic16c54", 3686400)); // correct? + pic.read_b().set(FUNC(magicard_base_state::pic_portb_r)); + pic.write_b().set(FUNC(magicard_base_state::pic_portb_w)); + + I2C_24C02(config, m_i2cmem).set_e0(1); + + config.device_remove("serial_id"); + config.device_remove("ds1207"); +} + + +/************************* +* Rom Load * +*************************/ + +/* + Magicard Ver 2.01 +*/ ROM_START( magicard ) ROM_REGION( 0x80000, "maincpu", 0 ) // 68070 Code & GFX ROM_LOAD16_WORD_SWAP( "magicorg.bin", 0x000000, 0x80000, CRC(810edf9f) SHA1(0f1638a789a4be7413aa019b4e198353ba9c12d9) ) ROM_REGION( 0x0100, "sereeprom", 0 ) // Serial EPROM - ROM_LOAD16_WORD_SWAP("mgorigee.bin", 0x0000, 0x0100, CRC(73522889) SHA1(3e10d6c1585c3a63cff717a0b950528d5373c781) ) + ROM_LOAD16_WORD_SWAP("mgorigee.bin", 0x0000, 0x0100, CRC(f09eb2b2) SHA1(2d6efcea6c0835ea754285e22354dff8f059fdf5) ) + + ROM_REGION(0x4d, "ds1207", 0) /* timekey */ + ROM_LOAD( "ds1207", 0x000000, 0x00004d, BAD_DUMP CRC(48528ccf) SHA1(182f5aa2938328bac59110eee1b340b3b4ea3e29) ) // created to match game + + ROM_REGION(0x4000, "nvram", 0) /* Default NVRAM */ + ROM_LOAD( "magicard.nv", 0x0000, 0x4000, CRC(3b7d957e) SHA1(2c56b7f37a2166a99c9e6b05d90ace0a4dd179e2) ) ROM_END +/* + Magicard 1.5 17.12.93 +*/ ROM_START( magicarda ) ROM_REGION( 0x80000, "maincpu", 0 ) // 68070 Code & GFX ROM_LOAD16_WORD_SWAP( "mcorigg2.bin", 0x00000, 0x20000, CRC(48546aa9) SHA1(23099a5e4c9f2c3386496f6d7f5bb7d435a6fb16) ) @@ -665,9 +991,18 @@ ROM_START( magicarda ) ROM_RELOAD( 0x40001, 0x20000 ) ROM_REGION( 0x0100, "sereeprom", 0 ) // Serial EPROM - ROM_LOAD("mgorigee.bin", 0x0000, 0x0100, CRC(73522889) SHA1(3e10d6c1585c3a63cff717a0b950528d5373c781) ) + ROM_LOAD("mgorigee.bin", 0x0000, 0x0100, CRC(f09eb2b2) SHA1(2d6efcea6c0835ea754285e22354dff8f059fdf5) ) + + ROM_REGION(0x4d, "ds1207", 0) /* timekey */ + ROM_LOAD( "ds1207", 0x000000, 0x00004d, BAD_DUMP CRC(4902b7c2) SHA1(6e6fe825cfcf39bae60ecc45ab0742772f87cf80) ) // created to match game + + ROM_REGION(0x4000, "nvram", 0) /* Default NVRAM */ + ROM_LOAD( "magicarda.nv", 0x0000, 0x4000, CRC(4d78bbcc) SHA1(943344f03a69ee25526e2b1f2e74722ae2601c11) ) ROM_END +/* + Magicard 1.5 17.12.93 +*/ ROM_START( magicardb ) ROM_REGION( 0x80000, "maincpu", 0 ) // 68070 Code & GFX ROM_LOAD16_WORD_SWAP( "mg_8.bin", 0x00000, 0x80000, CRC(f5499765) SHA1(63bcf40b91b43b218c1f9ec1d126a856f35d0844) ) @@ -675,6 +1010,15 @@ ROM_START( magicardb ) /*bigger than the other sets?*/ ROM_REGION( 0x20000, "other", 0 ) // unknown ROM_LOAD16_WORD_SWAP("mg_u3.bin", 0x00000, 0x20000, CRC(2116de31) SHA1(fb9c21ca936532e7c342db4bcaaac31c478b1a35) ) + + ROM_REGION( 0x0100, "sereeprom", 0 ) // Serial EPROM + ROM_LOAD("mgorigee.bin", 0x0000, 0x0100, CRC(fea8a821) SHA1(c744cac6af7621524fc3a2b0a9a135a32b33c81b) ) + + ROM_REGION(0x4d, "ds1207", 0) /* timekey */ + ROM_LOAD( "ds1207", 0x000000, 0x00004d, BAD_DUMP CRC(cbcc1a42) SHA1(4b577c85f5856192ce04051a2d305a9080192177) ) // created to match game + + ROM_REGION(0x4000, "nvram", 0) /* Default NVRAM */ + ROM_LOAD( "magicardb.nv", 0x0000, 0x4000, CRC(4d78bbcc) SHA1(943344f03a69ee25526e2b1f2e74722ae2601c11) ) ROM_END /* @@ -738,9 +1082,9 @@ ROM_END | |___________________| | |__________________________________________________________________________________________________| - Xtal 1: 30.000 MHz. - Xtal 2: 8.000 MHz. - Xtal 3: 19.660 MHz. + Xtal 1: 30.000 MHz. (66470) + Xtal 2: 8.000 MHz. (PIC?) + Xtal 3: 19.660 MHz. (68070) A = LT 0030 / LTC695CN / U18708 B = NEC Japan / D43256BGU-70LL / 0008XD041 @@ -811,9 +1155,9 @@ ROM_END XTAL: - Q1: 19.6608 Mhz - Q2: 30.000 Mhz - Q3: 3686.400 1Q08/95 + Q1: 19.6608 Mhz (68070) + Q2: 30.000 Mhz (66470) + Q3: 3686.400 1Q08/95 (PIC?) */ ROM_START( magicarde ) @@ -824,7 +1168,16 @@ ROM_START( magicarde ) ROM_LOAD("pic16c54.ic29", 0x0000, 0x1fff, CRC(9c225a49) SHA1(249c12d23d1a85de828652c55a1a19ef8ec378ef) ) ROM_REGION( 0x0100, "sereeprom", 0 ) // Serial EPROM - ROM_LOAD("st24c02.ic26", 0x0000, 0x0100, CRC(98287c67) SHA1(ad34e55c1ce4f77c27049dac88050ed3c94af1a0) ) + ROM_LOAD("st24c02.ic26", 0x0000, 0x0100, CRC(427bcdc7) SHA1(0b1debf6aa2a50717fcf85dfb8d98ba70871beb9) ) + + ROM_REGION(0x8, "serial_id", 0) /* serial number */ + ROM_LOAD( "ds2401", 0x000000, 0x000008, BAD_DUMP CRC(3f87b999) SHA1(29649749d521ced9dc7ef1d0d6ddb9a8beea360f) ) // created to match game + + ROM_REGION(0x4d, "ds1207", 0) /* timekey */ + ROM_LOAD( "ds1207", 0x000000, 0x00004d, BAD_DUMP CRC(b00bf924) SHA1(ab98b2955697765518d877d4e19dbe45de0d9503) ) // created to match game + + ROM_REGION(0x10000, "nvram", 0) /* Default NVRAM */ + ROM_LOAD( "magicarde.nv", 0x0000, 0x10000, CRC(6b9f6abd) SHA1(fd171f465a16d3f2da9c19924ee31f6e56ee746c) ) ROM_END /* @@ -840,9 +1193,9 @@ ROM_END XTAL: - Q1: 19.6608 Mhz - Q2: 30.000 Mhz - Q3: 3686.400 1Q08/95 + Q1: 19.6608 Mhz (68070) + Q2: 30.000 Mhz (66470) + Q3: 3686.400 1Q08/95 (PIC?) */ ROM_START( magicardea ) @@ -853,12 +1206,21 @@ ROM_START( magicardea ) ROM_LOAD("pic16c54.ic29", 0x0000, 0x1fff, CRC(9c225a49) SHA1(249c12d23d1a85de828652c55a1a19ef8ec378ef) ) ROM_REGION( 0x0100, "sereeprom", 0 ) // Serial EPROM - ROM_LOAD("st24c02.ic26", 0x0000, 0x0100, CRC(98287c67) SHA1(ad34e55c1ce4f77c27049dac88050ed3c94af1a0) ) + ROM_LOAD("st24c02.ic26", 0x0000, 0x0100, CRC(427bcdc7) SHA1(0b1debf6aa2a50717fcf85dfb8d98ba70871beb9) ) + + ROM_REGION(0x8, "serial_id", 0) /* serial number */ + ROM_LOAD( "ds2401", 0x000000, 0x000008, BAD_DUMP CRC(3f87b999) SHA1(29649749d521ced9dc7ef1d0d6ddb9a8beea360f) ) // created to match game + + ROM_REGION(0x4d, "ds1207", 0) /* timekey */ + ROM_LOAD( "ds1207", 0x000000, 0x00004d, BAD_DUMP CRC(b00bf924) SHA1(ab98b2955697765518d877d4e19dbe45de0d9503) ) // created to match game + + ROM_REGION(0x10000, "nvram", 0) /* Default NVRAM */ + ROM_LOAD( "magicardea.nv", 0x0000, 0x10000, CRC(a1043c84) SHA1(30c3bb43e91fc358a2592f9a6efbd146eec4e43c) ) ROM_END /* Magic Card Export 94 - Clubversion Export v2.9a + Clubversion Export v2.09a Vnr.02.08.94 CHECKSUM: 5B64 1x Philips SCC66470CAB 383610 @@ -872,8 +1234,20 @@ ROM_START( magicardeb ) ROM_REGION( 0x80000, "maincpu", 0 ) // 68070 Code & GFX ROM_LOAD16_WORD_SWAP( "27c4002_v2.9a_5b64.ic21", 0x00000, 0x80000, CRC(81ad0437) SHA1(117e2681541f786874cd0bce7f8bfb2bffb0b548) ) - // PIC undumped // Serial EPROM undumped + ROM_REGION( 0x0100, "sereeprom", 0 ) // Serial EPROM + ROM_LOAD("st24c02.ic26", 0x0000, 0x0100, BAD_DUMP CRC(6c695dd7) SHA1(7fb56c449f7592e200204f38a4cbb4cf7f0f1665) ) + + ROM_REGION(0x8, "serial_id", 0) /* serial number */ + ROM_LOAD( "ds2401", 0x000000, 0x000008, BAD_DUMP CRC(3f87b999) SHA1(29649749d521ced9dc7ef1d0d6ddb9a8beea360f) ) // created to match game + + ROM_REGION(0x4d, "ds1207", 0) /* timekey */ + ROM_LOAD( "ds1207", 0x000000, 0x00004d, BAD_DUMP CRC(b00bf924) SHA1(ab98b2955697765518d877d4e19dbe45de0d9503) ) // created to match game + + // PIC undumped + + ROM_REGION(0x10000, "nvram", 0) /* Default NVRAM */ + ROM_LOAD( "magicardeb.nv", 0x0000, 0x10000, CRC(f40bf542) SHA1(b73838f610dbf35099971d80e240abd672dd36e3) ) ROM_END /* @@ -892,6 +1266,9 @@ ROM_START( magicardec ) ROM_REGION( 0x80000, "maincpu", 0 ) // 68070 Code & GFX ROM_LOAD16_WORD_SWAP( "27c4002_v4.01_af18.ic21", 0x00000, 0x80000, CRC(7700fd22) SHA1(0555c08c82f56e6399a89f6408e52d9d0beba2ac) ) + + ROM_REGION(0x8, "serial_id", 0) /* serial number */ + ROM_LOAD( "ds2401", 0x000000, 0x000008, BAD_DUMP CRC(3f87b999) SHA1(29649749d521ced9dc7ef1d0d6ddb9a8beea360f) ) // created to match game // PIC undumped // Serial EPROM undumped ROM_END @@ -922,7 +1299,13 @@ ROM_START( magicardf ) ROM_LOAD("mx29f1610.ic30", 0x000000, 0x200000, CRC(c8ba9820) SHA1(fcae1e200c718b549b91d1110025595ffd7bdd51) ) ROM_REGION( 0x0100, "sereeprom", 0 ) // Serial EEPROM - ROM_LOAD("24lc02b.ic26", 0x0000, 0x0100, CRC(47c8b137) SHA1(6581e1f4ea65c833fa566c21c76dbe741af488f4) ) + ROM_LOAD("24lc02b.ic26", 0x0000, 0x0100, CRC(5cb1b2b2) SHA1(84d4535e5491d9a4a9c658d39df16757bc572a4b) ) + + ROM_REGION(0x8, "serial_id", 0) /* serial number */ + ROM_LOAD( "ds2401", 0x000000, 0x000008, BAD_DUMP CRC(3f87b999) SHA1(29649749d521ced9dc7ef1d0d6ddb9a8beea360f) ) // created to match game + + ROM_REGION(0x10000, "nvram", 0) /* Default NVRAM */ + ROM_LOAD( "magicardf.nv", 0x0000, 0x10000, CRC(8beb061b) SHA1(c29a2086dea30c98565e811d9686af35da42c9d9) ) ROM_END /* @@ -936,6 +1319,15 @@ ROM_START( magicardw ) ROM_REGION( 0x1fff, "pic16c54", 0 ) // decapped ROM_LOAD("pic16c54a.bin", 0x0000, 0x1fff, CRC(e777e814) SHA1(e0440be76fa1f3c7ae7d31e1b29a2ba73552231c) ) + + ROM_REGION(0x4d, "ds1207", 0) /* timekey */ + ROM_LOAD( "ds1207", 0x000000, 0x00004d, BAD_DUMP CRC(ab0b75a2) SHA1(3a3c594d77936e671d25f526459355cc446a0991) ) // created to match game + + ROM_REGION(0x4000, "nvram", 0) /* Default NVRAM */ + ROM_LOAD( "magicardw.nv", 0x0000, 0x4000, CRC(d6244455) SHA1(b6389574f1d4a4a64590d544c9bafe4892feb0a1) ) + + ROM_REGION( 0x0100, "sereeprom", 0 ) // Serial EEPROM + ROM_LOAD("24lc02b.ic26", 0x0000, 0x0100, CRC(fea8a821) SHA1(c744cac6af7621524fc3a2b0a9a135a32b33c81b) ) ROM_END @@ -1062,9 +1454,9 @@ ROM_END | |___________________| | |__________________________________________________________________________________________________| - Xtal 1: 30.000 MHz. - Xtal 2: 8.000 MHz. - Xtal 3: 19.660 MHz. + Xtal 1: 30.000 MHz. (66470) + Xtal 2: 8.000 MHz. (PIC?) + Xtal 3: 19.660 MHz. (68070) A = LT 0030 / LTC695CN / U18708 B = NEC Japan / D43256BGU-70LL / 0008XD041 @@ -1149,9 +1541,9 @@ ROM_END | |___________________| | |__________________________________________________________________________________________________| - Xtal 1: 30.000 MHz. - Xtal 2: 8.000 MHz. - Xtal 3: 19.660 MHz. + Xtal 1: 30.000 MHz. (66470) + Xtal 2: 8.000 MHz. (PIC?) + Xtal 3: 19.660 MHz. (68070) A = LT 0030 / LTC695CN / U18708 B = NEC Japan / D43256BGU-70LL / 0008XD041 @@ -1236,9 +1628,9 @@ ROM_END | |___________________| | |__________________________________________________________________________________________________| - Xtal 1: 30.000 MHz. - Xtal 2: 8.000 MHz. - Xtal 3: 19.660 MHz. + Xtal 1: 30.000 MHz. (66470) + Xtal 2: 8.000 MHz. (PIC?) + Xtal 3: 19.660 MHz. (68070) A = LT 0030 / LTC695CN / U18708 B = NEC Japan / D43256BGU-70LL / 0008XD041 @@ -1309,9 +1701,9 @@ ROM_END | IMPERA BOARD REV V2.1 |______________| |_________| | |___________________________________________________________________________________________________________________________| - XTAL1 = 30.000 - XTAL2 = 19.6608 - XTAL3 = 3686.400 + XTAL1 = 30.000 (66470) + XTAL2 = 19.6608 (68070) + XTAL3 = 3686.400 (PIC?) A = KM44C256CJ_6 B = TL7705ACP @@ -1331,6 +1723,7 @@ ROM_END /* Unknown 'TE06' + Version 1.1 14.09.94 PCB layout: ________________________________________________________________________________________________________________ @@ -1390,9 +1783,9 @@ ROM_END B = DS1210 C = Cover scratched - unreadable - XTAL1 = 19.6608 - XTAL2 = 30.000 - XTAL3 = 3.686JB + XTAL1 = 19.6608 (68070) + XTAL2 = 30.000 (66470) + XTAL3 = 3.686JB (PIC?) */ ROM_START( unkte06 ) @@ -1401,11 +1794,18 @@ ROM_START( unkte06 ) ROM_REGION( 0x1fff, "pic16c56", 0 ) // decapped ROM_LOAD("pic16c56.bin", 0x0000, 0x1fff, CRC(b5655603) SHA1(d9126c36f3fca7e769ea60aaa711bb304b4b6a11) ) + + ROM_REGION(0x4d, "ds1207", 0) /* timekey */ + ROM_LOAD( "ds1207", 0x000000, 0x00004d, BAD_DUMP CRC(cbcc1a42) SHA1(4b577c85f5856192ce04051a2d305a9080192177) ) // created to match game + + ROM_REGION(0x4000, "nvram", 0) /* Default NVRAM */ + ROM_LOAD( "unkte06.nv", 0x0000, 0x4000, CRC(5b62f04a) SHA1(0cc6404e1bb66801a562ff7a1479859c17e9f209) ) ROM_END /* Lucky 7 Impera + Version 04/91a PCB layout: ________________________________________________________________________________________________________________ @@ -1465,14 +1865,20 @@ ROM_END B = DS1210 C = Cover scratched - unreadable - XTAL1 = 19.6608 - XTAL2 = 30.000 + XTAL1 = 19.6608 (68070) + XTAL2 = 30.000 (66470) */ ROM_START( lucky7i ) ROM_REGION( 0x80000, "maincpu", 0 ) // 68070 Code & GFX ROM_LOAD16_WORD_SWAP( "27c210.6", 0x00000, 0x20000, CRC(3a99e9f3) SHA1(b9b533378ce514662cbd85a37ee138a2df760ed4) ) ROM_LOAD16_WORD_SWAP( "27c210.5", 0x20000, 0x20000, CRC(b4da8856) SHA1(a33158d75047561fa9674ceb6b22cc63b5b49aed) ) + + ROM_REGION(0x4d, "ds1207", 0) /* timekey */ + ROM_LOAD( "ds1207", 0x000000, 0x00004d, BAD_DUMP CRC(7b838ea7) SHA1(5c22b789251becd20f56f944b76c5b779e5a8892) ) // created to match game + + ROM_REGION(0x4000, "nvram", 0) /* Default NVRAM */ + ROM_LOAD( "lucky7i.nv", 0x0000, 0x4000, CRC(51960419) SHA1(ef7f9d7d9714fda0af23b311232194567887a264) ) ROM_END @@ -1566,6 +1972,12 @@ ROM_END ROM_START( unkpkr_w ) ROM_REGION( 0x80000, "maincpu", 0 ) // 68070 Code & GFX ROM_LOAD16_WORD_SWAP( "w.bin", 0x00000, 0x80000, CRC(28300427) SHA1(83ea014a818246f476d769ad06cb2eba1ce699e8) ) + + ROM_REGION(0x4d, "ds1207", 0) /* timekey */ + ROM_LOAD( "ds1207", 0x000000, 0x00004d, BAD_DUMP CRC(cbcc1a42) SHA1(4b577c85f5856192ce04051a2d305a9080192177) ) // created to match game + + ROM_REGION(0x4000, "nvram", 0) /* Default NVRAM */ + ROM_LOAD( "unkpkr_w.nv", 0x0000, 0x4000, CRC(2d2e1082) SHA1(f288fa800da59dc89cdca02e528c94161b149f1c) ) ROM_END /* @@ -1621,9 +2033,9 @@ ROM_END | +--+ +--+ +---------+ | +------------------------------------------------------------------------------+ - XTAL1: 30.0000 - XTAL2: 19.6608 - XTAL3: 16.000 + XTAL1: 30.0000 (66470) + XTAL2: 19.6608 (68070) + XTAL3: 16.000 (PIC?) A: TL7705ACP B: DS1210 @@ -1656,6 +2068,12 @@ ROM_START( dallaspk ) ROM_REGION( 0x80000, "maincpu", 0 ) // 68070 Code & GFX ROM_LOAD16_WORD_SWAP( "cz-v1-p.bin", 0x00000, 0x20000, CRC(ad575e3f) SHA1(4e22957c42610fec0a96bd85f4b766422b020d88) ) ROM_LOAD16_WORD_SWAP( "cz-v1-b.bin", 0x20000, 0x20000, CRC(2595d346) SHA1(34f09931d82b5376e4f3922222645c796dad0440) ) + + ROM_REGION(0x4d, "ds1207", 0) /* timekey */ + ROM_LOAD( "ds1207", 0x000000, 0x00004d, BAD_DUMP CRC(37adab02) SHA1(2b9859ae6cabfdb9c70f94ccc38a271caf6539aa) ) // created to match game + + ROM_REGION(0x4000, "nvram", 0) /* Default NVRAM */ + ROM_LOAD( "dallaspk.nv", 0x0000, 0x4000, CRC(4886d292) SHA1(d06bbeb06c7bc407cb1cf6f2a6d266e578d359e2) ) ROM_END @@ -1713,9 +2131,9 @@ ROM_END | IMPERA BOARD REV V2.1 |______________| |_________| | |___________________________________________________________________________________________________________________________| - XTAL1 = 30.000 - XTAL2 = 19.6608 - XTAL3 = 3686.400 + XTAL1 = 30.000 (66470) + XTAL2 = 19.6608 (68070) + XTAL3 = 3686.400 (PIC?) A = KM44C256CJ-7 B = TL7705ACP @@ -1728,42 +2146,36 @@ ROM_START( kajotcrd ) ROM_REGION( 0x0100, "sereeprom", 0 ) // Serial EPROM ROM_LOAD("x24c02.ic26", 0x0000, 0x0100, CRC(0f143d6f) SHA1(c293728a997cd0868705dced55955072c6ebf5c0) ) -ROM_END - -/********************************************* -* Driver Init * -*********************************************/ - -void magicard_state::init_magicard() -{ - //... -} + ROM_REGION(0x8, "serial_id", 0) /* serial number */ + ROM_LOAD( "ds2401", 0x000000, 0x000008, BAD_DUMP CRC(3f87b999) SHA1(29649749d521ced9dc7ef1d0d6ddb9a8beea360f) ) // created to match game +ROM_END -/********************************************* -* Game Drivers * -*********************************************/ - -// YEAR NAME PARENT MACHINE INPUT STATE INIT ROT COMPANY FULLNAME FLAGS -GAME( 199?, magicard, 0, magicard, magicard, magicard_state, init_magicard, ROT0, "Impera", "Magic Card (set 1)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 199?, magicarda, magicard, magicard, magicard, magicard_state, init_magicard, ROT0, "Impera", "Magic Card (set 2)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 199?, magicardb, magicard, magicard, magicard, magicard_state, init_magicard, ROT0, "Impera", "Magic Card (set 3)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 1994, magicarde, magicard, hotslots, magicard, magicard_state, init_magicard, ROT0, "Impera", "Magic Card Export 94 (v2.11a, set 1)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 1994, magicardea, magicard, hotslots, magicard, magicard_state, init_magicard, ROT0, "Impera", "Magic Card Export 94 (v2.11a, set 2)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 1994, magicardeb, magicard, hotslots, magicard, magicard_state, init_magicard, ROT0, "Impera", "Magic Card Export 94 (v2.9a)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 1998, magicardec, magicard, hotslots, magicard, magicard_state, init_magicard, ROT0, "Impera", "Magic Card Export (v4.01)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 1994, magicardf, magicard, hotslots, magicard, magicard_state, init_magicard, ROT0, "Impera", "Magic Export (V.211A)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 1998, magicardj, 0, hotslots, magicard, magicard_state, init_magicard, ROT0, "Impera", "Magic Card III Jackpot (4.01)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 1993, magicardw, magicard, magicard, magicard, magicard_state, init_magicard, ROT0, "Impera", "Magic Card - Wien (Sicherheitsversion 1.2)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 2001, magicle, 0, magicard, magicard, magicard_state, init_magicard, ROT0, "Impera", "Magic Lotto Export (5.03)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 2002, hotslots, 0, hotslots, magicard, magicard_state, init_magicard, ROT0, "Impera", "Hot Slots (6.00)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 1999, quingo, 0, hotslots, magicard, magicard_state, init_magicard, ROT0, "Impera", "Quingo Export (5.00)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 1999, belslots, 0, hotslots, magicard, magicard_state, init_magicard, ROT0, "Impera", "Bel Slots Export (5.01)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 2001, bigdeal0, 0, hotslots, magicard, magicard_state, init_magicard, ROT0, "Impera", "Big Deal Belgien (5.04)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 199?, puzzleme, 0, hotslots, magicard, magicard_state, init_magicard, ROT0, "Impera", "Puzzle Me!", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 199?, unkte06, 0, magicard, magicard, magicard_state, init_magicard, ROT0, "Impera", "unknown Poker 'TE06'", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) // strings in ROM -GAME( 199?, lucky7i, 0, magicard, magicard, magicard_state, init_magicard, ROT0, "Impera", "Lucky 7 (Impera)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 1993, unkpkr_w, 0, magicard, magicard, magicard_state, init_magicard, ROT0, "", "unknown Poker 'W'", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 1993, dallaspk, 0, magicard, magicard, magicard_state, init_magicard, ROT0, "", "Dallas Poker", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 1993, kajotcrd, 0, hotslots, magicard, magicard_state, init_magicard, ROT0, "Amatic", "Kajot Card (Version 1.01, Wien Euro)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) +/************************* +* Game Drivers * +*************************/ + +// YEAR NAME PARENT MACHINE INPUT STATE INIT ROT COMPANY FULLNAME FLAGS + +GAME( 199?, magicard, 0, magicard, magicard, magicard_state, empty_init, ROT0, "Impera", "Magic Card (set 1)", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) +GAME( 199?, magicarda, magicard, magicard, magicard, magicard_state, empty_init, ROT0, "Impera", "Magic Card (set 2)", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) +GAME( 199?, magicardb, 0, magicard, magicard, magicard_state, empty_init, ROT0, "Impera", "Magic Card (set 3)", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) +GAME( 1994, magicarde, 0, hotslots_pic54, magicarde, hotslots_state, empty_init, ROT0, "Impera", "Magic Card Export 94 (v2.11a, set 1)", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) +GAME( 1994, magicardea, magicarde,hotslots_pic54, magicarde, hotslots_state, empty_init, ROT0, "Impera", "Magic Card Export 94 (v2.11a, set 2)", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) +GAME( 1994, magicardeb, magicarde,hotslots, magicarde, hotslots_state, empty_init, ROT0, "Impera", "Magic Card Export 94 (v2.09a)", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) +GAME( 1998, magicardec, 0, hotslots, magicarde, hotslots_state, empty_init, ROT0, "Impera", "Magic Card III Jackpot (V4.01 6/98)", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) +GAME( 1994, magicardf, magicarde,hotslots, magicarde, hotslots_state, empty_init, ROT0, "Impera", "Magic Card Export 94 (V2.11a, set 3)", MACHINE_SUPPORTS_SAVE ) +GAME( 1998, magicardj, 0, hotslots, magicarde, hotslots_state, empty_init, ROT0, "Impera", "Magic Card III Jackpot (V4.01 7/98)", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) +GAME( 1993, magicardw, magicardb,magicard_pic54, magicard, magicard_state, empty_init, ROT0, "Impera", "Magic Card - Wien (Sicherheitsversion 1.2)", MACHINE_SUPPORTS_SAVE ) +GAME( 2001, magicle, 0, magicle, hotslots, hotslots_state, empty_init, ROT0, "Impera", "Magic Lotto Export (5.03)", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) +GAME( 2002, hotslots, 0, hotslots, hotslots, hotslots_state, empty_init, ROT0, "Impera", "Hot Slots (6.00)", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) +GAME( 1999, quingo, 0, magicle, hotslots, hotslots_state, empty_init, ROT0, "Impera", "Quingo Export (5.00)", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) +GAME( 1999, belslots, 0, magicle, hotslots, hotslots_state, empty_init, ROT0, "Impera", "Bel Slots Export (5.01)", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) +GAME( 2001, bigdeal0, 0, magicle, magicard, hotslots_state, empty_init, ROT0, "Impera", "Big Deal Belgien (5.04)", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) +GAME( 199?, puzzleme, 0, puzzleme, puzzleme, hotslots_state, empty_init, ROT0, "Impera", "Puzzle Me!", MACHINE_SUPPORTS_SAVE ) +GAME( 1994, unkte06, magicardb,unkte06, magicard, magicard_state, empty_init, ROT0, "Impera", "unknown Poker 'TE06'", MACHINE_SUPPORTS_SAVE ) // strings in ROM +GAME( 199?, lucky7i, 0, magicard, lucky7i, magicard_state, empty_init, ROT0, "Impera", "Lucky 7 (Impera) V04/91a", MACHINE_SUPPORTS_SAVE ) +GAME( 1993, unkpkr_w, magicardb,magicard, magicard, magicard_state, empty_init, ROT0, "", "unknown Poker 'W'", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) +GAME( 1993, dallaspk, 0, magicard, dallaspk, magicard_state, empty_init, ROT0, "", "Dallas Poker", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) +GAME( 1993, kajotcrd, 0, hotslots, magicard, hotslots_state, empty_init, ROT0, "Amatic", "Kajot Card (Version 1.01, Wien Euro)", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) diff --git a/src/mame/philips/cdicdic.cpp b/src/mame/philips/cdicdic.cpp index 91cc05d28a6..5094d971780 100644 --- a/src/mame/philips/cdicdic.cpp +++ b/src/mame/philips/cdicdic.cpp @@ -1313,10 +1313,10 @@ void cdicdic_device::regs_w(offs_t offset, uint16_t data, uint16_t mem_mask) uint16_t *ram = (uint16_t *)m_ram.get(); LOGMASKED(LOG_WRITES, "%s: cdic_w: DMA Control Register = %04x & %04x\n", machine().describe_context(), data, mem_mask); LOGMASKED(LOG_WRITES, "%s: Memory address counter: %08x\n", machine().describe_context(), m_scc->dma().channel[0].memory_address_counter); - LOGMASKED(LOG_WRITES, "%s: Doing copy, transferring %04x bytes %s\n", machine().describe_context(), count * 2, (m_scc->dma().channel[0].operation_control & OCR_D) ? "to main RAM" : "to device RAM"); + LOGMASKED(LOG_WRITES, "%s: Doing copy, transferring %04x bytes %s\n", machine().describe_context(), count * 2, (m_scc->dma().channel[0].operation_control & SCC68070_OCR_D) ? "to main RAM" : "to device RAM"); for (uint32_t index = start / 2; index < (start / 2 + count); index++) { - if (m_scc->dma().channel[0].operation_control & OCR_D) + if (m_scc->dma().channel[0].operation_control & SCC68070_OCR_D) { m_memory_space->write_word(index * 2, ram[device_index++]); } -- cgit v1.2.3