From b1bedd018d4ee29c71946368d46f68cbd5b8dc42 Mon Sep 17 00:00:00 2001 From: mooglyguy Date: Sat, 5 Jan 2019 22:13:58 +0100 Subject: [PATCH] -clickstart: Favor specific values over rand(), nw -devices/cpu/unsp: Added a function to get current chip-select state, nw -devicesp/machine/spg2xx: Various changes: [Ryan Holtz] * Added 4kHz/2kHz/1kHz/1Hz timers. * Added ADC read callback. * Fixed a bug with floating GPIO inputs. Clickstart games now generally get to the title screen or main menu, other than Bob The Builder, which is missing some graphics. nw --- src/devices/cpu/unsp/unsp.cpp | 5 ++ src/devices/cpu/unsp/unsp.h | 2 + src/devices/machine/spg2xx.cpp | 153 +++++++++++++++++++++++++++++--- src/devices/machine/spg2xx.h | 17 +++- src/mame/drivers/clickstart.cpp | 69 ++++++++++++-- 5 files changed, 226 insertions(+), 20 deletions(-) diff --git a/src/devices/cpu/unsp/unsp.cpp b/src/devices/cpu/unsp/unsp.cpp index af964f713f9..df48e6ae52d 100644 --- a/src/devices/cpu/unsp/unsp.cpp +++ b/src/devices/cpu/unsp/unsp.cpp @@ -967,3 +967,8 @@ void unsp_device::execute_set_input(int irqline, int state) break; } } + +uint8_t unsp_device::get_csb() +{ + return 1 << ((UNSP_LPC >> 20) & 3); +} diff --git a/src/devices/cpu/unsp/unsp.h b/src/devices/cpu/unsp/unsp.h index ad3f8250785..f54cf04ac57 100644 --- a/src/devices/cpu/unsp/unsp.h +++ b/src/devices/cpu/unsp/unsp.h @@ -68,6 +68,8 @@ public: void set_timer_interval(int timer, uint32_t interval); + uint8_t get_csb(); + protected: // device-level overrides virtual void device_start() override; diff --git a/src/devices/machine/spg2xx.cpp b/src/devices/machine/spg2xx.cpp index 0315ae6ebae..91d8041d056 100644 --- a/src/devices/machine/spg2xx.cpp +++ b/src/devices/machine/spg2xx.cpp @@ -48,7 +48,7 @@ DEFINE_DEVICE_TYPE(SPG28X, spg28x_device, "spg28x", "SPG280-series System-on-a-C #define LOG_PPU (LOG_PPU_READS | LOG_PPU_WRITES | LOG_UNKNOWN_PPU) #define LOG_ALL (LOG_IO | LOG_SPU | LOG_PPU | LOG_VLINES | LOG_SEGMENT) -#define VERBOSE (LOG_UART | LOG_UNKNOWN_IO) +#define VERBOSE (LOG_IO_READS | LOG_IO_WRITES | LOG_UART | LOG_UNKNOWN_IO | LOG_I2C) #include "logmacro.h" #define SPG_DEBUG_VIDEO (0) @@ -68,6 +68,7 @@ spg2xx_device::spg2xx_device(const machine_config &mconfig, device_type type, co , m_porta_in(*this) , m_portb_in(*this) , m_portc_in(*this) + , m_adc_in(*this) , m_eeprom_w(*this) , m_eeprom_r(*this) , m_uart_tx(*this) @@ -109,6 +110,7 @@ void spg2xx_device::device_start() m_porta_in.resolve_safe(0); m_portb_in.resolve_safe(0); m_portc_in.resolve_safe(0); + m_adc_in.resolve_safe(0x0fff); m_eeprom_w.resolve_safe(); m_eeprom_r.resolve_safe(0); m_uart_tx.resolve_safe(); @@ -131,9 +133,60 @@ void spg2xx_device::device_start() m_uart_rx_timer = timer_alloc(TIMER_UART_RX); m_uart_rx_timer->adjust(attotime::never); + m_4khz_timer = timer_alloc(TIMER_4KHZ); + m_4khz_timer->adjust(attotime::never); + m_stream = stream_alloc(0, 2, 44100); m_channel_debug = -1; + + save_item(NAME(m_hide_page0)); + save_item(NAME(m_hide_page1)); + save_item(NAME(m_hide_sprites)); + save_item(NAME(m_debug_sprites)); + save_item(NAME(m_debug_blit)); + save_item(NAME(m_sprite_index_to_debug)); + + save_item(NAME(m_debug_samples)); + save_item(NAME(m_debug_rates)); + + save_item(NAME(m_audio_regs)); + save_item(NAME(m_sample_shift)); + save_item(NAME(m_sample_count)); + save_item(NAME(m_sample_addr)); + save_item(NAME(m_channel_rate)); + save_item(NAME(m_channel_rate_accum)); + save_item(NAME(m_rampdown_frame)); + save_item(NAME(m_envclk_frame)); + save_item(NAME(m_envelope_addr)); + save_item(NAME(m_channel_debug)); + save_item(NAME(m_audio_curr_beat_base_count)); + + save_item(NAME(m_io_regs)); + save_item(NAME(m_uart_rx_fifo)); + save_item(NAME(m_uart_rx_fifo_start)); + save_item(NAME(m_uart_rx_fifo_end)); + save_item(NAME(m_uart_rx_fifo_count)); + save_item(NAME(m_uart_rx_available)); + save_item(NAME(m_uart_rx_irq)); + save_item(NAME(m_uart_tx_irq)); + + save_item(NAME(m_extint)); + + save_item(NAME(m_video_regs)); + save_item(NAME(m_sprite_limit)); + save_item(NAME(m_pal_flag)); + + save_item(NAME(m_2khz_divider)); + save_item(NAME(m_1khz_divider)); + save_item(NAME(m_4hz_divider)); + + save_item(NAME(m_uart_baud_rate)); + for (int i = 0; i < 16; i++) + { + save_item(NAME(m_adpcm[i].m_signal), i); + save_item(NAME(m_adpcm[i].m_step), i); + } } void spg2xx_device::device_reset() @@ -181,6 +234,12 @@ void spg2xx_device::device_reset() m_audio_regs[AUDIO_CHANNEL_ENV_MODE] = 0x3f; m_audio_beat->adjust(attotime::from_ticks(4, 281250), 0, attotime::from_ticks(4, 281250)); + + m_4khz_timer->adjust(attotime::from_hz(4096), 0, attotime::from_hz(4096)); + + m_2khz_divider = 0; + m_1khz_divider = 0; + m_4hz_divider = 0; } @@ -880,7 +939,7 @@ READ16_MEMBER(spg2xx_device::io_r) case 0x27: // ADC Data m_io_regs[0x27] = 0; - LOGMASKED(LOG_IO_READS, "io_r: ADC Data = %04x\n", val); + LOGMASKED(LOG_IO_READS, "%s: io_r: ADC Data = %04x\n", machine().describe_context(), val); break; case 0x29: // Wakeup Source @@ -1206,17 +1265,17 @@ WRITE16_MEMBER(spg2xx_device::io_w) case 0x25: // ADC Control { - LOGMASKED(LOG_IO_WRITES, "io_w: ADC Control = %04x\n", data); - //const uint16_t changed = m_io_regs[offset] ^ data; + LOGMASKED(LOG_IO_WRITES, "%s: io_w: ADC Control = %04x\n", machine().describe_context(), data); + const uint16_t changed = m_io_regs[offset] ^ data; m_io_regs[offset] = data; - //if (BIT(changed, 12) && BIT(data, 12) && !BIT(m_io_regs[offset], 1)) + if (BIT(changed, 12) && BIT(data, 12) && !BIT(m_io_regs[offset], 1)) { - //m_io_regs[0x27] = 0x80ff; - //const uint16_t old = IO_IRQ_STATUS; - //IO_IRQ_STATUS |= 0x2000; - //const uint16_t changed = IO_IRQ_STATUS ^ old; - //if (changed) - //check_irqs(changed); + m_io_regs[0x27] = 0x8000 | (m_adc_in() & 0x7fff); + const uint16_t old = IO_IRQ_STATUS; + IO_IRQ_STATUS |= 0x2000; + const uint16_t changed = IO_IRQ_STATUS ^ old; + if (changed) + check_irqs(changed); } break; } @@ -1469,9 +1528,51 @@ void spg2xx_device::device_timer(emu_timer &timer, device_timer_id id, int param case TIMER_UART_RX: uart_receive_tick(); break; + + case TIMER_4KHZ: + system_timer_tick(); + break; } } +void spg2xx_device::system_timer_tick() +{ + uint16_t check_mask = 0x0040; + IO_IRQ_STATUS |= 0x0040; + + if (machine().input().code_pressed_once(KEYCODE_H)) + { + IO_IRQ_STATUS |= 0x4000; + check_irqs(0x4000); + } + + m_2khz_divider++; + if (m_2khz_divider == 2) + { + m_2khz_divider = 0; + IO_IRQ_STATUS |= 0x0020; + check_mask |= 0x0020; + + m_1khz_divider++; + if (m_1khz_divider == 2) + { + m_1khz_divider = 0; + IO_IRQ_STATUS |= 0x0010; + check_mask |= 0x0010; + + m_4hz_divider++; + if (m_4hz_divider == 256) + { + m_4hz_divider = 0; + IO_IRQ_STATUS |= 0x0008; + check_mask |= 0x0008; + } + } + } + + check_irqs(check_mask); +} + void spg2xx_device::uart_transmit_tick() { LOGMASKED(LOG_UART, "uart_transmit_tick: Transmitting %02x, setting TxReady, clearing TxBusy\n", (uint8_t)m_io_regs[0x35]); @@ -1583,6 +1684,31 @@ void spg2xx_device::check_irqs(const uint16_t changed) } } +uint16_t spg2xx_device::do_special_gpio(uint32_t index, uint16_t mask) +{ + uint16_t data = 0; + switch (index) + { + case 0: // Port A + if (mask & 0xe000) + { + const uint8_t csel = m_cpu->get_csb() & 0x0e; + data = (csel << 12) & mask; + } + break; + case 1: // Port B + // To do + break; + case 2: // Port C + // To do + break; + default: + // Can't happen + break; + } + return data; +} + void spg2xx_device::do_gpio(uint32_t offset) { uint32_t index = (offset - 1) / 5; @@ -1592,10 +1718,12 @@ void spg2xx_device::do_gpio(uint32_t offset) uint16_t special = m_io_regs[5 * index + 5]; uint16_t push = dir; - uint16_t pull = (~dir) & (~attr); + uint16_t pull = ~dir; uint16_t what = (buffer & (push | pull)); what ^= (dir & ~attr); what &= ~special; + //if (index == 0) + //printf("buf:%04x, dir:%04x, pull:%04x, push:%04x\n", buffer, dir, pull, push); switch (index) { @@ -1613,6 +1741,7 @@ void spg2xx_device::do_gpio(uint32_t offset) break; } + what |= do_special_gpio(index, special); m_io_regs[5 * index + 1] = what; } diff --git a/src/devices/machine/spg2xx.h b/src/devices/machine/spg2xx.h index f8f705ef3ac..875a85ee663 100644 --- a/src/devices/machine/spg2xx.h +++ b/src/devices/machine/spg2xx.h @@ -60,6 +60,8 @@ public: auto portb_in() { return m_portb_in.bind(); } auto portc_in() { return m_portc_in.bind(); } + auto adc_in() { return m_adc_in.bind(); } + auto eeprom_w() { return m_eeprom_w.bind(); } auto eeprom_r() { return m_eeprom_r.bind(); } @@ -75,7 +77,7 @@ public: DECLARE_WRITE_LINE_MEMBER(vblank); protected: - spg2xx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const size_t sprite_limit) + spg2xx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const uint32_t sprite_limit) : spg2xx_device(mconfig, type, tag, owner, clock) { m_sprite_limit = sprite_limit; @@ -399,6 +401,7 @@ protected: static const device_timer_id TIMER_BEAT = 3; static const device_timer_id TIMER_UART_TX = 4; static const device_timer_id TIMER_UART_RX = 5; + static const device_timer_id TIMER_4KHZ = 6; virtual void device_start() override; virtual void device_reset() override; @@ -407,10 +410,13 @@ protected: void update_porta_special_modes(); void update_portb_special_modes(); void do_gpio(uint32_t offset); + uint16_t do_special_gpio(uint32_t index, uint16_t mask); void uart_transmit_tick(); void uart_receive_tick(); + void system_timer_tick(); + void do_i2c(); void do_cpu_dma(uint32_t len); @@ -474,7 +480,7 @@ protected: bool m_extint[2]; uint16_t m_video_regs[0x100]; - size_t m_sprite_limit; + uint32_t m_sprite_limit; uint16_t m_pal_flag; devcb_write16 m_porta_out; @@ -484,6 +490,8 @@ protected: devcb_read16 m_portb_in; devcb_read16 m_portc_in; + devcb_read16 m_adc_in; + devcb_write8 m_eeprom_w; devcb_read8 m_eeprom_r; @@ -496,6 +504,11 @@ protected: emu_timer *m_screenpos_timer; emu_timer *m_audio_beat; + emu_timer *m_4khz_timer; + uint32_t m_2khz_divider; + uint32_t m_1khz_divider; + uint32_t m_4hz_divider; + uint32_t m_uart_baud_rate; emu_timer *m_uart_tx_timer; emu_timer *m_uart_rx_timer; diff --git a/src/mame/drivers/clickstart.cpp b/src/mame/drivers/clickstart.cpp index 74fffc9c50a..9b0edd2fe42 100644 --- a/src/mame/drivers/clickstart.cpp +++ b/src/mame/drivers/clickstart.cpp @@ -3,7 +3,7 @@ /****************************************************************************** Leapfrog Clickstart Emulation - + Status: Calls to unmapped space @@ -13,7 +13,7 @@ calculation doesn't add up correctly. There is also a checksum in a footer area at the end of every ROM that does add up correctly in all cases. - + The ROM carts are marked for 4MByte ROMs at least so the sizes should be correct. @@ -59,10 +59,14 @@ private: DECLARE_READ16_MEMBER(rom_r); - DECLARE_READ16_MEMBER(portc_r) - { - return machine().rand(); - }; + DECLARE_WRITE16_MEMBER(porta_w); + DECLARE_WRITE16_MEMBER(portb_w); + DECLARE_WRITE16_MEMBER(portc_w); + DECLARE_READ16_MEMBER(porta_r); + DECLARE_READ16_MEMBER(portb_r); + DECLARE_READ16_MEMBER(portc_r); + + DECLARE_WRITE8_MEMBER(chip_sel_w); required_device m_maincpu; required_device m_screen; @@ -70,6 +74,8 @@ private: required_device m_cart; required_memory_region m_system_region; memory_region *m_cart_region; + + uint16_t m_unk_portc_toggle; }; @@ -81,10 +87,13 @@ void clickstart_state::machine_start() std::string region_tag; m_cart_region = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str()); } + + save_item(NAME(m_unk_portc_toggle)); } void clickstart_state::machine_reset() { + m_unk_portc_toggle = 0; } DEVICE_IMAGE_LOAD_MEMBER(clickstart_state, cart) @@ -112,6 +121,47 @@ READ16_MEMBER(clickstart_state::rom_r) } } +WRITE16_MEMBER(clickstart_state::porta_w) +{ + logerror("%s: porta_w: %04x & %04x\n", machine().describe_context(), data, mem_mask); +} + +WRITE16_MEMBER(clickstart_state::portb_w) +{ + logerror("%s: portb_w: %04x & %04x\n", machine().describe_context(), data, mem_mask); +} + +WRITE16_MEMBER(clickstart_state::portc_w) +{ + //logerror("%s: portc_w: %04x & %04x\n", machine().describe_context(), data, mem_mask); +} + +READ16_MEMBER(clickstart_state::porta_r) +{ + uint16_t data = 0x5000; + logerror("%s: porta_r: %04x & %04x\n", machine().describe_context(), data, mem_mask); + return data; +} + +READ16_MEMBER(clickstart_state::portb_r) +{ + logerror("%s: portb_r: %04x\n", machine().describe_context(), mem_mask); + return 0; +} + +READ16_MEMBER(clickstart_state::portc_r) +{ + uint16_t data = m_unk_portc_toggle; + m_unk_portc_toggle ^= 0x0400; + //logerror("%s: portc_r: %04x & %04x\n", machine().describe_context(), data, mem_mask); + return data; +} + +WRITE8_MEMBER(clickstart_state::chip_sel_w) +{ + // Seems unused, currently +} + void clickstart_state::mem_map(address_map &map) { map(0x000000, 0x3fffff).r(FUNC(clickstart_state::rom_r)); @@ -139,7 +189,14 @@ void clickstart_state::clickstart(machine_config &config) SPEAKER(config, "rspeaker").front_right(); SPG24X(config, m_spg, XTAL(27'000'000), m_maincpu, m_screen); + m_spg->porta_out().set(FUNC(clickstart_state::porta_w)); + m_spg->portb_out().set(FUNC(clickstart_state::portb_w)); + m_spg->portc_out().set(FUNC(clickstart_state::portc_w)); + m_spg->porta_in().set(FUNC(clickstart_state::porta_r)); + m_spg->portb_in().set(FUNC(clickstart_state::portb_r)); m_spg->portc_in().set(FUNC(clickstart_state::portc_r)); + m_spg->adc_in().set_constant(0x0fff); + m_spg->chip_select().set(FUNC(clickstart_state::chip_sel_w)); m_spg->add_route(ALL_OUTPUTS, "lspeaker", 0.5); m_spg->add_route(ALL_OUTPUTS, "rspeaker", 0.5);