From 04ed39a0514d522f157d28d227519172a9486c1d Mon Sep 17 00:00:00 2001 From: Ryan Holtz Date: Sun, 24 May 2020 22:02:04 +0200 Subject: [PATCH] -quizard: Replaced protection HLE with proper MCU hookup. Removed MUP flags. Re-promoted Quizard 1 and Quizard 2. [Ryan Holtz] -scc68070: Improved UART Tx/Rx behavior, though it still functions in parallel rather than serial. [Ryan Holtz] --- src/devices/machine/scc68070.cpp | 162 ++++++++------- src/devices/machine/scc68070.h | 16 +- src/mame/drivers/cdi.cpp | 337 +++++++------------------------ src/mame/includes/cdi.h | 73 +------ src/mame/machine/cdislavehle.cpp | 1 + 5 files changed, 196 insertions(+), 393 deletions(-) diff --git a/src/devices/machine/scc68070.cpp b/src/devices/machine/scc68070.cpp index 1eb91c6c93d..2363b01637f 100644 --- a/src/devices/machine/scc68070.cpp +++ b/src/devices/machine/scc68070.cpp @@ -32,9 +32,10 @@ TODO: #define LOG_MMU (1 << 5) #define LOG_IRQS (1 << 6) #define LOG_UNKNOWN (1 << 7) +#define LOG_MORE_UART (1 << 8) #define LOG_ALL (LOG_I2C | LOG_UART | LOG_TIMERS | LOG_DMA | LOG_MMU | LOG_IRQS | LOG_UNKNOWN) -#define VERBOSE (LOG_UART) +#define VERBOSE (0) #include "logmacro.h" @@ -84,6 +85,7 @@ scc68070_device::scc68070_device(const machine_config &mconfig, const char *tag, , m_iack5_callback(*this) , m_iack7_callback(*this) , m_uart_tx_callback(*this) + , m_uart_rtsn_callback(*this) , m_ipl(0) , m_in2_line(CLEAR_LINE) , m_in4_line(CLEAR_LINE) @@ -110,6 +112,7 @@ void scc68070_device::device_resolve_objects() m_iack5_callback.resolve_safe(autovector(5)); m_iack7_callback.resolve_safe(autovector(7)); m_uart_tx_callback.resolve_safe(); + m_uart_rtsn_callback.resolve_safe(); } //------------------------------------------------- @@ -148,8 +151,13 @@ void scc68070_device::device_start() save_item(NAME(m_uart.status_register)); save_item(NAME(m_uart.clock_select)); save_item(NAME(m_uart.command_register)); - save_item(NAME(m_uart.transmit_holding_register)); save_item(NAME(m_uart.receive_holding_register)); + save_item(NAME(m_uart.receive_pointer)); + save_item(NAME(m_uart.receive_buffer)); + save_item(NAME(m_uart.transmit_holding_register)); + save_item(NAME(m_uart.transmit_pointer)); + save_item(NAME(m_uart.transmit_buffer)); + save_item(NAME(m_uart.transmit_ctsn)); save_item(NAME(m_timers.timer_status_register)); save_item(NAME(m_timers.timer_control_register)); @@ -175,13 +183,13 @@ void scc68070_device::device_start() save_item(STRUCT_MEMBER(m_mmu.desc, segment)); save_item(STRUCT_MEMBER(m_mmu.desc, base)); - m_timers.timer0_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(scc68070_device::timer0_callback), this)); + m_timers.timer0_timer = timer_alloc(TIMER_TMR0); m_timers.timer0_timer->adjust(attotime::never); - m_uart.rx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(scc68070_device::rx_callback), this)); + m_uart.rx_timer = timer_alloc(TIMER_UART_RX); m_uart.rx_timer->adjust(attotime::never); - m_uart.tx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(scc68070_device::tx_callback), this)); + m_uart.tx_timer = timer_alloc(TIMER_UART_TX); m_uart.tx_timer->adjust(attotime::never); } @@ -216,6 +224,7 @@ void scc68070_device::device_reset() m_uart.receive_holding_register = 0; m_uart.receive_pointer = -1; m_uart.transmit_pointer = -1; + m_uart.transmit_ctsn = true; m_timers.timer_status_register = 0; m_timers.timer_control_register = 0; @@ -248,6 +257,24 @@ void scc68070_device::device_reset() } update_ipl(); + + m_uart.rx_timer->adjust(attotime::never); + m_uart.tx_timer->adjust(attotime::never); + m_timers.timer0_timer->adjust(attotime::never); +} + +//------------------------------------------------- +// device_timer - device-specific timer callback +//------------------------------------------------- + +void scc68070_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if (id == TIMER_TMR0) + timer0_callback(); + else if (id == TIMER_UART_RX) + rx_callback(); + else if (id == TIMER_UART_TX) + tx_callback(); } void scc68070_device::m68k_reset_peripherals() @@ -275,6 +302,10 @@ void scc68070_device::m68k_reset_peripherals() m_timers.timer_status_register = 0; m_timers.timer_control_register = 0; + m_uart.rx_timer->adjust(attotime::never); + m_uart.tx_timer->adjust(attotime::never); + m_timers.timer0_timer->adjust(attotime::never); + update_ipl(); } @@ -438,7 +469,7 @@ void scc68070_device::set_timer_callback(int channel) } } -TIMER_CALLBACK_MEMBER( scc68070_device::timer0_callback ) +void scc68070_device::timer0_callback() { m_timers.timer0 = m_timers.reload_register; m_timers.timer_status_register |= TSR_OV0; @@ -451,60 +482,25 @@ TIMER_CALLBACK_MEMBER( scc68070_device::timer0_callback ) set_timer_callback(0); } -void scc68070_device::uart_rx_check() +void scc68070_device::uart_ctsn(int state) { - if ((m_uart.command_register & 3) == 1) - { - uint32_t div = 0x10000 >> ((m_uart.clock_select >> 4) & 7); - m_uart.rx_timer->adjust(attotime::from_hz((49152000 / div) / 8)); - } - else - { - m_uart.status_register &= ~USR_RXRDY; - m_uart.rx_timer->adjust(attotime::never); - } -} - -void scc68070_device::uart_tx_check() -{ - if (((m_uart.command_register >> 2) & 3) == 1) - { - if (m_uart.transmit_pointer >= 0) - { - m_uart.status_register &= ~USR_TXRDY; - } - else - { - m_uart.status_register |= USR_TXRDY; - } - - if (m_uart.tx_timer->remaining() == attotime::never) - { - uint32_t div = 0x10000 >> (m_uart.clock_select & 7); - m_uart.tx_timer->adjust(attotime::from_hz((49152000 / div) / 8)); - } - } - else - { - m_uart.tx_timer->adjust(attotime::never); - } + m_uart.transmit_ctsn = state ? true : false; } void scc68070_device::uart_rx(uint8_t data) { m_uart.receive_pointer++; m_uart.receive_buffer[m_uart.receive_pointer] = data; - uart_rx_check(); } void scc68070_device::uart_tx(uint8_t data) { m_uart.transmit_pointer++; m_uart.transmit_buffer[m_uart.transmit_pointer] = data; - uart_tx_check(); + m_uart.status_register &= ~USR_TXEMT; } -TIMER_CALLBACK_MEMBER( scc68070_device::rx_callback ) +void scc68070_device::rx_callback() { if ((m_uart.command_register & 3) == 1) { @@ -527,8 +523,6 @@ TIMER_CALLBACK_MEMBER( scc68070_device::rx_callback ) update_ipl(); m_uart.status_register |= USR_RXRDY; - uint32_t div = 0x10000 >> ((m_uart.clock_select >> 4) & 7); - m_uart.rx_timer->adjust(attotime::from_hz((49152000 / div) / 8)); } else { @@ -539,43 +533,40 @@ TIMER_CALLBACK_MEMBER( scc68070_device::rx_callback ) { m_uart.status_register &= ~USR_RXRDY; } - - uart_rx_check(); } -TIMER_CALLBACK_MEMBER( scc68070_device::tx_callback ) +void scc68070_device::tx_callback() { if (((m_uart.command_register >> 2) & 3) == 1) { + m_uart.status_register |= USR_TXRDY; + m_uart_tx_int = true; update_ipl(); if (m_uart.transmit_pointer > -1) { + if (m_uart.transmit_ctsn && BIT(m_uart.mode_register, 4)) + { + return; + } + m_uart.transmit_holding_register = m_uart.transmit_buffer[0]; m_uart_tx_callback(m_uart.transmit_holding_register); - LOGMASKED(LOG_UART, "tx_callback: Transmitting %02x\n", machine().describe_context(), m_uart.transmit_holding_register); + LOGMASKED(LOG_MORE_UART, "tx_callback: Transmitting %02x\n", m_uart.transmit_holding_register); for(int index = 0; index < m_uart.transmit_pointer; index++) { m_uart.transmit_buffer[index] = m_uart.transmit_buffer[index+1]; } m_uart.transmit_pointer--; - - uint32_t div = 0x10000 >> (m_uart.clock_select & 7); - m_uart.tx_timer->adjust(attotime::from_hz((49152000 / div) / 8)); } - else + + if (m_uart.transmit_pointer < 0) { - m_uart.tx_timer->adjust(attotime::never); + m_uart.status_register |= USR_TXEMT; } } - else - { - m_uart.tx_timer->adjust(attotime::never); - } - - uart_tx_check(); } uint8_t scc68070_device::lir_r() @@ -746,13 +737,13 @@ uint8_t scc68070_device::umr_r() { // UART mode register: 80002011 if (!machine().side_effects_disabled()) - LOGMASKED(LOG_UART, "%s: UART Mode Register Read: %02x\n", machine().describe_context(), m_uart.mode_register); + LOGMASKED(LOG_MORE_UART, "%s: UART Mode Register Read: %02x\n", machine().describe_context(), m_uart.mode_register); return m_uart.mode_register | 0x20; } void scc68070_device::umr_w(uint8_t data) { - LOGMASKED(LOG_UART, "%s: UART Mode Register Write: %02x\n", machine().describe_context(), data); + LOGMASKED(LOG_MORE_UART, "%s: UART Mode Register Write: %02x\n", machine().describe_context(), data); m_uart.mode_register = data; } @@ -762,7 +753,7 @@ uint8_t scc68070_device::usr_r() if (!machine().side_effects_disabled()) { m_uart.status_register |= (1 << 1); - LOGMASKED(LOG_UART, "%s: UART Status Register Read: %02x\n", machine().describe_context(), m_uart.status_register); + LOGMASKED(LOG_MORE_UART, "%s: UART Status Register Read: %02x\n", machine().describe_context(), m_uart.status_register); } return m_uart.status_register | 0x08; // hack for magicard } @@ -779,6 +770,13 @@ void scc68070_device::ucsr_w(uint8_t data) { LOGMASKED(LOG_UART, "%s: UART Clock Select Write: %02x\n", machine().describe_context(), data); m_uart.clock_select = data; + + static const uint32_t s_baud_divisors[8] = { 65536, 32768, 16384, 4096, 2048, 1024, 512, 256 }; + + attotime rx_rate = attotime::from_ticks(s_baud_divisors[(data >> 4) & 7] * 10, 49152000); + attotime tx_rate = attotime::from_ticks(s_baud_divisors[data & 7] * 10, 49152000); + m_uart.rx_timer->adjust(rx_rate, 0, rx_rate); + m_uart.tx_timer->adjust(tx_rate, 0, tx_rate); } uint8_t scc68070_device::ucr_r() @@ -791,10 +789,36 @@ uint8_t scc68070_device::ucr_r() void scc68070_device::ucr_w(uint8_t data) { - LOGMASKED(LOG_UART, "%s: UART Command Register Write: %02x\n", machine().describe_context(), data); + LOGMASKED(LOG_MORE_UART, "%s: UART Command Register Write: %02x\n", machine().describe_context(), data); m_uart.command_register = data; - uart_rx_check(); - uart_tx_check(); + const uint8_t misc_command = (data & 0x70) >> 4; + switch (misc_command) + { + case 0x2: // Reset receiver + LOGMASKED(LOG_MORE_UART, "%s: Reset receiver\n", machine().describe_context()); + m_uart.receive_pointer = -1; + m_uart.command_register &= 0xf0; + m_uart.receive_holding_register = 0x00; + break; + case 0x3: // Reset transmitter + LOGMASKED(LOG_MORE_UART, "%s: Reset transmitter\n", machine().describe_context()); + m_uart.transmit_pointer = -1; + m_uart.status_register |= USR_TXEMT; + m_uart.command_register &= 0xf0; + m_uart.transmit_holding_register = 0x00; + break; + case 0x4: // Reset error status + LOGMASKED(LOG_MORE_UART, "%s: Reset error status\n", machine().describe_context()); + m_uart.status_register &= 0x87; // Clear error bits in USR + m_uart.command_register &= 0xf0; + break; + case 0x6: // Start break + LOGMASKED(LOG_MORE_UART, "%s: Start break (not yet implemented)\n", machine().describe_context()); + break; + case 0x7: // Stop break + LOGMASKED(LOG_MORE_UART, "%s: Stop break (not yet implemented)\n", machine().describe_context()); + break; + } } uint8_t scc68070_device::uth_r() @@ -807,7 +831,7 @@ uint8_t scc68070_device::uth_r() void scc68070_device::uth_w(uint8_t data) { - LOGMASKED(LOG_UART, "%s: UART Transmit Holding Register Write: %02x ('%c')\n", machine().describe_context(), data, (data >= 0x20 && data < 0x7f) ? data : ' '); + LOGMASKED(LOG_MORE_UART, "%s: UART Transmit Holding Register Write: %02x ('%c')\n", machine().describe_context(), data, (data >= 0x20 && data < 0x7f) ? data : ' '); uart_tx(data); m_uart.transmit_holding_register = data; } diff --git a/src/devices/machine/scc68070.h b/src/devices/machine/scc68070.h index 84d160fec9d..2bae392ab63 100644 --- a/src/devices/machine/scc68070.h +++ b/src/devices/machine/scc68070.h @@ -140,6 +140,7 @@ public: auto iack5_callback() { return m_iack5_callback.bind(); } 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(); } DECLARE_WRITE_LINE_MEMBER(in2_w); DECLARE_WRITE_LINE_MEMBER(in4_w); @@ -150,10 +151,11 @@ public: // external callbacks void uart_rx(uint8_t data); + void uart_ctsn(int state); - TIMER_CALLBACK_MEMBER( timer0_callback ); - TIMER_CALLBACK_MEMBER( rx_callback ); - TIMER_CALLBACK_MEMBER( tx_callback ); + void timer0_callback(); + void rx_callback(); + void tx_callback(); // register structures struct i2c_regs_t @@ -192,6 +194,7 @@ public: int16_t transmit_pointer; uint8_t transmit_buffer[32768]; emu_timer* tx_timer; + bool transmit_ctsn; }; struct timer_regs_t @@ -261,6 +264,7 @@ protected: virtual void device_resolve_objects() override; virtual void device_start() override; virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; // device_execute_interface overrides virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept override { return (clocks + 2 - 1) / 2; } @@ -273,6 +277,10 @@ private: void internal_map(address_map &map); void cpu_space_map(address_map &map); + static constexpr device_timer_id TIMER_TMR0 = 0; + static constexpr device_timer_id TIMER_UART_RX = 1; + static constexpr device_timer_id TIMER_UART_TX = 2; + void update_ipl(); uint8_t iack_r(offs_t offset); @@ -323,6 +331,7 @@ private: void uart_rx_check(); void uart_tx_check(); void uart_tx(uint8_t data); + void uart_do_tx(); void set_timer_callback(int channel); // callbacks @@ -331,6 +340,7 @@ private: devcb_read8 m_iack5_callback; devcb_read8 m_iack7_callback; devcb_write8 m_uart_tx_callback; + devcb_write_line m_uart_rtsn_callback; // internal state uint8_t m_ipl; diff --git a/src/mame/drivers/cdi.cpp b/src/mame/drivers/cdi.cpp index bdf696bde10..2ceeb1ebee6 100644 --- a/src/mame/drivers/cdi.cpp +++ b/src/mame/drivers/cdi.cpp @@ -31,14 +31,8 @@ STATUS: * PC85010 DSP Quizard: -- Quizard does not work due to MCU not being fully hooked up. - -- The Quizard MCU makes use of both serial ports, the second of which is - connected to the SCC68070's UART, and the first of which, which is connected - to the RDI and TDO pins of the SLAVE MCU's UART. Thus the Quizard MCU cannot - be hooked up fully until there is proper LLE of the SLAVE MCU, or input - reading is decoupled from the high-level simulation so that arbitrary serial - devices can be hooked up. +- Quizard 3 and 4 fail when going in-game, presumably due to CD-i emulation + faults. TODO: @@ -69,7 +63,13 @@ TODO: // TODO: NTSC system clock is 30.2098 MHz; additional 4.9152 MHz XTAL provided for UART #define CLOCK_A 30_MHz_XTAL -#define VERBOSE (1) +#define LOG_DVC (1 << 1) +#define LOG_QUIZARD_READS (1 << 2) +#define LOG_QUIZARD_WRITES (1 << 3) +#define LOG_QUIZARD_OTHER (1 << 4) +#define LOG_UART (1 << 5) + +#define VERBOSE (0) #include "logmacro.h" #define ENABLE_UART_PRINTING (0) @@ -144,52 +144,6 @@ void cdi_state::cdi910_mem(address_map &map) * Input ports * *************************/ -INPUT_CHANGED_MEMBER(quizard_state::mcu_input) -{ - bool send = false; - - switch (param) - { - case 0x39: - //if (m_input1.read_safe(0) & 0x01) send = true; - break; - case 0x37: - //if (m_input1.read_safe(0) & 0x02) send = true; - break; - case 0x31: - //if (m_input1.read_safe(0) & 0x04) send = true; - break; - case 0x32: - //if (m_input1.read_safe(0) & 0x08) send = true; - break; - case 0x33: - //if (m_input1.read_safe(0) & 0x10) send = true; - break; - - case 0x30: - //if (m_input2.read_safe(0) & 0x01) send = true; - break; - case 0x38: - //if (m_input2.read_safe(0) & 0x02) send = true; - break; - case 0x34: - //if (m_input2.read_safe(0) & 0x04) send = true; - break; - case 0x35: - //if (m_input2.read_safe(0) & 0x08) send = true; - break; - case 0x36: - //if (m_input2.read_safe(0) & 0x10) send = true; - break; - } - - if (send) - { - uint8_t data = uint8_t(param & 0x000000ff); - mcu_hle_tx(data); - } -} - static INPUT_PORTS_START( cdi ) PORT_START("DEBUG") PORT_CONFNAME( 0x01, 0x00, "Plane A Disable") @@ -269,8 +223,7 @@ static INPUT_PORTS_START( quizard ) PORT_BIT( 0xc8, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("P1") - PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 ) + PORT_BIT( 0x1f, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START1 ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START2 ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SERVICE1 ) @@ -283,10 +236,6 @@ static INPUT_PORTS_START( quizard ) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("Player 2 B") PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("Player 2 C") PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_START("P3") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON7 ) PORT_NAME("Fake RTS from Console") - PORT_BIT( 0xfe, IP_ACTIVE_HIGH, IPT_UNUSED ) INPUT_PORTS_END @@ -303,236 +252,103 @@ void cdi_state::machine_reset() void quizard_state::machine_start() { - save_item(NAME(m_seeds)); - save_item(NAME(m_state)); - save_item(NAME(m_mcu_value)); - save_item(NAME(m_mcu_ack)); + save_item(NAME(m_mcu_rx_from_cpu)); + save_item(NAME(m_mcu_initial_byte)); } void quizard_state::machine_reset() { cdi_state::machine_reset(); - memset(m_seeds, 0, 10 * sizeof(uint16_t)); - memset(m_state, 0, 8 * sizeof(uint8_t)); + m_mcu_rx_from_cpu = 0x00; + m_mcu_initial_byte = true; } -/*************************** -* Quizard Protection HLE * -***************************/ +/********************** +* Quizard Protection * +**********************/ -void quizard_state::set_mcu_ack(uint8_t ack) +void quizard_state::mcu_rtsn_from_cpu(int state) { - m_mcu_ack = ack; + LOGMASKED(LOG_UART, "MCU receiving RTSN from CPU: %d\n", state); } -void quizard_state::set_mcu_value(uint16_t value) +void quizard_state::mcu_rx_from_cpu(uint8_t data) { - m_mcu_value = value; -} - -void quizard_state::mcu_hle_tx(uint8_t data) -{ - m_maincpu->uart_rx(0x5a); - m_maincpu->uart_rx(data); -} - -void quizard_state::mcu_set_seeds(uint8_t *rx) -{ - m_seeds[0] = (rx[1] << 8) | rx[0]; - m_seeds[1] = (rx[3] << 8) | rx[2]; - m_seeds[2] = (rx[5] << 8) | rx[4]; - m_seeds[3] = (rx[7] << 8) | rx[6]; - m_seeds[4] = (rx[9] << 8) | rx[8]; - m_seeds[5] = (rx[11] << 8) | rx[10]; - m_seeds[6] = (rx[13] << 8) | rx[12]; - m_seeds[7] = (rx[15] << 8) | rx[14]; - m_seeds[8] = (rx[17] << 8) | rx[16]; - m_seeds[9] = (rx[19] << 8) | rx[18]; -} - -void quizard_state::mcu_calculate_state() -{ - //const uint16_t desired_bitfield = mcu_value; - const uint16_t field0 = 0x00ff; - const uint16_t field1 = m_mcu_value ^ 0x00ff; - - uint16_t total0 = 0; - uint16_t total1 = 0; - - for(int index = 0; index < 10; index++) + LOGMASKED(LOG_UART, "MCU receiving %02x from CPU\n", data); + if (m_mcu_initial_byte) { - if (field0 & (1 << index)) - { - total0 += m_seeds[index]; - } - if (field1 & (1 << index)) - { - total1 += m_seeds[index]; - } + m_mcu_initial_byte = false; + return; } - uint16_t hi0 = (total0 >> 8) + 0x40; - m_state[2] = hi0 / 2; - m_state[3] = hi0 - m_state[2]; + m_mcu_rx_from_cpu = data; - uint16_t lo0 = (total0 & 0x00ff) + 0x40; - m_state[0] = lo0 / 2; - m_state[1] = lo0 - m_state[0]; - - uint16_t hi1 = (total1 >> 8) + 0x40; - m_state[6] = hi1 / 2; - m_state[7] = hi1 - m_state[6]; - - uint16_t lo1 = (total1 & 0x00ff) + 0x40; - m_state[4] = lo1 / 2; - m_state[5] = lo1 - m_state[4]; -} - -void quizard_state::mcu_hle_rx(uint8_t data) -{ - static int state = 0; - static uint8_t rx[0x100]; - static uint8_t rx_ptr = 0xff; - - switch (state) - { - case 0: // Waiting for a leadoff byte - if (data == m_mcu_ack) // Sequence end - { - //scc68070_uart_rx(machine, scc68070, 0x5a); - //scc68070_uart_rx(machine, scc68070, 0x42); - } - else - { - switch (data) - { - case 0x44: // DATABASEPATH = **_DATABASE/ - rx[0] = 0x44; - rx_ptr = 1; - state = 3; - break; - case 0x2e: // Unknown; ignored - break; - case 0x56: // Seed start - rx_ptr = 0; - state = 1; - break; - default: - //printf("Unknown leadoff byte: %02x\n", data); - break; - } - } - break; - - case 1: // Receiving the seed - rx[rx_ptr] = data; - rx_ptr++; - if (rx_ptr == 20) - { - //printf("Calculating seeds\n"); - mcu_set_seeds(rx); - mcu_calculate_state(); - state = 2; - } - break; - - case 2: // Receiving the seed acknowledge - case 4: - if (data == m_mcu_ack) - { - if (state == 2) - { - state = 4; - } - else - { - state = 0; - } - //printf("Sending seed ack\n"); - m_maincpu->uart_rx(0x5a); - m_maincpu->uart_rx(m_state[0]); - m_maincpu->uart_rx(m_state[1]); - m_maincpu->uart_rx(m_state[2]); - m_maincpu->uart_rx(m_state[3]); - m_maincpu->uart_rx(m_state[4]); - m_maincpu->uart_rx(m_state[5]); - m_maincpu->uart_rx(m_state[6]); - m_maincpu->uart_rx(m_state[7]); - } - break; - - case 3: // Receiving the database path - rx[rx_ptr] = data; - rx_ptr++; - if (data == 0x0a) - { - /*rx[rx_ptr] = 0; - //printf("Database path: %s\n", rx); - scc68070_uart_rx(machine, scc68070, 0x5a); - scc68070_uart_rx(machine, scc68070, g_state[0]); - scc68070_uart_rx(machine, scc68070, g_state[1]); - scc68070_uart_rx(machine, scc68070, g_state[2]); - scc68070_uart_rx(machine, scc68070, g_state[3]); - scc68070_uart_rx(machine, scc68070, g_state[4]); - scc68070_uart_rx(machine, scc68070, g_state[5]); - scc68070_uart_rx(machine, scc68070, g_state[6]); - scc68070_uart_rx(machine, scc68070, g_state[7]);*/ - state = 0; - } - break; - } + m_mcu->set_input_line(MCS51_RX_LINE, ASSERT_LINE); + m_mcu->set_input_line(MCS51_RX_LINE, CLEAR_LINE); } uint8_t quizard_state::mcu_p0_r() { const uint8_t data = m_inputs[0]->read(); - LOG("%s: MCU Port 0 Read (%02x)\n", machine().describe_context(), data); + LOGMASKED(LOG_QUIZARD_READS, "%s: MCU Port 0 Read (%02x)\n", machine().describe_context(), data); return data; } uint8_t quizard_state::mcu_p1_r() { - const uint8_t data = m_inputs[1]->read(); - LOG("%s: MCU Port 1 Read (%02x)\n", machine().describe_context(), data); + uint8_t data = m_inputs[1]->read(); + if (BIT(~m_inputs[0]->read(), 4)) + data &= ~(1 << 4); + LOGMASKED(LOG_QUIZARD_READS, "%s: MCU Port 1 Read (%02x)\n", machine().describe_context(), data); return data; } uint8_t quizard_state::mcu_p2_r() { const uint8_t data = m_inputs[2]->read(); - LOG("%s: MCU Port 2 Read (%02x)\n", machine().describe_context(), data); + LOGMASKED(LOG_QUIZARD_READS, "%s: MCU Port 2 Read (%02x)\n", machine().describe_context(), data); return data; } uint8_t quizard_state::mcu_p3_r() { - const uint8_t data = 0x04 | (m_inputs[3]->read() ? 0x80 : 0x00); - LOG("%s: MCU Port 3 Read (%02x)\n", machine().describe_context(), data); - return data; + LOGMASKED(LOG_QUIZARD_READS, "%s: MCU Port 3 Read (%02x)\n", machine().describe_context(), 0x04); + return 0x04; +} + +void quizard_state::mcu_p0_w(uint8_t data) +{ + LOGMASKED(LOG_QUIZARD_WRITES, "%s: MCU Port 0 Write (%02x)\n", machine().describe_context(), data); +} + +void quizard_state::mcu_p1_w(uint8_t data) +{ + LOGMASKED(LOG_QUIZARD_WRITES, "%s: MCU Port 1 Write (%02x)\n", machine().describe_context(), data); } void quizard_state::mcu_p2_w(uint8_t data) { - LOG("%s: MCU Port 2 Write (%02x)\n", machine().describe_context(), data); - m_mcu->set_input_line(MCS51_INT1_LINE, BIT(data, 7) ? ASSERT_LINE : CLEAR_LINE); + LOGMASKED(LOG_QUIZARD_WRITES, "%s: MCU Port 2 Write (%02x)\n", machine().describe_context(), data); } void quizard_state::mcu_p3_w(uint8_t data) { - LOG("%s: MCU Port 3 Write (%02x)\n", machine().describe_context(), data); + LOGMASKED(LOG_QUIZARD_WRITES, "%s: MCU Port 3 Write (%02x)\n", machine().describe_context(), data); + m_maincpu->uart_ctsn(BIT(data, 6)); } void quizard_state::mcu_tx(uint8_t data) { - LOG("%s: MCU transmitting %02x\n", machine().describe_context(), data); + LOGMASKED(LOG_QUIZARD_OTHER, "%s: MCU transmitting %02x\n", machine().describe_context(), data); + m_maincpu->uart_rx(data); } uint8_t quizard_state::mcu_rx() { - uint8_t data = 0; - LOG("%s: MCU receiving %02x\n", machine().describe_context(), data); + uint8_t data = m_mcu_rx_from_cpu; + LOGMASKED(LOG_QUIZARD_OTHER, "%s: MCU receiving %02x\n", machine().describe_context(), data); return data; } @@ -542,13 +358,13 @@ uint8_t quizard_state::mcu_rx() READ16_MEMBER( cdi_state::dvc_r ) { - logerror("%s: dvc_r: %08x = 0000 & %04x\n", machine().describe_context(), 0xe80000 + (offset << 1), mem_mask); + LOGMASKED(LOG_DVC, "%s: dvc_r: %08x = 0000 & %04x\n", machine().describe_context(), 0xe80000 + (offset << 1), mem_mask); return 0; } WRITE16_MEMBER( cdi_state::dvc_w ) { - logerror("%s: dvc_w: %08x = %04x & %04x\n", machine().describe_context(), 0xe80000 + (offset << 1), data, mem_mask); + LOGMASKED(LOG_DVC, "%s: dvc_w: %08x = %04x & %04x\n", machine().describe_context(), 0xe80000 + (offset << 1), data, mem_mask); } /************************* @@ -794,13 +610,16 @@ void quizard_state::quizard(machine_config &config) { cdimono1_base(config); m_maincpu->set_addrmap(AS_PROGRAM, &quizard_state::cdimono1_mem); - m_maincpu->uart_tx_callback().set(FUNC(quizard_state::mcu_hle_rx)); + m_maincpu->uart_rtsn_callback().set(FUNC(quizard_state::mcu_rtsn_from_cpu)); + m_maincpu->uart_tx_callback().set(FUNC(quizard_state::mcu_rx_from_cpu)); I8751(config, m_mcu, 8000000); m_mcu->port_in_cb<0>().set(FUNC(quizard_state::mcu_p0_r)); m_mcu->port_in_cb<1>().set(FUNC(quizard_state::mcu_p1_r)); m_mcu->port_in_cb<2>().set(FUNC(quizard_state::mcu_p2_r)); m_mcu->port_in_cb<3>().set(FUNC(quizard_state::mcu_p3_r)); + m_mcu->port_out_cb<0>().set(FUNC(quizard_state::mcu_p0_w)); + m_mcu->port_out_cb<1>().set(FUNC(quizard_state::mcu_p1_w)); m_mcu->port_out_cb<2>().set(FUNC(quizard_state::mcu_p2_w)); m_mcu->port_out_cb<3>().set(FUNC(quizard_state::mcu_p3_w)); m_mcu->serial_tx_cb().set(FUNC(quizard_state::mcu_tx)); @@ -882,15 +701,15 @@ ROM_END /* Quizard notes The MCU controls the protection sequence, which in turn controls the game display language. - Each Quizard game (1,2,3,4) requires it's own MCU, you can upgrade between revisions by changing + Each Quizard game (1,2,3,4) requires its own MCU, you can upgrade between revisions by changing just the CD, but not between games as a new MCU is required. MCU Notes: i8751 MCU dumps confirmed good on original hardware German language MCUs for Quizard 1 through 4 are dumped - Czechoslovakian language MCU for Quizard 4 is dumped - Known to exist a Quizard 1 Italian language MCU IT 11 L2 (not dumped) - Known to exist is an alternate Quizard 2 German language MCU DE 122 D3 (not dumped) + Czech language MCU for Quizard 4 is dumped + Italian language MCU for Quizard 1 is known to exist (IT 11 L2, not dumped) + Alt. German language MCU for Quizard 2 is known to exist (DE 122 D3, not dumped) */ @@ -1071,24 +890,24 @@ CONS( 1991, cdimono2, 0, 0, cdimono2, cdimono2, cdi_state, empty_init, CONS( 1991, cdi910, 0, 0, cdi910, cdimono2, cdi_state, empty_init, "Philips", "CD-i 910-17P Mini-MMC (PAL)", MACHINE_NOT_WORKING ) CONS( 1991, cdi490a, 0, 0, cdimono1, cdi, cdi_state, empty_init, "Philips", "CD-i 490", MACHINE_NOT_WORKING ) -// The Quizard games are RETAIL CD-i units, with additional JAMMA adapters & dongles for protection, hence being 'clones' of the system. +// The Quizard games are retail CD-i units in a cabinet, with an additional JAMMA adapter and dongle for protection, hence being clones of the system. /* YEAR NAME PARENT MACHINE INPUT DEVICE INIT MONITOR COMPANY FULLNAME */ -GAME( 1995, cdibios, 0, cdimono1, quizard, cdi_state, empty_init, ROT0, "Philips", "CD-i (Mono-I) (PAL) BIOS", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IS_BIOS_ROOT ) +GAME( 1995, cdibios, 0, cdimono1, quizard, cdi_state, empty_init, ROT0, "Philips", "CD-i (Mono-I) (PAL) BIOS", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IS_BIOS_ROOT ) -GAME( 1995, quizard, cdibios, quizard, quizard, quizard1_state, empty_init, ROT0, "TAB Austria", "Quizard (v1.8, German, i8751 DE 11 D3)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_UNEMULATED_PROTECTION ) -GAME( 1995, quizard_17, quizard, quizard, quizard, quizard1_state, empty_init, ROT0, "TAB Austria", "Quizard (v1.7, German, i8751 DE 11 D3)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_UNEMULATED_PROTECTION ) -GAME( 1995, quizard_12, quizard, quizard, quizard, quizard1_state, empty_init, ROT0, "TAB Austria", "Quizard (v1.2, German, i8751 DE 11 D3)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_UNEMULATED_PROTECTION ) -GAME( 1995, quizard_10, quizard, quizard, quizard, quizard1_state, empty_init, ROT0, "TAB Austria", "Quizard (v1.0, German, i8751 DE 11 D3)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_UNEMULATED_PROTECTION ) +GAME( 1995, quizard, cdibios, quizard, quizard, quizard_state, empty_init, ROT0, "TAB Austria", "Quizard (v1.8, German, i8751 DE 11 D3)", MACHINE_IMPERFECT_SOUND ) +GAME( 1995, quizard_17, quizard, quizard, quizard, quizard_state, empty_init, ROT0, "TAB Austria", "Quizard (v1.7, German, i8751 DE 11 D3)", MACHINE_IMPERFECT_SOUND ) +GAME( 1995, quizard_12, quizard, quizard, quizard, quizard_state, empty_init, ROT0, "TAB Austria", "Quizard (v1.2, German, i8751 DE 11 D3)", MACHINE_IMPERFECT_SOUND ) +GAME( 1995, quizard_10, quizard, quizard, quizard, quizard_state, empty_init, ROT0, "TAB Austria", "Quizard (v1.0, German, i8751 DE 11 D3)", MACHINE_IMPERFECT_SOUND ) -GAME( 1995, quizard2, cdibios, quizard, quizard, quizard2_state, empty_init, ROT0, "TAB Austria", "Quizard 2 (v2.3, German, i8751 DN 122 D3)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_UNEMULATED_PROTECTION ) -GAME( 1995, quizard2_22, quizard2, quizard, quizard, quizard2_state, empty_init, ROT0, "TAB Austria", "Quizard 2 (v2.2, German, i8751 DN 122 D3)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_UNEMULATED_PROTECTION ) +GAME( 1995, quizard2, cdibios, quizard, quizard, quizard_state, empty_init, ROT0, "TAB Austria", "Quizard 2 (v2.3, German, i8751 DN 122 D3)", MACHINE_IMPERFECT_SOUND ) +GAME( 1995, quizard2_22, quizard2, quizard, quizard, quizard_state, empty_init, ROT0, "TAB Austria", "Quizard 2 (v2.2, German, i8751 DN 122 D3)", MACHINE_IMPERFECT_SOUND ) -// Quizard 3 and 4 will hang after inserting a coin (incomplete protection sims?) -GAME( 1995, quizard3, cdibios, quizard, quizard, quizard3_state, empty_init, ROT0, "TAB Austria", "Quizard 3 (v3.4, German, i8751 DE 132 D3)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_UNEMULATED_PROTECTION ) -GAME( 1995, quizard3a, quizard3, quizard, quizard, quizard3_state, empty_init, ROT0, "TAB Austria", "Quizard 3 (v3.4, German, i8751 DE 132 A1)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_UNEMULATED_PROTECTION ) -GAME( 1996, quizard3_32, quizard3, quizard, quizard, quizard3_state, empty_init, ROT0, "TAB Austria", "Quizard 3 (v3.2, German, i8751 DE 132 D3)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_UNEMULATED_PROTECTION ) +// Quizard 3 and 4 will hang after starting a game (CDIC issues?) +GAME( 1995, quizard3, cdibios, quizard, quizard, quizard_state, empty_init, ROT0, "TAB Austria", "Quizard 3 (v3.4, German, i8751 DE 132 D3)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND ) +GAME( 1995, quizard3a, quizard3, quizard, quizard, quizard_state, empty_init, ROT0, "TAB Austria", "Quizard 3 (v3.4, German, i8751 DE 132 A1)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND ) +GAME( 1996, quizard3_32, quizard3, quizard, quizard, quizard_state, empty_init, ROT0, "TAB Austria", "Quizard 3 (v3.2, German, i8751 DE 132 D3)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND ) -GAME( 1998, quizard4, cdibios, quizard, quizard, quizard4_state, empty_init, ROT0, "TAB Austria", "Quizard 4 Rainbow (v4.2, German, i8751 DE 142 D3)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_UNEMULATED_PROTECTION ) -GAME( 1998, quizard4cz, quizard4, quizard, quizard, quizard4_state, empty_init, ROT0, "TAB Austria", "Quizard 4 Rainbow (v4.2, Czech, i8751 TS142 CZ1)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_UNEMULATED_PROTECTION ) -GAME( 1998, quizard4_41, quizard4, quizard, quizard, quizard4_state, empty_init, ROT0, "TAB Austria", "Quizard 4 Rainbow (v4.1, German, i8751 DE 142 D3)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_UNEMULATED_PROTECTION ) -GAME( 1997, quizard4_40, quizard4, quizard, quizard, quizard4_state, empty_init, ROT0, "TAB Austria", "Quizard 4 Rainbow (v4.0, German, i8751 DE 142 D3)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_UNEMULATED_PROTECTION ) +GAME( 1998, quizard4, cdibios, quizard, quizard, quizard_state, empty_init, ROT0, "TAB Austria", "Quizard 4 Rainbow (v4.2, German, i8751 DE 142 D3)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND ) +GAME( 1998, quizard4cz, quizard4, quizard, quizard, quizard_state, empty_init, ROT0, "TAB Austria", "Quizard 4 Rainbow (v4.2, Czech, i8751 TS142 CZ1)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND ) +GAME( 1998, quizard4_41, quizard4, quizard, quizard, quizard_state, empty_init, ROT0, "TAB Austria", "Quizard 4 Rainbow (v4.1, German, i8751 DE 142 D3)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND ) +GAME( 1997, quizard4_40, quizard4, quizard, quizard, quizard_state, empty_init, ROT0, "TAB Austria", "Quizard 4 Rainbow (v4.0, German, i8751 DE 142 D3)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND ) diff --git a/src/mame/includes/cdi.h b/src/mame/includes/cdi.h index 9ff59b55b3b..c0c91c6dbc7 100644 --- a/src/mame/includes/cdi.h +++ b/src/mame/includes/cdi.h @@ -89,12 +89,6 @@ public: void quizard(machine_config &config); - DECLARE_INPUT_CHANGED_MEMBER(mcu_input); - -protected: - void set_mcu_value(uint16_t value); - void set_mcu_ack(uint8_t ack); - private: virtual void machine_start() override; virtual void machine_reset() override; @@ -103,71 +97,26 @@ private: uint8_t mcu_p1_r(); uint8_t mcu_p2_r(); uint8_t mcu_p3_r(); + void mcu_p0_w(uint8_t data); + void mcu_p1_w(uint8_t data); void mcu_p2_w(uint8_t data); void mcu_p3_w(uint8_t data); void mcu_tx(uint8_t data); uint8_t mcu_rx(); - void mcu_hle_tx(uint8_t data); - void mcu_calculate_state(); - void mcu_set_seeds(uint8_t *rx); - void mcu_hle_rx(uint8_t data); + void mcu_rx_from_cpu(uint8_t data); + void mcu_rtsn_from_cpu(int state); required_device m_mcu; - required_ioport_array<4> m_inputs; + required_ioport_array<3> m_inputs; - uint16_t m_seeds[10]; - uint8_t m_state[8]; - - uint16_t m_mcu_value; - uint8_t m_mcu_ack; + uint8_t m_mcu_rx_from_cpu; + bool m_mcu_initial_byte; }; -class quizard1_state : public quizard_state -{ -public: - quizard1_state(const machine_config &mconfig, device_type type, const char *tag) - : quizard_state(mconfig, type, tag) - { - set_mcu_value(0x021f); - set_mcu_ack(0x5a); - } -}; - -class quizard2_state : public quizard_state -{ -public: - quizard2_state(const machine_config &mconfig, device_type type, const char *tag) - : quizard_state(mconfig, type, tag) - { - // 0x2b1: Italian - // 0x001: French - // 0x188: German - set_mcu_value(0x0188); - set_mcu_ack(0x59); - } -}; - -class quizard3_state : public quizard_state -{ -public: - quizard3_state(const machine_config &mconfig, device_type type, const char *tag) - : quizard_state(mconfig, type, tag) - { - set_mcu_value(0x00ae); - set_mcu_ack(0x58); - } -}; - -class quizard4_state : public quizard_state -{ -public: - quizard4_state(const machine_config &mconfig, device_type type, const char *tag) - : quizard_state(mconfig, type, tag) - { - set_mcu_value(0x011f); - set_mcu_ack(0x57); - } -}; +// Quizard 2 language values: +// 0x2b1: Italian +// 0x001: French +// 0x188: German #endif // MAME_INCLUDES_CDI_H diff --git a/src/mame/machine/cdislavehle.cpp b/src/mame/machine/cdislavehle.cpp index 65d2de69012..0c1f7f5f827 100644 --- a/src/mame/machine/cdislavehle.cpp +++ b/src/mame/machine/cdislavehle.cpp @@ -23,6 +23,7 @@ TODO: #define LOG_READS (1 << 2) #define LOG_WRITES (1 << 3) #define LOG_UNKNOWNS (1 << 4) +#define LOG_ALL (LOG_IRQS | LOG_COMMANDS | LOG_READS | LOG_WRITES | LOG_UNKNOWNS) #define VERBOSE (0) #include "logmacro.h"