diff options
| author | 2026-05-19 20:44:10 +0100 | |
|---|---|---|
| committer | 2026-05-19 21:44:10 +0200 | |
| commit | f125c7a141c26513ca3210276b45e781920b4f16 (patch) | |
| tree | 5c064d112dea32f8e395a08490d448fd2927e4ce /src | |
| parent | 46dbf56bb9507a5c403189175451d370aad7ac6e (diff) | |
gpl951xx - more aggressive template use (#15352)
- generalplus_gpl951xx_soc - use templates for timebase and timers, add more timers [David Haywood]
- generalplus_gpl951xx_soc - basic 'manual' ADC mode support [David Haywood]
- generalplus_gpl951xx_soc - provide address when required in autocmd mode for spifc, to prevent wrong addresses being written [David Haywood]
- generalplus_gpl951xx_soc - add stub logging more registers [David Haywood]
- gpl_renderer - port improved linemap code from spg_renderer so that other BPPs can be handled [David Haywood]
- generalplus_gpl951xx_rtc - allow setting / reading of timer registers [David Haywood]
- generalplus_gpl951xx.cpp - various cleanups driver-side, including template use [David Haywood]
Diffstat (limited to 'src')
| -rw-r--r-- | src/devices/machine/generalplus_gpl162xx_soc.cpp | 10 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl162xx_soc_video.cpp | 19 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl951xx_rtc.cpp | 114 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl951xx_rtc.h | 20 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl951xx_soc.cpp | 602 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl951xx_soc.h | 89 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl_chx.cpp | 42 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl_chx.h | 3 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl_dma.cpp | 7 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl_timebase.cpp | 163 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl_timebase.h | 28 | ||||
| -rw-r--r-- | src/devices/machine/generic_spi_flash.cpp | 12 | ||||
| -rw-r--r-- | src/devices/machine/gpl_renderer.cpp | 131 | ||||
| -rw-r--r-- | src/devices/machine/gpl_renderer.h | 2 | ||||
| -rw-r--r-- | src/mame/handheld/generalplus_gpl951xx.cpp | 270 |
15 files changed, 991 insertions, 521 deletions
diff --git a/src/devices/machine/generalplus_gpl162xx_soc.cpp b/src/devices/machine/generalplus_gpl162xx_soc.cpp index 3dbc7c4f554..9ddda8f8479 100644 --- a/src/devices/machine/generalplus_gpl162xx_soc.cpp +++ b/src/devices/machine/generalplus_gpl162xx_soc.cpp @@ -577,13 +577,13 @@ u16 sunplus_gcm394_base_device::int_status2_r() LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::int_status2_r\n", machine().describe_context()); u16 ret = 0; - if (m_gpl_timebase->timebasea_irq_flag()) + if (m_gpl_timebase->timebase_irq_flag<0>()) ret |= 0x0100; - if (m_gpl_timebase->timebaseb_irq_flag()) + if (m_gpl_timebase->timebase_irq_flag<1>()) ret |= 0x0200; - if (m_gpl_timebase->timebasec_irq_flag()) + if (m_gpl_timebase->timebase_irq_flag<2>()) ret |= 0x0400; return ret; @@ -693,7 +693,7 @@ void sunplus_gcm394_base_device::mint_ctrl_w(u16 data) void sunplus_gcm394_base_device::update_interrupts(int state) { - if ((m_gpl_timebase->timebasea_irq_flag() && !m_disable_timebase_interrupts) || (m_gpl_timebase->timebaseb_irq_flag() && !m_disable_timebase_interrupts)) + if ((m_gpl_timebase->timebase_irq_flag<0>() && !m_disable_timebase_interrupts) || (m_gpl_timebase->timebase_irq_flag<1>() && !m_disable_timebase_interrupts)) { set_state_unsynced(UNSP_IRQ7_LINE, ASSERT_LINE); } @@ -702,7 +702,7 @@ void sunplus_gcm394_base_device::update_interrupts(int state) set_state_unsynced(UNSP_IRQ7_LINE, CLEAR_LINE); } - if ((m_gpl_timebase->timebasec_irq_flag() && !m_disable_timebase_interrupts) || (m_rtc_int_status & 0x0100)) + if ((m_gpl_timebase->timebase_irq_flag<2>() && !m_disable_timebase_interrupts) || (m_rtc_int_status & 0x0100)) { set_state_unsynced(UNSP_IRQ6_LINE, ASSERT_LINE); } diff --git a/src/devices/machine/generalplus_gpl162xx_soc_video.cpp b/src/devices/machine/generalplus_gpl162xx_soc_video.cpp index 76c94326008..031587fa8bb 100644 --- a/src/devices/machine/generalplus_gpl162xx_soc_video.cpp +++ b/src/devices/machine/generalplus_gpl162xx_soc_video.cpp @@ -282,7 +282,7 @@ void gcm394_base_video_device::device_reset() for (int i=0;i<0x100 * 0x10;i++) m_paletteram[i] = machine().rand()&0x7fff; - m_707f = 0x0000; + m_707f = 0x0001; m_703a_palettebank = 0x0000; m_video_irq_enable = 0x0000; m_video_irq_status = 0x0000; @@ -883,7 +883,22 @@ u16 gcm394_base_video_device::ppu_enable_r() } void gcm394_base_video_device::ppu_enable_w(u16 data) { - LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::ppu_enable_w %04x\n", machine().describe_context(), data); + u8 save_rom = (data & 0x8000) >> 15; + u8 unused = (data & 0x7000) >> 12; + u8 fb_mono = (data & 0x0c00) >> 10; + u8 spr25d = (data & 0x0200) >> 9; + u8 fb_format = (data & 0x0100) >> 8; + u8 fb_en = (data & 0x0080) >> 7; + u8 free_adr = (data & 0x0040) >> 6; + u8 vga_nointl = (data & 0x0020) >> 5; + u8 vga_en = (data & 0x0010) >> 4; + u8 tx_botup = (data & 0x0008) >> 3; + u8 tx_direct = (data & 0x0004) >> 2; + u8 tchar = (data & 0x0002) >> 1; + u8 ppu_en = (data & 0x0001) >> 0; + + LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::ppu_enable_w %04x (save_rom %01x, unused %01x, fb_mono %01x, spr25d %01x, fb_format %01x, fb_en %01x, free_adr %01x, vga_nointl %01x, vga_en %01x, tx_botup %01x, tx_direct %01x, tchar %01x, ppu_en %01x)\n", + machine().describe_context(), data, save_rom, unused, fb_mono, spr25d, fb_format, fb_en, free_adr, vga_nointl, vga_en, tx_botup, tx_direct, tchar, ppu_en); m_707f = data; m_renderer->set_video_reg_7f(data); diff --git a/src/devices/machine/generalplus_gpl951xx_rtc.cpp b/src/devices/machine/generalplus_gpl951xx_rtc.cpp index da303406d4a..da0414f5f46 100644 --- a/src/devices/machine/generalplus_gpl951xx_rtc.cpp +++ b/src/devices/machine/generalplus_gpl951xx_rtc.cpp @@ -6,7 +6,7 @@ #define LOG_RTC (1U << 1) -#define VERBOSE (0) +#define VERBOSE (LOG_RTC) #include "logmacro.h" @@ -36,10 +36,6 @@ inline void gpl951xx_rtc_device::writebyte(offs_t address, uint8_t data) space().write_byte(address, data); } -void gpl951xx_rtc_device::device_validity_check(validity_checker &valid) const -{ -} - void gpl951xx_rtc_device::device_start() { save_item(NAME(m_rtc_addr)); @@ -48,6 +44,15 @@ void gpl951xx_rtc_device::device_start() save_item(NAME(m_reg40)); save_item(NAME(m_reg50)); + + save_item(NAME(m_loadcnt)); + save_item(NAME(m_alarmdat)); + save_item(NAME(m_timerval)); + + // not on reset? (should be saved as NV?) + m_loadcnt = 0; + m_alarmdat = 0; + m_timerval = 0; } void gpl951xx_rtc_device::device_reset() @@ -60,24 +65,75 @@ void gpl951xx_rtc_device::device_reset() m_reg50 = 0; } +// Reg00 +// +// 4 Rtcclken +// 3 Rtcrst +// 2 Timerdir +// 1 SWreset +// 0 Busy + u8 gpl951xx_rtc_device::reg00_r() { LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg00_r\n", machine().describe_context()); return 0x00; } +// Reg01 +// +// 3 Slow_clk +// 2 Reserved +// 1 Strong +// 0 Reserved + u8 gpl951xx_rtc_device::reg01_r() { LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg01_r\n", machine().describe_context()); return 0x01; } +// Reg02 +// +// 'reliable' + +u8 gpl951xx_rtc_device::reg02_r() +{ + LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg02_r\n", machine().describe_context()); + return m_reg02; +} + +void gpl951xx_rtc_device::reg02_w(u8 data) +{ + LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg02_w %02x\n", machine().describe_context(), data); + m_reg02 = data; +} + +// Reg40 +// +// 3 HalfSecint +// 2 Rtcwakeup +// 1 Alarmint +// 0 Secint + +u8 gpl951xx_rtc_device::reg40_r() +{ + LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg40_r\n", machine().describe_context()); + return m_reg40; +} + void gpl951xx_rtc_device::reg40_w(u8 data) { LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg40_w %02x\n", machine().describe_context(), data); m_reg40 = data; } +// Reg50 +// +// 3 HalfSecint_en +// 2 Rtcwakeup_en +// 1 Alarmint_en +// 0 Secint_en + u8 gpl951xx_rtc_device::reg50_r() { LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg50_r\n", machine().describe_context()); @@ -90,13 +146,49 @@ void gpl951xx_rtc_device::reg50_w(u8 data) m_reg50 = data; } +void gpl951xx_rtc_device::loadcnt_w(offs_t offset, u8 data) +{ + u64 bits = (u64)0xff << (8 * offset); + u64 databits = (u64)data << (8 * offset); + m_loadcnt = m_loadcnt & ~bits; + m_loadcnt |= databits; + + LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::loadcnt_w (offset %02x) %02x (loadcnt is now %08x%08x)\n", machine().describe_context(), offset, data, (u32)(m_loadcnt >> 32), (u32)(m_loadcnt & 0xffffffff)); + + // TODO: not sure this is how it's reloaded + if (offset == 5) + m_timerval = m_loadcnt; +} + +void gpl951xx_rtc_device::alarmdat_w(offs_t offset, u8 data) +{ + u64 bits = (u64)0xff << (8 * offset); + u64 databits = (u64)data << (8 * offset); + m_alarmdat = m_alarmdat & ~bits; + m_alarmdat |= databits; + + LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::alarmdat_w (offset %02x) %02x (alarmdat is now %08x%08x)\n", machine().describe_context(), offset, data, (u32)(m_loadcnt >> 32), (u32)(m_loadcnt & 0xffffffff)); +} + +u8 gpl951xx_rtc_device::timerval_r(offs_t offset) +{ + LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::timerval_r (offset %02x)\n", machine().describe_context(), offset); + return m_timerval >> (offset * 8); +} + void gpl951xx_rtc_device::rtc_regs(address_map &map) { if (!has_configured_map(0)) { map(0x00, 0x00).r(FUNC(gpl951xx_rtc_device::reg00_r)); map(0x01, 0x01).r(FUNC(gpl951xx_rtc_device::reg01_r)); - map(0x40, 0x40).w(FUNC(gpl951xx_rtc_device::reg40_w)); + map(0x02, 0x02).rw(FUNC(gpl951xx_rtc_device::reg02_r), FUNC(gpl951xx_rtc_device::reg02_w)); + + map(0x10, 0x15).w(FUNC(gpl951xx_rtc_device::loadcnt_w)); + map(0x20, 0x25).w(FUNC(gpl951xx_rtc_device::alarmdat_w)); + map(0x30, 0x35).r(FUNC(gpl951xx_rtc_device::timerval_r)); + + map(0x40, 0x40).rw(FUNC(gpl951xx_rtc_device::reg40_r), FUNC(gpl951xx_rtc_device::reg40_w)); map(0x50, 0x50).rw(FUNC(gpl951xx_rtc_device::reg50_r), FUNC(gpl951xx_rtc_device::reg50_w)); // 0x80 - 0x8f reserved map(0x90, 0xff).ram(); @@ -149,3 +241,13 @@ void gpl951xx_rtc_device::rtc_request_w(u16 data) if (data & 2) m_read_dat = readbyte(m_rtc_addr); } + +TIMER_DEVICE_CALLBACK_MEMBER( gpl951xx_rtc_device::rtc_cb ) +{ + m_timerval++; +} + +void gpl951xx_rtc_device::device_add_mconfig(machine_config &config) +{ + TIMER(config, "rtc_timer").configure_periodic(FUNC(gpl951xx_rtc_device::rtc_cb), attotime::from_hz(32768)); +} diff --git a/src/devices/machine/generalplus_gpl951xx_rtc.h b/src/devices/machine/generalplus_gpl951xx_rtc.h index 11d011fe21b..209e25cd371 100644 --- a/src/devices/machine/generalplus_gpl951xx_rtc.h +++ b/src/devices/machine/generalplus_gpl951xx_rtc.h @@ -5,6 +5,8 @@ #pragma once +#include "machine/timer.h" + class gpl951xx_rtc_device : public device_t, public device_memory_interface { @@ -22,7 +24,7 @@ public: void rtc_request_w(u16 data); protected: - virtual void device_validity_check(validity_checker &valid) const override; + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; virtual void device_start() override ATTR_COLD; virtual void device_reset() override ATTR_COLD; virtual space_config_vector memory_space_config() const override; @@ -33,20 +35,36 @@ private: inline uint8_t readbyte(offs_t address); inline void writebyte(offs_t address, uint8_t data); + TIMER_DEVICE_CALLBACK_MEMBER(rtc_cb); + u8 reg00_r(); u8 reg01_r(); + u8 reg02_r(); + void reg02_w(u8 data); + u8 reg40_r(); void reg40_w(u8 data); u8 reg50_r(); void reg50_w(u8 data); + void loadcnt_w(offs_t offset, u8 data); + void alarmdat_w(offs_t offset, u8 data); + u8 timerval_r(offs_t offset); + u8 m_rtc_addr; u8 m_read_dat; u8 m_write_dat; + u8 m_reg02; + u8 m_reg40; u8 m_reg50; + + // these are 48-bit registers + u64 m_loadcnt; + u64 m_alarmdat; + u64 m_timerval; }; DECLARE_DEVICE_TYPE(GPL951XX_RTC, gpl951xx_rtc_device) diff --git a/src/devices/machine/generalplus_gpl951xx_soc.cpp b/src/devices/machine/generalplus_gpl951xx_soc.cpp index efea49eee48..ee6840ad0b5 100644 --- a/src/devices/machine/generalplus_gpl951xx_soc.cpp +++ b/src/devices/machine/generalplus_gpl951xx_soc.cpp @@ -1,6 +1,17 @@ // license:BSD-3-Clause // copyright-holders:David Haywood +// known SoCs +// +// GPL95100UA +// GPL95101UA (101 model again has fewer features) +// +// 'B' models have different timer e/f behavior amongst other changes +// GPL95100UB / GPL95100UB1 (unclear what difference is between UB and UB1) +// GPL95101UB / GPL95101UB1 (101 models have fewer features than 100) +// + + #include "emu.h" #include "generalplus_gpl951xx_soc.h" @@ -8,7 +19,7 @@ #define LOG_TFT (1U << 2) #define LOG_OTHER (1U << 3) -#define VERBOSE (LOG_SPIFC | LOG_TFT | LOG_OTHER) +#define VERBOSE (LOG_SPIFC | LOG_OTHER) #include "logmacro.h" @@ -123,6 +134,14 @@ void generalplus_gpl951xx_device::spifc_cmd_w(u16 data) m_spi_reset(1); m_spi_out_cmd(data & 0x00ff); + if (!(m_spifc_para & 0x1000)) + { + m_spi_out((m_spifc_addr >> 16) & 0xff); + m_spi_out((m_spifc_addr >> 8) & 0xff); + m_spi_out((m_spifc_addr >> 0) & 0xff); + + } + // how does byte count work? the FIFO is apparently in words for (int i = 0; i < m_spifc_rx_bc; i++) { @@ -359,10 +378,8 @@ void generalplus_gpl951xx_device::device_start() unsp_20_device::device_start(); save_item(NAME(m_byteswap)); - save_item(NAME(m_timerg_ctrl)); - save_item(NAME(m_timerg_preload)); - save_item(NAME(m_timerh_ctrl)); - save_item(NAME(m_timerh_preload)); + save_item(NAME(m_timer_ctrl)); + save_item(NAME(m_timer_preload)); save_item(NAME(m_spifc_ctrl)); save_item(NAME(m_spifc_ctrl2)); save_item(NAME(m_spifc_addr)); @@ -386,18 +403,25 @@ void generalplus_gpl951xx_device::device_start() save_item(NAME(m_int_priority_3)); save_item(NAME(m_misc_int_ctrl)); save_item(NAME(m_pllchange)); + save_item(NAME(m_tft_rgb_ctrl)); + save_item(NAME(m_madc_ctrl)); + save_item(NAME(m_madc_data)); } void generalplus_gpl951xx_device::device_reset() { unsp_20_device::device_reset(); m_spg_video->reset(); + m_spg_video->set_disallow_resolution_control(); m_byteswap = 0; - m_timerg_ctrl = 0; - m_timerg_preload = 0; - m_timerh_ctrl = 0; - m_timerh_preload = 0; + + for (int i = 0; i < 8; i++) + { + m_timer_ctrl[i] = 0; + m_timer_preload[i] = 0; + } + m_spifc_ctrl = 0; m_spifc_ctrl2 = 0; m_spifc_addr = 0; @@ -418,6 +442,7 @@ void generalplus_gpl951xx_device::device_reset() m_int_priority_3 = 0; m_misc_int_ctrl = 0; m_pllchange = 0; + m_tft_rgb_ctrl = 0; for (int i = 0; i < 6; i++) { @@ -436,174 +461,126 @@ void generalplus_gpl951xx_device::dac_0_w(uint16_t data) m_dac0->write(data); } -TIMER_DEVICE_CALLBACK_MEMBER( generalplus_gpl951xx_device::timer_g_cb ) -{ - m_timerg_ctrl |= 0x8000; - update_interrupts(1); - m_gpl_chx->process_cha_fifo(); // is cha hardwired to timerg overflow? -} - void generalplus_gpl951xx_device::dac_1_w(uint16_t data) { m_dac1->write(data); } -TIMER_DEVICE_CALLBACK_MEMBER( generalplus_gpl951xx_device::timer_h_cb ) -{ - m_timerh_ctrl |= 0x8000; - update_interrupts(1); - m_gpl_chx->process_chb_fifo(); // is chb hardwired to timerh overflow? -} - -u16 generalplus_gpl951xx_device::timerg_preload_r() -{ - logerror("%s: timerg_preload_r\n", machine().describe_context()); - return m_timerg_preload; -} +// Other timers are more generic +// although timers e and f have different behavior depending on SoC -void generalplus_gpl951xx_device::timerg_preload_w(u16 data) +template<int Timer> +u16 generalplus_gpl951xx_device::timer_ctrl_r() { - logerror("%s: timerg_preload_w %04x\n", machine().describe_context(), data); - m_timerg_preload = data; -} - -// P_TimerG_Ctrl - -// 15 TMGIF/C -// 14 TMGIE -// 13 TMGEN -// 12 -// 11 EXT0SEL[1] -// 10 EXT0SEL[0] -// 9 EXT1SEL[1] -// 8 EXT1SEL[0] -// 7 -// 6 SRCBSEL[2] -// 5 SRCBSEL[1] -// 4 SRCBSEL[0] -// 3 SRCASEL[3] -// 2 SRCASEL[2] -// 1 SRCASEL[1] -// 0 SRCASEL[0] - -u16 generalplus_gpl951xx_device::timerg_ctrl_r() -{ - logerror("%s: timerg_ctrl_r\n", machine().describe_context()); - u16 ret = m_timerg_ctrl; - return ret; + logerror("%s: timer%c_ctrl_r\n", machine().describe_context(), 'a'+Timer); + return m_timer_ctrl[Timer]; } -void generalplus_gpl951xx_device::timerg_ctrl_w(u16 data) +template<int Timer> +void generalplus_gpl951xx_device::timer_ctrl_w(u16 data) { - u8 tmgif_clear = (data & 0x8000) >> 15; - u8 tmgie = (data & 0x4000) >> 14; - u8 tmgen = (data & 0x2000) >> 13; + u8 tmxif_clear = (data & 0x8000) >> 15; + u8 tmxie = (data & 0x4000) >> 14; + u8 tmxen = (data & 0x2000) >> 13; u8 ext0sel = (data & 0x0c00) >> 10; u8 ext1sel = (data & 0x0300) >> 8; u8 srcbsel = (data & 0x0070) >> 4; u8 srcasel = (data & 0x000f) >> 0; - logerror("%s: timerg_ctrl_w %04x (tmgif_clear %01x) (interrupt enabled %01x) (timer enabled %01x) (ext0sel %01x) (ext1sel %01x) (srcbsel %s) (srcasel %s)\n", machine().describe_context(), data, tmgif_clear, tmgie, tmgen, ext0sel, ext1sel, m_srcb[srcbsel], m_srca[srcasel]); + logerror("%s: timer%c_ctrl_w %04x (tmxif_clear %01x) (interrupt enabled %01x) (timer enabled %01x) (ext0sel %01x) (ext1sel %01x) (srcbsel %01x) (srcasel %01x)\n", machine().describe_context(), 'a'+Timer, data, tmxif_clear, tmxie, tmxen, ext0sel, ext1sel, m_srcb[srcbsel], m_srca[srcasel]); if (data & 0x8000) { - m_timerg_ctrl &= 0x7fff; + m_timer_ctrl[Timer] &= 0x7fff; } - if ((data & 0x2000) != (m_timerg_ctrl & 0x2000)) + if ((data & 0x2000) != (m_timer_ctrl[Timer] & 0x2000)) { if (data & 0x2000) { - m_timer_g->adjust(attotime::zero, 0, attotime::from_hz(8000)); + // currently hardcoded, need to figure out how to use the preload and timer source registers properly! + if (Timer == 6) + m_timer[Timer]->adjust(attotime::zero, 0, attotime::from_hz(8000)); + else if (Timer == 3) + m_timer[Timer]->adjust(attotime::zero, 0, attotime::from_hz(20000)); + else + m_timer[Timer]->adjust(attotime::zero, 0, attotime::from_hz(1000)); } else { - m_timer_g->adjust(attotime::never); + m_timer[Timer]->adjust(attotime::never); } + } - m_timerg_ctrl = (m_timerg_ctrl & 0x8000) | (data & 0x7fff); + m_timer_ctrl[Timer] = (m_timer_ctrl[Timer] & 0x8000) | (data & 0x7fff); update_interrupts(1); } -u16 generalplus_gpl951xx_device::timerh_preload_r() +template<int Timer> +u16 generalplus_gpl951xx_device::timer_preload_r() { - logerror("%s: timerh_preload_r\n", machine().describe_context()); - return m_timerh_preload; + logerror("%s: timer%c_preload_r\n", machine().describe_context(), 'a'+Timer); + return m_timer_preload[Timer]; } -void generalplus_gpl951xx_device::timerh_preload_w(u16 data) +template<int Timer> +void generalplus_gpl951xx_device::timer_preload_w(u16 data) { - logerror("%s: timerh_preload_w %04x\n", machine().describe_context(), data); - m_timerh_preload = data; + logerror("%s: timer%c_preload_w %04x\n", machine().describe_context(), 'a'+Timer, data); + m_timer_preload[Timer] = data; } -// P_TimerH_Ctrl -// 15 TMHIF/C -// 14 TMHIE -// 13 TMHEN -// 12 -// -// 11 EXT0SEL[1] -// 10 EXT0SEL[0] -// 9 EXT1SEL[1] -// 8 EXT1SEL[0] + +// P_Timerx_CCPB_Ctrl // -// 7 -// 6 SRCBSEL[2] -// 5 SRCBSEL[1] -// 4 SRCBSEL[0] +// 15 CCPBxEN[1] - 00 = CCPB Mode Disabled, 01 = Capture Enabled, 10 = Comparison Enabled, 11 = PWM/BAM Enabled +// 14 CCPBxEN[0] +// 13 +// 12 // -// 3 SRCASEL[3] -// 2 SRCASEL[2] -// 1 SRCASEL[1] -// 0 SRCASEL[0] +// 11 +// 10 +// 9 CAPxSEL[1] - 00 = every falling, 01 = every rising, 10/11 = reserved +// 8 CAPxSEL[0] +// +// 7 +// 6 +// 5 CMPxSEL[1] - 00 = high pulse on CCPB, 01 = low pulse on CCPB, 10 = unaffected on CCPB, 11 = reserved +// 4 CMPxSEL[0] +// +// 3 +// 2 +// 1 PWMxSEL[1] - 00 = PWM mode/NRO output, 01 = PWM mode/NRZ output, 10 = BAM mode/NRO output, 11 = BAM mode/NRZ output +// 0 PWMxSEL[0] -u16 generalplus_gpl951xx_device::timerh_ctrl_r() +template<int Timer> +void generalplus_gpl951xx_device::timer_ccpb_ctrl_w(u16 data) { - u16 ret = m_timerh_ctrl; - logerror("%s: timerh_ctrl_r (returning %04x)\n", machine().describe_context(), ret); - return ret; + logerror("%s: timer%c_ccpb_ctrl_w %04x\n", machine().describe_context(), 'a'+Timer, data); } -void generalplus_gpl951xx_device::timerh_ctrl_w(u16 data) +template<int Timer> +u16 generalplus_gpl951xx_device::timer_upcount_r() { - u8 tmhif_clear = (data & 0x8000) >> 15; - u8 tmhie = (data & 0x4000) >> 14; - u8 tmhen = (data & 0x2000) >> 13; - u8 ext0sel = (data & 0x0c00) >> 10; - u8 ext1sel = (data & 0x0300) >> 8; - u8 srcbsel = (data & 0x0070) >> 4; - u8 srcasel = (data & 0x000f) >> 0; + logerror("%s: timera_upcount_r\n", machine().describe_context(), 'a'+Timer); + return machine().rand(); +} - logerror("%s: timerh_ctrl_w %04x (tmhif_clear %01x) (interrupt enabled %01x) (timer enabled %01x) (ext0sel %01x) (ext1sel %01x) (srcbsel %01x) (srcasel %01x)\n", machine().describe_context(), data, tmhif_clear, tmhie, tmhen, ext0sel, ext1sel, m_srcb[srcbsel], m_srca[srcasel]); - if (data & 0x8000) - { - logerror("cleared timerh flag\n"); - m_timerh_ctrl &= 0x7fff; - } - if ((data & 0x2000) != (m_timerh_ctrl & 0x2000)) - { - logerror("changed\n"); - if (data & 0x2000) - { - logerror("started timerh\n"); - m_timer_h->adjust(attotime::zero, 0, attotime::from_hz(1000)); - } - else - { - m_timer_h->adjust(attotime::never); - } - - } - - m_timerh_ctrl = (m_timerh_ctrl & 0x8000) | (data & 0x7fff); - update_interrupts(1); +u16 generalplus_gpl951xx_device::i2c_ctrl_r() +{ + logerror("%s: i2c_ctrl_r\n", machine().describe_context()); + return machine().rand(); } +u16 generalplus_gpl951xx_device::i2c_status_r() +{ + logerror("%s: i2c_status_r\n", machine().describe_context()); + return machine().rand(); +} // TFT @@ -706,6 +683,89 @@ void generalplus_gpl951xx_device::tft_memmode_wcmd_w(u16 data) m_memmode_wcmd = data; } + +u16 generalplus_gpl951xx_device::tft_rgb_ctrl_r() +{ + LOGMASKED(LOG_TFT, "%s: tft_rgb_ctrl_r\n", machine().describe_context()); + return m_tft_rgb_ctrl; +} + +void generalplus_gpl951xx_device::tft_rgb_ctrl_w(u16 data) +{ + LOGMASKED(LOG_TFT, "%s: tft_rgb_ctrl_w %04x\n", machine().describe_context(), data); + m_tft_rgb_ctrl = data; +} + +void generalplus_gpl951xx_device::tft_v_width_w(u16 data) +{ + LOGMASKED(LOG_TFT, "%s: tft_v_width_w %04x\n", machine().describe_context(), data); +} + +void generalplus_gpl951xx_device::tft_vsync_setup_w(u16 data) +{ + LOGMASKED(LOG_TFT, "%s: tft_vsync_setup_w %04x\n", machine().describe_context(), data); +} + +void generalplus_gpl951xx_device::tft_v_start_w(u16 data) +{ + LOGMASKED(LOG_TFT, "%s: tft_v_start_w %04x\n", machine().describe_context(), data); +} + +void generalplus_gpl951xx_device::tft_v_end_w(u16 data) +{ + LOGMASKED(LOG_TFT, "%s: tft_v_end_w %04x\n", machine().describe_context(), data); +} + +void generalplus_gpl951xx_device::tft_h_width_w(u16 data) +{ + LOGMASKED(LOG_TFT, "%s: tft_h_width_w %04x\n", machine().describe_context(), data); +} + +void generalplus_gpl951xx_device::tft_hsync_setup_w(u16 data) +{ + LOGMASKED(LOG_TFT, "%s: tft_hsync_setup_w %04x\n", machine().describe_context(), data); +} + +void generalplus_gpl951xx_device::tft_h_start_w(u16 data) +{ + LOGMASKED(LOG_TFT, "%s: tft_h_start_w %04x\n", machine().describe_context(), data); +} + +void generalplus_gpl951xx_device::tft_h_end_w(u16 data) +{ + LOGMASKED(LOG_TFT, "%s: tft_h_end_w %04x\n", machine().describe_context(), data); +} + +void generalplus_gpl951xx_device::tft_v_show_start_w(u16 data) +{ + LOGMASKED(LOG_TFT, "%s: tft_v_show_start_w %04x\n", machine().describe_context(), data); +} + +void generalplus_gpl951xx_device::tft_v_show_end_w(u16 data) +{ + LOGMASKED(LOG_TFT, "%s: tft_v_show_end_w %04x\n", machine().describe_context(), data); +} + +void generalplus_gpl951xx_device::tft_h_show_start_w(u16 data) +{ + LOGMASKED(LOG_TFT, "%s: tft_h_show_start_w %04x\n", machine().describe_context(), data); +} + +void generalplus_gpl951xx_device::tft_h_show_end_w(u16 data) +{ + LOGMASKED(LOG_TFT, "%s: tft_h_show_end_w %04x\n", machine().describe_context(), data); +} + +void generalplus_gpl951xx_device::free_height_w(u16 data) +{ + LOGMASKED(LOG_TFT, "%s: free_height_w %04x\n", machine().describe_context(), data); +} + +void generalplus_gpl951xx_device::free_width_w(u16 data) +{ + LOGMASKED(LOG_TFT, "%s: free_width_w %04x\n", machine().describe_context(), data); +} + // u16 generalplus_gpl951xx_device::spi_bank_r() @@ -720,28 +780,104 @@ void generalplus_gpl951xx_device::spi_bank_w(u16 data) m_spi_bank = data; } -TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_a_cb) +template<int Timer> +TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_cb) { -} + m_timer_ctrl[Timer] |= 0x8000; + update_interrupts(1); -TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_b_cb) -{ + if (Timer == 6) + m_gpl_chx->process_cha_fifo(); // is cha hardwired to timerg overflow? + else if (Timer == 7) + m_gpl_chx->process_chb_fifo(); // is cha hardwired to timerh overflow? } -TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_c_cb) + +TIMER_DEVICE_CALLBACK_MEMBER( generalplus_gpl951xx_device::adc_timer_cb ) { + m_madc_ctrl |= 0x8000; + m_madc_ctrl |= 0x0080; // apparently always set after the first ADC operation, no way to clear? } -TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_d_cb) + +// P_MADC_Ctrl +// +// 15 ADCRIF/C - ADC Ready Interrupt Flag/Clear +// 14 ADCRIEN - ADC Interrupt Enable +// 13 +// 12 +// +// 11 +// 10 +// 9 +// 8 +// +// 7 CNVRDY - Conversion Ready +// 6 STRCNV - Manual Start Conversion +// 5 MIASE - ADC Conversion Error Flag 1 +// 4 ASIME - ADC Conversion Error Flag 2 +// +// 3 CHSEL - ADC Channel Selection (manual mode) +// 2 +// 1 +// 0 + +u16 generalplus_gpl951xx_device::madc_ctrl_r() { + logerror("%s: madc_ctrl_r\n", machine().describe_context()); + return m_madc_ctrl; } -TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_e_cb) +void generalplus_gpl951xx_device::madc_ctrl_w(u16 data) { + logerror("%s: madc_ctrl_w %04x\n", machine().describe_context(), data); + + if (data & 0x8000) + { + // clear IRQ flag + data = data &~ 0x8000; + } + + if (data & 0x0010) + { + // clear Error Flag 2 + data = data &~ 0x0010; + } + + if (data & 0x0020) + { + // clear Error Flag 1 + data = data &~ 0x0020; + } + + if (data & 0x0040) // Manual start + { + data = data & ~0x0040; + data = data & ~0x0080; + + u8 channel = data & 0x0007; + + logerror("manual ADC conversion on port %s\n", m_adc_channels[channel]); + + if (channel < 6) + { + m_madc_data = m_adc_in[channel](); + } + else + { + m_madc_data = 0x0000; + } + + m_adc_timer->adjust(attotime::from_usec(10)); + } + + m_madc_ctrl = data; } -TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_f_cb) +u16 generalplus_gpl951xx_device::madc_data_r() { + logerror("%s: madc_data_r\n", machine().describe_context()); + return m_madc_data; } @@ -988,13 +1124,13 @@ u16 generalplus_gpl951xx_device::int_status2_r() LOGMASKED(LOG_OTHER, "%s: generalplus_gpl951xx_device::int_status2_r\n", machine().describe_context()); u16 ret = 0; - if (m_gpl_timebase->timebasea_irq_flag()) + if (m_gpl_timebase->timebase_irq_flag<0>()) ret |= 0x0100; - if (m_gpl_timebase->timebaseb_irq_flag()) + if (m_gpl_timebase->timebase_irq_flag<1>()) ret |= 0x0200; - if (m_gpl_timebase->timebasec_irq_flag()) + if (m_gpl_timebase->timebase_irq_flag<2>()) ret |= 0x0400; return ret; @@ -1033,12 +1169,18 @@ u16 generalplus_gpl951xx_device::int_status3_r() u16 ret = 0; LOGMASKED(LOG_OTHER, "%s: generalplus_gpl951xx_device::int_status3_r\n", machine().describe_context()); - if (m_timerh_ctrl & 0x8000) + if (m_timer_ctrl[7] & 0x8000) ret |= 0x8000; - if (m_timerg_ctrl & 0x8000) + if (m_timer_ctrl[6] & 0x8000) ret |= 0x4000; + if (m_timer_ctrl[1] & 0x8000) + ret |= 0x0200; + + if (m_timer_ctrl[0] & 0x8000) + ret |= 0x0100; + return ret; } @@ -1048,18 +1190,36 @@ void generalplus_gpl951xx_device::int_status3_w(u16 data) // bit 2 (SPU Beat Interrupt) is listed as R/W for GPL95, but not GPL162? (verify) } +u16 generalplus_gpl951xx_device::int_priority_1_r() +{ + LOGMASKED(LOG_OTHER, "%s: generalplus_gpl951xx_device::int_priority_1_r\n", machine().describe_context()); + return m_int_priority_1; +} + void generalplus_gpl951xx_device::int_priority_1_w(u16 data) { LOGMASKED(LOG_OTHER, "%s: generalplus_gpl951xx_device::int_priority_1_w %04x\n", machine().describe_context(), data); m_int_priority_1 = data; } +u16 generalplus_gpl951xx_device::int_priority_2_r() +{ + LOGMASKED(LOG_OTHER, "%s: generalplus_gpl951xx_device::int_priority_2_r\n", machine().describe_context()); + return m_int_priority_2; +} + void generalplus_gpl951xx_device::int_priority_2_w(u16 data) { LOGMASKED(LOG_OTHER, "%s: generalplus_gpl951xx_device::int_priority_2_w %04x\n", machine().describe_context(), data); m_int_priority_2 = data; } +u16 generalplus_gpl951xx_device::int_priority_3_r() +{ + LOGMASKED(LOG_OTHER, "%s: generalplus_gpl951xx_device::int_priority_3_r\n", machine().describe_context()); + return m_int_priority_3; +} + void generalplus_gpl951xx_device::int_priority_3_w(u16 data) { LOGMASKED(LOG_OTHER, "%s: generalplus_gpl951xx_device::int_priority_3_w %04x\n", machine().describe_context(), data); @@ -1150,15 +1310,15 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) map(0x007042, 0x007042).rw(m_spg_video, FUNC(gcm394_base_video_device::sprite_7042_extra_r), FUNC(gcm394_base_video_device::sprite_7042_extra_w)); // 7042 - SControl // map(0x007050, 0x007050).w(FUNC(generalplus_gpl951xx_device::tft_ctrl_w)); // 7050 - TFT_Ctrl - // 7051 - TFT_V_Width - // 7052 - TFT_VSync_Setup - // 7053 - TFT_V_Start - // 7054 - TFT_V_End - // 7055 - TFT_H_Width - // 7056 - TFT_HSync_Setup - // 7057 - TFT_H_Start - // 7058 - TFT_H_End - // 7059 - TFT_RGB_Ctrl + map(0x007051, 0x007051).w(FUNC(generalplus_gpl951xx_device::tft_v_width_w)); // 7051 - TFT_V_Width + map(0x007052, 0x007052).w(FUNC(generalplus_gpl951xx_device::tft_vsync_setup_w)); // 7052 - TFT_VSync_Setup + map(0x007053, 0x007053).w(FUNC(generalplus_gpl951xx_device::tft_v_start_w)); // 7053 - TFT_V_Start + map(0x007054, 0x007054).w(FUNC(generalplus_gpl951xx_device::tft_v_end_w)); // 7054 - TFT_V_End + map(0x007055, 0x007055).w(FUNC(generalplus_gpl951xx_device::tft_h_width_w)); // 7055 - TFT_H_Width + map(0x007056, 0x007056).w(FUNC(generalplus_gpl951xx_device::tft_hsync_setup_w)); // 7056 - TFT_HSync_Setup + map(0x007057, 0x007057).w(FUNC(generalplus_gpl951xx_device::tft_h_start_w)); // 7057 - TFT_H_Start + map(0x007058, 0x007058).w(FUNC(generalplus_gpl951xx_device::tft_h_end_w)); // 7058 - TFT_H_End + map(0x007059, 0x007059).rw(FUNC(generalplus_gpl951xx_device::tft_rgb_ctrl_r), FUNC(generalplus_gpl951xx_device::tft_rgb_ctrl_w)); // 7059 - TFT_RGB_Ctrl map(0x00705a, 0x00705a).r(FUNC(generalplus_gpl951xx_device::tft_status_r)); // 705a - TFT_Status map(0x00705b, 0x00705b).w(FUNC(generalplus_gpl951xx_device::tft_memmode_wcmd_w)); // 705b - TFT_MemMode_WCmd // 705c - TFT_MemMode_RCmd @@ -1176,10 +1336,10 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) // 7069 - US_Hoffset // 706a - US_Voffset // - // 706c - TFT_V_Show_Start - // 706d - TFT_V_Show_End - // 706e - TFT_H_Show_Start - // 706f - TFT_H_Show_End + map(0x00706c, 0x00706c).w(FUNC(generalplus_gpl951xx_device::tft_v_show_start_w)); // 706c - TFT_V_Show_Start + map(0x00706d, 0x00706d).w(FUNC(generalplus_gpl951xx_device::tft_v_show_end_w)); // 706d - TFT_V_Show_End + map(0x00706e, 0x00706e).w(FUNC(generalplus_gpl951xx_device::tft_h_show_start_w)); // 706e - TFT_H_Show_Start + map(0x00706f, 0x00706f).w(FUNC(generalplus_gpl951xx_device::tft_h_show_end_w)); // 706f - TFT_H_Show_End // map(0x007070, 0x007070).w(m_spg_video, FUNC(gcm394_base_video_device::video_dma_source_w)); // 7070 - SPDMA_Source map(0x007071, 0x007071).w(m_spg_video, FUNC(gcm394_base_video_device::video_dma_dest_w)); // 7071 - SPDMA_Target @@ -1207,8 +1367,8 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) // 70b8 - Tx3_N_PTRH // 70b9 - Tx3_A_PTRH // - // 70db - Free_Height - // 70dc - Free_Width + map(0x0070db, 0x0070db).w(FUNC(generalplus_gpl951xx_device::free_height_w)); // 70db - Free_Height + map(0x0070dc, 0x0070dc).w(FUNC(generalplus_gpl951xx_device::free_width_w)); // 70dc - Free_Width // map(0x0070e0, 0x0070e0).r(m_spg_video, FUNC(gcm394_base_video_device::video_70e0_prng_r)); // 70e0 - Random0 (15-bit) // 70e1 - Random1 (15-bit) @@ -1299,9 +1459,9 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) map(0x0078a0, 0x0078a0).rw(FUNC(generalplus_gpl951xx_device::int_status1_r), FUNC(generalplus_gpl951xx_device::int_status1_w)); // 78a0 - INT_Status1 map(0x0078a1, 0x0078a1).rw(FUNC(generalplus_gpl951xx_device::int_status2_r), FUNC(generalplus_gpl951xx_device::int_status2_w)); // 78a1 - INT_Status2 map(0x0078a2, 0x0078a2).rw(FUNC(generalplus_gpl951xx_device::int_status3_r), FUNC(generalplus_gpl951xx_device::int_status3_w)); // 78a2 - INT_Status3 - map(0x0078a3, 0x0078a3).w(FUNC(generalplus_gpl951xx_device::int_priority_1_w)); // 78a3 - INT_Priority1 - map(0x0078a4, 0x0078a4).w(FUNC(generalplus_gpl951xx_device::int_priority_2_w)); // 78a4 - INT_Priority2 - map(0x0078a5, 0x0078a5).w(FUNC(generalplus_gpl951xx_device::int_priority_3_w)); // 78a5 - INT_Priority3 + map(0x0078a3, 0x0078a3).rw(FUNC(generalplus_gpl951xx_device::int_priority_1_r), FUNC(generalplus_gpl951xx_device::int_priority_1_w)); // 78a3 - INT_Priority1 + map(0x0078a4, 0x0078a4).rw(FUNC(generalplus_gpl951xx_device::int_priority_2_r), FUNC(generalplus_gpl951xx_device::int_priority_2_w)); // 78a4 - INT_Priority2 + map(0x0078a5, 0x0078a5).rw(FUNC(generalplus_gpl951xx_device::int_priority_3_r), FUNC(generalplus_gpl951xx_device::int_priority_3_w)); // 78a5 - INT_Priority3 map(0x0078a6, 0x0078a6).w(FUNC(generalplus_gpl951xx_device::mint_ctrl_w)); // 78a6 - MINT_Ctrl // 78a7 - IOAB_KCIEN // 78a8 - IOC_KCIEN @@ -1318,27 +1478,30 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) map(0x0078b8, 0x0078b8).w(m_gpl_timebase, FUNC(gpl_timebase_device::timebase_reset_w)); // 78b8 - TimeBase_Reset - // 78c0 - I2C_Ctrl - // 78c1 - I2C_Status + map(0x0078c0, 0x0078c0).r(FUNC(generalplus_gpl951xx_device::i2c_ctrl_r)); // 78c0 - I2C_Ctrl + map(0x0078c1, 0x0078c1).r(FUNC(generalplus_gpl951xx_device::i2c_status_r)); // 78c1 - I2C_Status // 78c2 - I2C_Address // 78c3 - I2C_Data // 78c4 - I2C_Debounce // 78c5 - I2C_Clk // 78c6 - I2C_MISC - map(0x0078e0, 0x0078e0).rw(FUNC(generalplus_gpl951xx_device::timerg_ctrl_r), FUNC(generalplus_gpl951xx_device::timerg_ctrl_w)); // 78e0 - timerg_Ctrl + // Timer G + map(0x0078e0, 0x0078e0).rw(FUNC(generalplus_gpl951xx_device::timer_ctrl_r<6>), FUNC(generalplus_gpl951xx_device::timer_ctrl_w<6>)); // 78e0 - timerg_Ctrl // 78e1 - map(0x0078e2, 0x0078e2).rw(FUNC(generalplus_gpl951xx_device::timerg_preload_r), FUNC(generalplus_gpl951xx_device::timerg_preload_w)); // 78e2 - timerg_Preload + map(0x0078e2, 0x0078e2).rw(FUNC(generalplus_gpl951xx_device::timer_preload_r<6>), FUNC(generalplus_gpl951xx_device::timer_preload_w<6>)); // 78e2 - timerg_Preload // 78e3 - // 78e4 - TimerG_UpCount + map(0x0078e4, 0x0078e4).r(FUNC(generalplus_gpl951xx_device::timer_upcount_r<6>)); // 78e4 - TimerG_UpCount // 78e5 // 78e6 // 78e7 - map(0x0078e8, 0x0078e8).rw(FUNC(generalplus_gpl951xx_device::timerh_ctrl_r), FUNC(generalplus_gpl951xx_device::timerh_ctrl_w)); // timerh_Ctrl + + // Timer H + map(0x0078e8, 0x0078e8).rw(FUNC(generalplus_gpl951xx_device::timer_ctrl_r<7>), FUNC(generalplus_gpl951xx_device::timer_ctrl_w<7>)); // timerh_Ctrl // 78e9 - map(0x0078ea, 0x0078ea).rw(FUNC(generalplus_gpl951xx_device::timerh_preload_r), FUNC(generalplus_gpl951xx_device::timerh_preload_w)); // 78ea - timerh_Preload + map(0x0078ea, 0x0078ea).rw(FUNC(generalplus_gpl951xx_device::timer_preload_r<7>), FUNC(generalplus_gpl951xx_device::timer_preload_w<7>)); // 78ea - timerh_Preload // 78eb - // 78ec - TimerH_UpCount + map(0x0078ec, 0x0078ec).r(FUNC(generalplus_gpl951xx_device::timer_upcount_r<7>)); // 78ec - TimerH_UpCount // 78ed // 78ee // 78ef @@ -1383,8 +1546,8 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) // 7945 - SPI0_Misc // 79a0 - ADC_Setup - // 79a1 - MADC_Ctrl - // 79a2 - MADC_Data + map(0x0079a1, 0x0079a1).rw(FUNC(generalplus_gpl951xx_device::madc_ctrl_r), FUNC(generalplus_gpl951xx_device::madc_ctrl_w)); // 79a1 - MADC_Ctrl + map(0x0079a2, 0x0079a2).r(FUNC(generalplus_gpl951xx_device::madc_data_r)); // 79a2 - MADC_Data // 79a3 - ASADC_Ctrl // 79a4 - ASDAC_Data // 79a5 @@ -1420,43 +1583,48 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) // 79fa // 79fb - RTC_ClkDiv - // 7a00 - TimerA_Ctrl - // 7a01 - TimerA_CCPB_Ctrl - // 7a02 - TimerA_Preload + // Timer A + map(0x007a00, 0x007a00).rw(FUNC(generalplus_gpl951xx_device::timer_ctrl_r<0>), FUNC(generalplus_gpl951xx_device::timer_ctrl_w<0>)); // 7a00 - TimerA_Ctrl + map(0x007a01, 0x007a01).w(FUNC(generalplus_gpl951xx_device::timer_ccpb_ctrl_w<0>)); // 7a01 - TimerA_CCPB_Ctrl + map(0x007a02, 0x007a02).rw(FUNC(generalplus_gpl951xx_device::timer_preload_r<0>), FUNC(generalplus_gpl951xx_device::timer_preload_w<0>)); // 7a02 - TimerA_Preload // 7a03 - TimerA_CCPB_Reg - // 7a04 - TimerA_UpCount + map(0x007a04, 0x007a04).r(FUNC(generalplus_gpl951xx_device::timer_upcount_r<0>)); // 7a04 - TimerA_UpCount - // 7a08 - TimerB_Ctrl - // 7a09 - TimerB_CCPB_Ctrl - // 7a0a - TimerB_Preload + // Timer B + map(0x007a08, 0x007a08).rw(FUNC(generalplus_gpl951xx_device::timer_ctrl_r<1>), FUNC(generalplus_gpl951xx_device::timer_ctrl_w<1>)); // 7a08 - TimerB_Ctrl + map(0x007a09, 0x007a09).w(FUNC(generalplus_gpl951xx_device::timer_ccpb_ctrl_w<1>)); // 7a09 - TimerB_CCPB_Ctrl + map(0x007a0a, 0x007a0a).rw(FUNC(generalplus_gpl951xx_device::timer_preload_r<1>), FUNC(generalplus_gpl951xx_device::timer_preload_w<1>)); // 7a0a - TimerB_Preload // 7a0b - TimerB_CCPB_Reg - // 7a0c - TimerB_UpCount + map(0x007a0c, 0x007a0c).r(FUNC(generalplus_gpl951xx_device::timer_upcount_r<1>)); // 7a0c - TimerB_UpCount - // 7a10 - TimerC_Ctrl - // 7a11 - TimerC_CCPB_Ctrl - // 7a12 - TimerC_Preload + // Timer C + map(0x007a10, 0x007a10).rw(FUNC(generalplus_gpl951xx_device::timer_ctrl_r<2>), FUNC(generalplus_gpl951xx_device::timer_ctrl_w<2>)); // 7a10 - TimerC_Ctrl + map(0x007a11, 0x007a11).w(FUNC(generalplus_gpl951xx_device::timer_ccpb_ctrl_w<2>)); // 7a11 - TimerC_CCPB_Ctrl + map(0x007a12, 0x007a12).rw(FUNC(generalplus_gpl951xx_device::timer_preload_r<2>), FUNC(generalplus_gpl951xx_device::timer_preload_w<2>)); // 7a12 - TimerC_Preload // 7a13 - TimerC_CCPB_Reg - // 7a14 - TimerC_UpCount + map(0x007a14, 0x007a14).r(FUNC(generalplus_gpl951xx_device::timer_upcount_r<2>)); // 7a14 - TimerC_UpCount - // 7a18 - TimerD_Ctrl - // 7a19 - TimerD_CCPB_Ctrl - // 7a1a - TimerD_Preload + // Timer D + map(0x007a18, 0x007a18).rw(FUNC(generalplus_gpl951xx_device::timer_ctrl_r<3>), FUNC(generalplus_gpl951xx_device::timer_ctrl_w<3>)); // 7a18 - TimerD_Ctrl + map(0x007a19, 0x007a19).w(FUNC(generalplus_gpl951xx_device::timer_ccpb_ctrl_w<3>)); // 7a19 - TimerD_CCPB_Ctrl + map(0x007a1a, 0x007a1a).rw(FUNC(generalplus_gpl951xx_device::timer_preload_r<3>), FUNC(generalplus_gpl951xx_device::timer_preload_w<3>)); // 7a1a - TimerD_Preload // 7a1b - TimerD_CCPB_Reg - // 7a1c - TimerD_UpCount - - // 7a20 - TimerE_Ctrl - // 7a21 - TimerF_Ctrl - // 7a22 - TimerE_CCPB_Ctrl - // 7a23 - TimerF_CCPB_Ctrl - // 7a24 - TimerE_Preload - // 7a25 - TimerF_Preload - // 7a26 - TimerEF_CCPB4_Reg - // 7a27 - TimerEF_CCPB5_Reg - // 7a28 - TimerEF_CCPB6_Reg - // 7a29 - TimerEF_CCPB7_Reg - // 7a2a - TimerE_UpCount - // 7a2b - TimerF_UpCount - // 7a2c - TimerEF_CCPB_Se + map(0x007a1c, 0x007a1c).r(FUNC(generalplus_gpl951xx_device::timer_upcount_r<3>)); // 7a1c - TimerD_UpCount + + // Timers E & F + map(0x007a20, 0x007a20).rw(FUNC(generalplus_gpl951xx_device::timer_ctrl_r<4>), FUNC(generalplus_gpl951xx_device::timer_ctrl_w<4>)); // 7a20 - TimerE_Ctrl + map(0x007a21, 0x007a21).rw(FUNC(generalplus_gpl951xx_device::timer_ctrl_r<5>), FUNC(generalplus_gpl951xx_device::timer_ctrl_w<5>)); // 7a21 - TimerF_Ctrl + map(0x007a22, 0x007a22).w(FUNC(generalplus_gpl951xx_device::timer_ccpb_ctrl_w<4>)); // 7a22 - TimerE_CCPB_Ctrl + map(0x007a23, 0x007a23).w(FUNC(generalplus_gpl951xx_device::timer_ccpb_ctrl_w<5>)); // 7a23 - TimerF_CCPB_Ctrl + map(0x007a24, 0x007a24).rw(FUNC(generalplus_gpl951xx_device::timer_preload_r<4>), FUNC(generalplus_gpl951xx_device::timer_preload_w<4>)); // 7a24 - TimerE_Preload + map(0x007a25, 0x007a25).rw(FUNC(generalplus_gpl951xx_device::timer_preload_r<5>), FUNC(generalplus_gpl951xx_device::timer_preload_w<5>)); // 7a25 - TimerF_Preload + // 7a26 - TimerEF_CCPB4_Reg (differs between GPL951xx models) + // 7a27 - TimerEF_CCPB5_Reg (differs between GPL951xx models) + // 7a28 - TimerEF_CCPB6_Reg (differs between GPL951xx models - doesn't exist on 'B') + // 7a29 - TimerEF_CCPB7_Reg (differs between GPL951xx models - doesn't exist on 'B') + map(0x007a2a, 0x007a2a).r(FUNC(generalplus_gpl951xx_device::timer_upcount_r<4>)); // 7a2a - TimerE_UpCount + map(0x007a2b, 0x007a2b).r(FUNC(generalplus_gpl951xx_device::timer_upcount_r<5>)); // 7a2b - TimerF_UpCount + // 7a2c - TimerEF_CCPB_Sel (differs between GPL951xx models - 2 bits on 'B', 4 bits on GPL95100UA/GPL95101UA) // 7a40 - USBD_Config // 7a41 - USBD_Function @@ -1565,7 +1733,7 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) void generalplus_gpl951xx_device::update_interrupts(int state) { - if (m_gpl_timebase->timebasea_irq_flag() || m_gpl_timebase->timebaseb_irq_flag()) + if (m_gpl_timebase->timebase_irq_flag<0>() || m_gpl_timebase->timebase_irq_flag<1>()) { set_state_unsynced(UNSP_IRQ7_LINE, ASSERT_LINE); } @@ -1574,7 +1742,7 @@ void generalplus_gpl951xx_device::update_interrupts(int state) set_state_unsynced(UNSP_IRQ7_LINE, CLEAR_LINE); } - if (m_gpl_timebase->timebasec_irq_flag()) + if (m_gpl_timebase->timebase_irq_flag<2>()) { set_state_unsynced(UNSP_IRQ6_LINE, ASSERT_LINE); } @@ -1583,8 +1751,15 @@ void generalplus_gpl951xx_device::update_interrupts(int state) set_state_unsynced(UNSP_IRQ6_LINE, CLEAR_LINE); } - if (((m_timerg_ctrl & 0x8000) && (m_timerg_ctrl & 0x4000)) || - ((m_timerh_ctrl & 0x8000) && (m_timerh_ctrl & 0x4000))) + if (((m_timer_ctrl[7] & 0x8000) && (m_timer_ctrl[7] & 0x4000)) || + ((m_timer_ctrl[6] & 0x8000) && (m_timer_ctrl[6] & 0x4000)) || + ((m_timer_ctrl[5] & 0x8000) && (m_timer_ctrl[5] & 0x4000)) || + ((m_timer_ctrl[4] & 0x8000) && (m_timer_ctrl[4] & 0x4000)) || + ((m_timer_ctrl[3] & 0x8000) && (m_timer_ctrl[3] & 0x4000)) || + ((m_timer_ctrl[2] & 0x8000) && (m_timer_ctrl[2] & 0x4000)) || + ((m_timer_ctrl[1] & 0x8000) && (m_timer_ctrl[1] & 0x4000)) || + ((m_timer_ctrl[0] & 0x8000) && (m_timer_ctrl[0] & 0x4000)) + ) { set_state_unsynced(UNSP_IRQ4_LINE, ASSERT_LINE); } @@ -1663,15 +1838,19 @@ void generalplus_gpl951xx_device::device_add_mconfig(machine_config &config) m_spg_video->space_read_callback().set(FUNC(generalplus_gpl951xx_device::read_space)); m_spg_video->set_video_space(DEVICE_SELF, AS_PROGRAM); - TIMER(config, "timer_a").configure_generic(FUNC(generalplus_gpl951xx_device::timer_a_cb)); - TIMER(config, "timer_b").configure_generic(FUNC(generalplus_gpl951xx_device::timer_b_cb)); - TIMER(config, "timer_c").configure_generic(FUNC(generalplus_gpl951xx_device::timer_c_cb)); - TIMER(config, "timer_d").configure_generic(FUNC(generalplus_gpl951xx_device::timer_d_cb)); - TIMER(config, "timer_e").configure_generic(FUNC(generalplus_gpl951xx_device::timer_e_cb)); - TIMER(config, "timer_f").configure_generic(FUNC(generalplus_gpl951xx_device::timer_f_cb)); + TIMER(config, "timer_a").configure_generic(FUNC(generalplus_gpl951xx_device::timer_cb<0>)); + TIMER(config, "timer_b").configure_generic(FUNC(generalplus_gpl951xx_device::timer_cb<1>)); + TIMER(config, "timer_c").configure_generic(FUNC(generalplus_gpl951xx_device::timer_cb<2>)); + TIMER(config, "timer_d").configure_generic(FUNC(generalplus_gpl951xx_device::timer_cb<3>)); + // timers e and f are a little different + TIMER(config, "timer_e").configure_generic(FUNC(generalplus_gpl951xx_device::timer_cb<4>)); + TIMER(config, "timer_f").configure_generic(FUNC(generalplus_gpl951xx_device::timer_cb<5>)); + + // timers g and h are for the cha/chb DAC (and can overflow trigger each other, not the above) + TIMER(config, "timer_g").configure_generic(FUNC(generalplus_gpl951xx_device::timer_cb<6>)); + TIMER(config, "timer_h").configure_generic(FUNC(generalplus_gpl951xx_device::timer_cb<7>)); - TIMER(config, "timer_g").configure_generic(FUNC(generalplus_gpl951xx_device::timer_g_cb)); - TIMER(config, "timer_h").configure_generic(FUNC(generalplus_gpl951xx_device::timer_h_cb)); + TIMER(config, "adc_timer").configure_generic(FUNC(generalplus_gpl951xx_device::adc_timer_cb)); GPL951XX_RTC(config, m_rtc, 0); } @@ -1688,8 +1867,9 @@ generalplus_gpl951xx_device::generalplus_gpl951xx_device(const machine_config &m m_i80_data_out(*this), m_port_in(*this, 0), m_port_out(*this), - m_timer_g(*this, "timer_g"), - m_timer_h(*this, "timer_h"), + m_adc_in(*this, 0), + m_timer(*this, { "timer_a", "timer_b", "timer_c", "timer_d", "timer_e", "timer_f", "timer_g", "timer_h" }), + m_adc_timer(*this, "adc_timer"), m_rtc(*this, "rtc"), m_gpl_chx(*this, "gpl_chx"), m_dac0(*this, "dac0"), diff --git a/src/devices/machine/generalplus_gpl951xx_soc.h b/src/devices/machine/generalplus_gpl951xx_soc.h index dd71bf4d1c4..b42112563db 100644 --- a/src/devices/machine/generalplus_gpl951xx_soc.h +++ b/src/devices/machine/generalplus_gpl951xx_soc.h @@ -57,6 +57,13 @@ public: auto porte_out() { return m_port_out[4].bind(); } auto portf_out() { return m_port_out[5].bind(); } + auto adc0_in() { return m_adc_in[0].bind(); } + auto adc1_in() { return m_adc_in[1].bind(); } + auto adc2_in() { return m_adc_in[2].bind(); } + auto adc3_in() { return m_adc_in[3].bind(); } + auto adc4_in() { return m_adc_in[4].bind(); } + auto adc5_in() { return m_adc_in[5].bind(); } + void recieve_spi_fifo_data(u8 data); IRQ_CALLBACK_MEMBER(irq_vector_cb); @@ -116,14 +123,15 @@ private: void byte_swap_w(u16 data); // Timers (different compared to GPL162xx) - u16 timerg_ctrl_r(); - void timerg_ctrl_w(u16 data); - u16 timerg_preload_r(); - void timerg_preload_w(u16 data); - u16 timerh_ctrl_r(); - void timerh_ctrl_w(u16 data); - u16 timerh_preload_r(); - void timerh_preload_w(u16 data); + template<int Timer> u16 timer_preload_r(); + template<int Timer> void timer_preload_w(u16 data); + template<int Timer> u16 timer_ctrl_r(); + template<int Timer> void timer_ctrl_w(u16 data); + template<int Timer> void timer_ccpb_ctrl_w(u16 data); + template<int Timer> u16 timer_upcount_r(); + + u16 i2c_ctrl_r(); + u16 i2c_status_r(); void dac_0_w(uint16_t data); void dac_1_w(uint16_t data); @@ -178,6 +186,10 @@ private: void int_priority_1_w(u16 data); void int_priority_2_w(u16 data); void int_priority_3_w(u16 data); + u16 int_priority_1_r(); + u16 int_priority_2_r(); + u16 int_priority_3_r(); + void mint_ctrl_w(u16 data); void update_interrupts(int state); @@ -185,18 +197,34 @@ private: void audioirq_w(int state); void videoirq_w(int state); + u16 madc_ctrl_r(); + void madc_ctrl_w(u16 data); + u16 madc_data_r(); + + u16 tft_rgb_ctrl_r(); + void tft_rgb_ctrl_w(u16 data); + + void tft_v_width_w(u16 data); + void tft_vsync_setup_w(u16 data); + void tft_v_start_w(u16 data); + void tft_v_end_w(u16 data); + void tft_h_width_w(u16 data); + void tft_hsync_setup_w(u16 data); + void tft_h_start_w(u16 data); + void tft_h_end_w(u16 data); + void tft_v_show_start_w(u16 data); + void tft_v_show_end_w(u16 data); + void tft_h_show_start_w(u16 data); + void tft_h_show_end_w(u16 data); + void free_height_w(u16 data); + void free_width_w(u16 data); + inline u16 read_space(offs_t offset); inline void write_space(offs_t offset, u16 data); - TIMER_DEVICE_CALLBACK_MEMBER(timer_g_cb); - TIMER_DEVICE_CALLBACK_MEMBER(timer_h_cb); + template<int Timer> TIMER_DEVICE_CALLBACK_MEMBER(timer_cb); - TIMER_DEVICE_CALLBACK_MEMBER(timer_a_cb); - TIMER_DEVICE_CALLBACK_MEMBER(timer_b_cb); - TIMER_DEVICE_CALLBACK_MEMBER(timer_c_cb); - TIMER_DEVICE_CALLBACK_MEMBER(timer_d_cb); - TIMER_DEVICE_CALLBACK_MEMBER(timer_e_cb); - TIMER_DEVICE_CALLBACK_MEMBER(timer_f_cb); + TIMER_DEVICE_CALLBACK_MEMBER(adc_timer_cb); u16 m_byteswap; @@ -232,10 +260,20 @@ private: "f: reserved" }; - u16 m_timerg_preload; - u16 m_timerg_ctrl; - u16 m_timerh_preload; - u16 m_timerh_ctrl; + const char* m_adc_channels[8] = + { + "LINEIN 0", + "LINEIN 1", + "LINEIN 2", + "LINEIN 3", + "LINEIN 4", + "LINEIN 5", + "1.2V bandgap", + "LDOV50" + }; + + u16 m_timer_preload[8]; + u16 m_timer_ctrl[8]; u16 m_spifc_ctrl; u16 m_spifc_ctrl2; @@ -268,6 +306,11 @@ private: u16 m_memmode_wcmd; + u16 m_tft_rgb_ctrl; + + u16 m_madc_ctrl; + u16 m_madc_data; + // config u8 *m_spiregion; u32 m_spisize; @@ -282,9 +325,11 @@ private: devcb_read16::array<6> m_port_in; devcb_write16::array<6> m_port_out; + devcb_read16::array<6> m_adc_in; + // devices - required_device<timer_device> m_timer_g; - required_device<timer_device> m_timer_h; + required_device_array<timer_device, 8> m_timer; + required_device<timer_device> m_adc_timer; required_device<gpl951xx_rtc_device> m_rtc; required_device<gpl_chx_device> m_gpl_chx; required_device<dac_16bit_r2r_twos_complement_device> m_dac0; diff --git a/src/devices/machine/generalplus_gpl_chx.cpp b/src/devices/machine/generalplus_gpl_chx.cpp index 80fc90ee884..8c7ebc6b213 100644 --- a/src/devices/machine/generalplus_gpl_chx.cpp +++ b/src/devices/machine/generalplus_gpl_chx.cpp @@ -106,6 +106,8 @@ void gpl_chx_device::cha_ctrl_w(u16 data) } m_cha_ctrl = data; + + //check_cha_fifo_empty(); } // P_CHA_Data @@ -219,6 +221,8 @@ void gpl_chx_device::chb_ctrl_w(u16 data) } m_chb_ctrl = data; + + //check_chb_fifo_empty(); } // P_CHB_Data @@ -272,6 +276,20 @@ void gpl_chx_device::chb_fifo_w(u16 data) } } +void gpl_chx_device::check_cha_fifo_empty() +{ + u8 emptyamount = (m_cha_fifo_reg & 0x00f0) >> 4; + + if (m_cha_fifo_entries <= emptyamount) + { + if (m_cha_ctrl & 0x4000) + { + m_cha_ctrl |= 0x8000; + m_updateirqs_cb(1); + } + } +} + void gpl_chx_device::process_cha_fifo() { if (!(m_cha_ctrl & 0x2000)) @@ -292,13 +310,18 @@ void gpl_chx_device::process_cha_fifo() // trying to underflow the FIFO? } - u8 emptyamount = (m_cha_fifo_reg & 0x00f0) >> 4; + check_cha_fifo_empty(); +} - if (m_cha_fifo_entries <= emptyamount) +void gpl_chx_device::check_chb_fifo_empty() +{ + u8 emptyamount = (m_chb_fifo_reg & 0x00f0) >> 4; + + if (m_chb_fifo_entries <= emptyamount) { - if (m_cha_ctrl & 0x4000) + if (m_chb_ctrl & 0x4000) { - m_cha_ctrl |= 0x8000; + m_chb_ctrl |= 0x8000; m_updateirqs_cb(1); } } @@ -324,16 +347,7 @@ void gpl_chx_device::process_chb_fifo() // trying to underflow the FIFO? } - u8 emptyamount = (m_chb_fifo_reg & 0x00f0) >> 4; - - if (m_chb_fifo_entries <= emptyamount) - { - if (m_chb_ctrl & 0x4000) - { - m_chb_ctrl |= 0x8000; - m_updateirqs_cb(1); - } - } + check_chb_fifo_empty(); } void gpl_chx_device::device_add_mconfig(machine_config &config) diff --git a/src/devices/machine/generalplus_gpl_chx.h b/src/devices/machine/generalplus_gpl_chx.h index 041d16c765a..07cbcce8556 100644 --- a/src/devices/machine/generalplus_gpl_chx.h +++ b/src/devices/machine/generalplus_gpl_chx.h @@ -30,6 +30,9 @@ public: u16 chb_fifo_r(); void chb_fifo_w(u16 data); + void check_cha_fifo_empty(); + void check_chb_fifo_empty(); + void process_cha_fifo(); void process_chb_fifo(); diff --git a/src/devices/machine/generalplus_gpl_dma.cpp b/src/devices/machine/generalplus_gpl_dma.cpp index 98a77fb7133..f8b55db8307 100644 --- a/src/devices/machine/generalplus_gpl_dma.cpp +++ b/src/devices/machine/generalplus_gpl_dma.cpp @@ -202,7 +202,10 @@ void gpl_dma_device::trigger_systemm_dma(int channel) else if ((mode & 0x50) == 0x10) destdelta = -1; - LOGMASKED(LOG_GCM394_SYSDMA, "%s:possible DMA operation with params mode:%04x source:%08x (word offset) dest:%08x (word offset) length:%08x (words)\n", machine().describe_context(), mode, source, dest, length ); + static const char* tmode_names[4] = { "Memory to Memory", "Memory to IO", "IO to Memory", "Reserved" }; + u8 td = (mode & 0x0c00) >> 10; + + LOGMASKED(LOG_GCM394_SYSDMA, "%s:possible DMA operation with params mode:%04x (TD is %s) source:%08x (word offset) dest:%08x (word offset) length:%08x (words)\n", machine().describe_context(), mode, tmode_names[td], source, dest, length ); // wrlshunt transfers ROM to RAM, all RAM write addresses have 0x800000 in the destination set @@ -214,7 +217,7 @@ void gpl_dma_device::trigger_systemm_dma(int channel) u16 val; if (mode & 0x1000) { - val = (m_space_read_cb(source) & 0xFF) | (m_space_read_cb(source) << 8); + val = (m_space_read_cb(source) & 0xff) | (m_space_read_cb(source) << 8); i++; } else diff --git a/src/devices/machine/generalplus_gpl_timebase.cpp b/src/devices/machine/generalplus_gpl_timebase.cpp index 838ea14400f..ff0fddf2a04 100644 --- a/src/devices/machine/generalplus_gpl_timebase.cpp +++ b/src/devices/machine/generalplus_gpl_timebase.cpp @@ -14,39 +14,47 @@ DEFINE_DEVICE_TYPE(GPL_TIMEBASE, gpl_timebase_device, "gpl_timebase", "Generalpl gpl_timebase_device::gpl_timebase_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, GPL_TIMEBASE, tag, owner, clock), - m_timebase_a(*this, "timebase_a"), - m_timebase_b(*this, "timebase_b"), - m_timebase_c(*this, "timebase_c"), + m_timebasetimer(*this, { "timebase_a", "timebase_b", "timebase_c" }), m_updateirqs_cb(*this) { } void gpl_timebase_device::device_start() { - save_item(NAME(m_timebasea_ctrl)); - save_item(NAME(m_timebaseb_ctrl)); - save_item(NAME(m_timebasec_ctrl)); + save_item(NAME(m_timebase_ctrl)); save_item(NAME(m_timebase_reset)); } void gpl_timebase_device::device_reset() { - m_timebasea_ctrl = 0x0000; - m_timebaseb_ctrl = 0x0000; - m_timebasec_ctrl = 0x0000; + m_timebase_ctrl[0] = 0x0000; + m_timebase_ctrl[1] = 0x0000; + m_timebase_ctrl[2] = 0x0000; m_timebase_reset = 0x0000; } +attotime gpl_timebase_device::get_timer_period(int timer, int ctrlval) +{ + int which = (timer << 2) | ctrlval; + + if (which != 0) // timebase_a, fequency 0 is 'off' + { + int period = 1 << (which - 1); + return attotime::from_hz(period); + } + + return attotime::never; +} // Timebase ('fixed' frequency timers) // (each can select from 3 different frequencies, different for each timer) - -TIMER_DEVICE_CALLBACK_MEMBER( gpl_timebase_device::timebase_a_cb ) +template<u16 Timer> +TIMER_DEVICE_CALLBACK_MEMBER( gpl_timebase_device::timebase_cb ) { - // sets bit 15 in m_timebasec_ctrl, also visible (as read only) in P_INT_Status2, bit 8 + // sets bit 15 in m_timebase_ctrl[2], also visible (as read only) in P_INT_Status2, bit 8 // uses IRQ7 (FIQ option not available) - m_timebasea_ctrl |= 0x8000; + m_timebase_ctrl[Timer] |= 0x8000; m_updateirqs_cb(1); } @@ -70,127 +78,34 @@ TIMER_DEVICE_CALLBACK_MEMBER( gpl_timebase_device::timebase_a_cb ) // 1 TMBAS[1] // 0 TMBAS[0] 00 = Reserved, 01 = 1Hz, 10 = 2Hz, 11 = 4Hz -u16 gpl_timebase_device::timebasea_ctrl_r() -{ - LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebasea_ctrl_r\n", machine().describe_context()); - return m_timebasea_ctrl; -} - -void gpl_timebase_device::timebasea_ctrl_w(u16 data) -{ - LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebasea_ctrl_w %04x\n", machine().describe_context(), data); - - if (data & 0x8000) - { - m_timebasea_ctrl = data & 0x7fff; - m_updateirqs_cb(1); - } - else - { - m_timebasea_ctrl = data; - } - - if ((m_timebasea_ctrl & 0x6000) == 0x6000) - { - switch (m_timebasea_ctrl & 0x0003) - { - case 0x00: m_timebase_a->adjust(attotime::never); break; // invalid - case 0x01: m_timebase_a->adjust(attotime::from_hz(1)); break; - case 0x02: m_timebase_a->adjust(attotime::from_hz(2)); break; - case 0x03: m_timebase_a->adjust(attotime::from_hz(4)); break; - } - } - else - { - m_timebase_a->adjust(attotime::never); - } -} - -TIMER_DEVICE_CALLBACK_MEMBER( gpl_timebase_device::timebase_b_cb ) -{ - // sets bit 15 in m_timebaseb_ctrl, also visible (as read only) in P_INT_Status2, bit 9 - // uses IRQ7 (FIQ option not available) - m_timebaseb_ctrl |= 0x8000; - m_updateirqs_cb(1); -} - -u16 gpl_timebase_device::timebaseb_ctrl_r() +template<u16 Timer> u16 gpl_timebase_device::timebase_ctrl_r() { - LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebaseb_ctrl_r\n", machine().describe_context()); - return m_timebaseb_ctrl; + LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebase%c_ctrl_r\n", machine().describe_context(), 'a'+Timer); + return m_timebase_ctrl[Timer]; } -void gpl_timebase_device::timebaseb_ctrl_w(u16 data) +template<u16 Timer> void gpl_timebase_device::timebase_ctrl_w(u16 data) { - LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebaseb_ctrl_w %04x\n", machine().describe_context(), data); + LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebase%c_ctrl_w %04x\n", machine().describe_context(), 'a'+Timer, data); if (data & 0x8000) { - m_timebaseb_ctrl = data & 0x7fff; + m_timebase_ctrl[Timer] = data & 0x7fff; m_updateirqs_cb(1); } else { - m_timebaseb_ctrl = data; + m_timebase_ctrl[Timer] = data; } - if ((m_timebaseb_ctrl & 0x6000) == 0x6000) + if (m_timebase_ctrl[Timer] & 0x2000) { - switch (m_timebaseb_ctrl & 0x0003) - { - case 0x00: m_timebase_b->adjust(attotime::from_hz(8)); break; - case 0x01: m_timebase_b->adjust(attotime::from_hz(16)); break; - case 0x02: m_timebase_b->adjust(attotime::from_hz(32)); break; - case 0x03: m_timebase_b->adjust(attotime::from_hz(64)); break; - } + attotime period = get_timer_period(Timer, m_timebase_ctrl[Timer] & 0x0003); + m_timebasetimer[Timer]->adjust(period, 0, period); } else { - m_timebase_b->adjust(attotime::never); - } -} - -TIMER_DEVICE_CALLBACK_MEMBER( gpl_timebase_device::timebase_c_cb ) -{ - // sets bit 15 in m_timebasec_ctrl, also visible (as read only) in P_INT_Status2, bit 10 - // uses IRQ6 (FIQ option not available) - m_timebasec_ctrl |= 0x8000; - m_updateirqs_cb(1); -} - -u16 gpl_timebase_device::timebasec_ctrl_r() -{ - LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebasec_ctrl_r\n", machine().describe_context()); - return m_timebasec_ctrl; -} - -void gpl_timebase_device::timebasec_ctrl_w(u16 data) -{ - LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebasec_ctrl_w %04x\n", machine().describe_context(), data); - - if (data & 0x8000) - { - m_timebasec_ctrl = data & 0x7fff; - m_updateirqs_cb(1); - } - else - { - m_timebasec_ctrl = data; - } - - if ((m_timebasec_ctrl & 0x6000) == 0x6000) - { - switch (m_timebasec_ctrl & 0x0003) - { - case 0x00: m_timebase_c->adjust(attotime::from_hz(128)); break; - case 0x01: m_timebase_c->adjust(attotime::from_hz(256)); break; - case 0x02: m_timebase_c->adjust(attotime::from_hz(512)); break; - case 0x03: m_timebase_c->adjust(attotime::from_hz(1024)); break; - } - } - else - { - m_timebase_c->adjust(attotime::never); + m_timebasetimer[Timer]->adjust(attotime::never); } } @@ -200,9 +115,17 @@ void gpl_timebase_device::timebase_reset_w(u16 data) m_timebase_reset = data; } +u16 gpl_timebase_device::timebasea_ctrl_r() { return timebase_ctrl_r<0>(); } +u16 gpl_timebase_device::timebaseb_ctrl_r() { return timebase_ctrl_r<1>(); } +u16 gpl_timebase_device::timebasec_ctrl_r() { return timebase_ctrl_r<2>(); } + +void gpl_timebase_device::timebasea_ctrl_w(u16 data) { timebase_ctrl_w<0>(data); } +void gpl_timebase_device::timebaseb_ctrl_w(u16 data) { timebase_ctrl_w<1>(data); } +void gpl_timebase_device::timebasec_ctrl_w(u16 data) { timebase_ctrl_w<2>(data); } + void gpl_timebase_device::device_add_mconfig(machine_config &config) { - TIMER(config, "timebase_a").configure_generic(FUNC(gpl_timebase_device::timebase_a_cb)); - TIMER(config, "timebase_b").configure_generic(FUNC(gpl_timebase_device::timebase_b_cb)); - TIMER(config, "timebase_c").configure_generic(FUNC(gpl_timebase_device::timebase_c_cb)); + TIMER(config, "timebase_a").configure_generic(FUNC(gpl_timebase_device::timebase_cb<0>)); + TIMER(config, "timebase_b").configure_generic(FUNC(gpl_timebase_device::timebase_cb<1>)); + TIMER(config, "timebase_c").configure_generic(FUNC(gpl_timebase_device::timebase_cb<2>)); } diff --git a/src/devices/machine/generalplus_gpl_timebase.h b/src/devices/machine/generalplus_gpl_timebase.h index a6ad4969009..bac4c1f3f15 100644 --- a/src/devices/machine/generalplus_gpl_timebase.h +++ b/src/devices/machine/generalplus_gpl_timebase.h @@ -12,19 +12,16 @@ class gpl_timebase_device : public device_t public: gpl_timebase_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - bool timebasea_irq_flag() { return m_timebasea_ctrl & 0x8000 ? true : false; } - bool timebaseb_irq_flag() { return m_timebaseb_ctrl & 0x8000 ? true : false; } - bool timebasec_irq_flag() { return m_timebasec_ctrl & 0x8000 ? true : false; } + template<u16 Timer> bool timebase_irq_flag() { return ((m_timebase_ctrl[Timer] & 0x8000) && (m_timebase_ctrl[Timer] & 0x4000)) ? true : false; } auto updateirqs_callback() { return m_updateirqs_cb.bind(); } u16 timebasea_ctrl_r(); - void timebasea_ctrl_w(u16 data); - u16 timebaseb_ctrl_r(); - void timebaseb_ctrl_w(u16 data); - u16 timebasec_ctrl_r(); + + void timebasea_ctrl_w(u16 data); + void timebaseb_ctrl_w(u16 data); void timebasec_ctrl_w(u16 data); void timebase_reset_w(u16 data); @@ -35,19 +32,18 @@ protected: virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; private: - TIMER_DEVICE_CALLBACK_MEMBER(timebase_a_cb); - TIMER_DEVICE_CALLBACK_MEMBER(timebase_b_cb); - TIMER_DEVICE_CALLBACK_MEMBER(timebase_c_cb); + template<u16 Timer> TIMER_DEVICE_CALLBACK_MEMBER(timebase_cb); + + template<u16 Timer> u16 timebase_ctrl_r(); + template<u16 Timer> void timebase_ctrl_w(u16 data); + - u16 m_timebasea_ctrl; - u16 m_timebaseb_ctrl; - u16 m_timebasec_ctrl; + attotime get_timer_period(int timer, int ctrlval); + u16 m_timebase_ctrl[3]; u16 m_timebase_reset; - required_device<timer_device> m_timebase_a; - required_device<timer_device> m_timebase_b; - required_device<timer_device> m_timebase_c; + required_device_array<timer_device, 3> m_timebasetimer; devcb_write_line m_updateirqs_cb; }; diff --git a/src/devices/machine/generic_spi_flash.cpp b/src/devices/machine/generic_spi_flash.cpp index cf2825b7b0d..10a819d3276 100644 --- a/src/devices/machine/generic_spi_flash.cpp +++ b/src/devices/machine/generic_spi_flash.cpp @@ -242,8 +242,16 @@ void generic_spi_flash_device::process_write_command(u8 data) m_spi_addr = (m_spi_addr & 0xffff00) | (data); m_spi_state_step++; break; default: - LOGMASKED(LOG_SPI, "Write SPI data %02x\n", data); - m_spiptr[(m_spi_addr++) & (m_length - 1)] = data; + + if (m_spi_statusreg & 0x02) + { + LOGMASKED(LOG_SPI, "Write SPI data %02x at %08x\n", data, m_spi_addr); + m_spiptr[(m_spi_addr++) & (m_length - 1)] = data; + } + else + { + LOGMASKED(LOG_SPI, "Write SPI data %02x at %08x (but write protect enabled)\n", data, m_spi_addr); + } break; } } diff --git a/src/devices/machine/gpl_renderer.cpp b/src/devices/machine/gpl_renderer.cpp index f77c826819a..85126c6361e 100644 --- a/src/devices/machine/gpl_renderer.cpp +++ b/src/devices/machine/gpl_renderer.cpp @@ -226,101 +226,106 @@ void gpl_renderer_device::draw_tilestrip(bool read_from_csspace, uint32_t screen } } -void gpl_renderer_device::draw_linemap(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t *scrollregs, uint16_t *tilemapregs, address_space &spc, uint16_t *paletteram) + +void gpl_renderer_device::draw_linemap(bool read_from_csspace, const rectangle &cliprect, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t *scrollregs, uint16_t *tilemapregs, address_space &spc, uint16_t *paletteram) { - uint32_t ctrl = tilemapregs[1]; + // TODO, correct for segapet1 etc. but points at the wrong data for jak_s500 + // (is the data on jak_s500 in the correct place?) - if (0) - { - if (ctrl & 0x0010) - popmessage("bitmap mode %08x with rowscroll\n", tilegfxdata_addr); - else - popmessage("bitmap mode %08x\n", tilegfxdata_addr); - } + if ((scanline < cliprect.min_y) || (scanline >= cliprect.max_y)) + return; - // note, in interlace modes it appears every other line is unused? (480 entry table, but with blank values) - // and furthermore the rowscroll and rowzoom tables only have 240 entries, not enough for every line - // the end of the rowscroll table (entries 240-255) contain something else, maybe garbage data as it's offscreen, maybe not uint32_t tilemap = tilemapregs[2]; uint32_t palette_map = tilemapregs[3]; - uint32_t linebase = spc.read_word(tilemap + scanline); // every other word is unused, but there are only enough entries for 240 lines then, sometimes to do with interlace mode? - uint16_t palette = spc.read_word(palette_map + (scanline / 2)); + //uint32_t xscroll = scrollregs[0]; + uint32_t yscroll = scrollregs[1]; - if (scanline & 1) - palette >>= 8; - else - palette &= 0xff; + int realline = (scanline + yscroll) & 0xff; - if (!linebase) - return; - linebase = linebase | (palette << 16); + uint32_t tile = spc.read_word(tilemap + realline); + uint16_t palette = 0; - int upperpalselect = 0; - if (tilegfxdata_addr & 0x80000000) - upperpalselect = 1; + palette = spc.read_word(palette_map + realline / 2); + if (scanline & 1) + palette >>= 8; + else + palette &= 0x00ff; - tilegfxdata_addr &= 0x7ffffff; + int sourcebase = tile | (palette << 16); + sourcebase += tilegfxdata_addr; - // this logic works for jak_s500 and the test modes to get the correct base, doesn't seem to work for jak_car2 ingame, maybe data is copied to wrong place? - int gfxbase = (tilegfxdata_addr & 0x7ffffff) + (linebase & 0x7ffffff); + uint32_t ctrl = tilemapregs[1]; - for (int i = 0; i < 160; i++) // will have to be 320 for jak_car2 ingame, jak_s500 lines are wider than screen, and zoomed + if (ctrl & 0x80) // HiColor mode (rad_digi) { - uint16_t pix; - const int addr = gfxbase & 0x7ffffff; - if (addr < m_csbase) - { - pix = m_cpuspace->read_word(addr); - } - else + for (int i = 0; i < 320; i++) { - pix = m_cs_space->read_word(addr - m_csbase); + const uint16_t data = spc.read_word(sourcebase + i); + + if (!(data & 0x8000)) + { + m_linebuf[i] = data & 0x7fff; + } } - gfxbase++; + } + else + { + const uint32_t attr = tilemapregs[0]; + const uint8_t bpp = attr & 0x0003; + const uint32_t nc_bpp = ((bpp)+1) << 1; + uint32_t palette_offset = (attr & 0x0f00) >> 4; + palette_offset >>= nc_bpp; + palette_offset <<= nc_bpp; - int xx; - uint16_t pal; + uint32_t bits = 0; + uint32_t nbits = 0; - if ((scanline >= 0) && (scanline < 480)) + for (int i = cliprect.min_x; i <= cliprect.max_x; i++) { - xx = i * 2; - - pal = (pix & 0xff) | 0x100; - - if (upperpalselect) - pal |= 0x200; - - if (xx >= 0 && xx <= cliprect.max_x) + bits <<= nc_bpp; + if (nbits < nc_bpp) { - uint16_t rgb = paletteram[pal]; + uint16_t b; - if (!(rgb & 0x8000)) + if (!read_from_csspace) + { + b = spc.read_word(sourcebase++ & 0x3fffff); + } + else { - m_linebuf[xx] = rgb; + const int addr = sourcebase & 0x7ffffff; + if (sourcebase < m_csbase) + { + b = m_cpuspace->read_word(addr & 0x3fffff); + } + else + { + b = m_cs_space->read_word(addr - m_csbase); + } } + b = (b << 8) | (b >> 8); + bits |= b << (nc_bpp - nbits); + nbits += 16; + } + nbits -= nc_bpp; - xx = (i * 2) + 1; - pal = (pix >> 8) | 0x100; + uint32_t pal = palette_offset + (bits >> 16); + bits &= 0xffff; - if (upperpalselect) - pal |= 0x200; + uint16_t rgb = paletteram[pal]; - if (xx >= 0 && xx <= cliprect.max_x) + if (!(rgb & 0x8000)) { - uint16_t rgb = paletteram[pal]; - - if (!(rgb & 0x8000)) - { - m_linebuf[xx] = rgb; - } + m_linebuf[i] = rgb; } } } } + void gpl_renderer_device::draw_sprite(bool read_from_csspace, int extended_sprites_mode, uint32_t palbank, bool highres, const rectangle &cliprect, uint32_t scanline, int priority, uint32_t spritegfxdata_addr, uint32_t base_addr, address_space &spc, uint16_t *paletteram, uint16_t *spriteram) { uint32_t tilegfxdata_addr = spritegfxdata_addr; @@ -543,7 +548,7 @@ void gpl_renderer_device::draw_page(bool read_from_csspace, uint32_t palbank, co if (ctrl & 0x0001) // Bitmap / Linemap mode! (basically screen width tile mode) { - draw_linemap(cliprect, scanline, priority, tilegfxdata_addr_full, scrollregs, tilemapregs, spc, paletteram); + draw_linemap(read_from_csspace, cliprect, scanline, priority, tilegfxdata_addr_full, scrollregs, tilemapregs, spc, paletteram); return; } diff --git a/src/devices/machine/gpl_renderer.h b/src/devices/machine/gpl_renderer.h index f8920623d7a..a2afdf37cb9 100644 --- a/src/devices/machine/gpl_renderer.h +++ b/src/devices/machine/gpl_renderer.h @@ -66,7 +66,7 @@ private: inline void draw_tilestrip(bool read_from_csspace, uint32_t screenwidth, uint32_t drawwidthmask, const rectangle &cliprect, uint32_t tile_h, uint32_t tile_w, uint32_t tilegfxdata_addr, uint32_t tile, uint32_t tile_scanline, int drawx, bool flip_y, uint32_t palette_offset, const uint32_t nc_bpp, const uint32_t bits_per_row, const uint32_t words_per_tile, address_space &spc, uint16_t *palette, uint8_t blendlevel); inline void draw_tilestrip(bool read_from_csspace, uint32_t screenwidth, uint32_t drawwidthmask, bool blend, bool flip_x, const rectangle &cliprect, uint32_t tile_h, uint32_t tile_w, uint32_t tilegfxdata_addr, uint32_t tile, uint32_t tile_scanline, int drawx, bool flip_y, uint32_t palette_offset, const uint32_t nc_bpp, const uint32_t bits_per_row, const uint32_t words_per_tile, address_space &spc, uint16_t *paletteram, uint8_t blendlevel); inline void draw_sprite(bool read_from_csspace, int extended_sprites_mode, uint32_t palbank, bool highres, const rectangle &cliprect, uint32_t scanline, int priority, uint32_t spritegfxdata_addr, uint32_t base_addr, address_space &spc, uint16_t *paletteram, uint16_t *spriteram); - virtual void draw_linemap(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t *scrollregs, uint16_t *tilemapregs, address_space &spc, uint16_t *paletteram); + virtual void draw_linemap(bool read_from_csspace, const rectangle &cliprect, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t *scrollregs, uint16_t *tilemapregs, address_space &spc, uint16_t *paletteram); inline uint8_t mix_channel(uint8_t a, uint8_t b, uint8_t alpha); void update_vcmp_table(); void update_palette_lookup(); diff --git a/src/mame/handheld/generalplus_gpl951xx.cpp b/src/mame/handheld/generalplus_gpl951xx.cpp index 67fbe745973..7020f8cd7a3 100644 --- a/src/mame/handheld/generalplus_gpl951xx.cpp +++ b/src/mame/handheld/generalplus_gpl951xx.cpp @@ -22,6 +22,7 @@ public: m_screen(*this, "screen"), m_genspi(*this, "spi"), m_io(*this, "IN%u", 0U), + m_adc(*this, "ADC%u", 0U), m_lcdc(*this, "lcdc") { } @@ -32,6 +33,8 @@ public: void poke(machine_config &config) ATTR_COLD; void flufflav(machine_config &config) ATTR_COLD; void puni(machine_config &config) ATTR_COLD; + void bubltea(machine_config &config) ATTR_COLD; + void dsgnpal(machine_config &config) ATTR_COLD; void bftetris(machine_config &config) ATTR_COLD; void init_fif() ATTR_COLD; @@ -44,9 +47,9 @@ protected: u32 bftetris_screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - u16 porta_r(); - u16 portb_r(); - u16 portc_r(); + template <u8 Port> u16 port_r(); + template <u8 Port> u16 adc_r(); + void porta_w(u16 data); void spi_reset(u8 data); @@ -59,7 +62,8 @@ protected: required_device<generalplus_gpl951xx_device> m_maincpu; required_device<screen_device> m_screen; required_device<generic_spi_flash_device> m_genspi; - required_ioport_array<3> m_io; + required_ioport_array<6> m_io; + required_ioport_array<6> m_adc; required_device<bftetris_lcdc_device> m_lcdc; }; @@ -68,25 +72,18 @@ u32 generalplus_gpl951xx_game_state::bftetris_screen_update(screen_device &scree return m_lcdc->render_to_bitmap(screen, bitmap, cliprect); } - -u16 generalplus_gpl951xx_game_state::porta_r() -{ - u16 data = m_io[0]->read(); - logerror("Port A Read: %04x\n", data); - return data; -} - -u16 generalplus_gpl951xx_game_state::portb_r() +template <u8 Port> +u16 generalplus_gpl951xx_game_state::port_r() { - u16 data = m_io[1]->read(); - logerror("Port B Read: %04x\n", data); + u16 data = m_io[Port]->read(); + logerror("Port %c Read: %04x\n", 'A'+Port, data); return data; } -u16 generalplus_gpl951xx_game_state::portc_r() +template <u8 Port> +u16 generalplus_gpl951xx_game_state::adc_r() { - u16 data = m_io[2]->read(); - logerror("Port C Read: %04x\n", data); + u16 data = m_adc[Port]->read(); return data; } @@ -107,11 +104,84 @@ void generalplus_gpl951xx_game_state::machine_reset() m_maincpu->reset(); // reset CPU so vector gets read etc. } +// default port structure for debugging inputs +#define DEBUG_PORT(_name) \ + PORT_START(#_name) \ + PORT_DIPNAME( 0x0001, 0x0001, #_name ":0001" ) \ + PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) \ + PORT_DIPSETTING( 0x0001, DEF_STR( On ) ) \ + PORT_DIPNAME( 0x0002, 0x0002, #_name ":0002" ) \ + PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) \ + PORT_DIPSETTING( 0x0002, DEF_STR( On ) ) \ + PORT_DIPNAME( 0x0004, 0x0004, #_name ":0004" ) \ + PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) \ + PORT_DIPSETTING( 0x0004, DEF_STR( On ) ) \ + PORT_DIPNAME( 0x0008, 0x0008, #_name ":0008" ) \ + PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) \ + PORT_DIPSETTING( 0x0008, DEF_STR( On ) ) \ + PORT_DIPNAME( 0x0010, 0x0010, #_name ":0010" ) \ + PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) \ + PORT_DIPSETTING( 0x0010, DEF_STR( On ) ) \ + PORT_DIPNAME( 0x0020, 0x0020, #_name ":0020" ) \ + PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) \ + PORT_DIPSETTING( 0x0020, DEF_STR( On ) ) \ + PORT_DIPNAME( 0x0040, 0x0040, #_name ":0040" ) \ + PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) \ + PORT_DIPSETTING( 0x0040, DEF_STR( On ) ) \ + PORT_DIPNAME( 0x0080, 0x0080, #_name ":0080" ) \ + PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) \ + PORT_DIPSETTING( 0x0080, DEF_STR( On ) ) \ + PORT_DIPNAME( 0x0100, 0x0100, #_name ":0100" ) \ + PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) \ + PORT_DIPSETTING( 0x0100, DEF_STR( On ) ) \ + PORT_DIPNAME( 0x0200, 0x0200, #_name ":0200" ) \ + PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) \ + PORT_DIPSETTING( 0x0200, DEF_STR( On ) ) \ + PORT_DIPNAME( 0x0400, 0x0400, #_name ":0400" ) \ + PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) \ + PORT_DIPSETTING( 0x0400, DEF_STR( On ) ) \ + PORT_DIPNAME( 0x0800, 0x0800, #_name ":0800" ) \ + PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) \ + PORT_DIPSETTING( 0x0800, DEF_STR( On ) ) \ + PORT_DIPNAME( 0x1000, 0x1000, #_name ":1000" ) \ + PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) \ + PORT_DIPSETTING( 0x1000, DEF_STR( On ) ) \ + PORT_DIPNAME( 0x2000, 0x2000, #_name ":2000" ) \ + PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) \ + PORT_DIPSETTING( 0x2000, DEF_STR( On ) ) \ + PORT_DIPNAME( 0x4000, 0x4000, #_name ":4000" ) \ + PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) \ + PORT_DIPSETTING( 0x4000, DEF_STR( On ) ) \ + PORT_DIPNAME( 0x8000, 0x8000, #_name ":8000" ) \ + PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) \ + PORT_DIPSETTING( 0x8000, DEF_STR( On ) ) + +static INPUT_PORTS_START( base ) + DEBUG_PORT(IN0) + DEBUG_PORT(IN1) + DEBUG_PORT(IN2) + DEBUG_PORT(IN3) + DEBUG_PORT(IN4) + DEBUG_PORT(IN5) + + PORT_START("ADC0") + PORT_BIT( 0xffff, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_START("ADC1") + PORT_BIT( 0xffff, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_START("ADC2") + PORT_BIT( 0xffff, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_START("ADC3") + PORT_BIT( 0xffff, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_START("ADC4") + PORT_BIT( 0xffff, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_START("ADC5") + PORT_BIT( 0xffff, IP_ACTIVE_HIGH, IPT_UNKNOWN ) +INPUT_PORTS_END + static INPUT_PORTS_START( bfmpac ) - PORT_START("IN0") - PORT_START("IN1") + PORT_INCLUDE(base) - PORT_START("IN2") + PORT_MODIFY("IN2") PORT_DIPNAME( 0x0001, 0x0000, "0" ) PORT_DIPSETTING( 0x0000, DEF_STR( Off ) ) PORT_DIPSETTING( 0x0001, DEF_STR( On ) ) @@ -157,6 +227,69 @@ static INPUT_PORTS_START( bfspyhnt ) PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_BUTTON2 ) INPUT_PORTS_END +static INPUT_PORTS_START( puni ) + PORT_INCLUDE(base) + + PORT_MODIFY("IN5") + PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON1 ) + PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON2 ) + PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BUTTON3 ) +INPUT_PORTS_END + +static INPUT_PORTS_START( segapet1 ) + PORT_INCLUDE(base) + + PORT_MODIFY("IN1") + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON1 ) // hold this and 'button 3' on startup for a test mode + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON2 ) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON3 ) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON4 ) + + PORT_MODIFY("ADC5") + PORT_BIT( 0xffff, IP_ACTIVE_LOW, IPT_UNKNOWN ) +INPUT_PORTS_END + +static INPUT_PORTS_START( segapet2 ) + PORT_INCLUDE(base) + + PORT_MODIFY("IN1") + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("<") + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("OK") + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME(">") + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Cancel") + + PORT_MODIFY("ADC5") + PORT_BIT( 0xffff, IP_ACTIVE_LOW, IPT_UNKNOWN ) +INPUT_PORTS_END + +static INPUT_PORTS_START( bubltea ) // has 3 surface buttons and the straw + PORT_INCLUDE(base) + + PORT_MODIFY("IN1") + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Power / Next") + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Increase Value") + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Back") + + PORT_MODIFY("ADC5") + PORT_BIT( 0xffff, IP_ACTIVE_LOW, IPT_UNKNOWN ) +INPUT_PORTS_END + +static INPUT_PORTS_START( dsgnpal ) + PORT_INCLUDE(base) + + PORT_MODIFY("IN1") + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON1 ) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON2 ) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON3 ) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON4 ) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON5 ) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON6 ) + + PORT_MODIFY("ADC5") + PORT_BIT( 0xffff, IP_ACTIVE_LOW, IPT_UNKNOWN ) +INPUT_PORTS_END + void generalplus_gpl951xx_game_state::spi_reset(u8 data) { m_genspi->reset(); @@ -178,13 +311,11 @@ void generalplus_gpl951xx_game_state::spi_cmd_access_from_soc(u8 data) void generalplus_gpl951xx_game_state::lcd_i80_cmd(u16 data) { - logerror("lcd_i80_cmd %02x\n", data); m_lcdc->lcdc_command_w(data); } void generalplus_gpl951xx_game_state::lcd_i80_data(u16 data) { - logerror("lcd_i80_data %02x\n", data); m_lcdc->lcdc_data_w(data); } @@ -193,10 +324,20 @@ void generalplus_gpl951xx_game_state::lcd_i80_data(u16 data) void generalplus_gpl951xx_game_state::gpl951xx(machine_config &config) { GPL951XX(config, m_maincpu, 96000000/2, m_screen); - m_maincpu->porta_in().set(FUNC(generalplus_gpl951xx_game_state::porta_r)); - m_maincpu->portb_in().set(FUNC(generalplus_gpl951xx_game_state::portb_r)); - m_maincpu->portc_in().set(FUNC(generalplus_gpl951xx_game_state::portc_r)); + m_maincpu->porta_in().set(FUNC(generalplus_gpl951xx_game_state::port_r<0>)); + m_maincpu->portb_in().set(FUNC(generalplus_gpl951xx_game_state::port_r<1>)); + m_maincpu->portc_in().set(FUNC(generalplus_gpl951xx_game_state::port_r<2>)); + m_maincpu->portd_in().set(FUNC(generalplus_gpl951xx_game_state::port_r<3>)); + m_maincpu->porte_in().set(FUNC(generalplus_gpl951xx_game_state::port_r<4>)); + m_maincpu->portf_in().set(FUNC(generalplus_gpl951xx_game_state::port_r<5>)); m_maincpu->porta_out().set(FUNC(generalplus_gpl951xx_game_state::porta_w)); + m_maincpu->adc0_in().set(FUNC(generalplus_gpl951xx_game_state::adc_r<0>)); + m_maincpu->adc1_in().set(FUNC(generalplus_gpl951xx_game_state::adc_r<1>)); + m_maincpu->adc2_in().set(FUNC(generalplus_gpl951xx_game_state::adc_r<2>)); + m_maincpu->adc3_in().set(FUNC(generalplus_gpl951xx_game_state::adc_r<3>)); + m_maincpu->adc4_in().set(FUNC(generalplus_gpl951xx_game_state::adc_r<4>)); + m_maincpu->adc5_in().set(FUNC(generalplus_gpl951xx_game_state::adc_r<5>)); + m_maincpu->set_irq_acknowledge_callback(m_maincpu, FUNC(generalplus_gpl951xx_device::irq_vector_cb)); m_maincpu->add_route(ALL_OUTPUTS, "speaker", 0.5, 0); m_maincpu->add_route(ALL_OUTPUTS, "speaker", 0.5, 1); @@ -206,10 +347,10 @@ void generalplus_gpl951xx_game_state::gpl951xx(machine_config &config) m_maincpu->i80_cmd_out().set(FUNC(generalplus_gpl951xx_game_state::lcd_i80_cmd)); m_maincpu->i80_data_out().set(FUNC(generalplus_gpl951xx_game_state::lcd_i80_data)); - SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - m_screen->set_refresh_hz(60); + SCREEN(config, m_screen, SCREEN_TYPE_LCD); + m_screen->set_refresh_hz(30); // is this coming from the LCDC? 60 is definitely too fast for the IRQ rate m_screen->set_size(320*2, 262*2); - m_screen->set_visarea(0, (320*2)-1, 0, (240*2)-1); + m_screen->set_visarea(0, 320-1, 0, 240-1); m_screen->set_screen_update("maincpu", FUNC(generalplus_gpl951xx_device::screen_update)); m_screen->screen_vblank().set(m_maincpu, FUNC(generalplus_gpl951xx_device::vblank)); @@ -259,9 +400,12 @@ void generalplus_gpl951xx_game_state::flufflav(machine_config &config) m_genspi->set_jedec_manufacturer(0xc2); m_genspi->set_jedec_memtype(0x20); m_genspi->set_jedec_capacity(0x16); + + m_screen->set_visarea(0, 128-1, 0, 128-1); + m_screen->set_physical_aspect(1, 1); } -void generalplus_gpl951xx_game_state::puni(machine_config &config) +void generalplus_gpl951xx_game_state::dsgnpal(machine_config &config) { gpl951xx(config); m_genspi->set_jedec_manufacturer(0xc2); @@ -269,6 +413,21 @@ void generalplus_gpl951xx_game_state::puni(machine_config &config) m_genspi->set_jedec_capacity(0x17); } +void generalplus_gpl951xx_game_state::puni(machine_config &config) +{ + dsgnpal(config); + m_screen->set_visarea(0, 128-1, 0, 128-1); + m_screen->set_physical_aspect(1, 1); +} + +void generalplus_gpl951xx_game_state::bubltea(machine_config &config) +{ + dsgnpal(config); + m_screen->set_visarea(0, 128-1, 0, 160-1); + m_screen->set_physical_aspect(128, 160); +} + + void generalplus_gpl951xx_game_state::bftetris(machine_config &config) { fixitflx(config); @@ -276,7 +435,7 @@ void generalplus_gpl951xx_game_state::bftetris(machine_config &config) // all games have an LCDC, but bftetris programs it manually, while other games // seem to take the GPL95xx output and show that directly m_screen->set_size(320, 262); - m_screen->set_visarea(0, (320)-1, 0, (240)-1); + m_screen->set_visarea(0, 320-1, 0, 240-1); m_screen->set_screen_update(FUNC(generalplus_gpl951xx_game_state::bftetris_screen_update)); } @@ -515,30 +674,30 @@ CONS(2020, bftetris, 0, 0, bftetris, bfspyhnt, generalplus_gpl951xx_game_state, // unclear if colour matches, but there are multiple generations of these at least // uses PUNIRUNZU_MAIN_V3 pcb -CONS(2021, punirune, 0, 0, puni, bfspyhnt, generalplus_gpl951xx_game_state, empty_init, "Takara Tomy", "Punirunes (PUNIRUNZU_MAIN_V3, pastel blue, Europe)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) +CONS(2021, punirune, 0, 0, puni, puni, generalplus_gpl951xx_game_state, empty_init, "Takara Tomy", "Punirunes (PUNIRUNZU_MAIN_V3, pastel blue, Europe)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) // looks similar to above, but has HXR-1 instead of the usual markings on the PCB CONS(2021, punirunea, punirune, 0, puni, bfspyhnt, generalplus_gpl951xx_game_state, empty_init, "Takara Tomy", "Punirunes (HXR-1 PCB)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) // the case on these looks like the European release, including English title logo. CPU is a glob, PUNIRUNZU_MAIN_DICE_V1 on PCB -CONS(2021, punij1m, punirune, 0, puni, bfspyhnt, generalplus_gpl951xx_game_state, empty_init, "Takara Tomy", "Punirunes (PUNIRUNZU_MAIN_DICE_V1, mint, Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) -CONS(2021, punij1pk, punirune, 0, puni, bfspyhnt, generalplus_gpl951xx_game_state, empty_init, "Takara Tomy", "Punirunes (PUNIRUNZU_MAIN_DICE_V1, pink, Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) -CONS(2021, punij1pu, punirune, 0, puni, bfspyhnt, generalplus_gpl951xx_game_state, empty_init, "Takara Tomy", "Punirunes (PUNIRUNZU_MAIN_DICE_V1, purple, Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) +CONS(2021, punij1m, punirune, 0, puni, puni, generalplus_gpl951xx_game_state, empty_init, "Takara Tomy", "Punirunes (PUNIRUNZU_MAIN_DICE_V1, mint, Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) +CONS(2021, punij1pk, punirune, 0, puni, puni, generalplus_gpl951xx_game_state, empty_init, "Takara Tomy", "Punirunes (PUNIRUNZU_MAIN_DICE_V1, pink, Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) +CONS(2021, punij1pu, punirune, 0, puni, puni, generalplus_gpl951xx_game_state, empty_init, "Takara Tomy", "Punirunes (PUNIRUNZU_MAIN_DICE_V1, purple, Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) // the case on these is similar to the above, but the text is in Japanese, uses PUNIRUNZU_MAIN_V2 on pcb -CONS(2021, punij2pk, punirune, 0, puni, bfspyhnt, generalplus_gpl951xx_game_state, empty_init, "Takara Tomy", "Punirunes (PUNIRUNZU_MAIN_V2, pink, Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) +CONS(2021, punij2pk, punirune, 0, puni, puni, generalplus_gpl951xx_game_state, empty_init, "Takara Tomy", "Punirunes (PUNIRUNZU_MAIN_V2, pink, Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) // has a link feature -CONS(2021, punifrnd, 0, 0, puni, bfspyhnt, generalplus_gpl951xx_game_state, empty_init, "Takara Tomy", "Punirunes Punitomo Tsuushin (hot pink, Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) +CONS(2021, punifrnd, 0, 0, puni, puni, generalplus_gpl951xx_game_state, empty_init, "Takara Tomy", "Punirunes Punitomo Tsuushin (hot pink, Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) -CONS(2021, punistar, 0, 0, puni, bfspyhnt, generalplus_gpl951xx_game_state, empty_init, "Takara Tomy", "Punirunes Punistarz (pink, Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) +CONS(2021, punistar, 0, 0, puni, base, generalplus_gpl951xx_game_state, empty_init, "Takara Tomy", "Punirunes Punistarz (pink, Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) // 'Poo' emoji shaped item, comes in multiple colours, has a solder pad which might change between units // this was dumped from the 'Lavender' unit -CONS(2021, flufflav, 0, 0, flufflav, bfspyhnt, generalplus_gpl951xx_game_state, empty_init, "Happinet", "Fuwatcho Uncho Fuwa Fuwa (lavender, Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) +CONS(2021, flufflav, 0, 0, flufflav, bubltea, generalplus_gpl951xx_game_state, empty_init, "Happinet", "Fuwatcho Uncho Fuwa Fuwa (lavender, Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) // available in 2 colours, ROM confirmed to be the same on both -CONS(2021, pockrmsr, 0, 0, puni, bfspyhnt, generalplus_gpl951xx_game_state, empty_init, "Bandai", "Pocket Room - Sanrio Characters (Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) +CONS(2021, pockrmsr, 0, 0, puni, base, generalplus_gpl951xx_game_state, empty_init, "Bandai", "Pocket Room - Sanrio Characters (Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) // Pocket Monsters ガチッとゲットだぜ! モンスターボールゴー! - Pocket Monsters is printed on the inner shell, but not the box? CONS(2021, pokgoget, 0, 0, poke, bfspyhnt, generalplus_gpl951xx_game_state, empty_init, "Takara Tomy", "Gachitto Get da ze! Monster Ball Go! (210406, Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) @@ -555,31 +714,30 @@ CONS( 2021, smkcatch, 0, 0, puni, bfmpac, generalplus_gpl951xx_game_state, empty // or Sumikko Gurashi - Sumikko Catch DX (すみっコぐらし すみっコキャッチDX) = Sumikko Catch with pouch and strap // is there a subtitle for this one? it's different to the others -CONS( 201?, smkguras, 0, 0, puni, bfmpac, generalplus_gpl951xx_game_state, empty_init, "San-X / Tomy", "Sumikko Gurashi DX (Japan, set 1)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING) -CONS( 201?, smkgurasa, smkguras, 0, puni, bfmpac, generalplus_gpl951xx_game_state, empty_init, "San-X / Tomy", "Sumikko Gurashi DX (Japan, set 2)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING) +CONS( 201?, smkguras, 0, 0, puni, bubltea, generalplus_gpl951xx_game_state, empty_init, "San-X / Tomy", "Sumikko Gurashi DX (Japan, set 1)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING) +CONS( 201?, smkgurasa, smkguras, 0, puni, bubltea, generalplus_gpl951xx_game_state, empty_init, "San-X / Tomy", "Sumikko Gurashi DX (Japan, set 2)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING) -CONS( 2021, smkgacha, 0, 0, puni, bfmpac, generalplus_gpl951xx_game_state, empty_init, "San-X / Tomy", "Sumikko Gacha (Japan)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING) +CONS( 2021, smkgacha, 0, 0, puni, bubltea, generalplus_gpl951xx_game_state, empty_init, "San-X / Tomy", "Sumikko Gacha (Japan)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING) // there seem to be different versions of this available, is the software the same? -CONS( 201?, dsgnpal, 0, 0, puni, bfmpac, generalplus_gpl951xx_game_state, empty_init, "Tomy", "Kiratto Pri-Chan Design Palette (Japan)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING) +CONS( 201?, dsgnpal, 0, 0, dsgnpal, dsgnpal, generalplus_gpl951xx_game_state, empty_init, "Tomy", "Kiratto Pri-Chan Design Palette (Japan)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING | ROT270 ) + +// these have different version numbers (coming from the user/config area?) correlating to the colour of the device, even if the code the same +CONS( 2018, segapet1, 0, 0, puni, segapet1, generalplus_gpl951xx_game_state, empty_init, "Sega Toys", "Mocchiri Pet Mocchimaruzu (180615B P)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) +CONS( 2018, segapet1a, segapet1, 0, puni, segapet1, generalplus_gpl951xx_game_state, empty_init, "Sega Toys", "Mocchiri Pet Mocchimaruzu (180615B Y)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) -// for these Sega Toys pets the clones might end up being duplicates with only different user data, however they might also have different factory default data for each colour -// もっちりペット もっちまるず -CONS( 2018, segapet1, 0, 0, puni, bfspyhnt, generalplus_gpl951xx_game_state, empty_init, "Sega Toys", "Mocchiri Pet Mocchimaruzu (2018 version, set 1)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) -CONS( 2018, segapet1a, segapet1, 0, puni, bfspyhnt, generalplus_gpl951xx_game_state, empty_init, "Sega Toys", "Mocchiri Pet Mocchimaruzu (2018 version, set 2)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) -// a 'DX' version (dated 2020) also exists, unclear if it's different software or just different packaging with bonuses +// DX version of the first game, 2020 on box, updated fabric cover, still has 2018 on case, newer code revision +CONS( 2020, segaptdx, 0, 0, puni, segapet1, generalplus_gpl951xx_game_state, empty_init, "Sega Toys", "Mocchiri Pet Mocchimaruzu DX (190313A P)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) // also もっちりペット もっちまるず -CONS( 2019, segapet2, 0, 0, puni, bfspyhnt, generalplus_gpl951xx_game_state, empty_init, "Sega Toys", "Mocchiri Pet Mocchimaruzu (2019 version, set 1)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) -CONS( 2019, segapet2a, segapet2, 0, puni, bfspyhnt, generalplus_gpl951xx_game_state, empty_init, "Sega Toys", "Mocchiri Pet Mocchimaruzu (2019 version, set 2)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) +CONS( 2019, segapet2, 0, 0, puni, segapet2, generalplus_gpl951xx_game_state, empty_init, "Sega Toys", "Mocchiri Pet Mocchimaruzu (2019 version, set 1)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) +CONS( 2019, segapet2a, segapet2, 0, puni, segapet2, generalplus_gpl951xx_game_state, empty_init, "Sega Toys", "Mocchiri Pet Mocchimaruzu (2019 version, set 2)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) // these ones have motors in the ears and a more fluffy cover // もっちふわペット もっちまるず -CONS( 2020, segapet3, 0, 0, puni, bfspyhnt, generalplus_gpl951xx_game_state, empty_init, "Sega Toys", "Mocchifuwa Pet Mocchimaruzu (set 1)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) -CONS( 2020, segapet3a, segapet3, 0, puni, bfspyhnt, generalplus_gpl951xx_game_state, empty_init, "Sega Toys", "Mocchifuwa Pet Mocchimaruzu (set 2)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) +CONS( 2020, segapet3, 0, 0, puni, base, generalplus_gpl951xx_game_state, empty_init, "Sega Toys", "Mocchifuwa Pet Mocchimaruzu (set 1)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) +CONS( 2020, segapet3a, segapet3, 0, puni, base, generalplus_gpl951xx_game_state, empty_init, "Sega Toys", "Mocchifuwa Pet Mocchimaruzu (set 2)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) -// DX version of the first game, 2020 on box, updated fabric cover, still has 2018 on case, but different software? -CONS( 2020, segaptdx, 0, 0, puni, bfspyhnt, generalplus_gpl951xx_game_state, empty_init, "Sega Toys", "Mocchiri Pet Mocchimaruzu DX", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) // まぜまぜミックス!ぷにタピちゃん -CONS( 201?, bubltea, 0, 0, puni, bfspyhnt, generalplus_gpl951xx_game_state, empty_init, "Bandai", "Mazemaze Mix! Puni Tapi-chan (Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) +CONS( 201?, bubltea, 0, 0, bubltea, bubltea, generalplus_gpl951xx_game_state, empty_init, "Bandai", "Mazemaze Mix! Puni Tapi-chan (Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) |
