diff options
author | mooglyguy <therealmogminer@gmail.com> | 2018-10-18 18:49:43 +0200 |
---|---|---|
committer | mooglyguy <therealmogminer@gmail.com> | 2018-10-18 18:50:11 +0200 |
commit | 1603f8bf28fd7e747068f5d31b71aa3cad2da6e3 (patch) | |
tree | 982fdd55a352cf448f00d940c7ae2c5675ac7d5f | |
parent | 2da107644df4a032febd98fec81a1c13a5ce157b (diff) |
-spg2xx: Added chip select callback and rudimentary ADC hookup. [Ryan Holtz]
-vii: Initial V.Smile support; BIOS runs, games do not. [Ryan Holtz]
Note: V.Smile changes are currently very WIP, needs code cleanup. Just checking in so others can have a look.
-rw-r--r-- | src/devices/cpu/unsp/unsp.cpp | 11 | ||||
-rw-r--r-- | src/devices/machine/spg2xx.cpp | 126 | ||||
-rw-r--r-- | src/devices/machine/spg2xx.h | 4 | ||||
-rw-r--r-- | src/mame/drivers/vii.cpp | 318 |
4 files changed, 356 insertions, 103 deletions
diff --git a/src/devices/cpu/unsp/unsp.cpp b/src/devices/cpu/unsp/unsp.cpp index 4d820214608..ca8b149fe5d 100644 --- a/src/devices/cpu/unsp/unsp.cpp +++ b/src/devices/cpu/unsp/unsp.cpp @@ -245,6 +245,7 @@ void unsp_device::trigger_irq(int line) { if (!m_enable_irq || m_irq || m_fiq) { + //logerror("Enable %d, IRQ %d, FIQ %d, bailing\n", m_enable_irq ? 1 : 0, m_irq ? 1 : 0, m_fiq ? 1 : 0); return; } @@ -279,10 +280,12 @@ void unsp_device::check_irqs() if (highest_irq == UNSP_FIQ_LINE) { + //logerror("Trying to trigger FIQ\n"); trigger_fiq(); } else { + //logerror("Trying to trigger IRQ\n"); trigger_irq(highest_irq - 1); } } @@ -620,7 +623,7 @@ void unsp_device::execute_run() case 0x00: // r, [bp+imm6] m_icount -= 6; - r2 = UNSP_REG(BP) + OPIMM; + r2 = (uint16_t)(UNSP_REG(BP) + OPIMM); if (OP0 != 0x0d) r1 = read16(r2); break; @@ -685,19 +688,19 @@ void unsp_device::execute_run() if (OP0 != 0x0d) r1 = read16(r2); break; - case 1: // r, [<ds:>r--] + case 1: // r, [r--] r2 = UNSP_REG_I(opb); if (OP0 != 0x0d) r1 = read16(r2); UNSP_REG_I(opb)--; break; - case 2: // r, [<ds:>r++] + case 2: // r, [r++] r2 = UNSP_REG_I(opb); if (OP0 != 0x0d) r1 = read16(r2); UNSP_REG_I(opb)++; break; - case 3: // r, [<ds:>++r] + case 3: // r, [++r] UNSP_REG_I(opb)++; r2 = UNSP_REG_I(opb); if (OP0 != 0x0d) diff --git a/src/devices/machine/spg2xx.cpp b/src/devices/machine/spg2xx.cpp index fa4a45d14ff..fb7e1c0e2ad 100644 --- a/src/devices/machine/spg2xx.cpp +++ b/src/devices/machine/spg2xx.cpp @@ -18,28 +18,34 @@ DEFINE_DEVICE_TYPE(SPG28X, spg28x_device, "spg28x", "SPG280-series System-on-a-C #define LOG_IO_READS (1U << 0) #define LOG_IO_WRITES (1U << 1) -#define LOG_IRQS (1U << 2) -#define LOG_VLINES (1U << 3) -#define LOG_GPIO (1U << 4) -#define LOG_UART (1U << 5) -#define LOG_I2C (1U << 6) -#define LOG_DMA (1U << 7) -#define LOG_WATCHDOG (1U << 8) -#define LOG_SPU_READS (1U << 9) -#define LOG_SPU_WRITES (1U << 10) -#define LOG_CHANNEL_READS (1U << 11) -#define LOG_CHANNEL_WRITES (1U << 12) -#define LOG_ENVELOPES (1U << 13) -#define LOG_SAMPLES (1U << 14) -#define LOG_RAMPDOWN (1U << 15) -#define LOG_BEAT (1U << 16) -#define LOG_PPU_READS (1U << 17) -#define LOG_PPU_WRITES (1U << 18) -#define LOG_IO (LOG_IO_READS | LOG_IO_WRITES | LOG_IRQS | LOG_GPIO | LOG_UART | LOG_I2C | LOG_DMA) +#define LOG_UNKNOWN_IO (1U << 2) +#define LOG_IRQS (1U << 3) +#define LOG_VLINES (1U << 4) +#define LOG_GPIO (1U << 5) +#define LOG_UART (1U << 6) +#define LOG_I2C (1U << 7) +#define LOG_DMA (1U << 8) +#define LOG_SEGMENT (1U << 9) +#define LOG_WATCHDOG (1U << 10) +#define LOG_TIMERS (1U << 11) +#define LOG_SPU_READS (1U << 12) +#define LOG_SPU_WRITES (1U << 13) +#define LOG_UNKNOWN_SPU (1U << 14) +#define LOG_CHANNEL_READS (1U << 15) +#define LOG_CHANNEL_WRITES (1U << 16) +#define LOG_ENVELOPES (1U << 17) +#define LOG_SAMPLES (1U << 18) +#define LOG_RAMPDOWN (1U << 19) +#define LOG_BEAT (1U << 20) +#define LOG_PPU_READS (1U << 21) +#define LOG_PPU_WRITES (1U << 22) +#define LOG_UNKNOWN_PPU (1U << 23) +#define LOG_IO (LOG_IO_READS | LOG_IO_WRITES | LOG_IRQS | LOG_GPIO | LOG_UART | LOG_I2C | LOG_DMA | LOG_TIMERS | LOG_UNKNOWN_IO) #define LOG_CHANNELS (LOG_CHANNEL_READS | LOG_CHANNEL_WRITES) -#define LOG_SPU (LOG_SPU_READS | LOG_SPU_WRITES | LOG_CHANNEL_READS | LOG_CHANNEL_WRITES | LOG_ENVELOPES | LOG_SAMPLES | LOG_RAMPDOWN | LOG_BEAT) -#define LOG_PPU (LOG_PPU_READS | LOG_PPU_WRITES) -#define LOG_ALL (LOG_IO | LOG_SPU | LOG_PPU | LOG_VLINES) +#define LOG_SPU (LOG_SPU_READS | LOG_SPU_WRITES | LOG_UNKNOWN_SPU | LOG_CHANNEL_READS | LOG_CHANNEL_WRITES \ + | LOG_ENVELOPES | LOG_SAMPLES | LOG_RAMPDOWN | LOG_BEAT) +#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 (0) #include "logmacro.h" @@ -81,6 +87,7 @@ spg2xx_device::spg2xx_device(const machine_config &mconfig, device_type type, co , m_eeprom_w(*this) , m_eeprom_r(*this) , m_uart_tx(*this) + , m_chip_sel(*this) , m_cpu(*this, finder_base::DUMMY_TAG) , m_screen(*this, finder_base::DUMMY_TAG) , m_scrollram(*this, "scrollram") @@ -127,6 +134,7 @@ void spg2xx_device::device_start() m_eeprom_w.resolve_safe(); m_eeprom_r.resolve_safe(0); m_uart_tx.resolve_safe(); + m_chip_sel.resolve_safe(); m_tmb1 = timer_alloc(TIMER_TMB1); m_tmb2 = timer_alloc(TIMER_TMB2); @@ -597,7 +605,7 @@ READ16_MEMBER(spg2xx_device::video_r) return VIDEO_IRQ_STATUS; default: - LOGMASKED(LOG_PPU_READS, "video_r: Unknown register %04x = %04x\n", 0x2800 + offset, m_video_regs[offset]); + LOGMASKED(LOG_UNKNOWN_PPU, "video_r: Unknown register %04x = %04x\n", 0x2800 + offset, m_video_regs[offset]); break; } return m_video_regs[offset]; @@ -776,7 +784,7 @@ WRITE16_MEMBER(spg2xx_device::video_w) break; default: - LOGMASKED(LOG_PPU_WRITES, "video_w: Unknown register %04x = %04x\n", 0x2800 + offset, data); + LOGMASKED(LOG_UNKNOWN_PPU, "video_w: Unknown register %04x = %04x\n", 0x2800 + offset, data); m_video_regs[offset] = data; break; } @@ -845,6 +853,7 @@ void spg2xx_device::uart_rx(uint8_t data) { m_uart_rx_fifo[m_uart_rx_index] = data; m_uart_rx_index++; + m_io_regs[0x31] |= 1; if (m_uart_rx_index > (m_io_regs[0x37] & 7)) { const uint16_t old = IO_IRQ_STATUS; @@ -910,6 +919,11 @@ READ16_MEMBER(spg2xx_device::io_r) LOGMASKED(LOG_IO_READS, "io_r: ADC Control = %04x\n", val); break; + case 0x27: // ADC Data + m_io_regs[0x27] = 0; + LOGMASKED(LOG_IO_READS, "io_r: ADC Data = %04x\n", val); + break; + case 0x29: // Wakeup Source LOGMASKED(LOG_IO_READS, "io_r: Wakeup Source = %04x\n", val); break; @@ -929,7 +943,7 @@ READ16_MEMBER(spg2xx_device::io_r) case 0x2f: // Data Segment val = m_cpu->state_int(UNSP_SR) >> 10; - LOGMASKED(LOG_IO_READS, "io_r: Data Segment = %04x\n", val); + LOGMASKED(LOG_SEGMENT, "io_r: Data Segment = %04x\n", val); break; case 0x31: // UART Status @@ -988,7 +1002,7 @@ READ16_MEMBER(spg2xx_device::io_r) break; default: - LOGMASKED(LOG_IO_READS, "io_r: Unknown register %04x\n", 0x3d00 + offset); + LOGMASKED(LOG_UNKNOWN_IO, "io_r: Unknown register %04x\n", 0x3d00 + offset); break; } @@ -1212,6 +1226,7 @@ WRITE16_MEMBER(spg2xx_device::io_w) LOGMASKED(LOG_IO_WRITES, " WaitStates:%d, BusArbPrio:%s\n", (data >> 1) & 3, s_bus_arb[(data >> 3) & 7]); LOGMASKED(LOG_IO_WRITES, " ROMAddrDecode:%s\n", s_addr_decode[(data >> 6) & 3]); LOGMASKED(LOG_IO_WRITES, " RAMAddrDecode:%s\n", s_ram_decode[(data >> 8) & 15]); + m_chip_sel((data >> 6) & 3); m_io_regs[offset] = data; break; } @@ -1221,9 +1236,21 @@ WRITE16_MEMBER(spg2xx_device::io_w) break; case 0x25: // ADC Control + { LOGMASKED(LOG_IO_WRITES, "io_w: ADC Control = %04x\n", 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)) + { + 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); + } break; + } case 0x28: // Sleep Mode LOGMASKED(LOG_IO_WRITES, "io_w: Sleep Mode (%s enter value) = %04x\n", data == 0xaa55 ? "valid" : "invalid", data); @@ -1270,7 +1297,7 @@ WRITE16_MEMBER(spg2xx_device::io_w) { uint16_t ds = m_cpu->state_int(UNSP_SR); m_cpu->set_state_int(UNSP_SR, (ds & 0x03ff) | ((data & 0x3f) << 10)); - LOGMASKED(LOG_IO_WRITES, "io_w: Data Segment = %04x\n", data); + LOGMASKED(LOG_SEGMENT, "io_w: Data Segment = %04x\n", data); break; } @@ -1279,18 +1306,23 @@ WRITE16_MEMBER(spg2xx_device::io_w) static const char* const s_9th_bit[4] = { "0", "1", "Odd", "Even" }; LOGMASKED(LOG_UART, "io_w: UART Control = %04x (TxEn:%d, RxEn:%d, Bits:%d, MultiProc:%d, 9thBit:%s, TxIntEn:%d, RxIntEn:%d\n", data , BIT(data, 7), BIT(data, 6), BIT(data, 5) ? 9 : 8, BIT(data, 4), s_9th_bit[(data >> 2) & 3], BIT(data, 1), BIT(data, 0)); + const uint16_t changed = m_io_regs[offset] ^ data; m_io_regs[offset] = data; if (!BIT(data, 6)) { m_uart_rx_index = 0; memset(m_uart_rx_fifo, 0, 8); } + if (BIT(changed, 7) && BIT(data, 7)) + { + m_io_regs[0x31] |= 0x0002; + } break; } case 0x31: // UART Status - LOGMASKED(LOG_UART, "io_w: UART Status (read only) = %04x\n", data); - m_io_regs[offset] = data; + LOGMASKED(LOG_UART, "io_w: UART Status = %04x\n", data); + //m_io_regs[offset] &= ~data; break; case 0x33: // UART Baud Rate @@ -1301,6 +1333,7 @@ WRITE16_MEMBER(spg2xx_device::io_w) case 0x35: // UART TX Data LOGMASKED(LOG_UART, "io_w: UART Tx Data = %02x\n", data & 0x00ff); m_io_regs[offset] = data; + m_uart_tx((uint8_t)data); break; case 0x36: // UART RX Data @@ -1382,7 +1415,7 @@ WRITE16_MEMBER(spg2xx_device::io_w) break; default: - LOGMASKED(LOG_IO_WRITES, "io_w: Unknown register %04x = %04x\n", 0x3d00 + offset, data); + LOGMASKED(LOG_UNKNOWN_IO, "io_w: Unknown register %04x = %04x\n", 0x3d00 + offset, data); m_io_regs[offset] = data; break; } @@ -1394,21 +1427,17 @@ void spg2xx_device::device_timer(emu_timer &timer, device_timer_id id, int param { case TIMER_TMB1: { - const uint16_t old = (IO_IRQ_ENABLE & IO_IRQ_STATUS); + LOGMASKED(LOG_TIMERS, "TMB1 elapsed, setting IRQ Status bit 0 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 1, IO_IRQ_ENABLE); IO_IRQ_STATUS |= 1; - const uint16_t changed = old ^ (IO_IRQ_ENABLE & IO_IRQ_STATUS); - if (changed) - check_irqs(changed); + check_irqs(0x0001); break; } case TIMER_TMB2: { - const uint16_t old = m_io_regs[0x22] & m_io_regs[0x21]; + LOGMASKED(LOG_TIMERS, "TMB2 elapsed, setting IRQ Status bit 1 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 2, IO_IRQ_ENABLE); IO_IRQ_STATUS |= 2; - const uint16_t changed = old ^ (IO_IRQ_ENABLE & IO_IRQ_STATUS); - if (changed) - check_irqs(changed); + check_irqs(0x0002); break; } @@ -1440,10 +1469,14 @@ void spg2xx_device::check_irqs(const uint16_t changed) // } if (changed & 0x0c00) // Timer A, Timer B IRQ + { m_cpu->set_input_line(UNSP_IRQ2_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0c00) ? ASSERT_LINE : CLEAR_LINE); + } if (changed & 0x2100) // UART, ADC IRQ + { m_cpu->set_input_line(UNSP_IRQ3_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x2100) ? ASSERT_LINE : CLEAR_LINE); + } if (changed & (AUDIO_BIS_MASK | AUDIO_BIE_MASK)) // Beat IRQ { @@ -1460,13 +1493,20 @@ void spg2xx_device::check_irqs(const uint16_t changed) } if (changed & 0x1200) // External IRQ + { m_cpu->set_input_line(UNSP_IRQ5_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x1200) ? ASSERT_LINE : CLEAR_LINE); + } if (changed & 0x0070) // 1024Hz, 2048Hz, 4096Hz IRQ + { m_cpu->set_input_line(UNSP_IRQ6_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0070) ? ASSERT_LINE : CLEAR_LINE); + } if (changed & 0x008b) // TMB1, TMB2, 4Hz, key change IRQ + { + LOGMASKED(LOG_IRQS, "%ssserting timer IRQ (%04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b)); m_cpu->set_input_line(UNSP_IRQ7_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b) ? ASSERT_LINE : CLEAR_LINE); + } } void spg2xx_device::do_gpio(uint32_t offset) @@ -1665,7 +1705,7 @@ READ16_MEMBER(spg2xx_device::audio_r) break; default: - LOGMASKED(LOG_SPU_READS, "audio_r: Unknown register %04x = %04x\n", 0x3000 + offset, data); + LOGMASKED(LOG_UNKNOWN_SPU, "audio_r: Unknown register %04x = %04x\n", 0x3000 + offset, data); break; } } @@ -1767,13 +1807,13 @@ READ16_MEMBER(spg2xx_device::audio_r) break; default: - LOGMASKED(LOG_CHANNEL_READS, "audio_r: Unknown register %04x\n", 0x3000 + offset); + LOGMASKED(LOG_UNKNOWN_SPU, "audio_r: Unknown register %04x\n", 0x3000 + offset); break; } } else if (channel >= 16) { - LOGMASKED(LOG_CHANNEL_READS, "audio_r: Trying to read from channel %d\n", channel); + LOGMASKED(LOG_UNKNOWN_SPU, "audio_r: Trying to read from channel %d\n", channel); } return data; } @@ -2039,7 +2079,7 @@ WRITE16_MEMBER(spg2xx_device::audio_w) default: m_audio_regs[offset] = data; - LOGMASKED(LOG_SPU_WRITES, "audio_w: Unknown register %04x = %04x\n", 0x3000 + offset, data); + LOGMASKED(LOG_UNKNOWN_SPU, "audio_w: Unknown register %04x = %04x\n", 0x3000 + offset, data); break; } } @@ -2167,13 +2207,13 @@ WRITE16_MEMBER(spg2xx_device::audio_w) default: m_audio_regs[offset] = data; - LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Unknown register %04x = %04x\n", 0x3000 + offset, data); + LOGMASKED(LOG_UNKNOWN_SPU, "audio_w: Unknown register %04x = %04x\n", 0x3000 + offset, data); break; } } else if (channel >= 16) { - LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Trying to write to channel %d: %04x = %04x\n", channel, 0x3000 + offset, data); + LOGMASKED(LOG_UNKNOWN_SPU, "audio_w: Trying to write to channel %d: %04x = %04x\n", channel, 0x3000 + offset, data); } else { diff --git a/src/devices/machine/spg2xx.h b/src/devices/machine/spg2xx.h index 534f655b3c0..3e85537dbef 100644 --- a/src/devices/machine/spg2xx.h +++ b/src/devices/machine/spg2xx.h @@ -44,6 +44,8 @@ public: auto uart_tx() { return m_uart_tx.bind(); } + auto chip_select() { return m_chip_sel.bind(); } + void uart_rx(uint8_t data); uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); @@ -456,6 +458,8 @@ protected: devcb_write8 m_uart_tx; + devcb_write8 m_chip_sel; + emu_timer *m_tmb1; emu_timer *m_tmb2; emu_timer *m_screenpos_timer; diff --git a/src/mame/drivers/vii.cpp b/src/mame/drivers/vii.cpp index 85c999d71f5..a05a68c231b 100644 --- a/src/mame/drivers/vii.cpp +++ b/src/mame/drivers/vii.cpp @@ -77,9 +77,10 @@ Detailed list of bugs: #include "emu.h" #include "cpu/unsp/unsp.h" -#include "machine/spg2xx.h" +#include "machine/bankdev.h" #include "machine/i2cmem.h" #include "machine/nvram.h" +#include "machine/spg2xx.h" #include "bus/generic/slot.h" #include "bus/generic/carts.h" @@ -100,7 +101,7 @@ public: , m_debug_screen(*this, "debug_screen") #endif , m_spg(*this, "spg") - , m_bank(*this, "cart") + , m_bank(*this, "cartbank") , m_io_p1(*this, "P1") , m_io_p2(*this, "P2") , m_io_p3(*this, "P3") @@ -142,7 +143,7 @@ protected: required_device<screen_device> m_debug_screen; #endif required_device<spg2xx_device> m_spg; - required_memory_bank m_bank; + optional_memory_bank m_bank; protected: DECLARE_WRITE_LINE_MEMBER(poll_controls); @@ -152,7 +153,7 @@ protected: virtual void machine_reset() override; - void mem_map(address_map &map); + virtual void mem_map(address_map &map); uint32_t m_current_bank; @@ -178,6 +179,55 @@ protected: DECLARE_READ16_MEMBER(rad_crik_hack_r); }; +class vsmile_state : public spg2xx_game_state +{ +public: + vsmile_state(const machine_config &mconfig, device_type type, const char *tag) + : spg2xx_game_state(mconfig, type, tag) + , m_cart(*this, "cartslot") + , m_bankdev(*this, "bank") + , m_cart_banks(*this, "cartbank%u", 0U) + { } + + void vsmile(machine_config &config); + void vsmilep(machine_config &config); + +private: + virtual void machine_start() override; + virtual void machine_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + + static const device_timer_id TIMER_PAD = 0; + + virtual void mem_map(address_map &map) override; + void banked_map(address_map &map); + + DECLARE_DEVICE_IMAGE_LOAD_MEMBER(cart); + + DECLARE_READ16_MEMBER(portb_r); + DECLARE_READ16_MEMBER(portc_r); + DECLARE_WRITE16_MEMBER(portb_w); + DECLARE_WRITE16_MEMBER(portc_w); + + DECLARE_WRITE8_MEMBER(chip_sel_w); + + DECLARE_WRITE8_MEMBER(uart_tx); + + DECLARE_READ16_MEMBER(bank0_r); + DECLARE_READ16_MEMBER(bank1_r); + DECLARE_READ16_MEMBER(bank2_r); + DECLARE_READ16_MEMBER(bank3_r); + optional_device<generic_slot_device> m_cart; + memory_region *m_cart_rom; + required_device<address_map_bank_device> m_bankdev; + optional_memory_bank_array<4> m_cart_banks; + + emu_timer *m_pad_timer; + uint8_t m_pad_counter; + + uint16_t m_portb_data; + uint16_t m_portc_data; +}; class spg2xx_cart_state : public spg2xx_game_state { @@ -188,33 +238,17 @@ public: { } void vii(machine_config &config); - void vsmile(machine_config &config); - void vsmilep(machine_config &config); - - void init_vii(); private: DECLARE_WRITE16_MEMBER(vii_portb_w); DECLARE_DEVICE_IMAGE_LOAD_MEMBER(vii_cart); - DECLARE_DEVICE_IMAGE_LOAD_MEMBER(vsmile_cart); - - DECLARE_READ16_MEMBER(vsmile_porta_r); - DECLARE_READ16_MEMBER(vsmile_portb_r); - DECLARE_READ16_MEMBER(vsmile_portc_r); - DECLARE_WRITE16_MEMBER(vsmile_porta_w); - DECLARE_WRITE16_MEMBER(vsmile_portb_w); - DECLARE_WRITE16_MEMBER(vsmile_portc_w); virtual void machine_start() override; virtual void machine_reset() override; optional_device<generic_slot_device> m_cart; memory_region *m_cart_rom; - - uint16_t m_vsmile_porta_data; - uint16_t m_vsmile_portb_data; - uint16_t m_vsmile_portc_data; }; #define VERBOSE_LEVEL (4) @@ -298,40 +332,119 @@ WRITE16_MEMBER(spg2xx_cart_state::vii_portb_w) switch_bank(((data & 0x80) >> 7) | ((data & 0x20) >> 4)); } -READ16_MEMBER(spg2xx_cart_state::vsmile_porta_r) +void vsmile_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { - logerror("V.Smile Port A read, pull mask %04x\n", mem_mask); - return m_vsmile_porta_data & mem_mask; + if (id == TIMER_PAD) + { + m_pad_counter++; + if (m_pad_counter >= 100) + { + m_pad_counter = 0; + m_spg->uart_rx(0x55); + } + } } -READ16_MEMBER(spg2xx_cart_state::vsmile_portb_r) +#define VSMILE_PORTB_CS1 0x0001 +#define VSMILE_PORTB_CS2 0x0002 +#define VSMILE_PORTB_CART 0x0004 +#define VSMILE_PORTB_RESET 0x0008 +#define VSMILE_PORTB_FRONT24 0x0010 +#define VSMILE_PORTB_OFF 0x0020 +#define VSMILE_PORTB_OFF_SW 0x0040 +#define VSMILE_PORTB_ON_SW 0x0080 + +#define VSMILE_PORTC_VER 0x000f +#define VSMILE_PORTC_LOGO 0x0010 +#define VSMILE_PORTC_TEST 0x0020 +#define VSMILE_PORTC_AMP 0x0040 +#define VSMILE_PORTC_SYSRESET 0x0080 + +READ16_MEMBER(vsmile_state::bank0_r) { - logerror("V.Smile Port B read, pull mask %04x\n", mem_mask); - return m_vsmile_portb_data & mem_mask; + const uint16_t data = ((uint16_t*)m_cart_rom->base())[offset]; + //printf("bank0_r: %06x: %04x\n", offset, data); + return data; } -READ16_MEMBER(spg2xx_cart_state::vsmile_portc_r) +READ16_MEMBER(vsmile_state::bank1_r) { - logerror("V.Smile Port C read, pull mask %04x\n", mem_mask); - return m_vsmile_portc_data & mem_mask; + const uint16_t data = ((uint16_t*)m_cart_rom->base())[offset + 0x100000]; + //printf("bank1_r: %06x: %04x\n", offset + 0x100000, data); + return data; } -WRITE16_MEMBER(spg2xx_cart_state::vsmile_porta_w) +READ16_MEMBER(vsmile_state::bank2_r) { - logerror("V.Smile Port A write %04x, push mask %04x\n", data, mem_mask); - m_vsmile_porta_data = data & mem_mask; + const uint16_t data = ((uint16_t*)m_cart_rom->base())[offset + 0x200000]; + //printf("bank2_r: %06x: %04x\n", offset + 0x200000, data); + return data; } -WRITE16_MEMBER(spg2xx_cart_state::vsmile_portb_w) +READ16_MEMBER(vsmile_state::bank3_r) { - logerror("V.Smile Port B write %04x, push mask %04x\n", data, mem_mask); - m_vsmile_portb_data = data & mem_mask; + const uint16_t data = ((uint16_t*)memregion("maincpu")->base())[offset]; + //printf("bank3_r: %06x: %04x\n", offset + 0x300000, data); + return data; } -WRITE16_MEMBER(spg2xx_cart_state::vsmile_portc_w) +READ16_MEMBER(vsmile_state::portb_r) { - logerror("V.Smile Port C write %04x, push mask %04x\n", data, mem_mask); - m_vsmile_portc_data = data & mem_mask; + //const uint8_t inputs = m_io_p2->read(); + //const uint16_t input_bits = BIT(inputs, 0) ? VSMILE_PORTB_ON_SW : 0; + const uint16_t data = VSMILE_PORTB_ON_SW | (m_cart && m_cart->exists() ? VSMILE_PORTB_CART : 0); + logerror("V.Smile Port B read %04x, mask %04x\n", data, mem_mask); + //printf("V.Smile Port B read %04x, mask %04x\n", data, mem_mask); + return data; +} + +READ16_MEMBER(vsmile_state::portc_r) +{ + const uint16_t data = VSMILE_PORTC_LOGO | 0x0004; + logerror("V.Smile Port C read %04x, mask %04x\n", data, mem_mask); + return data; +} + +WRITE16_MEMBER(vsmile_state::portb_w) +{ + m_portb_data = data & mem_mask; + logerror("V.Smile Port B write %04x, mask %04x\n", m_portb_data, mem_mask); + //printf("V.Smile Port B write %04x, mask %04x\n", m_portb_data, mem_mask); +} + +WRITE16_MEMBER(vsmile_state::portc_w) +{ + m_portc_data = data & mem_mask; + logerror("V.Smile Port C write %04x, mask %04x\n", m_portc_data, mem_mask); + //printf("V.Smile Port C write %04x, mask %04x\n", m_portc_data, mem_mask); + //printf("%02x ", data >> 8); +} + +WRITE8_MEMBER(vsmile_state::uart_tx) +{ + logerror("UART Tx: %02x\n", data); +} + +WRITE8_MEMBER(vsmile_state::chip_sel_w) +{ + logerror("Chip select mode: %d\n", data); + const uint16_t cart_offset = m_cart && m_cart->exists() ? 4 : 0; + switch (data) + { + case 0: + logerror("Setting bank %d\n", cart_offset); + m_bankdev->set_bank(cart_offset); + break; + case 1: + logerror("Setting bank %d\n", 1 + cart_offset); + m_bankdev->set_bank(1 + cart_offset); + break; + case 2: + case 3: + logerror("Setting bank %d\n", 2 + cart_offset); + m_bankdev->set_bank(2 + cart_offset); + break; + } } READ16_MEMBER(spg2xx_game_state::walle_portc_r) @@ -382,7 +495,46 @@ READ16_MEMBER(spg2xx_game_state::jakks_porta_r) void spg2xx_game_state::mem_map(address_map &map) { - map(0x000000, 0x3fffff).bankr("cart"); + map(0x000000, 0x3fffff).bankr("cartbank"); + map(0x000000, 0x003fff).m(m_spg, FUNC(spg2xx_device::map)); +} + +void vsmile_state::banked_map(address_map &map) +{ + map(0x0000000, 0x00fffff).rom().region("maincpu", 0); + map(0x0100000, 0x01fffff).rom().region("maincpu", 0); + map(0x0200000, 0x02fffff).rom().region("maincpu", 0); + map(0x0300000, 0x03fffff).rom().region("maincpu", 0); + + map(0x0400000, 0x04fffff).rom().region("maincpu", 0); + map(0x0500000, 0x05fffff).rom().region("maincpu", 0); + map(0x0600000, 0x06fffff).rom().region("maincpu", 0); + map(0x0700000, 0x07fffff).rom().region("maincpu", 0); + + map(0x0800000, 0x08fffff).rom().region("maincpu", 0); + map(0x0900000, 0x09fffff).rom().region("maincpu", 0); + map(0x0a00000, 0x0afffff).rom().region("maincpu", 0); + map(0x0b00000, 0x0bfffff).rom().region("maincpu", 0); + + map(0x1000000, 0x10fffff).bankr("cartbank0"); + map(0x1100000, 0x11fffff).bankr("cartbank0"); + map(0x1200000, 0x12fffff).bankr("cartbank0"); + map(0x1300000, 0x13fffff).bankr("cartbank0"); + + map(0x1400000, 0x14fffff).bankr("cartbank0"); + map(0x1500000, 0x15fffff).bankr("cartbank0"); + map(0x1600000, 0x16fffff).bankr("cartbank1"); + map(0x1700000, 0x17fffff).bankr("cartbank1"); + + map(0x1800000, 0x18fffff).r(FUNC(vsmile_state::bank0_r)); + map(0x1900000, 0x19fffff).r(FUNC(vsmile_state::bank1_r)); + map(0x1a00000, 0x1afffff).nopr(); + map(0x1b00000, 0x1bfffff).r(FUNC(vsmile_state::bank3_r)); +} + +void vsmile_state::mem_map(address_map &map) +{ + map(0x000000, 0x3fffff).r(m_bankdev, FUNC(address_map_bank_device::read16)); map(0x000000, 0x003fff).m(m_spg, FUNC(spg2xx_device::map)); } @@ -429,6 +581,14 @@ static INPUT_PORTS_START( vsmile ) PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("Menu") PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("B Button") PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("X Button") + + PORT_START("P2") + PORT_DIPNAME( 0x0001, 0x0001, "POWER ON" ) + PORT_DIPSETTING( 0x0001, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x0002, 0x0002, "POWER OFF" ) + PORT_DIPSETTING( 0x0002, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) INPUT_PORTS_END static INPUT_PORTS_START( walle ) @@ -620,10 +780,48 @@ void spg2xx_cart_state::machine_start() m_bank->configure_entries(0, ceilf((float)m_cart_rom->bytes() / 0x800000), m_cart_rom->base(), 0x800000); m_bank->set_entry(0); } +} + +void vsmile_state::machine_start() +{ + // if there's a cart, override the standard banking + if (m_cart && m_cart->exists()) + { + std::string region_tag; + m_cart_rom = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str()); + for (uint32_t i = 0; i < 2; i++) + { + m_cart_banks[i]->configure_entries(0, (m_cart_rom->bytes() + 0x1fffff) / 0x200000, m_cart_rom->base(), 0x200000); + m_cart_banks[i]->set_entry(i); + } + } + else + { + for (uint32_t i = 0; i < 2; i++) + { + m_cart_rom = memregion("maincpu"); + m_cart_banks[i]->configure_entries(0, (m_cart_rom->bytes() + 0x1fffff) / 0x200000, m_cart_rom->base(), 0x200000); + m_cart_banks[i]->set_entry(0); + } + } - m_vsmile_porta_data = 0; - m_vsmile_portb_data = 0; - m_vsmile_portc_data = 0; + m_bankdev->set_bank(m_cart && m_cart->exists() ? 4 : 0); + + m_serial_eeprom = std::make_unique<uint8_t[]>(0x400); + if (m_nvram) + m_nvram->set_base(&m_serial_eeprom[0], 0x400); + + m_pad_timer = timer_alloc(TIMER_PAD); + m_pad_timer->adjust(attotime::never); +} + +void vsmile_state::machine_reset() +{ + m_portb_data = 0; + m_portc_data = 0; + + m_pad_timer->adjust(attotime::from_hz(100), 0, attotime::from_hz(100)); + m_pad_counter = 0; } void spg2xx_cart_state::machine_reset() @@ -699,7 +897,7 @@ DEVICE_IMAGE_LOAD_MEMBER(spg2xx_cart_state, vii_cart) return image_init_result::PASS; } -DEVICE_IMAGE_LOAD_MEMBER(spg2xx_cart_state, vsmile_cart) +DEVICE_IMAGE_LOAD_MEMBER(vsmile_state, cart) { uint32_t size = m_cart->common_get_size("rom"); @@ -778,7 +976,7 @@ void spg2xx_cart_state::vii(machine_config &config) SOFTWARE_LIST(config, "vii_cart").set_original("vii"); } -void spg2xx_cart_state::vsmile(machine_config &config) +void vsmile_state::vsmile(machine_config &config) { #if SPG2XX_VISUAL_AUDIO_DEBUG SPG24X(config, m_spg, XTAL(27'000'000), m_maincpu, m_screen, m_debug_screen); @@ -786,22 +984,30 @@ void spg2xx_cart_state::vsmile(machine_config &config) SPG24X(config, m_spg, XTAL(27'000'000), m_maincpu, m_screen); #endif spg2xx_base(config); + m_maincpu->set_addrmap(AS_PROGRAM, &vsmile_state::mem_map); - m_spg->porta_in().set(FUNC(spg2xx_cart_state::vsmile_porta_r)); - m_spg->portb_in().set(FUNC(spg2xx_cart_state::vsmile_portb_r)); - m_spg->portc_in().set(FUNC(spg2xx_cart_state::vsmile_portc_r)); - m_spg->porta_out().set(FUNC(spg2xx_cart_state::vsmile_porta_w)); - m_spg->portb_out().set(FUNC(spg2xx_cart_state::vsmile_portb_w)); - m_spg->portc_out().set(FUNC(spg2xx_cart_state::vsmile_portc_w)); + m_spg->portb_in().set(FUNC(vsmile_state::portb_r)); + m_spg->portc_in().set(FUNC(vsmile_state::portc_r)); + m_spg->portb_out().set(FUNC(vsmile_state::portb_w)); + m_spg->portc_out().set(FUNC(vsmile_state::portc_w)); + m_spg->chip_select().set(FUNC(vsmile_state::chip_sel_w)); + m_spg->uart_tx().set(FUNC(vsmile_state::uart_tx)); GENERIC_CARTSLOT(config, m_cart, generic_plain_slot, "vsmile_cart"); m_cart->set_width(GENERIC_ROM16_WIDTH); - m_cart->set_device_load(device_image_load_delegate(&spg2xx_cart_state::device_image_load_vsmile_cart, this)); + m_cart->set_device_load(device_image_load_delegate(&vsmile_state::device_image_load_cart, this)); + + ADDRESS_MAP_BANK(config, m_bankdev); + m_bankdev->set_addrmap(AS_PROGRAM, &vsmile_state::banked_map); + m_bankdev->set_endianness(ENDIANNESS_LITTLE); + m_bankdev->set_data_width(16); + m_bankdev->set_shift(-1); + m_bankdev->set_stride(0x400000); SOFTWARE_LIST(config, "cart_list").set_original("vsmile_cart"); } -void spg2xx_cart_state::vsmilep(machine_config &config) +void vsmile_state::vsmilep(machine_config &config) { vsmile(config); m_spg->set_pal(true); @@ -1091,10 +1297,10 @@ ROM_END // year, name, parent, compat, machine, input, class, init, company, fullname, flags // VTech systems -CONS( 2005, vsmile, 0, 0, vsmile, vsmile, spg2xx_cart_state, empty_init, "VTech", "V.Smile (US)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) -CONS( 2005, vsmileg, vsmile, 0, vsmilep, vsmile, spg2xx_cart_state, empty_init, "VTech", "V.Smile (Germany)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) -CONS( 2005, vsmilef, vsmile, 0, vsmilep, vsmile, spg2xx_cart_state, empty_init, "VTech", "V.Smile (France)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) -CONS( 2005, vsmileb, 0, 0, vsmile, vsmile, spg2xx_cart_state, empty_init, "VTech", "V.Smile Baby (US)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) +CONS( 2005, vsmile, 0, 0, vsmile, vsmile, vsmile_state, empty_init, "VTech", "V.Smile (US)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) +CONS( 2005, vsmileg, vsmile, 0, vsmilep, vsmile, vsmile_state, empty_init, "VTech", "V.Smile (Germany)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) +CONS( 2005, vsmilef, vsmile, 0, vsmilep, vsmile, vsmile_state, empty_init, "VTech", "V.Smile (France)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) +CONS( 2005, vsmileb, 0, 0, vsmile, vsmile, vsmile_state, empty_init, "VTech", "V.Smile Baby (US)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) // Jungle Soft TV games CONS( 2007, vii, 0, 0, vii, vii, spg2xx_cart_state, empty_init, "Jungle Soft / KenSingTon / Siatronics", "Vii", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) // motion controls are awkward, but playable for the most part |