summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--hash/popstar_cart.xml43
-rw-r--r--scripts/src/machine.lua6
-rw-r--r--src/devices/machine/generalplus_gpl1625x_soc.cpp1
-rw-r--r--src/devices/machine/generalplus_gpl162xx_soc.cpp942
-rw-r--r--src/devices/machine/generalplus_gpl162xx_soc.h139
-rw-r--r--src/devices/machine/generalplus_gpl162xx_soc_video.cpp18
-rw-r--r--src/devices/machine/generalplus_gpl951xx_rtc.cpp151
-rw-r--r--src/devices/machine/generalplus_gpl951xx_rtc.h54
-rw-r--r--src/devices/machine/generalplus_gpl951xx_soc.cpp811
-rw-r--r--src/devices/machine/generalplus_gpl951xx_soc.h175
-rw-r--r--src/devices/machine/generalplus_gpl_dma.cpp288
-rw-r--r--src/devices/machine/generalplus_gpl_dma.h53
-rw-r--r--src/devices/machine/generalplus_gpl_timebase.cpp208
-rw-r--r--src/devices/machine/generalplus_gpl_timebase.h57
-rw-r--r--src/mame/handheld/generalplus_gpl162xx_lcdtype.cpp (renamed from src/mame/tvgames/generalplus_gpl162xx_lcdtype.cpp)4
-rw-r--r--src/mame/handheld/generalplus_gpl951xx.cpp (renamed from src/mame/tvgames/generalplus_gpl951xx.cpp)70
-rw-r--r--src/mame/handheld/unknown_bftetris_lcdc.cpp357
-rw-r--r--src/mame/handheld/unknown_bftetris_lcdc.h38
-rw-r--r--src/mame/mame.lst93
-rw-r--r--src/mame/nintendo/nes_clone.cpp97
-rw-r--r--src/mame/nintendo/nes_vt02_vt03.cpp31
-rw-r--r--src/mame/nintendo/nes_vt369_vtunknown.cpp12
-rw-r--r--src/mame/skeleton/amlogic_aml7212.cpp73
-rw-r--r--src/mame/skeleton/tamagotchi_pix.cpp14
-rw-r--r--src/mame/tvgames/generalplus_gpl16250.cpp6
-rw-r--r--src/mame/tvgames/generalplus_gpl16250.h1
-rw-r--r--src/mame/tvgames/generalplus_gpl16250_rom.cpp11
-rw-r--r--src/mame/tvgames/generalplus_gpl16250_spi.cpp14
-rw-r--r--src/mame/tvgames/generalplus_gpl32612.cpp10
29 files changed, 3087 insertions, 690 deletions
diff --git a/hash/popstar_cart.xml b/hash/popstar_cart.xml
new file mode 100644
index 00000000000..58f69c608f8
--- /dev/null
+++ b/hash/popstar_cart.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<!DOCTYPE softwarelist SYSTEM "softwarelist.dtd">
+<!--
+license:CC0-1.0
+-->
+<softwarelist name="popstar_cart" description="Cartridges compatible with Popstar Karaoke">
+
+ <software name="5songs" supported="no"> <!-- this was the pack-in cart -->
+ <description>Popstar Karaoke - 5 Songs</description>
+ <year>2002</year>
+ <publisher>unknown</publisher>
+ <part name="cart" interface="popstar_cart">
+ <dataarea name="rom" size="0x80000">
+ <rom name="popstar_karaoke_5songs.u5" size="0x80000" crc="d0010434" sha1="967a0bea0a940757ff1c397c580a23c0055b3fca"/>
+ </dataarea>
+ </part>
+ </software>
+
+ <software name="popstar1" supported="no">
+ <description>Popstar Karaoke Vol. 1</description>
+ <year>2002</year>
+ <publisher>unknown</publisher>
+ <part name="cart" interface="popstar_cart">
+ <dataarea name="rom" size="0x80000">
+ <!-- checksum on label doesn't seem to match bytesum? -->
+ <rom name="popstar_karaoke_vol1.u5" size="0x80000" crc="ae1e0550" sha1="6b874630a3925f55b3d9755e331232eee8edd6f0" status="baddump"/>
+ </dataarea>
+ </part>
+ </software>
+
+ <software name="popstar2" supported="no">
+ <description>Popstar Karaoke Vol. 2</description>
+ <year>2002</year>
+ <publisher>unknown</publisher>
+ <part name="cart" interface="popstar_cart">
+ <dataarea name="rom" size="0x80000">
+ <!-- checksum on label doesn't seem to match bytesum? -->
+ <rom name="popstar_karaoke_vol2.u5" size="0x80000" crc="38eeac5b" sha1="6cd4f7b7f34fecd68564f9d14e773dba61607db8" status="baddump"/>
+ </dataarea>
+ </part>
+ </software>
+
+</softwarelist>
diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua
index 9dcb61bb16d..14828a0e7d6 100644
--- a/scripts/src/machine.lua
+++ b/scripts/src/machine.lua
@@ -3593,8 +3593,14 @@ if MACHINES["SPG2XX"] then
MAME_DIR .. "src/devices/machine/generalplus_gpl162xx_soc_video.h",
MAME_DIR .. "src/devices/machine/generalplus_gpl951xx_soc.cpp",
MAME_DIR .. "src/devices/machine/generalplus_gpl951xx_soc.h",
+ MAME_DIR .. "src/devices/machine/generalplus_gpl951xx_rtc.cpp",
+ MAME_DIR .. "src/devices/machine/generalplus_gpl951xx_rtc.h",
MAME_DIR .. "src/devices/machine/generalplus_gpce4_soc.cpp",
MAME_DIR .. "src/devices/machine/generalplus_gpce4_soc.h",
+ MAME_DIR .. "src/devices/machine/generalplus_gpl_dma.cpp",
+ MAME_DIR .. "src/devices/machine/generalplus_gpl_dma.h",
+ MAME_DIR .. "src/devices/machine/generalplus_gpl_timebase.cpp",
+ MAME_DIR .. "src/devices/machine/generalplus_gpl_timebase.h",
MAME_DIR .. "src/devices/machine/spg_renderer.cpp",
MAME_DIR .. "src/devices/machine/spg_renderer.h",
MAME_DIR .. "src/devices/machine/gpl_renderer.cpp",
diff --git a/src/devices/machine/generalplus_gpl1625x_soc.cpp b/src/devices/machine/generalplus_gpl1625x_soc.cpp
index c80303cc02e..444e577b3dd 100644
--- a/src/devices/machine/generalplus_gpl1625x_soc.cpp
+++ b/src/devices/machine/generalplus_gpl1625x_soc.cpp
@@ -317,6 +317,7 @@
// 78e0 - TimerE_Ctrl
// 78e2 - TimerE_Preload
// 78e4 - TimerE_UpCount
+
// 78e8 - TimerF_Ctrl
// 78ea - TimerF_Preload
// 78ec - TimerF_UpCount
diff --git a/src/devices/machine/generalplus_gpl162xx_soc.cpp b/src/devices/machine/generalplus_gpl162xx_soc.cpp
index 575a9741df5..c2975929bdf 100644
--- a/src/devices/machine/generalplus_gpl162xx_soc.cpp
+++ b/src/devices/machine/generalplus_gpl162xx_soc.cpp
@@ -60,9 +60,18 @@ sunplus_gcm394_base_device::sunplus_gcm394_base_device(const machine_config &mco
m_space_read_cb(*this, 0),
m_space_write_cb(*this),
m_dma_complete_cb(*this),
- m_alt_periodic_irq(false),
m_boot_mode(0),
- m_cs_callback(*this, DEVICE_SELF, FUNC(sunplus_gcm394_base_device::default_cs_callback))
+ m_cs_callback(*this, DEVICE_SELF, FUNC(sunplus_gcm394_base_device::default_cs_callback)),
+ m_timer_a(*this, "timer_a"),
+ m_timer_b(*this, "timer_b"),
+ m_timer_c(*this, "timer_c"),
+ m_timer_d(*this, "timer_d"),
+ m_timer_e(*this, "timer_e"),
+ m_timer_f(*this, "timer_f"),
+ m_scheduler(*this, "scheduler"),
+ m_gpl_dma(*this, "gpl_dma"),
+ m_gpl_timebase(*this, "gpl_timebase"),
+ m_disable_timebase_interrupts(false)
{
}
@@ -80,242 +89,40 @@ void sunplus_gcm394_base_device::default_cs_callback(u16 cs0, u16 cs1, u16 cs2,
}
-// **************************************** SYSTEM DMA device *************************************************
-
-u16 sunplus_gcm394_base_device::read_dma_params(int channel, int offset)
-{
- u16 retdata = m_dma_params[offset][channel];
- LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::read_dma_params (channel %01x) %01x returning %04x\n", machine().describe_context(), channel, offset, retdata);
- return retdata;
-}
-
-void sunplus_gcm394_base_device::write_dma_params(int channel, int offset, u16 data)
-{
- LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::write_dma_params (channel %01x) %01x %04x\n", machine().describe_context(), channel, offset, data);
-
- m_dma_params[offset][channel] = data;
-
- // TODO: very likely DMA happens whenever the length is not 0, as long as it's been enabled previously
- // jak_prft doesn't rewrite the offset 0 register between requests, and instead writes the length
- // as the final thing for each new request. other games do not write the length last, but turn off
- // register 0 before writing params, and enable it again afterwards
- // if that's the case, this code can be refactored to work on 'length' instead of the m_dma_latched
-
- if (offset == 3)
- {
- m_dma_latched[channel] = true;
-
- if (m_dma_params[0][channel] & 1)
- trigger_systemm_dma(channel);
- }
-
- if (offset == 0 && (data & 1))
- {
- if (m_dma_latched[channel])
- trigger_systemm_dma(channel);
- }
-
-}
-
-
-u16 sunplus_gcm394_base_device::system_dma_params_channel0_r(offs_t offset)
-{
- return read_dma_params(0, offset);
-}
-
-
-void sunplus_gcm394_base_device::system_dma_params_channel0_w(offs_t offset, u16 data)
-{
- write_dma_params(0, offset, data);
-}
-
-u16 sunplus_gcm394_base_device::system_dma_params_channel1_r(offs_t offset)
-{
- return read_dma_params(1, offset);
-}
-
-void sunplus_gcm394_base_device::system_dma_params_channel1_w(offs_t offset, u16 data)
-{
- write_dma_params(1, offset, data);
-}
-
-u16 sunplus_gcm394_base_device::system_dma_params_channel2_r(offs_t offset)
-{
- return read_dma_params(2, offset);
-}
-
-void sunplus_gcm394_base_device::system_dma_params_channel2_w(offs_t offset, u16 data)
-{
- write_dma_params(2, offset, data);
-}
-
-u16 sunplus_gcm394_base_device::system_dma_params_channel3_r(offs_t offset)
-{
- return read_dma_params(3, offset);
-}
-
-void sunplus_gcm394_base_device::system_dma_params_channel3_w(offs_t offset, u16 data)
-{
- write_dma_params(3, offset, data);
-}
-
-
-
-
-u16 sunplus_gcm394_base_device::system_dma_status_r()
-{
- LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::system_dma_status_r (7abf)\n", machine().describe_context());
-
- // bit 0 = channel 0 ready
- // bit 1 = channel 1 ready
-
- return 0x00ff;
-}
-
-void sunplus_gcm394_base_device::trigger_systemm_dma(int channel)
-{
- u16 mode = m_dma_params[0][channel];
- u32 source = m_dma_params[1][channel] | (m_dma_params[4][channel] << 16);
- u32 dest = m_dma_params[2][channel] | (m_dma_params[5][channel] << 16) ;
- u32 length = m_dma_params[3][channel] | (m_dma_params[6][channel] << 16);
- int sourcedelta = 0;
- int destdelta = 0;
-
- if ((mode & 0xa0) == 0x00)
- sourcedelta = 1;
- else if ((mode & 0xa0) == 0x20)
- sourcedelta = -1;
-
- if ((mode & 0x50) == 0x00)
- destdelta = 1;
- 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) while csbank is %02x\n", machine().describe_context(), mode, source, dest, length, m_membankswitch_7810 );
-
- // wrlshunt transfers ROM to RAM, all RAM write addresses have 0x800000 in the destination set
-
- source &= 0x0fffffff;
- length &= 0x0fffffff; // gormiti
-
- for (int i = 0; i < length; i++)
- {
- u16 val;
- if (mode & 0x1000)
- {
- val = (read_space(source) & 0xFF) | (read_space(source) << 8);
- i++;
- }
- else
- {
- val = read_space(source);
- }
-
- source += sourcedelta;
-
- if (mode & 0x2000)
- {
- write_space(dest, val & 0xFF);
- dest += destdelta;
- write_space(dest, val >> 8);
- }
- else
- {
- write_space(dest, val);
- }
-
- dest += destdelta;
- }
-
- m_dma_complete_cb(1); // allow some driver specific hacks for service modes
-
- // clear params after operation
- m_dma_params[0][channel] = m_dma_params[0][channel] & 0x00f7;
-
- m_dma_params[1][channel] = m_dma_params[2][channel] = m_dma_params[3][channel] = m_dma_params[4][channel] = m_dma_params[5][channel] = m_dma_params[6][channel] = 0x0000;
- m_dma_latched[channel] = false;
-
- //machine().debug_break();
-}
-
-void sunplus_gcm394_base_device::system_dma_7abf_unk_w(u16 data)
-{
- // if this isn't trigger, is it enable? (which could maybe used as similar if DMA only starts to happen if unmasked?)
-
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_dma_7abf_unk_w %04x\n", machine().describe_context(), data);
-}
-
-u16 sunplus_gcm394_base_device::system_dma_memtype_r()
-{
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_dma_memtype_r\n", machine().describe_context());
- return m_system_dma_memtype;
-}
-
-void sunplus_gcm394_base_device::system_dma_memtype_w(u16 data)
-{
- static char const* const types[16] =
- {
- "Unused / USB",
- "DAC CHA",
- "UART TX",
- "UART RX",
- "SD/MMC",
- "NAND Flash",
- "Serial Interface",
- "DAC CHB",
- "ADC Audo Sample Full",
- "SPI TX",
- "SPI RX",
- "RESERVED (c)",
- "RESERVED (d)",
- "RESERVED (e)",
- "RESERVED (f)"
- };
-
- m_system_dma_memtype = data;
-
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_dma_memtype_w %04x (CH3: %s | CH2: %s | CH1: %s | CH0: %s )\n", machine().describe_context(), data,
- types[((m_system_dma_memtype>>12)&0xf)],
- types[((m_system_dma_memtype>>8)&0xf)],
- types[((m_system_dma_memtype>>4)&0xf)],
- types[((m_system_dma_memtype)&0xf)]);
-
-}
-
-u16 sunplus_gcm394_base_device::system_7a35_r()
+u16 sunplus_gcm394_base_device::usb_7a35_r()
{
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_7a35_r\n", machine().describe_context());
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::usb_7a35_r\n", machine().describe_context());
return machine().rand();
}
-u16 sunplus_gcm394_base_device::system_7a37_r()
+u16 sunplus_gcm394_base_device::usb_7a37_r()
{
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_7a37_r\n", machine().describe_context());
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::usb_7a37_r\n", machine().describe_context());
return machine().rand();
}
-u16 sunplus_gcm394_base_device::system_7a39_r()
+u16 sunplus_gcm394_base_device::usb_7a39_r()
{
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_7a39_r\n", machine().describe_context());
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::usb_7a39_r\n", machine().describe_context());
return machine().rand();
}
-u16 sunplus_gcm394_base_device::system_7a3a_r()
+u16 sunplus_gcm394_base_device::usb_7a3a_r()
{
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_7a3a_r\n", machine().describe_context());
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::usb_7a3a_r\n", machine().describe_context());
return machine().rand();
}
-u16 sunplus_gcm394_base_device::system_7a46_r()
+u16 sunplus_gcm394_base_device::usb_7a46_r()
{
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_7a46_r\n", machine().describe_context());
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::usb_7a46_r\n", machine().describe_context());
return machine().rand();
}
-u16 sunplus_gcm394_base_device::system_7a54_r()
+u16 sunplus_gcm394_base_device::usb_7a54_r()
{
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_7a54_r\n", machine().describe_context());
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::usb_7a54_r\n", machine().describe_context());
return machine().rand();
}
@@ -327,11 +134,11 @@ u16 sunplus_gcm394_base_device::power_state_r()
return 0x0002;
}
-u16 sunplus_gcm394_base_device::unkarea_78fb_status_r()
+u16 sunplus_gcm394_base_device::dac_pga_r()
{
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78fb_status_r\n", machine().describe_context());
- m_78fb ^= 0x0100; // status flag for something?
- return m_78fb;
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::dac_pga_r\n", machine().describe_context());
+ m_dac_pga ^= 0x0100; // status flag for something?
+ return m_dac_pga;
}
// sets bit 0x0002 then expects it to have cleared
@@ -340,13 +147,33 @@ void sunplus_gcm394_base_device::cache_ctrl_w(u16 data) { LOGMASKED(LOG_GCM394,
// **************************************** 78xx region stubs *************************************************
-u16 sunplus_gcm394_base_device::unkarea_782d_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_782d_r\n", machine().describe_context()); return m_782d; }
-void sunplus_gcm394_base_device::unkarea_782d_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_782d_w %04x\n", machine().describe_context(), data); m_782d = data; }
+u16 sunplus_gcm394_base_device::raw_war_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::raw_war_r\n", machine().describe_context()); return m_782d; }
+void sunplus_gcm394_base_device::raw_war_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::raw_war_w %04x\n", machine().describe_context(), data); m_782d = data; }
-u16 sunplus_gcm394_base_device::unkarea_7803_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7803_r\n", machine().describe_context()); return m_sys_ctrl; }
-void sunplus_gcm394_base_device::unkarea_7803_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7803_w %04x\n", machine().describe_context(), data); m_sys_ctrl = data; }
+u16 sunplus_gcm394_base_device::sys_ctrl_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::sys_ctrl_r\n", machine().describe_context()); return m_sys_ctrl; }
+void sunplus_gcm394_base_device::sys_ctrl_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::sys_ctrl_w %04x\n", machine().describe_context(), data); m_sys_ctrl = data; }
-void sunplus_gcm394_base_device::clock_ctrl_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::clock_ctrl_w %04x\n", machine().describe_context(), data); m_clock_ctrl = data; }
+void sunplus_gcm394_base_device::clock_ctrl_w(u16 data)
+{
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::clock_ctrl_w %04x\n", machine().describe_context(), data);
+ m_clock_ctrl = data;
+}
+
+u16 sunplus_gcm394_base_device::clk_ctrl0_r()
+{
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::clk_ctrl0_r\n", machine().describe_context());
+ return 0x0000;
+}
+
+void sunplus_gcm394_base_device::clk_ctrl0_w(u16 data)
+{
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::clk_ctrl0 %04x\n", machine().describe_context(), data);
+}
+
+void sunplus_gcm394_base_device::watchdog_ctrl_w(u16 data)
+{
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::watchdog_ctrl_w %04x\n", machine().describe_context(), data);
+}
void sunplus_gcm394_base_device::waitmode_enter_780c_w(u16 data)
{
@@ -387,6 +214,17 @@ void sunplus_gcm394_base_device::pllchange_w(u16 data)
m_pllchange = data;
}
+u16 sunplus_gcm394_base_device::pllclkwait_r()
+{
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::pllclkwait_r\n", machine().describe_context());
+ return 0x0000;
+}
+
+void sunplus_gcm394_base_device::pllclkwait_w(u16 data)
+{
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::pllclkwait_w %04x\n", machine().describe_context(), data);
+}
+
void sunplus_gcm394_base_device::chipselect_csx_memory_device_control_w(offs_t offset, u16 data)
{
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::chipselect_csx_memory_device_control_w %04x (782x registers offset %d)\n", machine().describe_context(), data, offset);
@@ -417,7 +255,7 @@ void sunplus_gcm394_base_device::device_post_load()
m_cs_callback(m_782x[0], m_782x[1], m_782x[2], m_782x[3], m_782x[4]);
}
-void sunplus_gcm394_base_device::unkarea_7835_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7835_w %04x\n", machine().describe_context(), data); m_7835 = data; }
+void sunplus_gcm394_base_device::mcs0_page_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::mcs0_page_w %04x\n", machine().describe_context(), data); m_7835 = data; }
// IO here?
@@ -588,7 +426,7 @@ void sunplus_gcm394_base_device::iod_data_w(u16 data)
u16 sunplus_gcm394_base_device::iod_buffer_r()
{
LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::iod_buffer_r\n", machine().describe_context());
- return 0xffff;// m_7871;
+ return 0xffff;
}
void sunplus_gcm394_base_device::iod_buffer_w(u16 data)
@@ -643,6 +481,18 @@ void sunplus_gcm394_base_device::iod_mux_w(u16 data)
LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::iod_mux_w %04x\n", machine().describe_context(), data);
}
+u16 sunplus_gcm394_base_device::ioe_buffer_r()
+{
+ LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioe_buffer_r\n", machine().describe_context());
+ return 0xffff;
+}
+
+void sunplus_gcm394_base_device::ioe_buffer_w(u16 data)
+{
+ LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioe_buffer_w %04x\n", machine().describe_context(), data);
+ //m_porte_out(data);
+}
+
u16 sunplus_gcm394_base_device::ioe_dir_r()
{
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::ioe_dir_r\n", machine().describe_context());
@@ -667,11 +517,27 @@ void sunplus_gcm394_base_device::ioe_attrib_w(u16 data)
m_ioe_attrib = data;
}
-void sunplus_gcm394_base_device::int_status1_w(u16 data)
-{
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::int_status1_w %04x\n", machine().describe_context(), data);
- m_int_status1 = data;
-}
+
+// P_INT_Status1 (different on GPL162xx vs GP95xx)
+// 15 KEYIF
+// 14 ADCRIF
+// 13 TFTUFIF
+// 12 TFTEIF
+//
+// 11 UTIRIF
+// 10 SPIIF
+// 9 FPIF
+// 8
+//
+// 7 ASIF
+// 6
+// 5 AUDBIF
+// 4 AUDAIF
+
+// 3 USB
+// 2 DMA
+// 1 EXTBIF
+// 0 EXTAIF
u16 sunplus_gcm394_base_device::int_status1_r()
{
@@ -679,10 +545,87 @@ u16 sunplus_gcm394_base_device::int_status1_r()
return 0x0000;// machine().rand();
}
+void sunplus_gcm394_base_device::int_status1_w(u16 data)
+{
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::int_status1_w %04x\n", machine().describe_context(), data);
+ //m_int_status1 = data;
+}
+
+// P_INT_Status2 (different on GPL162xx vs GP95xx)
+// 15 TMDIF
+// 14 TMCIF
+// 13 TMBIF
+// 12 TMAIF
+//
+// 11 KSIF
+// 10 TMBCIF
+// 9 TMBBIF
+// 8 TMBAIF
+//
+// 7 SDC2
+// 6 SDC1
+// 5
+// 4 NAND
+//
+// 3
+// 2 SCHIF
+// 1 ALMIF
+// 0 HMSIF
+
u16 sunplus_gcm394_base_device::int_status2_r()
{
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::int_status2_r\n", machine().describe_context());
- return 0xffff;// machine().rand();
+ u16 ret = 0;
+
+ if (m_gpl_timebase->timebasea_irq_flag())
+ ret |= 0x0100;
+
+ if (m_gpl_timebase->timebaseb_irq_flag())
+ ret |= 0x0200;
+
+ if (m_gpl_timebase->timebasec_irq_flag())
+ ret |= 0x0400;
+
+ return ret;
+}
+
+void sunplus_gcm394_base_device::int_status2_w(u16 data)
+{
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::int_status2_w %04x\n", machine().describe_context(), data);
+ // none of this bits are listed as wrieable for GPL95xx or GPL162xx
+}
+
+// P_INT_Status3 (different on GPL162xx vs GP95xx)
+// 15
+// 14
+// 13
+// 12
+//
+// 11
+// 10
+// 9
+// 8 UMAA
+//
+// 7
+// 6
+// 5
+// 4
+//
+// 3
+// 2 BEAT
+// 1 ENV
+// 0 CHANNEL
+
+u16 sunplus_gcm394_base_device::int_status3_r()
+{
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::int_status3_r\n", machine().describe_context());
+ return 0x0000;
+}
+
+void sunplus_gcm394_base_device::int_status3_w(u16 data)
+{
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::int_status3_w %04x\n", machine().describe_context(), data);
+ // bit 2 (SPU Beat Interrupt) is listed as R/W for GPL95, but not GPL162? (verify)
}
void sunplus_gcm394_base_device::int_priority_1_w(u16 data)
@@ -709,58 +652,115 @@ void sunplus_gcm394_base_device::mint_ctrl_w(u16 data)
m_misc_int_ctrl = data;
}
-void sunplus_gcm394_base_device::timebasea_ctrl_w(u16 data)
+// FIQ
+// many sources can be set to FIQ
+//
+// IRQ0
+// Audio Channel A FIFO Empty
+// Audio Channel B FIFO Empty
+//
+// IRQ1
+// ?
+//
+// IRQ2
+// External interrupt A
+//
+// IRQ3
+// SPI interrupt
+// DMA interrupt
+// USB interrupt
+//
+// IRQ4
+// Timer A/B/C/D interrupt
+// SPU interrupt
+//
+// IRQ5
+// Key Change interrupt
+// PPU interrupt
+// NAND Overflow/Underflow interrupt
+//
+// IRQ6
+// Timebase C interrupt
+// Scheduler interrupt (RTC)
+// SDC2 Controller interrupt
+//
+// IRQ7
+// Timebase A interrupt
+// Timebase B interrupt
+// Alarm interrupt
+// Hour/Minute/Second/Half-Second interrupt (RTC)
+// Unexpected memory access interrupt
+
+void sunplus_gcm394_base_device::update_interrupts(int state)
{
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::timebasea_ctrl_w %04x\n", machine().describe_context(), data);
- m_timebasea_ctrl = data;
+ if ((m_gpl_timebase->timebasea_irq_flag() && !m_disable_timebase_interrupts) || (m_gpl_timebase->timebaseb_irq_flag() && !m_disable_timebase_interrupts))
+ {
+ set_state_unsynced(UNSP_IRQ7_LINE, ASSERT_LINE);
+ }
+ else
+ {
+ set_state_unsynced(UNSP_IRQ7_LINE, CLEAR_LINE);
+ }
+
+ if ((m_gpl_timebase->timebasec_irq_flag() && !m_disable_timebase_interrupts) || (m_rtc_int_status & 0x0100))
+ {
+ set_state_unsynced(UNSP_IRQ6_LINE, ASSERT_LINE);
+ }
+ else
+ {
+ set_state_unsynced(UNSP_IRQ6_LINE, CLEAR_LINE);
+ }
}
-void sunplus_gcm394_base_device::timebaseb_ctrl_w(u16 data)
+
+// programmable timers
+
+TIMER_DEVICE_CALLBACK_MEMBER(sunplus_gcm394_base_device::timer_a_cb)
{
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::timebaseb_ctrl_w %04x\n", machine().describe_context(), data);
- m_timebaseb_ctrl = data;
}
-u16 sunplus_gcm394_base_device::timebasec_ctrl_r()
+TIMER_DEVICE_CALLBACK_MEMBER(sunplus_gcm394_base_device::timer_b_cb)
{
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::timebasec_ctrl_r\n", machine().describe_context());
- return 0xffff;// m_timebasec_ctrl;
}
-void sunplus_gcm394_base_device::timebasec_ctrl_w(u16 data)
+TIMER_DEVICE_CALLBACK_MEMBER(sunplus_gcm394_base_device::timer_c_cb)
{
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::timebasec_ctrl_w %04x\n", machine().describe_context(), data);
- m_timebasec_ctrl = data;
}
-void sunplus_gcm394_base_device::timebase_reset_w(u16 data)
+TIMER_DEVICE_CALLBACK_MEMBER(sunplus_gcm394_base_device::timer_d_cb)
{
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::timebase_reset_w %04x\n", machine().describe_context(), data);
- m_timebase_reset = data;
}
-u16 sunplus_gcm394_base_device::cha_ctrl_r()
+TIMER_DEVICE_CALLBACK_MEMBER(sunplus_gcm394_base_device::timer_e_cb)
{
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::cha_ctrl_r\n", machine().describe_context());
- return 0xffff;
}
-void sunplus_gcm394_base_device::cha_ctrl_w(u16 data)
+TIMER_DEVICE_CALLBACK_MEMBER(sunplus_gcm394_base_device::timer_f_cb)
{
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::cha_ctrl_w %04x\n", machine().describe_context(), data);
- m_cha_ctrl = data;
}
u16 sunplus_gcm394_base_device::timera_ctrl_r()
{
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::timera_ctrl_r\n", machine().describe_context());
- return machine().rand();
+ return m_timera_ctrl;
+}
+
+void sunplus_gcm394_base_device::timera_ctrl_w(u16 data)
+{
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::timera_ctrl_w %04x\n", machine().describe_context(), data);
+ m_timera_ctrl = data;
}
u16 sunplus_gcm394_base_device::timerb_ctrl_r()
{
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::timerb_ctrl_r\n", machine().describe_context());
- return 0xffff;
+ return m_timerb_ctrl;
+}
+
+void sunplus_gcm394_base_device::timerb_ctrl_w(u16 data)
+{
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::timerb_ctrl_w %04x\n", machine().describe_context(), data);
+ m_timerb_ctrl = data;
}
u16 sunplus_gcm394_base_device::timerc_ctrl_r()
@@ -775,14 +775,74 @@ u16 sunplus_gcm394_base_device::timerd_ctrl_r()
return machine().rand();
}
-// **************************************** 793x uknown region stubs *************************************************
+// CHA (for sound output)
+
+u16 sunplus_gcm394_base_device::cha_ctrl_r()
+{
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::cha_ctrl_r\n", machine().describe_context());
+ return 0xffff;
+}
+
+void sunplus_gcm394_base_device::cha_ctrl_w(u16 data)
+{
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::cha_ctrl_w %04x\n", machine().describe_context(), data);
+ m_cha_ctrl = data;
+}
+
+
+// UART
-u16 sunplus_gcm394_base_device::unkarea_7904_r()
+u16 sunplus_gcm394_base_device::uart_status_r()
{
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7904_r\n", machine().describe_context());
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::uart_status_r\n", machine().describe_context());
return machine().rand(); // lazertag waits on a bit, status flag for something?
}
+// RTC
+
+TIMER_DEVICE_CALLBACK_MEMBER(sunplus_gcm394_base_device::scheduler_cb)
+{
+ if (m_rtc_int_ctrl & 0x0100)
+ {
+ logerror("scheduler setting\n");
+ m_rtc_int_status |= 0x0100;
+ update_interrupts(1);
+ }
+}
+
+
+// P_RTC_Ctrl
+//
+// 15 RTCEN - RTC Module Enable
+// 14
+// 13
+// 12
+
+// 11
+// 10 ALMEN - Alarm Function Enable
+// 9 HMSEN - Hour/Minute/Second Update Enable
+// 8 SCHEN - Scheduler Function Enable
+
+// 7
+// 6
+// 5
+// 4
+
+// 3
+// 2 SCHSEL[2] - Secheduler Period
+// 1 SCHSEL[1]
+// 0 SCHSEL[0]
+//
+// Scheduler Periods are
+// 0: 16hz
+// 1: 32Hz
+// 2: 64Hz
+// 3: 128Hz
+// 4: 256Hz
+// 5: 512Hz
+// 6: 1024Hz
+// 7: 2048Hz
+
u16 sunplus_gcm394_base_device::rtc_ctrl_r()
{
// does this return data written, or is it a status flag?
@@ -792,10 +852,60 @@ u16 sunplus_gcm394_base_device::rtc_ctrl_r()
void sunplus_gcm394_base_device::rtc_ctrl_w(u16 data)
{
- LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::rtc_ctrl_w %04x\n", machine().describe_context(), data);
+ u16 no_use = data & 0x78f8;
+ u8 rtcen = (data & 0x8000) >> 15;
+ u8 almen = (data & 0x0400) >> 10;
+ u8 hmsen = (data & 0x0200) >> 9;
+ u8 schen = (data & 0x0100) >> 8;
+ u8 schsel = (data & 0x0007) >> 0;
+
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::rtc_ctrl_w %04x (unused %04x, rtc enable %d, alarm enable %d, hours/min/sec enable %d, scheduler enable %d, schselect %01x)\n", machine().describe_context(), data, no_use, rtcen, almen, hmsen, schen, schsel);
m_rtc_ctrl = data;
+
+ if (rtcen)
+ {
+ if (schen)
+ {
+ //logerror("scheduler timer enabled\n");
+ attotime period = attotime::from_hz(1 << (4 + schsel));
+ m_scheduler->adjust(period, 0, period);
+ }
+ else
+ {
+ //logerror("scheduler timer disabled\n");
+ m_scheduler->adjust(attotime::never);
+ }
+ }
+ else
+ {
+ //logerror("scheduler timer disabled\n");
+ m_scheduler->adjust(attotime::never);
+ }
+
}
+// P_RTC_INT_Status
+//
+// 15
+// 14
+// 13
+// 12
+
+// 11
+// 10 ALMIEF/C - Alarm Interrupt Flag/Clear
+// 9
+// 8 SCHIF/C - Scheduler Interrupt Flag/Clear
+
+// 7
+// 6
+// 5
+// 4
+
+// 3 HRIF/C - Hour Interrupt Flag/Clear
+// 2 MINIF/C - Minute Interrupt Flag/Clear
+// 1 SECIF/C - Second Interrupt Flag/Clear
+// 0 HSECIF/C - Half Second Interrupt Flag/Clear
+
// value of 7935 is read then written in irq6, nothing happens unless bit 0x0100 was set, which could be some kind of irq source being acked?
u16 sunplus_gcm394_base_device::rtc_int_status_r()
{
@@ -807,11 +917,50 @@ void sunplus_gcm394_base_device::rtc_int_status_w(u16 data)
{
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::rtc_int_status_w %04x\n", machine().describe_context(), data);
m_rtc_int_status &= ~data;
- //checkirq6();
+ update_interrupts(1);
}
-u16 sunplus_gcm394_base_device::rtc_int_ctrl_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::rtc_int_ctrl_r\n", machine().describe_context()); return 0x0000; }
-void sunplus_gcm394_base_device::rtc_int_ctrl_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::rtc_int_ctrl_w %04x\n", machine().describe_context(), data); m_rtc_int_ctrl = data; }
+// P_RTC_INT_Ctrl
+//
+// 15
+// 14
+// 13
+// 12
+
+// 11
+// 10 ALMIEN - Alarm Interrupt Enable (IRQ7)
+// 9
+// 8 SCHIEN - Scheduler Interrupt Enable (IRQ6)
+
+// 7
+// 6
+// 5
+// 4
+
+// 3 HRIEN - Hour Interrupt Enable
+// 2 MINIEN - Minute Interrupt Enable
+// 1 SECIEN - Second Interrupt Enable
+// 0 HSECIEN - Half Second Interrupt Enable
+
+u16 sunplus_gcm394_base_device::rtc_int_ctrl_r()
+{
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::rtc_int_ctrl_r\n", machine().describe_context());
+ return m_rtc_int_ctrl;
+}
+
+void sunplus_gcm394_base_device::rtc_int_ctrl_w(u16 data)
+{
+ u16 no_use = data & 0xfaf0;
+ u8 almien = (data & 0x0400) >> 10;
+ u8 schien = (data & 0x0100) >> 8;
+ u8 hrien = (data & 0x0008) >> 3;
+ u8 minien = (data & 0x0004) >> 2;
+ u8 secien = (data & 0x0002) >> 1;
+ u8 hsecien = (data & 0x0001) >> 0;
+
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::rtc_int_ctrl_w %04x (unused %04x, alarm irq enable %d, scheduler irq enable %d, hour irq enable %d, minute irq enable %d, second irq enable %d, half-second irq enable %d)\n", machine().describe_context(), data, no_use, almien, schien, hrien, minien, secien, hsecien);
+ m_rtc_int_ctrl = data;
+}
// **************************************** 794x SPI *************************************************
@@ -835,13 +984,30 @@ void sunplus_gcm394_base_device::spi_7942_txdata_w(u16 data)
// **************************************** 796x unknown *************************************************
-void sunplus_gcm394_base_device::unkarea_7960_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7960_w %04x\n", machine().describe_context(), data); m_7960 = data; }
+void sunplus_gcm394_base_device::adc_setup_w(u16 data)
+{
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::adc_setup_w %04x\n", machine().describe_context(), data);
+ m_adc_setup = data;
+}
// 7961 and 7962 are used by dressmtv when detecting battery status, adc?
-u16 sunplus_gcm394_base_device::unkarea_7961_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7961_r\n", machine().describe_context()); return 0xffff; /* return m_7961; */ }
-void sunplus_gcm394_base_device::unkarea_7961_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7961_w %04x\n", machine().describe_context(), data); m_7961 = data; }
+u16 sunplus_gcm394_base_device::madc_ctrl_r()
+{
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::madc_ctrl_r\n", machine().describe_context());
+ return 0xffff; /* return m_madc_ctrl; */
+}
-u16 sunplus_gcm394_base_device::unkarea_7962_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7962_r\n", machine().describe_context()); return 0xffff; }
+void sunplus_gcm394_base_device::madc_ctrl_w(u16 data)
+{
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::madc_ctrl_w %04x\n", machine().describe_context(), data);
+ m_madc_ctrl = data;
+}
+
+u16 sunplus_gcm394_base_device::madc_data_r()
+{
+ LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::madc_data_r\n", machine().describe_context());
+ return 0xffff;
+}
// **************************************** fallthrough logger etc. *************************************************
@@ -1011,6 +1177,7 @@ void sunplus_gcm394_base_device::unk_w(offs_t offset, u16 data)
// 7806 - Reset_Flag
// 7807 - Clock_Ctrl
// 7808 - LVR_Ctrl
+// 7809 - P_IO_Map_Ctrl
// 780a - Watchdog_Ctrl
// 780b - Watchdog_Clear
// 780c - WAIT
@@ -1325,23 +1492,25 @@ void sunplus_gcm394_base_device::base_internal_map(address_map &map)
// 78xx region = system regs?
// ######################################################################################################################################################################################
- map(0x007803, 0x007803).rw(FUNC(sunplus_gcm394_base_device::unkarea_7803_r), FUNC(sunplus_gcm394_base_device::unkarea_7803_w));
+ map(0x007803, 0x007803).rw(FUNC(sunplus_gcm394_base_device::sys_ctrl_r), FUNC(sunplus_gcm394_base_device::sys_ctrl_w));
+ map(0x007804, 0x007804).rw(FUNC(sunplus_gcm394_base_device::clk_ctrl0_r), FUNC(sunplus_gcm394_base_device::clk_ctrl0_w));
map(0x007807, 0x007807).w(FUNC(sunplus_gcm394_base_device::clock_ctrl_w));
// 7808
- // 780a
-
+ map(0x00780a, 0x00780a).w(FUNC(sunplus_gcm394_base_device::watchdog_ctrl_w));
+ map(0x00780b, 0x00780b).nopw(); // watchdog clear
map(0x00780c, 0x00780c).w(FUNC(sunplus_gcm394_base_device::waitmode_enter_780c_w));
map(0x00780f, 0x00780f).r(FUNC(sunplus_gcm394_base_device::power_state_r));
map(0x007810, 0x007810).rw(FUNC(sunplus_gcm394_base_device::membankswitch_7810_r), FUNC(sunplus_gcm394_base_device::membankswitch_7810_w)); // 7810 Bank Switch Control Register (P_BankSwitch_Ctrl) (maybe)
- map(0x007819, 0x007819).rw(FUNC(sunplus_gcm394_base_device::cache_ctrl_r), FUNC(sunplus_gcm394_base_device::cache_ctrl_w));
+ map(0x007816, 0x007816).w(FUNC(sunplus_gcm394_base_device::unkarea_7816_w)); // undocumented, check what writes it
- map(0x007816, 0x007816).w(FUNC(sunplus_gcm394_base_device::unkarea_7816_w));
map(0x007817, 0x007817).w(FUNC(sunplus_gcm394_base_device::pllchange_w));
+ map(0x007818, 0x007818).rw(FUNC(sunplus_gcm394_base_device::pllclkwait_r), FUNC(sunplus_gcm394_base_device::pllclkwait_w)); // 7818 - PLLCLKWait
+ map(0x007819, 0x007819).rw(FUNC(sunplus_gcm394_base_device::cache_ctrl_r), FUNC(sunplus_gcm394_base_device::cache_ctrl_w));
// ######################################################################################################################################################################################
// 782x region = memory config / control
@@ -1353,10 +1522,10 @@ void sunplus_gcm394_base_device::base_internal_map(address_map &map)
// 0047 | 0044 7823 Chip Select (CS3) Memory Device Control (P_MC53_Ctrl)
// 0047 | 0044 7824 Chip Select (CS4) Memory Device Control (P_MC54_Ctrl)
- map(0x00782d, 0x00782d).rw(FUNC(sunplus_gcm394_base_device::unkarea_782d_r), FUNC(sunplus_gcm394_base_device::unkarea_782d_w)); // on startup
+ map(0x00782d, 0x00782d).rw(FUNC(sunplus_gcm394_base_device::raw_war_r), FUNC(sunplus_gcm394_base_device::raw_war_w)); // on startup
// 782f
- map(0x007835, 0x007835).w(FUNC(sunplus_gcm394_base_device::unkarea_7835_w));
+ map(0x007835, 0x007835).w(FUNC(sunplus_gcm394_base_device::mcs0_page_w));
// 783a
// 783b
@@ -1364,51 +1533,69 @@ void sunplus_gcm394_base_device::base_internal_map(address_map &map)
// 783d
// 783e
- // 7840 - accessed by code in RAM when changing bank in tkmag220
- // 7841 - ^^
+ // 7840 - accessed by code in RAM when changing bank in tkmag220 (P_Mem_Ctrl on GPL162xxA)
+ // 7841 - ^^ (P_Addr_Ctrl on GPL162xxA)
// ######################################################################################################################################################################################
- // 786x - 787x - IO related?
+ // 786x - 788x - IO related
+ // on GPL162xx the ports each have different capability / features
+ // and there are a few other bits mixed in here
// ######################################################################################################################################################################################
map(0x007860, 0x007860).rw(FUNC(sunplus_gcm394_base_device::ioa_data_r), FUNC(sunplus_gcm394_base_device::ioa_data_w)); // 7860 I/O PortA Data Register
map(0x007861, 0x007861).rw(FUNC(sunplus_gcm394_base_device::ioa_buffer_r), FUNC(sunplus_gcm394_base_device::ioa_buffer_w)); // 7861 I/O PortA Buffer Register
map(0x007862, 0x007862).rw(FUNC(sunplus_gcm394_base_device::ioa_dir_r), FUNC(sunplus_gcm394_base_device::ioa_dir_w)); // 7862 I/O PortA Direction Register
map(0x007863, 0x007863).rw(FUNC(sunplus_gcm394_base_device::ioa_attrib_r), FUNC(sunplus_gcm394_base_device::ioa_attrib_w)); // 7863 I/O PortA Attribute Register
+ // 7864 P_IOA_Drv
map(0x007868, 0x007868).rw(FUNC(sunplus_gcm394_base_device::iob_data_r), FUNC(sunplus_gcm394_base_device::iob_data_w)); // on startup // 7868 I/O PortB Data Register
map(0x007869, 0x007869).rw(FUNC(sunplus_gcm394_base_device::iob_buffer_r), FUNC(sunplus_gcm394_base_device::iob_buffer_w)); // 7869 I/O PortB Buffer Register // jak_s500
map(0x00786a, 0x00786a).rw(FUNC(sunplus_gcm394_base_device::iob_dir_r), FUNC(sunplus_gcm394_base_device::iob_dir_w)); // 786a I/O PortB Direction Register
map(0x00786b, 0x00786b).rw(FUNC(sunplus_gcm394_base_device::iob_attrib_r), FUNC(sunplus_gcm394_base_device::iob_attrib_w)); // 786b I/O PortB Attribute Register
- // 786c I/O PortB Latch / Wakeup
+ // 786c P_IOB_Latch (I/O PortB Latch / Wakeup)
+ // 786d P_IOB_Drv
map(0x007870, 0x007870).rw(FUNC(sunplus_gcm394_base_device::ioc_data_r) ,FUNC(sunplus_gcm394_base_device::ioc_data_w)); // 7870 I/O PortC Data Register
map(0x007871, 0x007871).rw(FUNC(sunplus_gcm394_base_device::ioc_buffer_r), FUNC(sunplus_gcm394_base_device::ioc_buffer_w)); // 7871 I/O PortC Buffer Register
map(0x007872, 0x007872).rw(FUNC(sunplus_gcm394_base_device::ioc_dir_r), FUNC(sunplus_gcm394_base_device::ioc_dir_w)); // 7872 I/O PortC Direction Register
map(0x007873, 0x007873).rw(FUNC(sunplus_gcm394_base_device::ioc_attrib_r), FUNC(sunplus_gcm394_base_device::ioc_attrib_w)); // 7873 I/O PortC Attribute Register
-
- // 7874 (data 0x1249) (bkrankp data 0x36db)
+ // 7874 P_SDRAM_Drv (data 0x1249) (bkrankp data 0x36db)
+ // 7875 P_IOC_Drv
+ // 7876 P_SDRAM_Dly (SDRAM Port Delay Adjustment Register)
+ // 7877 P_IOC_Latch (I/O PortC Latch Register for Wakeup)
map(0x007878, 0x007878).rw(FUNC(sunplus_gcm394_base_device::iod_data_r) ,FUNC(sunplus_gcm394_base_device::iod_data_w)); // 7878 I/O PortD Data Register
map(0x007879, 0x007879).rw(FUNC(sunplus_gcm394_base_device::iod_buffer_r), FUNC(sunplus_gcm394_base_device::iod_buffer_w)); // 7879 I/O PortD Buffer Register
map(0x00787a, 0x00787a).rw(FUNC(sunplus_gcm394_base_device::iod_dir_r), FUNC(sunplus_gcm394_base_device::iod_dir_w)); // 787a I/O PortD Direction Register
map(0x00787b, 0x00787b).rw(FUNC(sunplus_gcm394_base_device::iod_attib_r), FUNC(sunplus_gcm394_base_device::iod_attib_w)); // 787b I/O PortD Attribute Register
map(0x00787c, 0x00787c).rw(FUNC(sunplus_gcm394_base_device::iod_drv_r), FUNC(sunplus_gcm394_base_device::iod_drv_w)); // P_IOD_Drv - I/O PortD Driving Capability Register
- map(0x00787d, 0x00787d).rw(FUNC(sunplus_gcm394_base_device::iod_mux_r), FUNC(sunplus_gcm394_base_device::iod_mux_w)); // 787e (data 0x1249) (bkrankp data 0x36db)
-
- // 7880
+ // 787d - P_IOD_Dly (I/O PortD Delay Adjustment Register)
+ // 787e - P_CS_Drc (CS Port Driving Capability)
+ // 787f - P_CS_Dly (CS Port Delay Adjustment Register)
+ // 7880 - P_IOE_DATA
+ map(0x007881, 0x007881).rw(FUNC(sunplus_gcm394_base_device::ioe_buffer_r), FUNC(sunplus_gcm394_base_device::ioe_buffer_w));
map(0x007882, 0x007882).rw(FUNC(sunplus_gcm394_base_device::ioe_dir_r), FUNC(sunplus_gcm394_base_device::ioe_dir_w));
map(0x007883, 0x007883).rw(FUNC(sunplus_gcm394_base_device::ioe_attrib_r), FUNC(sunplus_gcm394_base_device::ioe_attrib_w));
-
- // 0x7888 (data 0x1249) (bkrankp data 0x36db), written with 7874 / 787c / 787e above
+ // 7884 - P_IOE_Drv
+
+ // 0x7888 - P_MEM_DRV
+ // 0x7889 - P_MEM_DLY0
+ // 0x788a - P_MEM_DLY1
+ // 0x788b - P_MEM_DLY2
+ // 0x788c - P_MEM_DLY3
+ // 0x788d - P_MEM_DLY4
+ // 0x788e - P_MEM_DLY5
+ // 0x788f - P_MEM_DLY6
// ######################################################################################################################################################################################
// 78ax - interrupt controller?
// ######################################################################################################################################################################################
map(0x0078a0, 0x0078a0).rw(FUNC(sunplus_gcm394_base_device::int_status1_r), FUNC(sunplus_gcm394_base_device::int_status1_w));
- map(0x0078a1, 0x0078a1).r(FUNC(sunplus_gcm394_base_device::int_status2_r));
+ map(0x0078a1, 0x0078a1).rw(FUNC(sunplus_gcm394_base_device::int_status2_r), FUNC(sunplus_gcm394_base_device::int_status2_w));
+ // 78a2 (is int_status3 on GPL95xx)
+ map(0x0078a3, 0x0078a3).rw(FUNC(sunplus_gcm394_base_device::int_status3_r), FUNC(sunplus_gcm394_base_device::int_status3_w));
map(0x0078a4, 0x0078a4).w(FUNC(sunplus_gcm394_base_device::int_priority_1_w));
map(0x0078a5, 0x0078a5).w(FUNC(sunplus_gcm394_base_device::int_priority_2_w));
@@ -1420,34 +1607,60 @@ void sunplus_gcm394_base_device::base_internal_map(address_map &map)
// 78bx - timer control?
// ######################################################################################################################################################################################
- map(0x0078b0, 0x0078b0).w(FUNC(sunplus_gcm394_base_device::timebasea_ctrl_w)); // 78b0 TimeBase A Control Register (P_TimeBaseA_Ctrl)
- map(0x0078b1, 0x0078b1).w(FUNC(sunplus_gcm394_base_device::timebaseb_ctrl_w)); // 78b1 TimeBase B Control Register (P_TimeBaseB_Ctrl)
- map(0x0078b2, 0x0078b2).rw(FUNC(sunplus_gcm394_base_device::timebasec_ctrl_r), FUNC(sunplus_gcm394_base_device::timebasec_ctrl_w)); // 78b2 TimeBase C Control Register (P_TimeBaseC_Ctrl)
+ map(0x0078b0, 0x0078b0).rw(m_gpl_timebase, FUNC(gpl_timebase_device::timebasea_ctrl_r), FUNC(gpl_timebase_device::timebasea_ctrl_w)); // 78b0 TimeBase A Control Register (P_TimeBaseA_Ctrl)
+ map(0x0078b1, 0x0078b1).rw(m_gpl_timebase, FUNC(gpl_timebase_device::timebaseb_ctrl_r), FUNC(gpl_timebase_device::timebaseb_ctrl_w)); // 78b1 TimeBase B Control Register (P_TimeBaseB_Ctrl)
+ map(0x0078b2, 0x0078b2).rw(m_gpl_timebase, FUNC(gpl_timebase_device::timebasec_ctrl_r), FUNC(gpl_timebase_device::timebasec_ctrl_w)); // 78b2 TimeBase C Control Register (P_TimeBaseC_Ctrl)
+
+ map(0x0078b8, 0x0078b8).w(m_gpl_timebase, FUNC(gpl_timebase_device::timebase_reset_w)); // 78b8 - TimeBase_Reset
- map(0x0078b8, 0x0078b8).w(FUNC(sunplus_gcm394_base_device::timebase_reset_w)); // 78b8 TimeBase Counter Reset Register (P_TimeBase_Reset)
- map(0x0078c0, 0x0078c0).r(FUNC(sunplus_gcm394_base_device::timera_ctrl_r)); // beijuehh
+ map(0x0078c0, 0x0078c0).rw(FUNC(sunplus_gcm394_base_device::timera_ctrl_r), FUNC(sunplus_gcm394_base_device::timera_ctrl_w)); // beijuehh
+ // 78c1 - TimerA_CCCtrl
+ // 78c2 - TimerA_Preload
+ // 78c3 - TimerA_CCReg
+ // 78c4 - TimerA_UpCount
- map(0x0078c8, 0x0078c8).r(FUNC(sunplus_gcm394_base_device::timerb_ctrl_r)); // dressmtv
+ map(0x0078c8, 0x0078c8).rw(FUNC(sunplus_gcm394_base_device::timerb_ctrl_r), FUNC(sunplus_gcm394_base_device::timerb_ctrl_w)); // dressmtv
+ // 78c9 - TimerB_CCCtrl
+ // 78ca - TimerB_Preload
+ // 78cb - TimerB_CCReg
+ // 78cc - TimerB_UpCount
map(0x0078d0, 0x0078d0).r(FUNC(sunplus_gcm394_base_device::timerc_ctrl_r)); // jak_s500
+ // 78d1 - TimerC_CCCtrl
+ // 78d2 - TimerC_Preload
+ // 78d3 - TimerC_CCReg
+ // 78d4 - TimerC_UpCount
map(0x0078d8, 0x0078d8).r(FUNC(sunplus_gcm394_base_device::timerd_ctrl_r)); // jak_tsh
+ // 78da - TimerD_Preload
+ // 78dc - TimerD_UpCount
+ // 78e0 - TimerE_Ctrl
+ // 78e2 - TimerE_Preload
+ // 78e4 - TimerE_UpCount
+
+ // 78e8 - TimerF_Ctrl
+ // 78ea - TimerF_Preload
+ // 78ec - TimerF_UpCount
// ######################################################################################################################################################################################
- // 78fx - unknown
+ // 78fx - DAC FIFO etc.
// ######################################################################################################################################################################################
map(0x0078f0, 0x0078f0).rw(FUNC(sunplus_gcm394_base_device::cha_ctrl_r), FUNC(sunplus_gcm394_base_device::cha_ctrl_w));
- map(0x0078fb, 0x0078fb).r(FUNC(sunplus_gcm394_base_device::unkarea_78fb_status_r));
+ map(0x0078fb, 0x0078fb).r(FUNC(sunplus_gcm394_base_device::dac_pga_r));
// ######################################################################################################################################################################################
- // 793x - misc?
+ // 790x - UART
// ######################################################################################################################################################################################
- map(0x007904, 0x007904).r(FUNC(sunplus_gcm394_base_device::unkarea_7904_r)); // lazertag after a while
+ map(0x007904, 0x007904).r(FUNC(sunplus_gcm394_base_device::uart_status_r)); // lazertag after a while
+
+ // ######################################################################################################################################################################################
+ // 792x -793x - RTC
+ // ######################################################################################################################################################################################
map(0x007934, 0x007934).rw(FUNC(sunplus_gcm394_base_device::rtc_ctrl_r), FUNC(sunplus_gcm394_base_device::rtc_ctrl_w));
map(0x007935, 0x007935).rw(FUNC(sunplus_gcm394_base_device::rtc_int_status_r), FUNC(sunplus_gcm394_base_device::rtc_int_status_w));
@@ -1465,33 +1678,35 @@ void sunplus_gcm394_base_device::base_internal_map(address_map &map)
map(0x007945, 0x007945).r(FUNC(sunplus_gcm394_base_device::spi_7945_misc_control_reg_r)); // 7945 P_SPI_Misc - SPI Misc Control Register (jak_s500 accelerometer)
// ######################################################################################################################################################################################
- // 796x - unknown
+ // 796x - ADC
// ######################################################################################################################################################################################
- // possible adc?
- map(0x007960, 0x007960).w(FUNC(sunplus_gcm394_base_device::unkarea_7960_w));
- map(0x007961, 0x007961).rw(FUNC(sunplus_gcm394_base_device::unkarea_7961_r), FUNC(sunplus_gcm394_base_device::unkarea_7961_w));
- map(0x007962, 0x007962).r(FUNC(sunplus_gcm394_base_device::unkarea_7962_r));
+ map(0x007960, 0x007960).w(FUNC(sunplus_gcm394_base_device::adc_setup_w));
+ map(0x007961, 0x007961).rw(FUNC(sunplus_gcm394_base_device::madc_ctrl_r), FUNC(sunplus_gcm394_base_device::madc_ctrl_w));
+ map(0x007962, 0x007962).r(FUNC(sunplus_gcm394_base_device::madc_data_r));
// ######################################################################################################################################################################################
- // 7axx region = system (including dma)
+ // 7axx region = usb?
// ######################################################################################################################################################################################
- // USB?
- map(0x007a35, 0x007a35).r(FUNC(sunplus_gcm394_base_device::system_7a35_r)); // wlsair60
- map(0x007a37, 0x007a37).r(FUNC(sunplus_gcm394_base_device::system_7a37_r)); // wlsair60
- map(0x007a39, 0x007a39).r(FUNC(sunplus_gcm394_base_device::system_7a39_r)); // wlsair60
- map(0x007a3a, 0x007a3a).r(FUNC(sunplus_gcm394_base_device::system_7a3a_r)); // ?
- map(0x007a46, 0x007a46).r(FUNC(sunplus_gcm394_base_device::system_7a46_r)); // wlsair60
- map(0x007a54, 0x007a54).r(FUNC(sunplus_gcm394_base_device::system_7a54_r)); // wlsair60
+ map(0x007a35, 0x007a35).r(FUNC(sunplus_gcm394_base_device::usb_7a35_r)); // wlsair60
+ map(0x007a37, 0x007a37).r(FUNC(sunplus_gcm394_base_device::usb_7a37_r)); // wlsair60
+ map(0x007a39, 0x007a39).r(FUNC(sunplus_gcm394_base_device::usb_7a39_r)); // wlsair60
+ map(0x007a3a, 0x007a3a).r(FUNC(sunplus_gcm394_base_device::usb_7a3a_r)); // ?
+ map(0x007a46, 0x007a46).r(FUNC(sunplus_gcm394_base_device::usb_7a46_r)); // wlsair60
+ map(0x007a54, 0x007a54).r(FUNC(sunplus_gcm394_base_device::usb_7a54_r)); // wlsair60
+
+ // ######################################################################################################################################################################################
+ // 7a80 - 7abf = dma controller
+ // ######################################################################################################################################################################################
- map(0x007a80, 0x007a87).rw(FUNC(sunplus_gcm394_base_device::system_dma_params_channel0_r), FUNC(sunplus_gcm394_base_device::system_dma_params_channel0_w));
- map(0x007a88, 0x007a8f).rw(FUNC(sunplus_gcm394_base_device::system_dma_params_channel1_r), FUNC(sunplus_gcm394_base_device::system_dma_params_channel1_w)); // jak_tsm writes here
- map(0x007a90, 0x007a97).rw(FUNC(sunplus_gcm394_base_device::system_dma_params_channel2_r), FUNC(sunplus_gcm394_base_device::system_dma_params_channel2_w)); // bkrankp writes here (is this on all types or just SPI?)
- map(0x007a98, 0x007a9f).rw(FUNC(sunplus_gcm394_base_device::system_dma_params_channel3_r), FUNC(sunplus_gcm394_base_device::system_dma_params_channel3_w)); // not seen, but probably
+ map(0x007a80, 0x007a87).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_params_channel0_r), FUNC(gpl_dma_device::system_dma_params_channel0_w));
+ map(0x007a88, 0x007a8f).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_params_channel1_r), FUNC(gpl_dma_device::system_dma_params_channel1_w)); // jak_tsm writes here
+ map(0x007a90, 0x007a97).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_params_channel2_r), FUNC(gpl_dma_device::system_dma_params_channel2_w)); // bkrankp writes here (is this on all types or just SPI?)
+ map(0x007a98, 0x007a9f).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_params_channel3_r), FUNC(gpl_dma_device::system_dma_params_channel3_w)); // not seen, but probably
- map(0x007abe, 0x007abe).rw(FUNC(sunplus_gcm394_base_device::system_dma_memtype_r), FUNC(sunplus_gcm394_base_device::system_dma_memtype_w)); // 7abe - written with DMA stuff (source type for each channel so that device handles timings properly?)
- map(0x007abf, 0x007abf).rw(FUNC(sunplus_gcm394_base_device::system_dma_status_r), FUNC(sunplus_gcm394_base_device::system_dma_7abf_unk_w));
+ map(0x007abe, 0x007abe).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_memtype_r), FUNC(gpl_dma_device::system_dma_memtype_w)); // 7abe - written with DMA stuff (source type for each channel so that device handles timings properly?)
+ map(0x007abf, 0x007abf).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_status_r), FUNC(gpl_dma_device::system_dma_status_w));
// ######################################################################################################################################################################################
// 7bxx-7fxx = audio
@@ -1580,10 +1795,6 @@ void sunplus_gcm394_base_device::device_start()
m_cs_callback.resolve();
- m_unk_timer = timer_alloc(FUNC(sunplus_gcm394_base_device::unknown_tick), this);
- m_unk_timer->adjust(attotime::never);
-
- save_item(NAME(m_dma_params));
save_item(NAME(m_sys_ctrl));
save_item(NAME(m_clock_ctrl));
save_item(NAME(m_membankswitch_7810));
@@ -1610,38 +1821,24 @@ void sunplus_gcm394_base_device::device_start()
save_item(NAME(m_int_priority_2));
save_item(NAME(m_int_priority_3));
save_item(NAME(m_misc_int_ctrl));
- save_item(NAME(m_timebasea_ctrl));
- save_item(NAME(m_timebaseb_ctrl));
- save_item(NAME(m_timebasec_ctrl));
- save_item(NAME(m_timebase_reset));
save_item(NAME(m_cha_ctrl));
- save_item(NAME(m_78fb));
+ save_item(NAME(m_dac_pga));
save_item(NAME(m_rtc_ctrl));
save_item(NAME(m_rtc_int_status));
save_item(NAME(m_rtc_int_ctrl));
- save_item(NAME(m_7960));
- save_item(NAME(m_7961));
- save_item(NAME(m_system_dma_memtype));
+ save_item(NAME(m_adc_setup));
+ save_item(NAME(m_madc_ctrl));
save_item(NAME(m_csbase));
save_item(NAME(m_romtype));
+ save_item(NAME(m_timera_ctrl));
+ save_item(NAME(m_timerb_ctrl));
}
void sunplus_gcm394_base_device::device_reset()
{
unsp_20_device::device_reset();
- for (int j = 0; j < 3; j++)
- {
- for (int i = 0; i < 7; i++)
- {
- m_dma_params[i][j] = 0x0000;
- }
- m_dma_latched[j] = false;
- }
-
- // 78xx unknown
-
- m_78fb = 0x0000;
+ m_dac_pga = 0x0000;
m_782d = 0x0000;
m_clock_ctrl = 0x0000;
@@ -1685,25 +1882,17 @@ void sunplus_gcm394_base_device::device_reset()
m_misc_int_ctrl = 0x0000;
- m_timebasea_ctrl = 0x0000;
- m_timebaseb_ctrl = 0x0000;
- m_timebasec_ctrl = 0x0000;
-
- m_timebase_reset = 0x0000;
m_cha_ctrl = 0x0000;
- // 79xx unknown
-
m_rtc_ctrl = 0x0000;
m_rtc_int_status = 0x0000;
m_rtc_int_ctrl = 0x0000;
- m_7960 = 0x0000;
- m_7961 = 0x0000;
-
- m_system_dma_memtype = 0x0000;
+ m_adc_setup = 0x0000;
+ m_madc_ctrl = 0x0000;
- m_unk_timer->adjust(attotime::from_hz(60), 0, attotime::from_hz(60));
+ m_timera_ctrl = 0x0000;
+ m_timerb_ctrl = 0x0000;
m_spg_video->reset();
}
@@ -1713,8 +1902,8 @@ IRQ_CALLBACK_MEMBER(sunplus_gcm394_base_device::irq_vector_cb)
{
//logerror("irq_vector_cb %d\n", irqline);
- if (irqline == UNSP_IRQ6_LINE)
- set_state_unsynced(UNSP_IRQ6_LINE, CLEAR_LINE);
+ //if (irqline == UNSP_IRQ6_LINE)
+ // set_state_unsynced(UNSP_IRQ6_LINE, CLEAR_LINE);
if (irqline == UNSP_IRQ4_LINE)
set_state_unsynced(UNSP_IRQ4_LINE, CLEAR_LINE);
@@ -1723,16 +1912,6 @@ IRQ_CALLBACK_MEMBER(sunplus_gcm394_base_device::irq_vector_cb)
}
-void sunplus_gcm394_base_device::checkirq6()
-{
-/*
- if (m_rtc_int_status & 0x0100)
- set_state_unsynced(UNSP_IRQ6_LINE, ASSERT_LINE);
- else
- set_state_unsynced(UNSP_IRQ6_LINE, CLEAR_LINE);
-*/
-}
-
/* the IRQ6 interrupt on Wrlshunt
reads 78a1, checks bit 0400
if it IS set, just increases value in RAM at 1a2e (no ack)
@@ -1757,20 +1936,6 @@ void sunplus_gcm394_base_device::checkirq6()
*/
-
-TIMER_CALLBACK_MEMBER(sunplus_gcm394_base_device::unknown_tick)
-{
- m_rtc_int_status |= 0x0100;
-
- if (m_alt_periodic_irq)
- set_state_unsynced(UNSP_IRQ4_LINE, ASSERT_LINE);
- else
- set_state_unsynced(UNSP_IRQ6_LINE, ASSERT_LINE);
-
- // checkirq6();
-}
-
-
void sunplus_gcm394_base_device::audioirq_w(int state)
{
//set_state_unsynced(UNSP_IRQ5_LINE, state);
@@ -1812,21 +1977,40 @@ void sunplus_gcm394_base_device::write_space(offs_t offset, u16 data)
}
}
-
+void sunplus_gcm394_base_device::dma_complete(int state)
+{
+ m_dma_complete_cb(state);
+}
void sunplus_gcm394_base_device::device_add_mconfig(machine_config &config)
{
SUNPLUS_GCM394_AUDIO(config, m_spg_audio, DERIVED_CLOCK(1, 1));
m_spg_audio->write_irq_callback().set(FUNC(sunplus_gcm394_base_device::audioirq_w));
m_spg_audio->space_read_callback().set(FUNC(sunplus_gcm394_base_device::read_space));
-
m_spg_audio->add_route(0, *this, 1.0, 0);
m_spg_audio->add_route(1, *this, 1.0, 1);
+ GPL_DMA(config, m_gpl_dma, 0);
+ m_gpl_dma->space_read_callback().set(FUNC(sunplus_gcm394_base_device::read_space));
+ m_gpl_dma->space_write_callback().set(FUNC(sunplus_gcm394_base_device::write_space));
+ m_gpl_dma->dma_complete_callback().set(FUNC(sunplus_gcm394_base_device::dma_complete));
+
+ GPL_TIMEBASE(config, m_gpl_timebase, 0);
+ m_gpl_timebase->updateirqs_callback().set(FUNC(sunplus_gcm394_base_device::update_interrupts));
+
GCM394_VIDEO(config, m_spg_video, DERIVED_CLOCK(1, 1), DEVICE_SELF, m_screen);
m_spg_video->write_video_irq_callback().set(FUNC(sunplus_gcm394_base_device::videoirq_w));
m_spg_video->space_read_callback().set(FUNC(sunplus_gcm394_base_device::read_space));
m_spg_video->set_video_space(DEVICE_SELF, AS_PROGRAM);
+
+ TIMER(config, "timer_a").configure_generic(FUNC(sunplus_gcm394_base_device::timer_a_cb));
+ TIMER(config, "timer_b").configure_generic(FUNC(sunplus_gcm394_base_device::timer_b_cb));
+ TIMER(config, "timer_c").configure_generic(FUNC(sunplus_gcm394_base_device::timer_c_cb));
+ TIMER(config, "timer_d").configure_generic(FUNC(sunplus_gcm394_base_device::timer_d_cb));
+ TIMER(config, "timer_e").configure_generic(FUNC(sunplus_gcm394_base_device::timer_e_cb));
+ TIMER(config, "timer_f").configure_generic(FUNC(sunplus_gcm394_base_device::timer_f_cb));
+
+ TIMER(config, "scheduler").configure_generic(FUNC(sunplus_gcm394_base_device::scheduler_cb));
}
diff --git a/src/devices/machine/generalplus_gpl162xx_soc.h b/src/devices/machine/generalplus_gpl162xx_soc.h
index ca779e9412e..eed874be1c4 100644
--- a/src/devices/machine/generalplus_gpl162xx_soc.h
+++ b/src/devices/machine/generalplus_gpl162xx_soc.h
@@ -12,8 +12,13 @@
#pragma once
#include "cpu/unsp/unsp.h"
+#include "machine/timer.h"
+
#include "screen.h"
#include "emupal.h"
+
+#include "generalplus_gpl_dma.h"
+#include "generalplus_gpl_timebase.h"
#include "generalplus_gpl162xx_soc_video.h"
#include "spg2xx_audio.h"
@@ -43,6 +48,9 @@ public:
auto nand_read_callback() { return m_nand_read_cb.bind(); }
+ // hack for beijuehh / bornkidh
+ void disable_timebase_interrupts() { m_disable_timebase_interrupts = true; }
+
template <typename... T> void set_cs_config_callback(T &&... args) { m_cs_callback.set(std::forward<T>(args)...); }
template <typename T> void set_cs_space(T &&tag, int no)
{
@@ -55,7 +63,6 @@ public:
void vblank(int state) { m_spg_video->vblank(state); }
void set_bootmode(int mode) { m_boot_mode = mode; }
- void set_alt_periodic_irq(bool alt) { m_alt_periodic_irq = alt; }
IRQ_CALLBACK_MEMBER(irq_vector_cb);
void default_cs_callback(u16 cs0, u16 cs1, u16 cs2, u16 cs3, u16 cs4 );
@@ -98,9 +105,6 @@ protected:
optional_address_space m_cs_space;
u32 m_csbase;
- u16 m_dma_params[8][4];
- bool m_dma_latched[4];
-
// unk 78xx
u16 m_sys_ctrl;
@@ -144,25 +148,21 @@ protected:
u16 m_misc_int_ctrl;
- u16 m_timebasea_ctrl;
- u16 m_timebaseb_ctrl;
- u16 m_timebasec_ctrl;
-
- u16 m_timebase_reset;
-
u16 m_cha_ctrl;
- u16 m_78fb;
+ u16 m_dac_pga;
// unk 79xx
u16 m_rtc_ctrl;
u16 m_rtc_int_status;
u16 m_rtc_int_ctrl;
- u16 m_7960;
- u16 m_7961;
+ u16 m_adc_setup;
+ u16 m_madc_ctrl;
+
+ u16 m_timera_ctrl;
+ u16 m_timerb_ctrl;
- u16 m_system_dma_memtype;
u16 internalrom_lower32_r(offs_t offset);
@@ -177,34 +177,29 @@ protected:
devcb_write16 m_space_write_cb;
devcb_write_line m_dma_complete_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(scheduler_cb);
+
u16 unk_r(offs_t offset);
void unk_w(offs_t offset, u16 data);
- void write_dma_params(int channel, int offset, u16 data);
- u16 read_dma_params(int channel, int offset);
- void trigger_systemm_dma(int channel);
-
- u16 system_dma_params_channel0_r(offs_t offset);
- void system_dma_params_channel0_w(offs_t offset, u16 data);
- u16 system_dma_params_channel1_r(offs_t offset);
- void system_dma_params_channel1_w(offs_t offset, u16 data);
- u16 system_dma_params_channel2_r(offs_t offset);
- void system_dma_params_channel2_w(offs_t offset, u16 data);
- u16 system_dma_params_channel3_r(offs_t offset);
- void system_dma_params_channel3_w(offs_t offset, u16 data);
- u16 system_dma_status_r();
- void system_dma_7abf_unk_w(u16 data);
- u16 system_dma_memtype_r();
- void system_dma_memtype_w(u16 data);
u16 power_state_r();
- u16 unkarea_78fb_status_r();
+ u16 dac_pga_r();
- u16 unkarea_7803_r();
- void unkarea_7803_w(u16 data);
+ u16 sys_ctrl_r();
+ void sys_ctrl_w(u16 data);
void clock_ctrl_w(u16 data);
+ u16 clk_ctrl0_r();
+ void clk_ctrl0_w(u16 data);
+
void waitmode_enter_780c_w(u16 data);
u16 membankswitch_7810_r();
@@ -213,15 +208,20 @@ protected:
void unkarea_7816_w(u16 data);
void pllchange_w(u16 data);
+ u16 pllclkwait_r();
+ void pllclkwait_w(u16 data);
+
+ void watchdog_ctrl_w(u16 data);
+
u16 cache_ctrl_r();
void cache_ctrl_w(u16 data);
void chipselect_csx_memory_device_control_w(offs_t offset, u16 data);
- void unkarea_7835_w(u16 data);
+ void mcs0_page_w(u16 data);
- u16 unkarea_782d_r();
- void unkarea_782d_w(u16 data);
+ u16 raw_war_r();
+ void raw_war_w(u16 data);
// Port A
u16 ioa_data_r();
@@ -267,16 +267,20 @@ protected:
u16 iod_mux_r();
void iod_mux_w(u16 data);
-
+ u16 ioe_buffer_r();
+ void ioe_buffer_w(u16 data);
u16 ioe_dir_r();
void ioe_dir_w(u16 data);
u16 ioe_attrib_r();
void ioe_attrib_w(u16 data);
void int_status1_w(u16 data);
+ void int_status2_w(u16 data);
+ void int_status3_w(u16 data);
u16 int_status1_r();
u16 int_status2_r();
+ u16 int_status3_r();
void int_priority_1_w(u16 data);
void int_priority_2_w(u16 data);
@@ -284,16 +288,13 @@ protected:
void mint_ctrl_w(u16 data);
- void timebasea_ctrl_w(u16 data);
- void timebaseb_ctrl_w(u16 data);
-
- u16 timebasec_ctrl_r();
- void timebasec_ctrl_w(u16 data);
-
- void timebase_reset_w(u16 data);
-
+ virtual void update_interrupts(int state);
+
u16 timera_ctrl_r();
+ void timera_ctrl_w(u16 data);
+
u16 timerb_ctrl_r();
+ void timerb_ctrl_w(u16 data);
u16 timerc_ctrl_r();
u16 timerd_ctrl_r();
@@ -301,7 +302,7 @@ protected:
u16 cha_ctrl_r();
void cha_ctrl_w(u16 data);
- u16 unkarea_7904_r();
+ u16 uart_status_r();
u16 rtc_ctrl_r();
void rtc_ctrl_w(u16 data);
@@ -316,35 +317,45 @@ protected:
u16 spi_7945_misc_control_reg_r();
void spi_7942_txdata_w(u16 data);
- void unkarea_7960_w(u16 data);
- u16 unkarea_7961_r();
- void unkarea_7961_w(u16 data);
- u16 unkarea_7962_r();
+ void adc_setup_w(u16 data);
+ u16 madc_ctrl_r();
+ void madc_ctrl_w(u16 data);
+ u16 madc_data_r();
void videoirq_w(int state);
void audioirq_w(int state);
- u16 system_7a35_r();
- u16 system_7a37_r();
- u16 system_7a39_r();
- u16 system_7a3a_r();
- u16 system_7a46_r();
- u16 system_7a54_r();
-
- void checkirq6();
-
- emu_timer *m_unk_timer;
-
- TIMER_CALLBACK_MEMBER(unknown_tick);
+ u16 usb_7a35_r();
+ u16 usb_7a37_r();
+ u16 usb_7a39_r();
+ u16 usb_7a3a_r();
+ u16 usb_7a46_r();
+ u16 usb_7a54_r();
inline u16 read_space(offs_t offset);
inline void write_space(offs_t offset, u16 data);
- bool m_alt_periodic_irq; // might be multiple timers, might be a register to configure, currently a config option.
-
// config registers (external pins)
int m_boot_mode; // 2 pins determine boot mode, likely only read at power-on
sunplus_gcm394_cs_callback_device m_cs_callback;
+
+ required_device<timer_device> m_timer_a;
+ required_device<timer_device> m_timer_b;
+ required_device<timer_device> m_timer_c;
+ required_device<timer_device> m_timer_d;
+ required_device<timer_device> m_timer_e;
+ required_device<timer_device> m_timer_f;
+ required_device<timer_device> m_scheduler;
+
+ required_device<gpl_dma_device> m_gpl_dma;
+ required_device<gpl_timebase_device> m_gpl_timebase;
+
+ // config/hacks
+ bool m_disable_timebase_interrupts;
+
+private:
+ void dma_complete(int state);
+
};
diff --git a/src/devices/machine/generalplus_gpl162xx_soc_video.cpp b/src/devices/machine/generalplus_gpl162xx_soc_video.cpp
index faf840213d7..cf5b56ce346 100644
--- a/src/devices/machine/generalplus_gpl162xx_soc_video.cpp
+++ b/src/devices/machine/generalplus_gpl162xx_soc_video.cpp
@@ -312,6 +312,11 @@ void gcm394_base_video_device::device_reset()
m_sprite_7022_gfxbase_lsb = 0;
m_sprite_702d_gfxbase_msb = 0;
+
+ m_page0_addr_lsb = 0;
+ m_page0_addr_msb = 0;
+ m_page1_addr_lsb = 0;
+ m_page1_addr_msb = 0;
m_page2_addr_lsb = 0;
m_page2_addr_msb = 0;
m_page3_addr_lsb = 0;
@@ -327,7 +332,10 @@ u32 gcm394_base_video_device::screen_update(screen_device &screen, bitmap_rgb32
// The 'bitmap test mode' in jak_car2 requires this to be black instead.
// jak_s500 briely sets pen 0 of the layer to magenta, but then ends up erasing it
+ bool readfromcsspace = true;
+ if (!m_cs_space)
+ readfromcsspace = false;
if (0)
{
@@ -398,12 +406,12 @@ u32 gcm394_base_video_device::screen_update(screen_device &screen, bitmap_rgb32
for (int i = 0; i < 4; i++)
{
- m_renderer->draw_page(true, m_703a_palettebank, cliprect, scanline, i, m_page0_addr_msb, m_page0_addr_lsb, m_tmap0_scroll, m_tmap0_regs, mem, m_paletteram, m_rowscroll, 0);
- m_renderer->draw_page(true, m_703a_palettebank, cliprect, scanline, i, m_page1_addr_msb, m_page1_addr_lsb, m_tmap1_scroll, m_tmap1_regs, mem, m_paletteram, m_rowscroll, 1);
- m_renderer->draw_page(true, m_703a_palettebank, cliprect, scanline, i, m_page2_addr_msb, m_page2_addr_lsb, m_tmap2_scroll, m_tmap2_regs, mem, m_paletteram, m_rowscroll, 2);
- m_renderer->draw_page(true, m_703a_palettebank, cliprect, scanline, i, m_page3_addr_msb, m_page3_addr_lsb, m_tmap3_scroll, m_tmap3_regs, mem, m_paletteram, m_rowscroll, 3);
+ m_renderer->draw_page(readfromcsspace, m_703a_palettebank, cliprect, scanline, i, m_page0_addr_msb, m_page0_addr_lsb, m_tmap0_scroll, m_tmap0_regs, mem, m_paletteram, m_rowscroll, 0);
+ m_renderer->draw_page(readfromcsspace, m_703a_palettebank, cliprect, scanline, i, m_page1_addr_msb, m_page1_addr_lsb, m_tmap1_scroll, m_tmap1_regs, mem, m_paletteram, m_rowscroll, 1);
+ m_renderer->draw_page(readfromcsspace, m_703a_palettebank, cliprect, scanline, i, m_page2_addr_msb, m_page2_addr_lsb, m_tmap2_scroll, m_tmap2_regs, mem, m_paletteram, m_rowscroll, 2);
+ m_renderer->draw_page(readfromcsspace, m_703a_palettebank, cliprect, scanline, i, m_page3_addr_msb, m_page3_addr_lsb, m_tmap3_scroll, m_tmap3_regs, mem, m_paletteram, m_rowscroll, 3);
- m_renderer->draw_sprites(true, m_use_legacy_mode ? 2 : 1, m_703a_palettebank, highres, cliprect, scanline, i, sprites_addr, mem, m_paletteram, m_spriteram);
+ m_renderer->draw_sprites(readfromcsspace, m_use_legacy_mode ? 2 : 1, m_703a_palettebank, highres, cliprect, scanline, i, sprites_addr, mem, m_paletteram, m_spriteram);
}
m_renderer->apply_saturation_and_fade(bitmap, cliprect, scanline);
diff --git a/src/devices/machine/generalplus_gpl951xx_rtc.cpp b/src/devices/machine/generalplus_gpl951xx_rtc.cpp
new file mode 100644
index 00000000000..da303406d4a
--- /dev/null
+++ b/src/devices/machine/generalplus_gpl951xx_rtc.cpp
@@ -0,0 +1,151 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+#include "emu.h"
+#include "generalplus_gpl951xx_rtc.h"
+
+#define LOG_RTC (1U << 1)
+
+#define VERBOSE (0)
+
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(GPL951XX_RTC, gpl951xx_rtc_device, "gpl951xx_rtc", "GPL951XX Real Time Clock")
+
+gpl951xx_rtc_device::gpl951xx_rtc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, GPL951XX_RTC, tag, owner, clock),
+ device_memory_interface(mconfig, *this),
+ m_space_config("rtc", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(gpl951xx_rtc_device::rtc_regs), this))
+{
+}
+
+device_memory_interface::space_config_vector gpl951xx_rtc_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(0, &m_space_config)
+ };
+}
+
+inline uint8_t gpl951xx_rtc_device::readbyte(offs_t address)
+{
+ return space().read_byte(address);
+}
+
+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));
+ save_item(NAME(m_read_dat));
+ save_item(NAME(m_write_dat));
+
+ save_item(NAME(m_reg40));
+ save_item(NAME(m_reg50));
+}
+
+void gpl951xx_rtc_device::device_reset()
+{
+ m_rtc_addr = 0;
+ m_read_dat = 0;
+ m_write_dat = 0;
+
+ m_reg40 = 0;
+ m_reg50 = 0;
+}
+
+u8 gpl951xx_rtc_device::reg00_r()
+{
+ LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg00_r\n", machine().describe_context());
+ return 0x00;
+}
+
+u8 gpl951xx_rtc_device::reg01_r()
+{
+ LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg01_r\n", machine().describe_context());
+ return 0x01;
+}
+
+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;
+}
+
+u8 gpl951xx_rtc_device::reg50_r()
+{
+ LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg50_r\n", machine().describe_context());
+ return m_reg50;
+}
+
+void gpl951xx_rtc_device::reg50_w(u8 data)
+{
+ LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg50_w %02x\n", machine().describe_context(), data);
+ m_reg50 = data;
+}
+
+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(0x50, 0x50).rw(FUNC(gpl951xx_rtc_device::reg50_r), FUNC(gpl951xx_rtc_device::reg50_w));
+ // 0x80 - 0x8f reserved
+ map(0x90, 0xff).ram();
+ }
+}
+
+
+u16 gpl951xx_rtc_device::rtc_readdata_r()
+{
+ LOGMASKED(LOG_RTC, "%s: rtc_readdata_r\n", machine().describe_context());
+ return m_read_dat;
+}
+
+// 15-1 unused
+// 0 RDY
+u16 gpl951xx_rtc_device::rtc_ready_r()
+{
+ LOGMASKED(LOG_RTC, "%s: rtc_ready_r\n", machine().describe_context());
+ return 0x0001;
+}
+
+
+// 15-1 unused
+// 0 SIEN (Serial interface enabled)
+void gpl951xx_rtc_device::rtc_ctrl_w(u16 data)
+{
+ LOGMASKED(LOG_RTC, "%s: rtc_ctrl_w %04x\n", machine().describe_context(), data);
+}
+
+void gpl951xx_rtc_device::rtc_addr_w(u16 data)
+{
+ LOGMASKED(LOG_RTC, "%s: rtc_addr_w %04x\n", machine().describe_context(), data);
+ m_rtc_addr = data & 0xff;
+}
+
+void gpl951xx_rtc_device::rtc_writedata_w(u16 data)
+{
+ LOGMASKED(LOG_RTC, "%s: rtc_writedata_w %04x\n", machine().describe_context(), data);
+ m_write_dat = data;
+}
+
+// 15-2 unused
+// 1 Read Request
+// 0 Write Request
+void gpl951xx_rtc_device::rtc_request_w(u16 data)
+{
+ LOGMASKED(LOG_RTC, "%s: rtc_request_w %04x\n", machine().describe_context(), data);
+ if (data & 1)
+ writebyte(m_rtc_addr, m_write_dat);
+ if (data & 2)
+ m_read_dat = readbyte(m_rtc_addr);
+}
diff --git a/src/devices/machine/generalplus_gpl951xx_rtc.h b/src/devices/machine/generalplus_gpl951xx_rtc.h
new file mode 100644
index 00000000000..11d011fe21b
--- /dev/null
+++ b/src/devices/machine/generalplus_gpl951xx_rtc.h
@@ -0,0 +1,54 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+#ifndef MAME_MACHINE_GENERALPLUS_GPL951XX_RTC_H
+#define MAME_MACHINE_GENERALPLUS_GPL951XX_RTC_H
+
+#pragma once
+
+class gpl951xx_rtc_device : public device_t,
+ public device_memory_interface
+{
+public:
+
+ gpl951xx_rtc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void rtc_regs(address_map &map) ATTR_COLD;
+
+ u16 rtc_readdata_r();
+ u16 rtc_ready_r();
+ void rtc_ctrl_w(u16 data);
+ void rtc_addr_w(u16 data);
+ void rtc_writedata_w(u16 data);
+ void rtc_request_w(u16 data);
+
+protected:
+ virtual void device_validity_check(validity_checker &valid) const override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual space_config_vector memory_space_config() const override;
+
+private:
+ const address_space_config m_space_config;
+
+ inline uint8_t readbyte(offs_t address);
+ inline void writebyte(offs_t address, uint8_t data);
+
+ u8 reg00_r();
+ u8 reg01_r();
+
+ void reg40_w(u8 data);
+
+ u8 reg50_r();
+ void reg50_w(u8 data);
+
+ u8 m_rtc_addr;
+ u8 m_read_dat;
+ u8 m_write_dat;
+
+ u8 m_reg40;
+ u8 m_reg50;
+};
+
+DECLARE_DEVICE_TYPE(GPL951XX_RTC, gpl951xx_rtc_device)
+
+#endif // MAME_MACHINE_GENERALPLUS_GPL951XX_RTC_H
diff --git a/src/devices/machine/generalplus_gpl951xx_soc.cpp b/src/devices/machine/generalplus_gpl951xx_soc.cpp
index 6d6eb8a4f79..3c961475fa0 100644
--- a/src/devices/machine/generalplus_gpl951xx_soc.cpp
+++ b/src/devices/machine/generalplus_gpl951xx_soc.cpp
@@ -5,8 +5,10 @@
#include "generalplus_gpl951xx_soc.h"
#define LOG_SPIFC (1U << 1)
+#define LOG_TFT (1U << 2)
+#define LOG_OTHER (1U << 3)
-#define VERBOSE (LOG_SPIFC)
+#define VERBOSE (LOG_SPIFC | LOG_TFT | LOG_OTHER)
#include "logmacro.h"
@@ -309,8 +311,24 @@ void generalplus_gpl951xx_device::spifc_ctrl2_w(u16 data)
m_spifc_ctrl2 = data;
}
+u16 generalplus_gpl951xx_device::spi_improve_r()
+{
+ LOGMASKED(LOG_SPIFC, "%s: spi_improve_r\n", machine().describe_context());
+ return 0x0000;
+}
+
+void generalplus_gpl951xx_device::spi_improve_w(u16 data)
+{
+ LOGMASKED(LOG_SPIFC, "%s: spi_improve_w %04x\n", machine().describe_context(), data);
+}
+
// Other bits
+void generalplus_gpl951xx_device::pm_ctrl_w(u16 data)
+{
+ LOGMASKED(LOG_SPIFC, "%s: pm_ctrl_w %04x\n", machine().describe_context(), data);
+}
+
u16 generalplus_gpl951xx_device::pllsel_r()
{
logerror("%s: pllsel_r\n", machine().describe_context());
@@ -324,19 +342,6 @@ void generalplus_gpl951xx_device::pllsel_w(u16 data)
m_pllchange = data;
}
-
-u16 generalplus_gpl951xx_device::rtc_readdata_r()
-{
- return 0xffff; // hangs if returning 0
-}
-
-u16 generalplus_gpl951xx_device::rtc_ready_r()
-{
- // status bits?
- return machine().rand();
-}
-
-
u16 generalplus_gpl951xx_device::byte_swap_r()
{
return m_byteswap;
@@ -351,12 +356,13 @@ void generalplus_gpl951xx_device::byte_swap_w(u16 data)
void generalplus_gpl951xx_device::device_start()
{
- sunplus_gcm394_base_device::device_start();
+ unsp_20_device::device_start();
+
save_item(NAME(m_byteswap));
- save_item(NAME(m_gpl951xx_timerg_ctrl));
- save_item(NAME(m_gpl951xx_timerg_preload));
- save_item(NAME(m_gpl951xx_timerh_ctrl));
- save_item(NAME(m_gpl951xx_timerh_preload));
+ 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_spifc_ctrl));
save_item(NAME(m_spifc_ctrl2));
save_item(NAME(m_spifc_addr));
@@ -367,18 +373,32 @@ void generalplus_gpl951xx_device::device_start()
save_item(NAME(m_spifc_timing));
save_item(NAME(m_bytes_in_spifc_rx_fifo));
save_item(NAME(m_spi_bank));
+ save_item(NAME(m_memmode_wcmd));
save_item(NAME(m_spifc_rx_fifo));
save_item(NAME(m_spifc_rx_read_latch));
+ save_item(NAME(m_io_dir));
+ save_item(NAME(m_io_attrib));
+ save_item(NAME(m_sys_ctrl));
+ save_item(NAME(m_clock_ctrl));
+ save_item(NAME(m_cache_ctrl));
+ save_item(NAME(m_int_priority_1));
+ save_item(NAME(m_int_priority_2));
+ save_item(NAME(m_int_priority_3));
+ save_item(NAME(m_misc_int_ctrl));
+ save_item(NAME(m_cha_ctrl));
+ save_item(NAME(m_pllchange));
}
void generalplus_gpl951xx_device::device_reset()
{
- sunplus_gcm394_base_device::device_reset();
+ unsp_20_device::device_reset();
+ m_spg_video->reset();
+
m_byteswap = 0;
- m_gpl951xx_timerg_ctrl = 0;
- m_gpl951xx_timerg_preload = 0;
- m_gpl951xx_timerh_ctrl = 0;
- m_gpl951xx_timerh_preload = 0;
+ m_timerg_ctrl = 0;
+ m_timerg_preload = 0;
+ m_timerh_ctrl = 0;
+ m_timerh_preload = 0;
m_spifc_ctrl = 0;
m_spifc_ctrl2 = 0;
m_spifc_addr = 0;
@@ -389,8 +409,23 @@ void generalplus_gpl951xx_device::device_reset()
m_spifc_timing = 0;
m_bytes_in_spifc_rx_fifo = 0;
m_spifc_rx_read_latch = 0;
-
+ m_memmode_wcmd = 0;
m_spi_bank = 0;
+ m_sys_ctrl = 0;
+ m_clock_ctrl = 0;
+ m_cache_ctrl = 0;
+ m_int_priority_1 = 0;
+ m_int_priority_2 = 0;
+ m_int_priority_3 = 0;
+ m_misc_int_ctrl = 0;
+ m_cha_ctrl = 0;
+ m_pllchange = 0;
+
+ for (int i = 0; i < 6; i++)
+ {
+ m_io_dir[i] = 0;
+ m_io_attrib[i] = 0;
+ }
for (int i = 0; i < 16 * 2; i++)
m_spifc_rx_fifo[i] = 0;
@@ -398,16 +433,16 @@ void generalplus_gpl951xx_device::device_reset()
// Timers
-u16 generalplus_gpl951xx_device::gpl951xx_timerg_preload_r()
+u16 generalplus_gpl951xx_device::timerg_preload_r()
{
- logerror("%s: gpl951xx_timerg_preload_r\n", machine().describe_context());
- return m_gpl951xx_timerg_preload;
+ logerror("%s: timerg_preload_r\n", machine().describe_context());
+ return m_timerg_preload;
}
-void generalplus_gpl951xx_device::gpl951xx_timerg_preload_w(u16 data)
+void generalplus_gpl951xx_device::timerg_preload_w(u16 data)
{
- logerror("%s: gpl951xx_timerg_preload_w %04x\n", machine().describe_context(), data);
- m_gpl951xx_timerg_preload = data;
+ logerror("%s: timerg_preload_w %04x\n", machine().describe_context(), data);
+ m_timerg_preload = data;
}
// P_TimerG_Ctrl
@@ -429,14 +464,14 @@ void generalplus_gpl951xx_device::gpl951xx_timerg_preload_w(u16 data)
// 1 SRCASEL[1]
// 0 SRCASEL[0]
-u16 generalplus_gpl951xx_device::gpl951xx_timerg_ctrl_r()
+u16 generalplus_gpl951xx_device::timerg_ctrl_r()
{
- logerror("%s: gpl951xx_timerg_ctrl_r\n", machine().describe_context());
- u16 ret = m_gpl951xx_timerg_ctrl;
+ logerror("%s: timerg_ctrl_r\n", machine().describe_context());
+ u16 ret = m_timerg_ctrl;
return ret;
}
-void generalplus_gpl951xx_device::gpl951xx_timerg_ctrl_w(u16 data)
+void generalplus_gpl951xx_device::timerg_ctrl_w(u16 data)
{
u8 tmgif_clear = (data & 0x8000) >> 15;
u8 tmgie = (data & 0x4000) >> 14;
@@ -446,16 +481,18 @@ void generalplus_gpl951xx_device::gpl951xx_timerg_ctrl_w(u16 data)
u8 srcbsel = (data & 0x0070) >> 4;
u8 srcasel = (data & 0x000f) >> 0;
- logerror("%s: gpl951xx_timerg_ctrl_w %04x (tmgif_clear %01x) (interrupt enabled %01x) (timer enabled %01x) (ext0sel %01x) (ext1sel %01x) (srcbsel %01x) (srcasel %01x)\n", machine().describe_context(), data, tmgif_clear, tmgie, tmgen, ext0sel, ext1sel, srcbsel, srcasel);
+ logerror("%s: timerg_ctrl_w %04x (tmgif_clear %01x) (interrupt enabled %01x) (timer enabled %01x) (ext0sel %01x) (ext1sel %01x) (srcbsel %01x) (srcasel %01x)\n", machine().describe_context(), data, tmgif_clear, tmgie, tmgen, ext0sel, ext1sel, srcbsel, srcasel);
if (data & 0x8000)
- m_gpl951xx_timerg_ctrl &= 0x7fff;
+ {
+ m_timerg_ctrl &= 0x7fff;
+ }
- if ((data & 0x2000) != (m_gpl951xx_timerg_ctrl & 0x2000))
+ if ((data & 0x2000) != (m_timerg_ctrl & 0x2000))
{
if (data & 0x2000)
{
- m_timer_g->adjust(attotime::zero, 0, attotime::from_hz(8'000'000));
+ m_timer_g->adjust(attotime::zero, 0, attotime::from_hz(2000));
}
else
{
@@ -463,19 +500,20 @@ void generalplus_gpl951xx_device::gpl951xx_timerg_ctrl_w(u16 data)
}
}
- m_gpl951xx_timerg_ctrl = (m_gpl951xx_timerg_ctrl & 0x8000) | (data & 0x7fff);
+ m_timerg_ctrl = (m_timerg_ctrl & 0x8000) | (data & 0x7fff);
+ update_interrupts(1);
}
-u16 generalplus_gpl951xx_device::gpl951xx_timerh_preload_r()
+u16 generalplus_gpl951xx_device::timerh_preload_r()
{
- logerror("%s: gpl951xx_timerh_preload_r\n", machine().describe_context());
- return m_gpl951xx_timerh_preload;
+ logerror("%s: timerh_preload_r\n", machine().describe_context());
+ return m_timerh_preload;
}
-void generalplus_gpl951xx_device::gpl951xx_timerh_preload_w(u16 data)
+void generalplus_gpl951xx_device::timerh_preload_w(u16 data)
{
- logerror("%s: gpl951xx_timerh_preload_w %04x\n", machine().describe_context(), data);
- m_gpl951xx_timerh_preload = data;
+ logerror("%s: timerh_preload_w %04x\n", machine().describe_context(), data);
+ m_timerh_preload = data;
}
// P_TimerH_Ctrl
@@ -500,14 +538,14 @@ void generalplus_gpl951xx_device::gpl951xx_timerh_preload_w(u16 data)
// 1 SRCASEL[1]
// 0 SRCASEL[0]
-u16 generalplus_gpl951xx_device::gpl951xx_timerh_ctrl_r()
+u16 generalplus_gpl951xx_device::timerh_ctrl_r()
{
- u16 ret = m_gpl951xx_timerh_ctrl;
- logerror("%s: gpl951xx_timerh_ctrl_r (returning %04x)\n", machine().describe_context(), ret);
+ u16 ret = m_timerh_ctrl;
+ logerror("%s: timerh_ctrl_r (returning %04x)\n", machine().describe_context(), ret);
return ret;
}
-void generalplus_gpl951xx_device::gpl951xx_timerh_ctrl_w(u16 data)
+void generalplus_gpl951xx_device::timerh_ctrl_w(u16 data)
{
u8 tmhif_clear = (data & 0x8000) >> 15;
u8 tmhie = (data & 0x4000) >> 14;
@@ -517,21 +555,21 @@ void generalplus_gpl951xx_device::gpl951xx_timerh_ctrl_w(u16 data)
u8 srcbsel = (data & 0x0070) >> 4;
u8 srcasel = (data & 0x000f) >> 0;
- logerror("%s: gpl951xx_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, srcbsel, srcasel);
+ 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, srcbsel, srcasel);
if (data & 0x8000)
{
logerror("cleared timerh flag\n");
- m_gpl951xx_timerh_ctrl &= 0x7fff;
+ m_timerh_ctrl &= 0x7fff;
}
- if ((data & 0x2000) != (m_gpl951xx_timerh_ctrl & 0x2000))
+ 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(8'000'000));
+ m_timer_h->adjust(attotime::zero, 0, attotime::from_hz(2000));
}
else
{
@@ -540,10 +578,114 @@ void generalplus_gpl951xx_device::gpl951xx_timerh_ctrl_w(u16 data)
}
- m_gpl951xx_timerh_ctrl = (m_gpl951xx_timerh_ctrl & 0x8000) | (data & 0x7fff);
+ m_timerh_ctrl = (m_timerh_ctrl & 0x8000) | (data & 0x7fff);
+ update_interrupts(1);
+}
+
+
+// TFT
+
+// 15
+// 14
+// 13
+// 12
+//
+// 11
+// 10
+// 9
+// 8
+//
+// 7 MEM_STATE[3] or HSTS[1] - horizontal status register
+// 6 MEM_STATE[2] or HSTS[0]
+// 5 MEM_STATE[1] or VSTS[1] - vertical status register
+// 4 MEM_STATE[0] or VSTS[0]
+//
+// 3
+// 2
+// 1 Frame Interrupt Occured
+// 0
+
+u16 generalplus_gpl951xx_device::tft_status_r()
+{
+ u16 ret = 0x0000;
+ LOGMASKED(LOG_TFT, "%s: tft_status_r\n", machine().describe_context());
+ return ret;
+}
+
+// 15 VSU
+// 14 INLA
+// 13 BEN
+// 12 HCMP
+//
+// 11 DINV
+// 10 CINV
+// 9 HINV
+// 8 VINV
+//
+// 7 MODE[3]
+// 6 MODE[2]
+// 5 MODE[1]
+// 4 MODE[0]
+//
+// 3 CLK_SEL[2]
+// 2 CLK_SEL[1]
+// 1 CLK_SEL[0]
+// 0 TFTEN
+void generalplus_gpl951xx_device::tft_ctrl_w(u16 data)
+{
+ u8 vsu = (data & 0x8000) >> 15;
+ u8 inla = (data & 0x4000) >> 14;
+ u8 ben = (data & 0x2000) >> 13;
+ u8 hcmp = (data & 0x1000) >> 12;
+ u8 dinv = (data & 0x0800) >> 11;
+ u8 cinv = (data & 0x0400) >> 10;
+ u8 hinv = (data & 0x0200) >> 9;
+ u8 vinv = (data & 0x0100) >> 8;
+ u8 mode = (data & 0x00f0) >> 4;
+ u8 clk_s = (data & 0x000e) >> 1;
+ u8 tften = (data & 0x0001) >> 0;
+
+ static const char* modenames[16] =
+ {
+ "0: UPS051 mode",
+ "1: UPS052 mode",
+ "2: CCIR656 mode",
+ "3: PARALLEL mode",
+ "4: TOCN mode",
+ "5: reserved",
+ "6: reserved",
+ "7: reserved",
+ "8: I80 CMD write",
+ "9: I80 CMD read",
+ "a: I80 DATA write",
+ "b: I80 DATA read",
+ "c: I80 Continuous mode",
+ "d: I80 Single mode",
+ "e: reserved",
+ "f: reserved"
+ };
+
+ LOGMASKED(LOG_TFT, "%s: tft_ctrl_w %04x (vsa %1x inla %1x ben %1x hcmp %1x dinv %1x cinv %1x hinv %1x vinv %1x mode (%s) clck_s %1x tft_en %1x\n", machine().describe_context(), data,
+ vsu, inla, ben, hcmp, dinv, cinv, hinv, vinv, modenames[mode], clk_s, tften);
+
+ if (tften)
+ {
+ if (mode == 0x8)
+ m_i80_cmd_out(m_memmode_wcmd);
+ else if (mode == 0x0a)
+ m_i80_data_out(m_memmode_wcmd);
+ }
+}
+
+void generalplus_gpl951xx_device::tft_memmode_wcmd_w(u16 data)
+{
+ LOGMASKED(LOG_TFT, "%s: tft_memmode_wcmd_w %04x\n", machine().describe_context(), data);
+ m_memmode_wcmd = data;
}
+//
+
u16 generalplus_gpl951xx_device::spi_bank_r()
{
LOGMASKED(LOG_SPIFC, "%s: spi_bank_r\n", machine().describe_context());
@@ -556,6 +698,298 @@ void generalplus_gpl951xx_device::spi_bank_w(u16 data)
m_spi_bank = data;
}
+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)
+ ret |= 0x8000;
+
+ if (m_timerg_ctrl & 0x8000)
+ ret |= 0x4000;
+
+ return ret;
+}
+
+void generalplus_gpl951xx_device::int_status3_w(u16 data)
+{
+ LOGMASKED(LOG_OTHER, "%s: generalplus_gpl951xx_device::int_status3_w %04x\n", machine().describe_context(), data);
+ // bit 2 (SPU Beat Interrupt) is listed as R/W for GPL95, but not GPL162? (verify)
+}
+
+TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_a_cb)
+{
+}
+
+TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_b_cb)
+{
+}
+
+TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_c_cb)
+{
+}
+
+TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_d_cb)
+{
+}
+
+TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_e_cb)
+{
+}
+
+TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_f_cb)
+{
+}
+
+
+template<int Port>
+u16 generalplus_gpl951xx_device::io_data_r()
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_data_r\n", machine().describe_context(), m_portnames[Port]);
+ return m_port_in[Port]();
+}
+
+template<int Port>
+void generalplus_gpl951xx_device::io_data_w(u16 data)
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_data_w %04x\n", machine().describe_context(), m_portnames[Port], data);
+ m_port_out[Port](data);
+}
+
+template<int Port>
+u16 generalplus_gpl951xx_device::io_buffer_r()
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_buffer_r\n", machine().describe_context(), m_portnames[Port]);
+ return m_port_in[Port]();
+}
+
+template<int Port>
+void generalplus_gpl951xx_device::io_buffer_w(u16 data)
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_buffer_w %04x\n", machine().describe_context(), m_portnames[Port], data);
+ m_port_out[Port](data);
+}
+
+template<int Port>
+u16 generalplus_gpl951xx_device::io_dir_r()
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_dir_r\n", machine().describe_context(), m_portnames[Port]);
+ return m_io_dir[Port];
+}
+
+template<int Port>
+void generalplus_gpl951xx_device::io_dir_w(u16 data)
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_dir_w %04x\n", machine().describe_context(), m_portnames[Port], data);
+ m_io_dir[Port] = data;
+}
+
+template<int Port>
+u16 generalplus_gpl951xx_device::io_attrib_r()
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_attrib_r\n", machine().describe_context(), m_portnames[Port]);
+ return m_io_attrib[Port];
+}
+
+template<int Port>
+void generalplus_gpl951xx_device::io_attrib_w(u16 data)
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_attrib_w %04x\n", machine().describe_context(), m_portnames[Port], data);
+ m_io_attrib[Port] = data;
+}
+
+template<int Port>
+u16 generalplus_gpl951xx_device::io_drv_r()
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_drv_r\n", machine().describe_context(), m_portnames[Port]);
+ return 0xffff;
+}
+
+template<int Port>
+void generalplus_gpl951xx_device::io_drv_w(u16 data)
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_drv_w %04x\n", machine().describe_context(), m_portnames[Port], data);
+}
+
+template<int Port>
+u16 generalplus_gpl951xx_device::io_mux_r()
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_mux_r\n", machine().describe_context(), m_portnames[Port]);
+ return 0xffff;
+}
+
+template<int Port>
+void generalplus_gpl951xx_device::io_mux_w(u16 data)
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_mux_w %04x\n", machine().describe_context(), m_portnames[Port], data);
+}
+
+template<int Port>
+u16 generalplus_gpl951xx_device::io_latch_r()
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_latch_r\n", machine().describe_context(), m_portnames[Port]);
+ return 0xffff;
+}
+
+template<int Port>
+void generalplus_gpl951xx_device::io_latch_w(u16 data)
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_latch_w %04x\n", machine().describe_context(), m_portnames[Port], data);
+}
+
+template<int Port>
+u16 generalplus_gpl951xx_device::io_keyen_r()
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_keyen_r\n", machine().describe_context(), m_portnames[Port]);
+ return 0xffff;
+}
+
+template<int Port>
+void generalplus_gpl951xx_device::io_keyen_w(u16 data)
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_keyen_w %04x\n", machine().describe_context(), m_portnames[Port], data);
+}
+
+// Misc
+
+u16 generalplus_gpl951xx_device::sys_ctrl_r()
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::sys_ctrl_r\n", machine().describe_context());
+ return m_sys_ctrl;
+}
+
+void generalplus_gpl951xx_device::sys_ctrl_w(u16 data)
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::sys_ctrl_w %04x\n", machine().describe_context(), data);
+ m_sys_ctrl = data;
+}
+
+void generalplus_gpl951xx_device::clock_ctrl_w(u16 data)
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::clock_ctrl_w %04x\n", machine().describe_context(), data);
+ m_clock_ctrl = data;
+}
+
+u16 generalplus_gpl951xx_device::clk_ctrl0_r()
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::clk_ctrl0_r\n", machine().describe_context());
+ return 0x0000;
+}
+
+void generalplus_gpl951xx_device::clk_ctrl0_w(u16 data)
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::clk_ctrl0 %04x\n", machine().describe_context(), data);
+}
+
+void generalplus_gpl951xx_device::watchdog_ctrl_w(u16 data)
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::watchdog_ctrl_w %04x\n", machine().describe_context(), data);
+}
+
+u16 generalplus_gpl951xx_device::power_state_r()
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::power_state_r\n", machine().describe_context());
+ return 0x0002;
+}
+
+u16 generalplus_gpl951xx_device::pllclkwait_r()
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::pllclkwait_r\n", machine().describe_context());
+ return 0x0000;
+}
+
+void generalplus_gpl951xx_device::pllclkwait_w(u16 data)
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::pllclkwait_w %04x\n", machine().describe_context(), data);
+}
+
+// sets bit 0x0002 then expects it to have cleared
+u16 generalplus_gpl951xx_device::cache_ctrl_r()
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::cache_ctrl_r\n", machine().describe_context());
+ return m_cache_ctrl & ~ 0x0002;
+}
+
+void generalplus_gpl951xx_device::cache_ctrl_w(u16 data)
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::cache_ctrl_w %04x\n", machine().describe_context(), data);
+ m_cache_ctrl = data;
+}
+
+u16 generalplus_gpl951xx_device::int_status1_r()
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::int_status1_r\n", machine().describe_context());
+ return 0x0000;
+}
+
+void generalplus_gpl951xx_device::int_status1_w(u16 data)
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::int_status1_w %04x\n", machine().describe_context(), data);
+ //m_int_status1 = data;
+}
+
+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())
+ ret |= 0x0100;
+
+ if (m_gpl_timebase->timebaseb_irq_flag())
+ ret |= 0x0200;
+
+ if (m_gpl_timebase->timebasec_irq_flag())
+ ret |= 0x0400;
+
+ return ret;
+}
+
+void generalplus_gpl951xx_device::int_status2_w(u16 data)
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::int_status2_w %04x\n", machine().describe_context(), data);
+ // none of this bits are listed as writeable for GPL95xx or GPL162xx
+}
+
+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;
+}
+
+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;
+}
+
+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);
+ m_int_priority_3 = data;
+}
+
+void generalplus_gpl951xx_device::mint_ctrl_w(u16 data)
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::mint_ctrl_w %04x\n", machine().describe_context(), data);
+ m_misc_int_ctrl = data;
+}
+
+// CHA (for sound output)
+
+u16 generalplus_gpl951xx_device::cha_ctrl_r()
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::cha_ctrl_r\n", machine().describe_context());
+ return 0xffff;
+}
+
+void generalplus_gpl951xx_device::cha_ctrl_w(u16 data)
+{
+ LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::cha_ctrl_w %04x\n", machine().describe_context(), data);
+ m_cha_ctrl = data;
+}
+
u16 generalplus_gpl951xx_device::spi_direct_r(offs_t offset)
{
@@ -585,6 +1019,19 @@ u16 generalplus_gpl951xx_device::spi_direct_bank_r(offs_t offset)
}
+template<int Port>
+void generalplus_gpl951xx_device::add_port(address_map &map, u32 base)
+{
+ map(base + 0x0, base + 0x0).rw(FUNC(generalplus_gpl951xx_device::io_data_r<Port>), FUNC(generalplus_gpl951xx_device::io_data_w<Port>));
+ map(base + 0x1, base + 0x1).rw(FUNC(generalplus_gpl951xx_device::io_buffer_r<Port>), FUNC(generalplus_gpl951xx_device::io_buffer_w<Port>));
+ map(base + 0x2, base + 0x2).rw(FUNC(generalplus_gpl951xx_device::io_dir_r<Port>), FUNC(generalplus_gpl951xx_device::io_dir_w<Port>));
+ map(base + 0x3, base + 0x3).rw(FUNC(generalplus_gpl951xx_device::io_attrib_r<Port>), FUNC(generalplus_gpl951xx_device::io_attrib_w<Port>));
+ map(base + 0x4, base + 0x4).rw(FUNC(generalplus_gpl951xx_device::io_drv_r<Port>), FUNC(generalplus_gpl951xx_device::io_drv_w<Port>));
+ map(base + 0x5, base + 0x5).rw(FUNC(generalplus_gpl951xx_device::io_mux_r<Port>), FUNC(generalplus_gpl951xx_device::io_mux_w<Port>));
+ map(base + 0x6, base + 0x6).rw(FUNC(generalplus_gpl951xx_device::io_latch_r<Port>), FUNC(generalplus_gpl951xx_device::io_latch_w<Port>));
+ map(base + 0x7, base + 0x7).rw(FUNC(generalplus_gpl951xx_device::io_keyen_r<Port>), FUNC(generalplus_gpl951xx_device::io_keyen_w<Port>));
+}
+
void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
{
map(0x000000, 0x0027ff).ram().share("mainram");
@@ -620,7 +1067,7 @@ 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
//
- // 7050 - TFT_Ctrl
+ 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
@@ -630,8 +1077,8 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
// 7057 - TFT_H_Start
// 7058 - TFT_H_End
// 7059 - TFT_RGB_Ctrl
- // 705a - TFT_Status
- // 705b - TFT_MemMode_WCmd
+ 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
//
// 705e - STN_PIC_SEG
@@ -692,14 +1139,14 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
// 7800 - BodyID
// 7801 - unused
// 7802 - PwrKey_State
- // 7803 - SYS_CTRL
- // 7804 - CLK_Ctrl0
+ map(0x007803, 0x007803).rw(FUNC(generalplus_gpl951xx_device::sys_ctrl_r), FUNC(generalplus_gpl951xx_device::sys_ctrl_w)); // 7803 - SYS_CTRL (seems quite different between SoCs)
+ map(0x007804, 0x007804).rw(FUNC(generalplus_gpl951xx_device::clk_ctrl0_r), FUNC(generalplus_gpl951xx_device::clk_ctrl0_w)); // 7804 - CLK_Ctrl0
// 7805 - CLK_Ctrl1
// 7806 - Reset_Flag
map(0x007807, 0x007807).w(FUNC(generalplus_gpl951xx_device::clock_ctrl_w)); // 7807 - Clock_Ctrl
// 7808 - LVR_Ctrl
- // 7809 - PM_Ctrl
- // 780a - Watchdog_Ctrl
+ map(0x00780a, 0x00780a).w(FUNC(generalplus_gpl951xx_device::pm_ctrl_w)); // 7809 - PM_Ctrl
+ map(0x00780a, 0x00780a).w(FUNC(generalplus_gpl951xx_device::watchdog_ctrl_w)); // 780a - Watchdog_Ctrl
map(0x00780b, 0x00780b).nopw(); // Watchdog_Clear
// 780c - WAIT
// 780d - HALT
@@ -713,7 +1160,7 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
// 7815 - unused
// 7816 - unused
map(0x007817, 0x007817).rw(FUNC(generalplus_gpl951xx_device::pllsel_r), FUNC(generalplus_gpl951xx_device::pllsel_w)); // 7817 - PLL_Sel
- // 7818 - PLLWaitCLK
+ map(0x007818, 0x007818).rw(FUNC(generalplus_gpl951xx_device::pllclkwait_r), FUNC(generalplus_gpl951xx_device::pllclkwait_w)); // 7818 - PLLWaitCLK
map(0x007819, 0x007819).rw(FUNC(generalplus_gpl951xx_device::cache_ctrl_r), FUNC(generalplus_gpl951xx_device::cache_ctrl_w)); // 7819 - Cache_Ctrl
// 781a - Cache_HitRate
// 781b - unused
@@ -729,6 +1176,8 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
// 7832 - CHECKSUM0_HB
// 7833 - CHECKSUM1_HB
//
+ map(0x007840, 0x007840).rw(FUNC(generalplus_gpl951xx_device::spi_improve_r), FUNC(generalplus_gpl951xx_device::spi_improve_w));// 7840 - P_SPI_Improve
+ //
// 7848 - ECC_LPRL_HB
// 7849 - ECC_LPRH_HB
// 784a - ECC_CPR_HB
@@ -755,67 +1204,25 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
// 785e - ECC_ERR0_LB or BCH_Parity5
// 785f - ECC_ERR1_LB or BCH_Parity6
- map(0x007860, 0x007860).rw(FUNC(generalplus_gpl951xx_device::ioa_data_r), FUNC(generalplus_gpl951xx_device::ioa_data_w)); // 7860 - IOA_Data
- map(0x007861, 0x007861).rw(FUNC(generalplus_gpl951xx_device::ioa_buffer_r), FUNC(generalplus_gpl951xx_device::ioa_buffer_w)); // 7861 - IOA_Buffer
- map(0x007862, 0x007862).rw(FUNC(generalplus_gpl951xx_device::ioa_dir_r), FUNC(generalplus_gpl951xx_device::ioa_dir_w)); // 7862 - IOA_Dir
- map(0x007863, 0x007863).rw(FUNC(generalplus_gpl951xx_device::ioa_attrib_r), FUNC(generalplus_gpl951xx_device::ioa_attrib_w)); // 7863 - IOA_Attrib
- // 7864 - IOA_Drv
- // 7865 - IOA_Mux
- // 7866 - IOA_Latch
- // 7867 - IOA_KeyEN
-
- map(0x007868, 0x007868).rw(FUNC(generalplus_gpl951xx_device::iob_data_r), FUNC(generalplus_gpl951xx_device::iob_data_w)); // 7868 - IOB_Data
- map(0x007869, 0x007869).rw(FUNC(generalplus_gpl951xx_device::iob_buffer_r), FUNC(generalplus_gpl951xx_device::iob_buffer_w)); // 7869 - IOB_Buffer
- map(0x00786a, 0x00786a).rw(FUNC(generalplus_gpl951xx_device::iob_dir_r), FUNC(generalplus_gpl951xx_device::iob_dir_w)); // 786a - IOB_Dir
- map(0x00786b, 0x00786b).rw(FUNC(generalplus_gpl951xx_device::iob_attrib_r), FUNC(generalplus_gpl951xx_device::iob_attrib_w)); // 786b - IOB_Attrib
- // 786c - IOB_Drv
- // 786d - IOB_Mux
- // 786e - IOB_Latch
- // 786f - IOB_KeyEN
-
- map(0x007870, 0x007870).rw(FUNC(generalplus_gpl951xx_device::ioc_data_r) ,FUNC(generalplus_gpl951xx_device::ioc_data_w)); // 7870 - IOC_Data
- map(0x007871, 0x007871).rw(FUNC(generalplus_gpl951xx_device::ioc_buffer_r), FUNC(generalplus_gpl951xx_device::ioc_buffer_w)); // 7871 - IOC_Buffer
- map(0x007872, 0x007872).rw(FUNC(generalplus_gpl951xx_device::ioc_dir_r), FUNC(generalplus_gpl951xx_device::ioc_dir_w)); // 7872 - IOC_Dir
- map(0x007873, 0x007873).rw(FUNC(generalplus_gpl951xx_device::ioc_attrib_r), FUNC(generalplus_gpl951xx_device::ioc_attrib_w)); // 7873 - IOC_Attrib
- // 7874 - IOC_Drv
- // 7875 - IOC_Mux
- // 7876 - IOC_Latch
- // 7877 - IOC_KeyEN
-
- map(0x007878, 0x007878).rw(FUNC(generalplus_gpl951xx_device::iod_data_r) ,FUNC(generalplus_gpl951xx_device::iod_data_w)); // 7878 - IOD_Data
- map(0x007879, 0x007879).rw(FUNC(generalplus_gpl951xx_device::iod_buffer_r), FUNC(generalplus_gpl951xx_device::iod_buffer_w)); // 7879 - IOD_Buffer
- map(0x00787a, 0x00787a).rw(FUNC(generalplus_gpl951xx_device::iod_dir_r), FUNC(generalplus_gpl951xx_device::iod_dir_w)); // 787a - IOD_Dir
- map(0x00787b, 0x00787b).rw(FUNC(generalplus_gpl951xx_device::iod_attib_r), FUNC(generalplus_gpl951xx_device::iod_attib_w)); // 787b - IOD_Attrib
- map(0x00787c, 0x00787c).rw(FUNC(generalplus_gpl951xx_device::iod_drv_r), FUNC(generalplus_gpl951xx_device::iod_drv_w)); // 787c - IOD_Drv
- map(0x00787d, 0x00787d).rw(FUNC(generalplus_gpl951xx_device::iod_mux_r), FUNC(generalplus_gpl951xx_device::iod_mux_w)); // 787d - IOD_Mux
-
- // 7880 - IOE_Data
- // 7881 - IOE_Buffer
- // 7882 - IOE_Dir
- // 7883 - IOE_Attrib
- // 7884 - IOE_Drv
- // 7885 - IOE_Mux
- // 7886 - IOE_Latch
- // 7877 - IOE_KeyEN
-
- // 7888 - IOF_Data
- // 7889 - IOF_Buffer
- // 788a - IOF_Dir
- // 788b - IOF_Attrib
- // 788c - IOF_Drv
- // 788d - IOF_Mux
- // 788e - IOF_Latch
- // 788f - IOF_KeyEN
+ // Ports addresses on GPL951xx have more logical arrangement compared to GPL162xx
+ // and there is an additional 'Port F'
+
+ add_port<0>(map, 0x007860); // 0x7860 - 0x7867 - Port A
+ add_port<1>(map, 0x007868); // 0x7868 - 0x786f - Port B
+ add_port<2>(map, 0x007870); // 0x7870 - 0x7877 - Port C
+ add_port<3>(map, 0x007878); // 0x7878 - 0x787f - Port D
+ add_port<4>(map, 0x007880); // 0x7880 - 0x7887 - Port E
+ add_port<5>(map, 0x007888); // 0x7888 - 0x788f - Port F
map(0x0078a0, 0x0078a0).rw(FUNC(generalplus_gpl951xx_device::int_status1_r), FUNC(generalplus_gpl951xx_device::int_status1_w)); // 78a0 - INT_Status1
- map(0x0078a1, 0x0078a1).r(FUNC(generalplus_gpl951xx_device::int_status2_r)); // 78a1 - INT_Status2
- // 78a2 - INT_Status3
- // 78a3 - INT_Priority1
- map(0x0078a4, 0x0078a4).w(FUNC(generalplus_gpl951xx_device::int_priority_1_w)); // 78a4 - INT_Priority2
- map(0x0078a5, 0x0078a5).w(FUNC(generalplus_gpl951xx_device::int_priority_2_w)); // 78a5 - INT_Priority3
- map(0x0078a6, 0x0078a6).w(FUNC(generalplus_gpl951xx_device::int_priority_3_w)); // 78a6 - MINT_Ctrl
+ 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(0x0078a6, 0x0078a6).w(FUNC(generalplus_gpl951xx_device::mint_ctrl_w)); // 78a6 - MINT_Ctrl
// 78a7 - IOAB_KCIEN
- map(0x0078a8, 0x0078a8).w(FUNC(generalplus_gpl951xx_device::mint_ctrl_w)); // 78a8 - IOC_KCIEN
+ // 78a8 - IOC_KCIEN
// 78a9 - IOE_KCIEN
// 78aa - IOF_KCIEN
// 78ab - IOAB_KCIFC
@@ -823,11 +1230,11 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
// 78ad - IOE_ KCIFC
// 78ae - IOF_ KCIFC
- map(0x0078b0, 0x0078b0).w(FUNC(generalplus_gpl951xx_device::timebasea_ctrl_w)); // 78b0 - TimeBaseA_Ctrl
- map(0x0078b1, 0x0078b1).w(FUNC(generalplus_gpl951xx_device::timebaseb_ctrl_w)); // 78b1 - TimeBaseB_Ctrl
- map(0x0078b2, 0x0078b2).rw(FUNC(generalplus_gpl951xx_device::timebasec_ctrl_r), FUNC(generalplus_gpl951xx_device::timebasec_ctrl_w)); // 78b2 - TimeBaseC_Ctrl
+ map(0x0078b0, 0x0078b0).rw(m_gpl_timebase, FUNC(gpl_timebase_device::timebasea_ctrl_r), FUNC(gpl_timebase_device::timebasea_ctrl_w)); // 78b0 TimeBase A Control Register (P_TimeBaseA_Ctrl)
+ map(0x0078b1, 0x0078b1).rw(m_gpl_timebase, FUNC(gpl_timebase_device::timebaseb_ctrl_r), FUNC(gpl_timebase_device::timebaseb_ctrl_w)); // 78b1 TimeBase B Control Register (P_TimeBaseB_Ctrl)
+ map(0x0078b2, 0x0078b2).rw(m_gpl_timebase, FUNC(gpl_timebase_device::timebasec_ctrl_r), FUNC(gpl_timebase_device::timebasec_ctrl_w)); // 78b2 TimeBase C Control Register (P_TimeBaseC_Ctrl)
- map(0x0078b8, 0x0078b8).w(FUNC(generalplus_gpl951xx_device::timebase_reset_w)); // 78b8 - TimeBase_Reset
+ map(0x0078b8, 0x0078b8).w(m_gpl_timebase, FUNC(gpl_timebase_device::timebase_reset_w)); // 78b8 - TimeBase_Reset
// 78c0 - I2C_Ctrl
// 78c1 - I2C_Status
@@ -837,17 +1244,17 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
// 78c5 - I2C_Clk
// 78c6 - I2C_MISC
- map(0x0078e0, 0x0078e0).rw(FUNC(generalplus_gpl951xx_device::gpl951xx_timerg_ctrl_r), FUNC(generalplus_gpl951xx_device::gpl951xx_timerg_ctrl_w)); // 78e0 - gpl951xx_timerg_Ctrl
+ map(0x0078e0, 0x0078e0).rw(FUNC(generalplus_gpl951xx_device::timerg_ctrl_r), FUNC(generalplus_gpl951xx_device::timerg_ctrl_w)); // 78e0 - timerg_Ctrl
// 78e1
- map(0x0078e2, 0x0078e2).rw(FUNC(generalplus_gpl951xx_device::gpl951xx_timerg_preload_r), FUNC(generalplus_gpl951xx_device::gpl951xx_timerg_preload_w)); // 78e2 - gpl951xx_timerg_Preload
+ map(0x0078e2, 0x0078e2).rw(FUNC(generalplus_gpl951xx_device::timerg_preload_r), FUNC(generalplus_gpl951xx_device::timerg_preload_w)); // 78e2 - timerg_Preload
// 78e3
// 78e4 - TimerG_UpCount
// 78e5
// 78e6
// 78e7
- map(0x0078e8, 0x0078e8).rw(FUNC(generalplus_gpl951xx_device::gpl951xx_timerh_ctrl_r), FUNC(generalplus_gpl951xx_device::gpl951xx_timerh_ctrl_w)); // gpl951xx_timerh_Ctrl
+ map(0x0078e8, 0x0078e8).rw(FUNC(generalplus_gpl951xx_device::timerh_ctrl_r), FUNC(generalplus_gpl951xx_device::timerh_ctrl_w)); // timerh_Ctrl
// 78e9
- map(0x0078ea, 0x0078ea).rw(FUNC(generalplus_gpl951xx_device::gpl951xx_timerh_preload_r), FUNC(generalplus_gpl951xx_device::gpl951xx_timerh_preload_w)); // 78ea - gpl951xx_timerh_Preload
+ map(0x0078ea, 0x0078ea).rw(FUNC(generalplus_gpl951xx_device::timerh_preload_r), FUNC(generalplus_gpl951xx_device::timerh_preload_w)); // 78ea - timerh_Preload
// 78eb
// 78ec - TimerH_UpCount
// 78ed
@@ -919,19 +1326,19 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
// 79be - MICAGC_Enable
// 79bf - MICAGC_Status
- // 79f0 - RTC_Ctrl
- // 79f1 - RTC_Addr
- // 79f2 - RTC_WriteData
- // 79f3 - RTC_Request
- map(0x0079f4, 0x0079f4).r(FUNC(generalplus_gpl951xx_device::rtc_ready_r)); // RTC_Ready
- map(0x0079f5, 0x0079f5).r(FUNC(generalplus_gpl951xx_device::rtc_readdata_r)); // RTC_ReadData
+ map(0x0079f0, 0x0079f0).w(m_rtc, FUNC(gpl951xx_rtc_device::rtc_ctrl_w)); // 79f0 - RTC_Ctrl
+ map(0x0079f1, 0x0079f1).w(m_rtc, FUNC(gpl951xx_rtc_device::rtc_addr_w)); // 79f1 - RTC_Addr
+ map(0x0079f2, 0x0079f2).w(m_rtc, FUNC(gpl951xx_rtc_device::rtc_writedata_w)); // 79f2 - RTC_WriteData
+ map(0x0079f3, 0x0079f3).w(m_rtc, FUNC(gpl951xx_rtc_device::rtc_request_w)); // 79f3 - RTC_Request
+ map(0x0079f4, 0x0079f4).r(m_rtc, FUNC(gpl951xx_rtc_device::rtc_ready_r)); // RTC_Ready
+ map(0x0079f5, 0x0079f5).r(m_rtc, FUNC(gpl951xx_rtc_device::rtc_readdata_r)); // RTC_ReadData
// 79f6
// 79f7
// 79f8
// 79fa
// 79fb - RTC_ClkDiv
- // 7a00 - TimerA_Ctr
+ // 7a00 - TimerA_Ctrl
// 7a01 - TimerA_CCPB_Ctrl
// 7a02 - TimerA_Preload
// 7a03 - TimerA_CCPB_Reg
@@ -993,9 +1400,9 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
// 7a55 - USBD_BOBufPointer
// 7a56 - USBD_EP0RTR
// 7a57 - USBD_EP0RR
- // 7a58 - USBD_ EP0VR
- // 7a59 - USBD_ EP0IR
- // 7a5a - USBD_ EP0LR
+ // 7a58 - USBD_EP0VR
+ // 7a59 - USBD_EP0IR
+ // 7a5a - USBD_EP0LR
//
// 7a60 - USBD_DMAWrtCountL
// 7a61 - USBD_DMAWrtCountH
@@ -1009,15 +1416,15 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
//
// 7a6c - USBD_INTF
- map(0x007a80, 0x007a87).rw(FUNC(generalplus_gpl951xx_device::system_dma_params_channel0_r), FUNC(generalplus_gpl951xx_device::system_dma_params_channel0_w));
- map(0x007a88, 0x007a8f).rw(FUNC(generalplus_gpl951xx_device::system_dma_params_channel1_r), FUNC(generalplus_gpl951xx_device::system_dma_params_channel1_w));
+ map(0x007a80, 0x007a87).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_params_channel0_r), FUNC(gpl_dma_device::system_dma_params_channel0_w));
+ map(0x007a88, 0x007a8f).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_params_channel1_r), FUNC(gpl_dma_device::system_dma_params_channel1_w));
//
// 7ab0 - DMA_SPRISize0
// 7ab1 - DMA_SPRISize1
//
// 7abd - DMA_LineLength
- map(0x007abe, 0x007abe).rw(FUNC(generalplus_gpl951xx_device::system_dma_memtype_r), FUNC(generalplus_gpl951xx_device::system_dma_memtype_w)); // 7abe - DMA_SS
- map(0x007abf, 0x007abf).rw(FUNC(generalplus_gpl951xx_device::system_dma_status_r), FUNC(generalplus_gpl951xx_device::system_dma_7abf_unk_w)); // 7abf - DMA_INT
+ map(0x007abe, 0x007abe).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_memtype_r), FUNC(gpl_dma_device::system_dma_memtype_w)); // 7abe - DMA_SS
+ map(0x007abf, 0x007abf).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_status_r), FUNC(gpl_dma_device::system_dma_status_w)); // 7abf - DMA_INT
//
// 7ac0 - CTS_Ctrl1
// 7ac1 - CTS_CH
@@ -1074,33 +1481,139 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
map(0x200000, 0x3fffff).r(FUNC(generalplus_gpl951xx_device::spi_direct_bank_r));
}
+void generalplus_gpl951xx_device::update_interrupts(int state)
+{
+ if (m_gpl_timebase->timebasea_irq_flag() || m_gpl_timebase->timebaseb_irq_flag())
+ {
+ set_state_unsynced(UNSP_IRQ7_LINE, ASSERT_LINE);
+ }
+ else
+ {
+ set_state_unsynced(UNSP_IRQ7_LINE, CLEAR_LINE);
+ }
+
+ if (m_gpl_timebase->timebasec_irq_flag())
+ {
+ set_state_unsynced(UNSP_IRQ6_LINE, ASSERT_LINE);
+ }
+ else
+ {
+ 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)))
+ {
+ set_state_unsynced(UNSP_IRQ4_LINE, ASSERT_LINE);
+ }
+ else
+ {
+ set_state_unsynced(UNSP_IRQ4_LINE, CLEAR_LINE);
+ }
+}
+
TIMER_DEVICE_CALLBACK_MEMBER( generalplus_gpl951xx_device::timer_g_cb )
{
- m_gpl951xx_timerg_ctrl |= 0x8000;
+ m_timerg_ctrl |= 0x8000;
+ update_interrupts(1);
}
TIMER_DEVICE_CALLBACK_MEMBER( generalplus_gpl951xx_device::timer_h_cb )
{
- m_gpl951xx_timerh_ctrl |= 0x8000;
+ m_timerh_ctrl |= 0x8000;
+ update_interrupts(1);
+}
+
+u16 generalplus_gpl951xx_device::read_space(offs_t offset)
+{
+ address_space &space = this->space(AS_PROGRAM);
+ u16 val = space.read_word(offset);
+ return val;
+}
+
+void generalplus_gpl951xx_device::write_space(offs_t offset, u16 data)
+{
+ address_space &space = this->space(AS_PROGRAM);
+ space.write_word(offset, data);
+}
+
+IRQ_CALLBACK_MEMBER(generalplus_gpl951xx_device::irq_vector_cb)
+{
+ if (irqline == UNSP_IRQ4_LINE)
+ set_state_unsynced(UNSP_IRQ4_LINE, CLEAR_LINE);
+
+ return 0;
+}
+
+void generalplus_gpl951xx_device::audioirq_w(int state)
+{
+ //set_state_unsynced(UNSP_IRQ5_LINE, state);
+}
+
+void generalplus_gpl951xx_device::videoirq_w(int state)
+{
+ set_state_unsynced(UNSP_IRQ5_LINE, state);
}
void generalplus_gpl951xx_device::device_add_mconfig(machine_config &config)
{
- sunplus_gcm394_base_device::device_add_mconfig(config);
+ SUNPLUS_GCM394_AUDIO(config, m_spg_audio, DERIVED_CLOCK(1, 1));
+ m_spg_audio->write_irq_callback().set(FUNC(generalplus_gpl951xx_device::audioirq_w));
+ m_spg_audio->space_read_callback().set(FUNC(generalplus_gpl951xx_device::read_space));
+ m_spg_audio->add_route(0, *this, 1.0, 0);
+ m_spg_audio->add_route(1, *this, 1.0, 1);
+
+ GPL_DMA(config, m_gpl_dma, 0);
+ m_gpl_dma->space_read_callback().set(FUNC(generalplus_gpl951xx_device::read_space));
+ m_gpl_dma->space_write_callback().set(FUNC(generalplus_gpl951xx_device::write_space));
+
+ GPL_TIMEBASE(config, m_gpl_timebase, 0);
+ m_gpl_timebase->updateirqs_callback().set(FUNC(generalplus_gpl951xx_device::update_interrupts));
+
+ GCM394_VIDEO(config, m_spg_video, DERIVED_CLOCK(1, 1), DEVICE_SELF, m_screen);
+ m_spg_video->write_video_irq_callback().set(FUNC(generalplus_gpl951xx_device::videoirq_w));
+ 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_g").configure_generic(FUNC(generalplus_gpl951xx_device::timer_g_cb));
TIMER(config, "timer_h").configure_generic(FUNC(generalplus_gpl951xx_device::timer_h_cb));
+
+ GPL951XX_RTC(config, m_rtc, 0);
}
DEFINE_DEVICE_TYPE(GPL951XX, generalplus_gpl951xx_device, "gpl951xx", "GeneralPlus GPL951xx")
-generalplus_gpl951xx_device::generalplus_gpl951xx_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
- sunplus_gcm394_base_device(mconfig, GPL951XX, tag, owner, clock, address_map_constructor(FUNC(generalplus_gpl951xx_device::gpspi_direct_internal_map), this)),
+generalplus_gpl951xx_device::generalplus_gpl951xx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal) :
+ unsp_20_device(mconfig, type, tag, owner, clock, internal),
+ device_mixer_interface(mconfig, *this),
m_spi_out(*this),
m_spi_out_cmd(*this),
m_spi_reset(*this),
+ m_i80_cmd_out(*this),
+ 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_timer_h(*this, "timer_h"),
+ m_rtc(*this, "rtc"),
+ m_gpl_dma(*this, "gpl_dma"),
+ m_gpl_timebase(*this, "gpl_timebase"),
+ m_screen(*this, finder_base::DUMMY_TAG),
+ m_spg_video(*this, "spgvideo"),
+ m_spg_audio(*this, "spgaudio"),
+ m_mainram(*this, "mainram")
+{
+}
+
+generalplus_gpl951xx_device::generalplus_gpl951xx_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ generalplus_gpl951xx_device(mconfig, GPL951XX, tag, owner, clock, address_map_constructor(FUNC(generalplus_gpl951xx_device::gpspi_direct_internal_map), this))
{
}
diff --git a/src/devices/machine/generalplus_gpl951xx_soc.h b/src/devices/machine/generalplus_gpl951xx_soc.h
index 799b3168162..5c0814ba8f7 100644
--- a/src/devices/machine/generalplus_gpl951xx_soc.h
+++ b/src/devices/machine/generalplus_gpl951xx_soc.h
@@ -6,11 +6,22 @@
#pragma once
-#include "generalplus_gpl162xx_soc.h"
+
+#include "cpu/unsp/unsp.h"
#include "machine/timer.h"
-class generalplus_gpl951xx_device : public sunplus_gcm394_base_device
+#include "screen.h"
+#include "emupal.h"
+
+#include "generalplus_gpl_dma.h"
+#include "generalplus_gpl_timebase.h"
+#include "generalplus_gpl162xx_soc_video.h"
+#include "generalplus_gpl951xx_rtc.h"
+#include "spg2xx_audio.h"
+
+
+class generalplus_gpl951xx_device : public unsp_20_device, public device_mixer_interface
{
public:
template <typename T>
@@ -18,9 +29,6 @@ public:
generalplus_gpl951xx_device(mconfig, tag, owner, clock)
{
m_screen.set_tag(std::forward<T>(screen_tag));
- //m_csbase = 0x30000;
- // TODO: is cs_space even used by this type?
- m_csbase = 0xffffffff;
}
generalplus_gpl951xx_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
@@ -31,12 +39,36 @@ public:
auto spi_out_cmd() { return m_spi_out_cmd.bind(); }
auto spi_reset() { return m_spi_reset.bind(); }
+ auto i80_cmd_out() { return m_i80_cmd_out.bind(); }
+ auto i80_data_out() { return m_i80_data_out.bind(); }
+
+ auto porta_in() { return m_port_in[0].bind(); }
+ auto portb_in() { return m_port_in[1].bind(); }
+ auto portc_in() { return m_port_in[2].bind(); }
+ auto portd_in() { return m_port_in[3].bind(); }
+ auto porte_in() { return m_port_in[4].bind(); }
+ auto portf_in() { return m_port_in[5].bind(); }
+
+ auto porta_out() { return m_port_out[0].bind(); }
+ auto portb_out() { return m_port_out[1].bind(); }
+ auto portc_out() { return m_port_out[2].bind(); }
+ auto portd_out() { return m_port_out[3].bind(); }
+ auto porte_out() { return m_port_out[4].bind(); }
+ auto portf_out() { return m_port_out[5].bind(); }
+
void recieve_spi_fifo_data(u8 data);
+ IRQ_CALLBACK_MEMBER(irq_vector_cb);
+ u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { return m_spg_video->screen_update(screen, bitmap, cliprect); }
+ void vblank(int state) { m_spg_video->vblank(state); }
+
protected:
+ generalplus_gpl951xx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal);
+
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
void gpspi_direct_internal_map(address_map &map) ATTR_COLD;
+ template<int Port> void add_port(address_map& map, u32 base) ATTR_COLD;
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
@@ -67,6 +99,15 @@ private:
u16 spifc_ctrl2_r();
void spifc_ctrl2_w(u16 data);
+ u16 spi_improve_r();
+ void spi_improve_w(u16 data);
+
+ void pm_ctrl_w(u16 data);
+
+ u16 tft_status_r();
+ void tft_ctrl_w(u16 data);
+ void tft_memmode_wcmd_w(u16 data);
+
u16 pllsel_r();
void pllsel_w(u16 data);
@@ -74,19 +115,34 @@ private:
u16 byte_swap_r();
void byte_swap_w(u16 data);
- // RTC
- u16 rtc_readdata_r();
- u16 rtc_ready_r();
-
// Timers (different compared to GPL162xx)
- u16 gpl951xx_timerg_ctrl_r();
- void gpl951xx_timerg_ctrl_w(u16 data);
- u16 gpl951xx_timerg_preload_r();
- void gpl951xx_timerg_preload_w(u16 data);
- u16 gpl951xx_timerh_ctrl_r();
- void gpl951xx_timerh_ctrl_w(u16 data);
- u16 gpl951xx_timerh_preload_r();
- void gpl951xx_timerh_preload_w(u16 data);
+ 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);
+
+ static constexpr std::string m_portnames[6] = { "a", "b", "c", "d", "e", "f" };
+
+ template<int Port> u16 io_data_r();
+ template<int Port> void io_data_w(u16 data);
+ template<int Port> u16 io_buffer_r();
+ template<int Port> void io_buffer_w(u16 data);
+ template<int Port> u16 io_dir_r();
+ template<int Port> void io_dir_w(u16 data);
+ template<int Port> u16 io_attrib_r();
+ template<int Port> void io_attrib_w(u16 data);
+ template<int Port> u16 io_drv_r();
+ template<int Port> void io_drv_w(u16 data);
+ template<int Port> u16 io_mux_r();
+ template<int Port> void io_mux_w(u16 data);
+ template<int Port> u16 io_latch_r();
+ template<int Port> void io_latch_w(u16 data);
+ template<int Port> u16 io_keyen_r();
+ template<int Port> void io_keyen_w(u16 data);
u16 spi_bank_r();
void spi_bank_w(u16 data);
@@ -96,15 +152,60 @@ private:
u8 get_byte_from_rx_fifo();
+ u16 sys_ctrl_r();
+ void sys_ctrl_w(u16 data);
+
+ void clock_ctrl_w(u16 data);
+ u16 clk_ctrl0_r();
+ void clk_ctrl0_w(u16 data);
+
+ u16 power_state_r();
+ void watchdog_ctrl_w(u16 data);
+
+ u16 pllclkwait_r();
+ void pllclkwait_w(u16 data);
+
+ u16 cache_ctrl_r();
+ void cache_ctrl_w(u16 data);
+
+ void int_status1_w(u16 data);
+ void int_status2_w(u16 data);
+ void int_status3_w(u16 data);
+ u16 int_status1_r();
+ u16 int_status2_r();
+ u16 int_status3_r();
+ void int_priority_1_w(u16 data);
+ void int_priority_2_w(u16 data);
+ void int_priority_3_w(u16 data);
+ void mint_ctrl_w(u16 data);
+
+ u16 cha_ctrl_r();
+ void cha_ctrl_w(u16 data);
+
+ void update_interrupts(int state);
+
+ void audioirq_w(int state);
+ void videoirq_w(int state);
+
+ 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);
+ 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);
+
u16 m_byteswap;
- u16 m_gpl951xx_timerg_preload;
- u16 m_gpl951xx_timerg_ctrl;
- u16 m_gpl951xx_timerh_preload;
- u16 m_gpl951xx_timerh_ctrl;
+ u16 m_timerg_preload;
+ u16 m_timerg_ctrl;
+ u16 m_timerh_preload;
+ u16 m_timerh_ctrl;
u16 m_spifc_ctrl;
u16 m_spifc_ctrl2;
@@ -118,8 +219,27 @@ private:
u8 m_spifc_rx_fifo[16 * 2];
u16 m_spifc_rx_read_latch;
+ u16 m_io_dir[6];
+ u16 m_io_attrib[6];
+
+ u16 m_sys_ctrl;
+ u16 m_clock_ctrl;
+ u16 m_cache_ctrl;
+
+ u16 m_int_priority_1;
+ u16 m_int_priority_2;
+ u16 m_int_priority_3;
+
+ u16 m_misc_int_ctrl;
+
+ u16 m_cha_ctrl;
+
+ u16 m_pllchange;
+
u16 m_spi_bank;
+ u16 m_memmode_wcmd;
+
// config
u8 *m_spiregion;
u32 m_spisize;
@@ -128,9 +248,22 @@ private:
devcb_write8 m_spi_out_cmd;
devcb_write8 m_spi_reset;
+ devcb_write16 m_i80_cmd_out;
+ devcb_write16 m_i80_data_out;
+
+ devcb_read16::array<6> m_port_in;
+ devcb_write16::array<6> m_port_out;
+
// devices
required_device<timer_device> m_timer_g;
required_device<timer_device> m_timer_h;
+ required_device<gpl951xx_rtc_device> m_rtc;
+ required_device<gpl_dma_device> m_gpl_dma;
+ required_device<gpl_timebase_device> m_gpl_timebase;
+ required_device<screen_device> m_screen;
+ required_device<gcm394_video_device> m_spg_video;
+ required_device<sunplus_gcm394_audio_device> m_spg_audio;
+ required_shared_ptr<u16> m_mainram;
};
DECLARE_DEVICE_TYPE(GPL951XX, generalplus_gpl951xx_device)
diff --git a/src/devices/machine/generalplus_gpl_dma.cpp b/src/devices/machine/generalplus_gpl_dma.cpp
new file mode 100644
index 00000000000..5d6510246fb
--- /dev/null
+++ b/src/devices/machine/generalplus_gpl_dma.cpp
@@ -0,0 +1,288 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+#include "emu.h"
+#include "generalplus_gpl_dma.h"
+
+#define LOG_GCM394_SYSDMA (1U << 1)
+
+#define VERBOSE (LOG_GCM394_SYSDMA)
+
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(GPL_DMA, gpl_dma_device, "gpl_dma", "Generalplus GPL162xx / GPL951xx System DMA")
+
+gpl_dma_device::gpl_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, GPL_DMA, tag, owner, clock),
+ m_space_read_cb(*this, 0),
+ m_space_write_cb(*this),
+ m_dma_complete_cb(*this)
+{
+}
+
+void gpl_dma_device::device_start()
+{
+ save_item(NAME(m_dma_params));
+ save_item(NAME(m_dma_latched));
+ save_item(NAME(m_system_dma_memtype));
+}
+
+void gpl_dma_device::device_reset()
+{
+ for (int j = 0; j < 4; j++)
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ m_dma_params[i][j] = 0x0000;
+ }
+ m_dma_latched[j] = 0;
+ }
+
+ m_system_dma_memtype = 0x0000;
+}
+
+
+// **************************************** SYSTEM DMA device *************************************************
+
+// note, GPL162xx has 4 channels, GPL951xx only has 2
+// sources also differ
+
+u16 gpl_dma_device::read_dma_params(int channel, int offset)
+{
+ u16 retdata = m_dma_params[offset][channel];
+ LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::read_dma_params (channel %01x) %01x returning %04x\n", machine().describe_context(), channel, offset, retdata);
+ return retdata;
+}
+
+void gpl_dma_device::write_dma_params(int channel, int offset, u16 data)
+{
+ LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::write_dma_params (channel %01x) %01x %04x\n", machine().describe_context(), channel, offset, data);
+
+ m_dma_params[offset][channel] = data;
+
+ // TODO: very likely DMA happens whenever the length is not 0, as long as it's been enabled previously
+ // jak_prft doesn't rewrite the offset 0 register between requests, and instead writes the length
+ // as the final thing for each new request. other games do not write the length last, but turn off
+ // register 0 before writing params, and enable it again afterwards
+ // if that's the case, this code can be refactored to work on 'length' instead of the m_dma_latched
+
+ if (offset == 3)
+ {
+ m_dma_latched[channel] = true;
+
+ if (m_dma_params[0][channel] & 1)
+ trigger_systemm_dma(channel);
+ }
+
+ if (offset == 0 && (data & 1))
+ {
+ if (m_dma_latched[channel])
+ trigger_systemm_dma(channel);
+ }
+
+}
+
+
+u16 gpl_dma_device::system_dma_params_channel0_r(offs_t offset)
+{
+ return read_dma_params(0, offset);
+}
+
+
+void gpl_dma_device::system_dma_params_channel0_w(offs_t offset, u16 data)
+{
+ write_dma_params(0, offset, data);
+}
+
+u16 gpl_dma_device::system_dma_params_channel1_r(offs_t offset)
+{
+ return read_dma_params(1, offset);
+}
+
+void gpl_dma_device::system_dma_params_channel1_w(offs_t offset, u16 data)
+{
+ write_dma_params(1, offset, data);
+}
+
+u16 gpl_dma_device::system_dma_params_channel2_r(offs_t offset)
+{
+ return read_dma_params(2, offset);
+}
+
+void gpl_dma_device::system_dma_params_channel2_w(offs_t offset, u16 data)
+{
+ write_dma_params(2, offset, data);
+}
+
+u16 gpl_dma_device::system_dma_params_channel3_r(offs_t offset)
+{
+ return read_dma_params(3, offset);
+}
+
+void gpl_dma_device::system_dma_params_channel3_w(offs_t offset, u16 data)
+{
+ write_dma_params(3, offset, data);
+}
+
+// P_DMA_INT
+//
+// 15
+// 14
+// 13
+// 12
+//
+// 11 CH3BY - channel busy flags (read only)
+// 10 CH2BY
+// 9 CH1BY
+// 8 CH0BY
+//
+// 7 CH3TOIF - channel timeout flags
+// 6 CH2TOIF
+// 5 CH1TOIF
+// 4 CH0TOIF
+//
+// 3 CH3IF - channel complete interrupt flags (write to clear)
+// 2 CH2IF
+// 1 CH1IF
+// 0 CH0IF
+
+u16 gpl_dma_device::system_dma_status_r()
+{
+ LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::system_dma_status_r (7abf)\n", machine().describe_context());
+ return 0x00ff;
+}
+
+void gpl_dma_device::system_dma_status_w(u16 data)
+{
+ // writes to the low 4 bits clear the channel complete interrupt flags
+ LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::system_dma_status_w %04x\n", machine().describe_context(), data);
+}
+
+// m_dma_params[0] is P_DMA_Ctrl
+//
+// 15 WriteReq (0 = request data out, 1 = request data in)
+// 14 TM (0 = single transfer mode, 1 = demand transfer mode)
+// 13 TARByte (0 = 16-bit target, 1 = 8-bit target)
+// 12 SRCByte (0 = 16-bit source, 1 = 8-bit source)
+
+// 11 TD[1] (00 = Memory to Memory, 01 = Memory to I/O, 10 = I/O to Memory, 11 = invalid)
+// 10 TD[0]
+// 9 RS (1 = reset channel)
+// 8 CIE (1 = enable DMA interrupt)
+
+// 7 SF (0 = increase/decrease source enabled, 1 = no increment)
+// 6 DF (0 = increase/decrease dest enabled, 1 = no increment)
+// 5 SD (0 = increase source, 1 = decrease source)
+// 4 DD (0 = increase dest, 1 = decrease dest)
+
+// 3 DBF(r)/NORM_I(w) (DBF: 1 = DMA Double Buffer Full, NORM_I: DMA Normal Interrupt mode)
+// 2 MODE (0 = Software Mode/Auto Mode, 1 = External Mode request)
+// 1 BS(r/o) (0 = DMA idle, 1 = DMA busy)
+// 0 CE (0 = Channel Disabled, 1 = Channel Enabled)
+
+void gpl_dma_device::trigger_systemm_dma(int channel)
+{
+ u16 mode = m_dma_params[0][channel];
+ u32 source = m_dma_params[1][channel] | (m_dma_params[4][channel] << 16);
+ u32 dest = m_dma_params[2][channel] | (m_dma_params[5][channel] << 16) ;
+ u32 length = m_dma_params[3][channel] | (m_dma_params[6][channel] << 16);
+ int sourcedelta = 0;
+ int destdelta = 0;
+
+ if ((mode & 0xa0) == 0x00)
+ sourcedelta = 1;
+ else if ((mode & 0xa0) == 0x20)
+ sourcedelta = -1;
+
+ if ((mode & 0x50) == 0x00)
+ destdelta = 1;
+ 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 );
+
+ // wrlshunt transfers ROM to RAM, all RAM write addresses have 0x800000 in the destination set
+
+ source &= 0x0fffffff;
+ length &= 0x0fffffff; // gormiti
+
+ for (int i = 0; i < length; i++)
+ {
+ u16 val;
+ if (mode & 0x1000)
+ {
+ val = (m_space_read_cb(source) & 0xFF) | (m_space_read_cb(source) << 8);
+ i++;
+ }
+ else
+ {
+ val = m_space_read_cb(source);
+ }
+
+ source += sourcedelta;
+
+ if (mode & 0x2000)
+ {
+ m_space_write_cb(dest, val & 0xFF);
+ dest += destdelta;
+ m_space_write_cb(dest, val >> 8);
+ }
+ else
+ {
+ m_space_write_cb(dest, val);
+ }
+
+ dest += destdelta;
+ }
+
+ m_dma_complete_cb(1); // allow some driver specific hacks for service modes
+
+ // clear params after operation
+ m_dma_params[0][channel] = m_dma_params[0][channel] & 0x00f7;
+
+ m_dma_params[1][channel] = m_dma_params[2][channel] = m_dma_params[3][channel] = m_dma_params[4][channel] = m_dma_params[5][channel] = m_dma_params[6][channel] = 0x0000;
+ m_dma_latched[channel] = false;
+
+ //machine().debug_break();
+}
+
+
+
+u16 gpl_dma_device::system_dma_memtype_r()
+{
+ LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::system_dma_memtype_r\n", machine().describe_context());
+ return m_system_dma_memtype;
+}
+
+void gpl_dma_device::system_dma_memtype_w(u16 data)
+{
+ // these sources differ between models
+ static char const* const types[16] =
+ {
+ "Unused / USB",
+ "DAC CHA",
+ "UART TX",
+ "UART RX",
+ "SDC/MMC 1", // reserved (GPL951xx)
+ "NAND Flash",
+ "Serial Interface", // ADC Auto Sample Full (GPL951xx)
+ "DAC CHB",
+ "ADC Auto Sample Full", // MIC ADC Auto Sample Full (GPL951xx)
+ "SPI TX",
+ "SPI RX",
+ "USB ISO Out", // reserved (GPL951xx)
+ "USB ISO In", // reserved (GPL951xx)
+ "SDC/MMC 2", // reserved (GPL951xx)
+ "SPUL", // SPI1 TX (GP951xx)
+ "SPUH" // SPI1 RX (GP951xx)
+ };
+
+ m_system_dma_memtype = data;
+
+ LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::system_dma_memtype_w %04x (CH3: %s | CH2: %s | CH1: %s | CH0: %s )\n", machine().describe_context(), data,
+ types[((m_system_dma_memtype>>12)&0xf)],
+ types[((m_system_dma_memtype>>8)&0xf)],
+ types[((m_system_dma_memtype>>4)&0xf)],
+ types[((m_system_dma_memtype)&0xf)]);
+
+}
diff --git a/src/devices/machine/generalplus_gpl_dma.h b/src/devices/machine/generalplus_gpl_dma.h
new file mode 100644
index 00000000000..de914250bf0
--- /dev/null
+++ b/src/devices/machine/generalplus_gpl_dma.h
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+#ifndef MAME_MACHINE_GENERALPLUS_GPL_DMA_H
+#define MAME_MACHINE_GENERALPLUS_GPL_DMA_H
+
+#pragma once
+
+class gpl_dma_device : public device_t
+{
+public:
+ gpl_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ auto space_read_callback() { return m_space_read_cb.bind(); }
+ auto space_write_callback() { return m_space_write_cb.bind(); }
+ auto dma_complete_callback() { return m_dma_complete_cb.bind(); }
+
+ u16 system_dma_status_r();
+ void system_dma_status_w(u16 data);
+ u16 system_dma_memtype_r();
+ void system_dma_memtype_w(u16 data);
+
+ void write_dma_params(int channel, int offset, u16 data);
+ u16 read_dma_params(int channel, int offset);
+
+ u16 system_dma_params_channel0_r(offs_t offset);
+ void system_dma_params_channel0_w(offs_t offset, u16 data);
+ u16 system_dma_params_channel1_r(offs_t offset);
+ void system_dma_params_channel1_w(offs_t offset, u16 data);
+ u16 system_dma_params_channel2_r(offs_t offset);
+ void system_dma_params_channel2_w(offs_t offset, u16 data);
+ u16 system_dma_params_channel3_r(offs_t offset);
+ void system_dma_params_channel3_w(offs_t offset, u16 data);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ void trigger_systemm_dma(int channel);
+
+private:
+
+ u16 m_system_dma_memtype;
+ u16 m_dma_params[8][4];
+ u8 m_dma_latched[4];
+
+ devcb_read16 m_space_read_cb;
+ devcb_write16 m_space_write_cb;
+ devcb_write_line m_dma_complete_cb;
+};
+
+DECLARE_DEVICE_TYPE(GPL_DMA, gpl_dma_device)
+
+#endif // MAME_MACHINE_GENERALPLUS_GPL_DMA_H
diff --git a/src/devices/machine/generalplus_gpl_timebase.cpp b/src/devices/machine/generalplus_gpl_timebase.cpp
new file mode 100644
index 00000000000..6c5464d26e9
--- /dev/null
+++ b/src/devices/machine/generalplus_gpl_timebase.cpp
@@ -0,0 +1,208 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+#include "emu.h"
+#include "generalplus_gpl_timebase.h"
+
+#define LOG_TIMEBASE (1U << 1)
+
+#define VERBOSE (0)
+
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(GPL_TIMEBASE, gpl_timebase_device, "gpl_timebase", "Generalplus GPL162xx / GPL951xx System Timebase")
+
+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_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_reset));
+}
+
+void gpl_timebase_device::device_reset()
+{
+ m_timebasea_ctrl = 0x0000;
+ m_timebaseb_ctrl = 0x0000;
+ m_timebasec_ctrl = 0x0000;
+ m_timebase_reset = 0x0000;
+}
+
+
+// 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 )
+{
+ // sets bit 15 in m_timebasec_ctrl, also visible (as read only) in P_INT_Status2, bit 8
+ // uses IRQ7 (FIQ option not available)
+ m_timebasea_ctrl |= 0x8000;
+ m_updateirqs_cb(1);
+}
+
+// P_TimeBaseA_Ctrl
+//
+// 15 TMBAIF/C
+// 14 TMBAIE
+// 13 TMBAEN
+// 12
+//
+// 11
+// 10
+// 9
+// 8
+// 7
+// 6
+// 5
+// 4
+// 3
+// 2
+// 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()
+{
+ LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebaseb_ctrl_r\n", machine().describe_context());
+ return m_timebaseb_ctrl;
+}
+
+void gpl_timebase_device::timebaseb_ctrl_w(u16 data)
+{
+ LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebaseb_ctrl_w %04x\n", machine().describe_context(), data);
+
+ if (data & 0x8000)
+ {
+ m_timebaseb_ctrl = data & 0x7fff;
+ m_updateirqs_cb(1);
+ }
+ else
+ {
+ m_timebaseb_ctrl = data;
+ }
+
+ if ((m_timebaseb_ctrl & 0x6000) == 0x6000)
+ {
+ 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;
+ }
+ }
+ 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);
+ }
+}
+
+void gpl_timebase_device::timebase_reset_w(u16 data)
+{
+ LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebase_reset_w %04x\n", machine().describe_context(), data);
+ m_timebase_reset = 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));
+}
diff --git a/src/devices/machine/generalplus_gpl_timebase.h b/src/devices/machine/generalplus_gpl_timebase.h
new file mode 100644
index 00000000000..a6ad4969009
--- /dev/null
+++ b/src/devices/machine/generalplus_gpl_timebase.h
@@ -0,0 +1,57 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+#ifndef MAME_MACHINE_GENERALPLUS_GPL_TIMEBASE_H
+#define MAME_MACHINE_GENERALPLUS_GPL_TIMEBASE_H
+
+#pragma once
+
+#include "machine/timer.h"
+
+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; }
+
+ 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 timebasec_ctrl_w(u16 data);
+
+ void timebase_reset_w(u16 data);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ 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);
+
+ u16 m_timebasea_ctrl;
+ u16 m_timebaseb_ctrl;
+ u16 m_timebasec_ctrl;
+
+ 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;
+
+ devcb_write_line m_updateirqs_cb;
+};
+
+DECLARE_DEVICE_TYPE(GPL_TIMEBASE, gpl_timebase_device)
+
+#endif // MAME_MACHINE_GENERALPLUS_GPL_TIMEBASE_H
diff --git a/src/mame/tvgames/generalplus_gpl162xx_lcdtype.cpp b/src/mame/handheld/generalplus_gpl162xx_lcdtype.cpp
index d46b038f373..e3e63b77504 100644
--- a/src/mame/tvgames/generalplus_gpl162xx_lcdtype.cpp
+++ b/src/mame/handheld/generalplus_gpl162xx_lcdtype.cpp
@@ -3,11 +3,11 @@
/* These contain a similar game selection to the devices in unk6502_st2xxx.cpp but on updated hardware
- The hardware appears to be an abuse of the GPL16250 SoC. The palette and sprite banks are used, but as work-ram
+ The hardware appears to be an abuse of the GPL162xx SoC. The palette and sprite banks are used, but as work-ram
rather than for their intended purpose, and the rest of the GPL16250 video hardware is either entirely bypassed
or doesn't exist. All video is software rendered and output directly to the LCD Controller.
- If this is confirmed via a decap then this should be merged with the GPL16250 implementation.
+ If this is confirmed via a decap then this should be merged with the GPL162xx implementation.
The coding of these is similar to the unk6502_st2xxx.cpp too, with all game specific function calls being loaded
on the fly from the SPI to a tiny portion of work RAM, with graphics likewise being loaded and decompressed for
diff --git a/src/mame/tvgames/generalplus_gpl951xx.cpp b/src/mame/handheld/generalplus_gpl951xx.cpp
index 6352ed29342..67fbe745973 100644
--- a/src/mame/tvgames/generalplus_gpl951xx.cpp
+++ b/src/mame/handheld/generalplus_gpl951xx.cpp
@@ -9,6 +9,8 @@
#include "machine/generalplus_gpl951xx_soc.h"
#include "machine/generic_spi_flash.h"
+#include "unknown_bftetris_lcdc.h"
+
namespace {
class generalplus_gpl951xx_game_state : public driver_device
@@ -19,7 +21,8 @@ public:
m_maincpu(*this, "maincpu"),
m_screen(*this, "screen"),
m_genspi(*this, "spi"),
- m_io(*this, "IN%u", 0U)
+ m_io(*this, "IN%u", 0U),
+ m_lcdc(*this, "lcdc")
{
}
@@ -29,6 +32,7 @@ public:
void poke(machine_config &config) ATTR_COLD;
void flufflav(machine_config &config) ATTR_COLD;
void puni(machine_config &config) ATTR_COLD;
+ void bftetris(machine_config &config) ATTR_COLD;
void init_fif() ATTR_COLD;
@@ -38,6 +42,8 @@ protected:
void gpl951xx(machine_config &config) ATTR_COLD;
+ u32 bftetris_screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
u16 porta_r();
u16 portb_r();
u16 portc_r();
@@ -47,12 +53,21 @@ protected:
void spi_access_from_soc(u8 data);
void spi_cmd_access_from_soc(u8 data);
+ void lcd_i80_cmd(u16 data);
+ void lcd_i80_data(u16 data);
+
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_device<bftetris_lcdc_device> m_lcdc;
};
+u32 generalplus_gpl951xx_game_state::bftetris_screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ return m_lcdc->render_to_bitmap(screen, bitmap, cliprect);
+}
+
u16 generalplus_gpl951xx_game_state::porta_r()
{
@@ -161,6 +176,19 @@ 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);
+}
+
+
void generalplus_gpl951xx_game_state::gpl951xx(machine_config &config)
{
@@ -169,23 +197,24 @@ void generalplus_gpl951xx_game_state::gpl951xx(machine_config &config)
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_out().set(FUNC(generalplus_gpl951xx_game_state::porta_w));
- m_maincpu->set_irq_acknowledge_callback(m_maincpu, FUNC(sunplus_gcm394_base_device::irq_vector_cb));
+ 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);
- m_maincpu->set_bootmode(0);
- m_maincpu->set_cs_space(DEVICE_SELF, 0);
m_maincpu->spi_out().set(FUNC(generalplus_gpl951xx_game_state::spi_access_from_soc));
m_maincpu->spi_out_cmd().set(FUNC(generalplus_gpl951xx_game_state::spi_cmd_access_from_soc));
m_maincpu->spi_reset().set(FUNC(generalplus_gpl951xx_game_state::spi_reset));
-;
+ 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(20); // 20hz update gives more correct speed (and working inputs) in fixitflx and bfdigdug, but speed should probably be limited in some other way
m_screen->set_refresh_hz(60);
m_screen->set_size(320*2, 262*2);
m_screen->set_visarea(0, (320*2)-1, 0, (240*2)-1);
- m_screen->set_screen_update("maincpu", FUNC(sunplus_gcm394_device::screen_update));
- m_screen->screen_vblank().set(m_maincpu, FUNC(sunplus_gcm394_device::vblank));
+ m_screen->set_screen_update("maincpu", FUNC(generalplus_gpl951xx_device::screen_update));
+
+ m_screen->screen_vblank().set(m_maincpu, FUNC(generalplus_gpl951xx_device::vblank));
+
+ UNKNOWN_BFTETRIS_LCDC(config, m_lcdc, 0);
GENERIC_SPI_FLASH(config, m_genspi, 0);
@@ -240,6 +269,19 @@ void generalplus_gpl951xx_game_state::puni(machine_config &config)
m_genspi->set_jedec_capacity(0x17);
}
+void generalplus_gpl951xx_game_state::bftetris(machine_config &config)
+{
+ fixitflx(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_screen_update(FUNC(generalplus_gpl951xx_game_state::bftetris_screen_update));
+}
+
+
+
// There should be a small internal ROM (0x4000) bytes that does some basic setup
ROM_START( fixitflx )
@@ -318,6 +360,11 @@ ROM_START( punirune )
ROM_LOAD16_WORD_SWAP( "25l64.ic103", 0x0000, 0x800000, CRC(0737edc0) SHA1(fce19d91a0522a75e676197fb18645b8c6a273b8) )
ROM_END
+ROM_START( punirunea )
+ ROM_REGION16_BE(0x800000, "spi", ROMREGION_ERASE00)
+ ROM_LOAD16_WORD_SWAP( "25l64.ic3", 0x0000, 0x800000, CRC(a7a9aad0) SHA1(2c81d9a831360882b79b4dab0966c828ddb5a9e3) )
+ROM_END
+
ROM_START( punij1m )
ROM_REGION16_BE(0x800000, "spi", ROMREGION_ERASE00)
ROM_LOAD16_WORD_SWAP( "japan_v1pcb_mint_25l6433f.ic103", 0x0000, 0x800000, CRC(76f28b5b) SHA1(be04d60c88df52951dd51eab2f5bf5f1dc2405e8) )
@@ -462,13 +509,16 @@ CONS(2017, bfmpac, 0, 0, bfpacman, bfmpac, generalplus_gpl951xx_game_state,
CONS(2017, bfgalaga, 0, 0, bfpacman, bfmpac, generalplus_gpl951xx_game_state, init_fif, "Basic Fun", "Galaga (mini arcade)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
CONS(2018, bfdigdug, 0, 0, bfpacman, bfmpac, generalplus_gpl951xx_game_state, init_fif, "Basic Fun", "Dig Dug (mini arcade)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
CONS(2019, bfspyhnt, 0, 0, fixitflx, bfspyhnt, generalplus_gpl951xx_game_state, init_fif, "Basic Fun", "Spy Hunter (mini arcade)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
-CONS(2019, bftetris, 0, 0, fixitflx, bfspyhnt, generalplus_gpl951xx_game_state, init_fif, "Basic Fun", "Tetris (mini arcade)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
+CONS(2020, bftetris, 0, 0, bftetris, bfspyhnt, generalplus_gpl951xx_game_state, init_fif, "Basic Fun", "Tetris (mini arcade)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
// games below use GPL95101 series chips, which might be different but are definitely unSP2.0 chips that run from SPI directly
// 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, bfspyhnt, 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)
diff --git a/src/mame/handheld/unknown_bftetris_lcdc.cpp b/src/mame/handheld/unknown_bftetris_lcdc.cpp
new file mode 100644
index 00000000000..cffc25436f7
--- /dev/null
+++ b/src/mame/handheld/unknown_bftetris_lcdc.cpp
@@ -0,0 +1,357 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+#include "emu.h"
+#include "unknown_bftetris_lcdc.h"
+
+// probably some kind of STxxxx LCDC, but support for 320+ resolutions
+
+DEFINE_DEVICE_TYPE(UNKNOWN_BFTETRIS_LCDC, bftetris_lcdc_device, "bftetris_lcdc", "Unknown STxxxx LCDC (bftetris)")
+
+bftetris_lcdc_device::bftetris_lcdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, UNKNOWN_BFTETRIS_LCDC, tag, owner, clock)
+{
+}
+
+u32 bftetris_lcdc_device::render_to_bitmap(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ bitmap.fill(0, cliprect);
+
+ if (m_displayon)
+ {
+ if (m_sleep)
+ return 0;
+
+ for (int y = cliprect.min_x; y <= cliprect.max_y; y++)
+ {
+ u32* dst = &bitmap.pix(y);
+
+ for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
+ {
+ int count = (y * 0x200) + x;
+
+ u16 dat = m_displaybuffer[count];
+
+ int b = ((dat >> 0) & 0x1f) << 3;
+ int g = ((dat >> 5) & 0x3f) << 2;
+ int r = ((dat >> 11) & 0x1f) << 3;
+
+ dst[x] = (r << 16) | (g << 8) | (b << 0);
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+void bftetris_lcdc_device::lcdc_command_w(u16 data)
+{
+ m_command = data;
+ m_commandstep = 0;
+
+ if (m_command == 0x10)
+ {
+ logerror("command is %02x (SLEEP IN - no params expected)\n", m_command);
+ m_sleep = 1;
+ }
+ else if (m_command == 0x11)
+ {
+ logerror("command is %02x (SLEEP OUT - no params expected)\n", m_command);
+ m_sleep = 0;
+ }
+ else if (m_command == 0x29)
+ {
+ logerror("command is %02x (DISPLAY ON - no params expected)\n", m_command);
+ m_displayon = 1;
+ }
+ else if (m_command == 0x2a)
+ {
+ logerror("command is %02x (CASET - 4 params expected)\n", m_command);
+ }
+ else if (m_command == 0x2b)
+ {
+ logerror("command is %02x (RASET - 4 params expected)\n", m_command);
+ }
+ else if (m_command == 0x2c)
+ {
+ logerror("command is %02x (MEMORY WRITE - unlimited params)\n", m_command);
+ }
+ else if (m_command == 0x36)
+ {
+ logerror("command is %02x (MADCTL - 1 param expected)\n", m_command);
+ }
+ else if (m_command == 0x3a)
+ {
+ logerror("command is %02x (COLMOD - 1 param expected)\n", m_command);
+ }
+ else if (m_command == 0xb1)
+ {
+ logerror("command is %02x (FRMCTR1 - 3 params expected)\n", m_command);
+ }
+ else if (m_command == 0xb2)
+ {
+ logerror("command is %02x (FRMCTR2 - 3 params expected)\n", m_command);
+ }
+ else if (m_command == 0xb3)
+ {
+ logerror("command is %02x (FRMCTR3 - 6 params expected)\n", m_command);
+ }
+ else if (m_command == 0xb4)
+ {
+ logerror("command is %02x (INVCTR - 1 param expected)\n", m_command);
+ }
+ else if (m_command == 0xc0)
+ {
+ logerror("command is %02x (PWCTR1 - 2 or 3 params expected)\n", m_command);
+ }
+ else if (m_command == 0xc1)
+ {
+ logerror("command is %02x (PWCTR2 - 1 param expected)\n", m_command);
+ }
+ else if (m_command == 0xc2)
+ {
+ logerror("command is %02x (PWCTR3 - 2 params expected)\n", m_command);
+ }
+ else if (m_command == 0xc3)
+ {
+ logerror("command is %02x (PWCTR4 - 2 params expected)\n", m_command);
+ }
+ else if (m_command == 0xc4)
+ {
+ logerror("command is %02x (PWCTR5 - 2 params expected)\n", m_command);
+ }
+ else if (m_command == 0xc5)
+ {
+ logerror("command is %02x (VMCTR - 1 param expected)\n", m_command);
+ }
+ else if (m_command == 0xe0)
+ {
+ logerror("command is %02x (GMCTRP - 16 params expected)\n", m_command);
+ }
+ else if (m_command == 0xe1)
+ {
+ logerror("command is %02x (GMCTRN - 16 params expected)\n", m_command);
+ }
+ else
+ {
+ logerror("lcdc unknown command is %02x\n", m_command);
+ }
+}
+
+u16 bftetris_lcdc_device::lcdc_data_r()
+{
+ return 0;
+}
+
+void bftetris_lcdc_device::lcdc_data_w(u16 data)
+{
+ if (m_command == 0x2b)
+ {
+ switch (m_commandstep)
+ {
+ case 0: m_posminy = data << 8 | (m_posminy & 0xff); break;
+ case 1: m_posminy = (m_posminy & 0xff00) | data; break;
+ case 2: m_posmaxy = data << 8 | (m_posmaxy & 0xff); break;
+ case 3:
+ m_posmaxy = (m_posmaxy & 0xff00) | data; m_posy = m_posminy;
+ logerror("Y Min %04x Y Max %04x\n", m_posminy, m_posmaxy);
+ break;
+ }
+ }
+ else if (m_command == 0x2a)
+ {
+ switch (m_commandstep)
+ {
+ case 0: m_posminx = data << 8 | (m_posminx & 0xff); break;
+ case 1: m_posminx = (m_posminx & 0xff00) | data; break;
+ case 2: m_posmaxx = data << 8 | (m_posmaxx & 0xff); break;
+ case 3:
+ m_posmaxx = (m_posmaxx & 0xff00) | data; m_posx = m_posminx;
+ logerror("X Min %04x X Max %04x\n", m_posminx, m_posmaxx);
+ break;
+ }
+ }
+ else if (m_command == 0x2c)
+ {
+ m_displaybuffer[((m_posx + (m_posy * 0x200))) & 0x1ffff] = data;
+
+ m_posx++;
+ if (m_posx > m_posmaxx)
+ {
+ m_posx = m_posminx;
+ m_posy++;
+
+ if (m_posy > m_posmaxy)
+ {
+ m_posy = m_posminy;
+ }
+ }
+ }
+ else if (m_command == 0x36) // MADCTL (Memory Data Access Control)
+ {
+ switch (m_commandstep)
+ {
+ case 0: logerror("MADCTL set to %02x\n", data); break;
+ default: logerror("unexpected parameter for command %02x\n", m_command); break;
+ }
+ }
+ else if (m_command == 0x3a) // COLMOD (Interface Pixel Format)
+ {
+ switch (m_commandstep)
+ {
+ case 0: logerror("COLMOD set to %02x\n", data); break;
+ default: logerror("unexpected parameter for command %02x\n", m_command); break;
+ }
+ }
+ else if (m_command == 0xb1) // FRMCTR1 (Frame Rate Control, normal mode / full colors)
+ {
+ switch (m_commandstep)
+ {
+ case 0: logerror("FRMCTR1 param 1 set to %02x\n", data); break;
+ case 1: logerror("FRMCTR1 param 2 set to %02x\n", data); break;
+ case 2: logerror("FRMCTR1 param 3 set to %02x\n", data); break;
+ default: logerror("unexpected parameter for command %02x\n", m_command); break;
+ }
+ }
+ else if (m_command == 0xb2) // FRMCTR2 (Frame Rate Control, idle mode / 8 colors)
+ {
+ switch (m_commandstep)
+ {
+ case 0: logerror("FRMCTR2 param 1 set to %02x\n", data); break;
+ case 1: logerror("FRMCTR2 param 2 set to %02x\n", data); break;
+ case 2: logerror("FRMCTR2 param 3 set to %02x\n", data); break;
+ default: logerror("unexpected parameter for command %02x\n", m_command); break;
+ }
+ }
+ else if (m_command == 0xb3) // FRMCTR3 (Frame Rate Control, partial mode / full colors)
+ {
+ switch (m_commandstep)
+ {
+ case 0: logerror("FRMCTR3 param 1 set to %02x\n", data); break;
+ case 1: logerror("FRMCTR3 param 2 set to %02x\n", data); break;
+ case 2: logerror("FRMCTR3 param 3 set to %02x\n", data); break;
+ case 3: logerror("FRMCTR3 param 4 set to %02x\n", data); break;
+ case 4: logerror("FRMCTR3 param 5 set to %02x\n", data); break;
+ case 5: logerror("FRMCTR3 param 6 set to %02x\n", data); break;
+ default: logerror("unexpected parameter for command %02x\n", m_command); break;
+ }
+ }
+ else if (m_command == 0xb4) // INVCTR (Display Inversion Control)
+ {
+ switch (m_commandstep)
+ {
+ case 0: logerror("INVCTR set to %02x\n", data); break;
+ default: logerror("unexpected parameter for command %02x\n", m_command); break;
+ }
+ }
+ else if (m_command == 0xc0) // PWCTR1 (Power Control 1)
+ {
+ switch (m_commandstep)
+ {
+ case 0: logerror("PWCTR1 param 1 set to %02x\n", data); break;
+ case 1: logerror("PWCTR1 param 2 set to %02x\n", data); break;
+ case 2: logerror("PWCTR1 param 3 set to %02x\n", data); break; // UNKNOWN_BFTETRIS_LCDC has a 3rd param here, UNKNOWN_BFTETRIS_LCDCV does not
+ default: logerror("unexpected parameter for command %02x (%02x)\n", m_command, data); break;
+ }
+ }
+ else if (m_command == 0xc1) // PWCTR2 (Power Control 2)
+ {
+ switch (m_commandstep)
+ {
+ case 0: logerror("PWCTR2 param 1 set to %02x\n", data); break;
+ default: logerror("unexpected parameter for command %02x\n", m_command); break;
+ }
+ }
+ else if (m_command == 0xc2) // PWCTR3 (Power Control 3, normal mode / full colors)
+ {
+ switch (m_commandstep)
+ {
+ case 0: logerror("PWCTR3 param 1 set to %02x\n", data); break;
+ case 1: logerror("PWCTR3 param 2 set to %02x\n", data); break;
+ default: logerror("unexpected parameter for command %02x\n", m_command); break;
+ }
+ }
+ else if (m_command == 0xc3) // PWCTR4 (Power Control 4, idle mode / 8 colors)
+ {
+ switch (m_commandstep)
+ {
+ case 0: logerror("PWCTR4 param 1 set to %02x\n", data); break;
+ case 1: logerror("PWCTR4 param 2 set to %02x\n", data); break;
+ default: logerror("unexpected parameter for command %02x\n", m_command); break;
+ }
+ }
+ else if (m_command == 0xc4) // PWCTR5 (Power Control 5, partial mode / full colors)
+ {
+ switch (m_commandstep)
+ {
+ case 0: logerror("PWCTR5 param 1 set to %02x\n", data); break;
+ case 1: logerror("PWCTR5 param 2 set to %02x\n", data); break;
+ default: logerror("unexpected parameter for command %02x\n", m_command); break;
+ }
+ }
+ else if (m_command == 0xc5) // VMCTR (VCOM Control)
+ {
+ switch (m_commandstep)
+ {
+ case 0: logerror("VMCTR param 1 set to %02x\n", data); break;
+ default: logerror("unexpected parameter for command %02x\n", m_command); break;
+ }
+ }
+ else if (m_command == 0xe0) // GMCTRP (Gamma +polarity Correction Characteristics)
+ {
+ if (m_commandstep < 16)
+ {
+ logerror("GMCTRP param %d set to %02x\n", m_commandstep + 1, data);
+ }
+ else
+ {
+ logerror("unexpected parameter for command %02x\n", m_command);
+ }
+ }
+ else if (m_command == 0xe1) // GMCTRN (Gamma -polarity Correction Characteristics)
+ {
+ if (m_commandstep < 16)
+ {
+ logerror("GMCTRN param %d set to %02x\n", m_commandstep + 1, data);
+ }
+ else
+ {
+ logerror("unexpected parameter for command %02x\n", m_command);
+ }
+ }
+
+ m_commandstep++;
+
+}
+
+void bftetris_lcdc_device::device_start()
+{
+ std::fill(std::begin(m_displaybuffer), std::end(m_displaybuffer), 0);
+ m_posx = 0;
+ m_posy = 0;
+ m_posminx = 0;
+ m_posmaxx = 0;
+ m_posminy = 0;
+ m_posmaxy = 0;
+ m_command = 0;
+ m_commandstep = 0;
+ m_displayon = 0;
+ m_sleep = 1;
+
+ save_item(NAME(m_displaybuffer));
+ save_item(NAME(m_posx));
+ save_item(NAME(m_posy));
+ save_item(NAME(m_posminx));
+ save_item(NAME(m_posmaxx));
+ save_item(NAME(m_posminy));
+ save_item(NAME(m_posmaxy));
+ save_item(NAME(m_command));
+ save_item(NAME(m_commandstep));
+ save_item(NAME(m_displayon));
+ save_item(NAME(m_sleep));
+}
+
+void bftetris_lcdc_device::device_reset()
+{
+}
diff --git a/src/mame/handheld/unknown_bftetris_lcdc.h b/src/mame/handheld/unknown_bftetris_lcdc.h
new file mode 100644
index 00000000000..7405becdc00
--- /dev/null
+++ b/src/mame/handheld/unknown_bftetris_lcdc.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+#ifndef MAME_HANDHELD_UNKNOWN_BFTETRIS_LCDC_H
+#define MAME_HANDHELD_UNKNOWN_BFTETRIS_LCDC_H
+
+#pragma once
+
+DECLARE_DEVICE_TYPE(UNKNOWN_BFTETRIS_LCDC, bftetris_lcdc_device)
+
+class bftetris_lcdc_device : public device_t
+{
+public:
+ // construction/destruction
+ bftetris_lcdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void lcdc_command_w(u16 data);
+ u16 lcdc_data_r();
+ void lcdc_data_w(u16 data);
+
+ u32 render_to_bitmap(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ u16 m_displaybuffer[512 * 256];
+ u16 m_posx, m_posy;
+ u16 m_posminx, m_posmaxx;
+ u16 m_posminy, m_posmaxy;
+ u8 m_command;
+ u8 m_commandstep;
+ u8 m_displayon;
+ u8 m_sleep;
+};
+
+#endif // MAME_HANDHELD_UNKNOWN_BFTETRIS_LCDC_H
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index c354afbe3a6..363ca3fe9ca 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -19628,6 +19628,48 @@ taturtf
@source:handheld/generalplus_gpel31xx.cpp
tamameet
+@source:handheld/generalplus_gpl162xx_lcdtype.cpp
+pcp8718
+pcp8728
+bkid218
+
+@source:handheld/generalplus_gpl951xx.cpp
+fixitflx
+bfdigdug
+bfgalaga
+bfmpac
+bfpacman
+bfspyhnt
+bftetris
+bubltea
+dsgnpal
+flufflav
+pockrmsr
+pokebala
+pokeissh
+pokemech
+pokgoget
+punifrnd
+punij1m
+punij1pk
+punij1pu
+punij2pk
+punirune
+punirunea
+punistar
+segapet1
+segapet1a
+segapet2
+segapet2a
+segapet3
+segapet3a
+segaptdx
+smkcatch
+smkgacha
+smkguras
+smkgurasa
+wiwcs
+
@source:handheld/gmaster.cpp
gmaster
@@ -36010,6 +36052,7 @@ dnce2000
nytsudo
papsudok
pjoypj001
+popstar
pv95in1
racechl8
vtvppong
@@ -36107,6 +36150,8 @@ vt25in1
vtboxing
vtpinball
vtsndtest
+vjtv2500
+vjtv2501
wldsoctv
zdog
zudugo
@@ -36270,6 +36315,7 @@ tup240
unk128vt
unk198vt
unkra200
+urban240
vibes240
vibes240a
zl383
@@ -43830,6 +43876,9 @@ am1000
burningr
creepyrl
+@source:skeleton/amlogic_aml7212.cpp
+popstarz
+
@source:skeleton/amusement_6502.cpp
unkamus
@@ -44637,6 +44686,7 @@ luckyvl
@source:skeleton/tamagotchi_pix.cpp
precur2w
+rotom800
tamapix
@source:skeleton/tavernie.cpp
@@ -47724,47 +47774,7 @@ pokegach
prailpls
starbuck
vmastspi
-
-@source:tvgames/generalplus_gpl951xx.cpp
-fixitflx
-bfdigdug
-bfgalaga
-bfmpac
-bfpacman
-bfspyhnt
-bftetris
-bubltea
-dsgnpal
-flufflav
-pockrmsr
-pokebala
-pokeissh
-pokemech
-pokgoget
-punifrnd
-punij1m
-punij1pk
-punij1pu
-punij2pk
-punirune
-punistar
-segapet1
-segapet1a
-segapet2
-segapet2a
-segapet3
-segapet3a
-segaptdx
-smkcatch
-smkgacha
-smkguras
-smkgurasa
-wiwcs
-
-@source:tvgames/generalplus_gpl162xx_lcdtype.cpp
-pcp8718
-pcp8728
-bkid218
+wildking
@source:tvgames/generalplus_gpl32612.cpp
airobo
@@ -47793,6 +47803,7 @@ jak_ddhp
jak_prhp
jak_swbstrik
jak_tmnthp
+jpad
jpaddp
kidizmb
kidizmp
diff --git a/src/mame/nintendo/nes_clone.cpp b/src/mame/nintendo/nes_clone.cpp
index 132778164ca..6bc01e64179 100644
--- a/src/mame/nintendo/nes_clone.cpp
+++ b/src/mame/nintendo/nes_clone.cpp
@@ -6,13 +6,17 @@
*/
#include "emu.h"
+
+#include "bus/generic/slot.h"
+#include "bus/generic/carts.h"
#include "cpu/m6502/rp2a03.h"
+#include "machine/bankdev.h"
#include "video/ppu2c0x.h"
+
#include "emupal.h"
#include "screen.h"
+#include "softlist_dev.h"
#include "speaker.h"
-#include "machine/bankdev.h"
-
namespace {
@@ -120,6 +124,29 @@ private:
uint8_t m_rombase = 0;
};
+class nes_clone_popstar_state : public nes_clone_state
+{
+public:
+ nes_clone_popstar_state(const machine_config &mconfig, device_type type, const char *tag) :
+ nes_clone_state(mconfig, type, tag),
+ m_cart(*this, "cartslot"),
+ m_cart_region(nullptr)
+ { }
+ void nes_clone_popstar(machine_config &config) ATTR_COLD;
+
+private:
+ virtual void machine_start() override ATTR_COLD;
+
+ void nes_clone_popstar_map(address_map &map) ATTR_COLD;
+
+ uint8_t rom_r(offs_t offset);
+
+ DECLARE_DEVICE_IMAGE_LOAD_MEMBER(cart_load);
+
+ required_device<generic_slot_device> m_cart;
+ memory_region *m_cart_region;
+};
+
class nes_clone_sudoku_state : public nes_clone_state
{
public:
@@ -642,6 +669,65 @@ void nes_clone_dancexpt_state::nes_clone_dancexpt_map(address_map &map)
map(0xc000, 0xffff).rom().region("maincpu", 0x1c000);
}
+/**************************************************
+ Popstar Karaoke Specifics
+**************************************************/
+
+void nes_clone_popstar_state::nes_clone_popstar(machine_config &config)
+{
+ nes_clone_pal(config);
+ m_maincpu->set_addrmap(AS_PROGRAM, &nes_clone_popstar_state::nes_clone_popstar_map);
+
+ GENERIC_CARTSLOT(config, m_cart, generic_plain_slot, "popstar_cart");
+ m_cart->set_width(GENERIC_ROM8_WIDTH);
+ m_cart->set_device_load(FUNC(nes_clone_popstar_state::cart_load));
+
+ SOFTWARE_LIST(config, "cart_list").set_original("popstar_cart");
+}
+
+
+void nes_clone_popstar_state::nes_clone_popstar_map(address_map &map)
+{
+ nes_clone_basemap(map);
+
+ map(0x8000, 0xffff).r(FUNC(nes_clone_popstar_state::rom_r));
+}
+
+uint8_t nes_clone_popstar_state::rom_r(offs_t offset)
+{
+ if (!m_cart_region)
+ return 0x00;
+
+ return m_cart_region->base()[offset + 0x18000];
+}
+
+
+void nes_clone_popstar_state::machine_start()
+{
+ nes_clone_state::machine_start();
+
+ // if there's a cart, override the standard banking
+ if (m_cart && m_cart->exists())
+ {
+ m_cart_region = memregion(std::string(m_cart->tag()) + GENERIC_ROM_REGION_TAG);
+
+ // wordsum is printed on the ROM globs
+ u16 checksum = 0;
+ for (int i = 0; i < m_cart_region->bytes(); i++)
+ {
+ checksum += m_cart_region->base()[i];
+ }
+ logerror("wordsum was %04x\n", checksum);
+ }
+}
+
+DEVICE_IMAGE_LOAD_MEMBER(nes_clone_popstar_state::cart_load)
+{
+ uint32_t size = m_cart->common_get_size("rom");
+ m_cart->rom_alloc(size, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
+ m_cart->common_load_rom(m_cart->get_rom_base(), size, "rom");
+ return std::make_pair(std::error_condition(), std::string());
+}
/**************************************************
Dance 2000 Specifics
@@ -1451,6 +1537,10 @@ ROM_START( pv95in1 )
ROM_LOAD( "mx29f1610atc.ic2a", 0x00000, 0x200000, CRC(ca88e21c) SHA1(559d13806c9539f983ae929a0132af8ef381bd12) )
ROM_END
+ROM_START( popstar )
+ ROM_REGION( 0x200000, "maincpu", ROMREGION_ERASE00 )
+ // 2 globs in base unit, but neither seems to be a ROM, one might be a sound MCU
+ROM_END
void nes_clone_state::init_nes_clone()
{
@@ -1509,3 +1599,6 @@ CONS( 2005, racechl8, 0, 0, nes_clone_afbm7800, nes_clone, nes_clone_taikee_new_
// probably not VT based
CONS( 200?, pv95in1, 0, 0, nes_clone_afbm7800, nes_clone, nes_clone_taikee_new_state, init_nes_clone, "Play Vision", "Play Vision 95 Games in 1", MACHINE_NOT_WORKING )
+
+// mapper at 500x? has custom sound rather than standard NES APU or VTxx sounds, possibly an extra MCU or sound chip in the unit (see https://www.youtube.com/watch?v=OsydFoHW3Lc )
+CONS( 200?, popstar, 0, 0, nes_clone_popstar, nes_clone, nes_clone_popstar_state, init_nes_clone, "<unknown>", "Popstar Karaoke", MACHINE_NOT_WORKING )
diff --git a/src/mame/nintendo/nes_vt02_vt03.cpp b/src/mame/nintendo/nes_vt02_vt03.cpp
index 30aa2d40d20..22c913c649a 100644
--- a/src/mame/nintendo/nes_vt02_vt03.cpp
+++ b/src/mame/nintendo/nes_vt02_vt03.cpp
@@ -131,6 +131,8 @@ public:
nes_vt_state(mconfig, type, tag)
{ }
+ void nes_vt_pjoy_1mb(machine_config &config) ATTR_COLD;
+ void nes_vt_pjoy_2mb(machine_config &config) ATTR_COLD;
void nes_vt_pjoy_4mb(machine_config &config) ATTR_COLD;
};
@@ -699,16 +701,27 @@ void nes_vt_hum_state::nes_vt_hummer_4mb(machine_config &config)
m_soc->set_addrmap(AS_PROGRAM, &nes_vt_hum_state::vt_external_space_map_4mbyte);
}
-void nes_vt_pjoy_state::nes_vt_pjoy_4mb(machine_config &config)
+void nes_vt_pjoy_state::nes_vt_pjoy_1mb(machine_config &config)
{
NES_VT02_VT03_SOC(config, m_soc, NTSC_APU_CLOCK);
configure_soc(m_soc);
- m_soc->set_addrmap(AS_PROGRAM, &nes_vt_sp69_state::vt_external_space_map_4mbyte);
+ m_soc->set_addrmap(AS_PROGRAM, &nes_vt_sp69_state::vt_external_space_map_1mbyte);
//m_soc->set_8000_scramble(0x4, 0x5, 0x0, 0x1, 0x2, 0x3); // this is the default config in the SoC device
m_soc->set_8006_scramble(0x8, 0x7);
m_soc->set_410x_scramble(0x8, 0x7);
}
+void nes_vt_pjoy_state::nes_vt_pjoy_2mb(machine_config &config)
+{
+ nes_vt_pjoy_1mb(config);
+ m_soc->set_addrmap(AS_PROGRAM, &nes_vt_sp69_state::vt_external_space_map_2mbyte);
+}
+
+void nes_vt_pjoy_state::nes_vt_pjoy_4mb(machine_config &config)
+{
+ nes_vt_pjoy_1mb(config);
+ m_soc->set_addrmap(AS_PROGRAM, &nes_vt_sp69_state::vt_external_space_map_4mbyte);
+}
void nes_vt_sp69_state::nes_vt_4mb_sp69(machine_config &config)
{
@@ -1287,6 +1300,16 @@ ROM_START( pjoys60 )
ROM_LOAD( "power joy supermax 60-in-1.prg", 0x00000, 0x400000, CRC(1ab45228) SHA1(d148924afc39fc588235331a1a30df6e0d8e1e18) )
ROM_END
+ROM_START( vjtv2500 )
+ ROM_REGION( 0x100000, "mainrom", ROMREGION_ERASEFF )
+ ROM_LOAD( "tvjoypro2500.u2", 0x00000, 0x100000, CRC(d2e29e79) SHA1(c04cb4af3236d1cd568c18550035c69d66bb897e) )
+ROM_END
+
+ROM_START( vjtv2501 )
+ ROM_REGION( 0x200000, "mainrom", ROMREGION_ERASEFF )
+ ROM_LOAD( "tvjoypro2501.bin", 0x00000, 0x200000, CRC(9a1a3aef) SHA1(b0ddb464f6d0e8e7ba5714335c8eb1d0d52d481f) )
+ROM_END
+
ROM_START( joysti30 )
ROM_REGION( 0x400000, "mainrom", 0 )
ROM_LOAD( "joystick30.bin", 0x00000, 0x400000, CRC(b3f089af) SHA1(478d53d38eeffdbc4a1271d0e060aeb29e919502) )
@@ -1612,6 +1635,10 @@ CONS( 200?, pjoyn50, 0, 0, nes_vt_4mb, nes_vt, nes_vt_state, empty
CONS( 200?, pjoys30, 0, 0, nes_vt_pjoy_4mb, nes_vt, nes_vt_pjoy_state, empty_init, "<unknown>", "PowerJoy Supermax 30 in 1", MACHINE_IMPERFECT_GRAPHICS )
CONS( 200?, pjoys60, 0, 0, nes_vt_pjoy_4mb, nes_vt, nes_vt_pjoy_state, empty_init, "<unknown>", "PowerJoy Supermax 60 in 1", MACHINE_IMPERFECT_GRAPHICS )
+// these have WT051-CPU on the sub-board, and WT062-MAIN on the main board
+CONS( 2004, vjtv2500, 0, 0, nes_vt_pjoy_1mb, nes_vt, nes_vt_pjoy_state, empty_init, "VideoJet", "TV Joy Pro 15-in-1 (2500)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
+CONS( 2005, vjtv2501, 0, 0, nes_vt_pjoy_2mb, nes_vt, nes_vt_pjoy_state, empty_init, "VideoJet", "TV Joy Pro 30-in-1 (2501)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
+
// doesn't boot, bad dump
CONS( 201?, cbrs8, 0, 0, nes_vt_16mb, nes_vt, nes_vt_state, empty_init, "CoolBoy", "CoolBoy RS-8 168 in 1", MACHINE_NOT_WORKING )
diff --git a/src/mame/nintendo/nes_vt369_vtunknown.cpp b/src/mame/nintendo/nes_vt369_vtunknown.cpp
index 0ce35eda01a..f50e96a25ee 100644
--- a/src/mame/nintendo/nes_vt369_vtunknown.cpp
+++ b/src/mame/nintendo/nes_vt369_vtunknown.cpp
@@ -923,6 +923,10 @@ ROM_START( 240in1ar )
ROM_LOAD( "mw-106-2g.u3", 0x00000, 0x8000000, CRC(c46d2ca9) SHA1(0fff7d3461ff620c5b5e43f54f9e7badd089b951) )
ROM_END
+ROM_START( urban240 )
+ ROM_REGION( 0x8000000, "mainrom", 0 )
+ ROM_LOAD( "urban240.u3", 0x00000, 0x8000000, CRC(73d03f0d) SHA1(a1615dba39e9114ace7a8ad68f46195da655bf35) )
+ROM_END
ROM_START( rtvgc300 )
ROM_REGION( 0x8000000, "mainrom", 0 )
@@ -1820,15 +1824,17 @@ CONS( 201?, dgun2572, 0, 0, vt36x_32mb, vt369, vt36x_state, init_dgun2572, "dr
// NOT SPI roms, altswap sets code starts with '6a'
-CONS( 201?, red5mam, 0, 0, vt36x_altswap_32mb_4banks_red5mam, vt369, vt36x_state, empty_init, "Red5", "Mini Arcade Machine (Red5, 'Xtra Game')", MACHINE_NOT_WORKING ) // 128Mbyte ROM, must be externally banked or different addressing scheme
+CONS( 201?, red5mam, 0, 0, vt36x_altswap_32mb_4banks_red5mam, vt369, vt36x_state, empty_init, "Red5", "Mini Arcade Machine (Red5, 'Xtra Game')", MACHINE_NOT_WORKING )
+
+CONS( 2016, dgun2593, 0, 0, vt36x_altswap_32mb_4banks_red5mam, vt369, vt36x_state, empty_init, "dreamGEAR", "My Arcade Retro Arcade Machine - 300 Handheld Video Games (DGUN-2593)", MACHINE_NOT_WORKING )
-CONS( 2016, dgun2593, 0, 0, vt36x_altswap_32mb_4banks_red5mam, vt369, vt36x_state, empty_init, "dreamGEAR", "My Arcade Retro Arcade Machine - 300 Handheld Video Games (DGUN-2593)", MACHINE_NOT_WORKING ) // 128Mbyte ROM, must be externally banked or different addressing scheme
+CONS( 201?, urban240, 0, 0, vt36x_altswap_32mb_4banks_red5mam, vt369, vt36x_state, empty_init, "Urban Outfitters", "Mini Arcade Machine 240-in-1 (translucent case)", MACHINE_NOT_WORKING )
CONS( 200?, gcs2mgp, 0, 0, vt36x_altswap_16mb, vt369_rot, vt36x_state, empty_init, "Jungle's Soft", "Mini Game Player 48-in-1", MACHINE_NOT_WORKING | ROT270 )
// Not the same as the other 240-in-1 machine from Thumbs Up below (tup240) This one makes greater use of newer VT features with most games having sampled music, not APU sound.
// Several of the games contained in here are buggy / broken on real hardware (see https://www.youtube.com/watch?v=-mgGNaDQ1HE )
-CONS( 201?, 240in1ar, 0, 0, vt36x_altswap_32mb_4banks_red5mam, vt369, vt36x_state, empty_init, "Thumbs Up", "Mini Arcade Machine (Thumbs Up, 240IN1ARC)", MACHINE_NOT_WORKING ) // 128Mbyte ROM, must be externally banked or different addressing scheme
+CONS( 201?, 240in1ar, 0, 0, vt36x_altswap_32mb_4banks_red5mam, vt369, vt36x_state, empty_init, "Thumbs Up", "Mini Arcade Machine (Thumbs Up, 240IN1ARC)", MACHINE_NOT_WORKING )
// portable fan + famiclone combo handheld, very similar to 240in1ar
CONS( 2020, nubsupmf, 0, 0, vt36x_altswap_4mb, vt369, vt36x_state, empty_init, "<unknown>", "NubSup Mini Game Fan", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS )
diff --git a/src/mame/skeleton/amlogic_aml7212.cpp b/src/mame/skeleton/amlogic_aml7212.cpp
new file mode 100644
index 00000000000..81ec50e9b9d
--- /dev/null
+++ b/src/mame/skeleton/amlogic_aml7212.cpp
@@ -0,0 +1,73 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+// has an @mlogic AML7212, unknown CPU core
+
+#include "emu.h"
+
+#include "screen.h"
+#include "speaker.h"
+
+namespace {
+
+class amlogic_aml7212_popstarz_state : public driver_device
+{
+public:
+ amlogic_aml7212_popstarz_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag)
+ , m_screen(*this, "screen")
+ { }
+
+ void popstarz(machine_config &config) ATTR_COLD;
+
+protected:
+ virtual void machine_start() override ATTR_COLD;
+ virtual void machine_reset() override ATTR_COLD;
+
+private:
+ required_device<screen_device> m_screen;
+
+ uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+ void mem_map(address_map &map) ATTR_COLD;
+};
+
+uint32_t amlogic_aml7212_popstarz_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ return 0;
+}
+
+void amlogic_aml7212_popstarz_state::machine_start()
+{
+}
+
+void amlogic_aml7212_popstarz_state::machine_reset()
+{
+}
+
+static INPUT_PORTS_START( popstarz )
+INPUT_PORTS_END
+
+void amlogic_aml7212_popstarz_state::popstarz(machine_config &config)
+{
+ SCREEN(config, m_screen, SCREEN_TYPE_LCD);
+ m_screen->set_refresh_hz(60);
+ m_screen->set_size(320, 256); // unknown resolution
+ m_screen->set_visarea(0, 320-1, 0, 255-1);
+ m_screen->set_screen_update(FUNC(amlogic_aml7212_popstarz_state::screen_update));
+
+ SPEAKER(config, "mono").front_center();
+}
+
+ROM_START( popstarz )
+ ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASEFF )
+ // contains compressed(?) code/data
+ ROM_LOAD( "kh29lv160cb.ic903", 0x000000, 0x200000, CRC(95c79782) SHA1(eda0dda4ee0f108f8259e7805505a4e5d29dc5d7) )
+
+ ROM_REGION( 0x42000000, "nand", ROMREGION_ERASEFF )
+ ROM_LOAD( "k9g8g08u0a_tsop48.ic902", 0x000000, 0x42000000, CRC(4a0a22cf) SHA1(eba69c5432c6b730e9ab50b196bedc1928890f5f) )
+ROM_END
+
+} // anonymous namespace
+
+CONS( 201?, popstarz, 0, 0, popstarz, popstarz, amlogic_aml7212_popstarz_state, empty_init, "<unknown>", "Popstarz Karaoke (GK8000)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING )
diff --git a/src/mame/skeleton/tamagotchi_pix.cpp b/src/mame/skeleton/tamagotchi_pix.cpp
index 6285bca8ff9..fd29a2b643b 100644
--- a/src/mame/skeleton/tamagotchi_pix.cpp
+++ b/src/mame/skeleton/tamagotchi_pix.cpp
@@ -15,9 +15,8 @@ SN73231M1N-000
Dual-core ARM Cortex-M3 SoC (Sonix SNC7320 series)
-other sources mention that the Tamagotchi Pix uses a GeneralPlus GP32 (ARM)
-series CPU, so are there multiple hardware revisions or is that information
-incorrect?
+Other sources mention that the Tamagotchi Pix uses a GeneralPlus GP32 (ARM)
+series CPU, apparently the GP32 was only used for the first production run.
device has a camera
@@ -146,6 +145,12 @@ ROM_START( precur2w )
ROM_LOAD( "by25q64ess.bin", 0x000000, 0x800000, CRC(35351cd0) SHA1(0b07a613c3e9b638e531ba668d72ebefd459d0d4) )
ROM_END
+ROM_START( rotom800 )
+ // this is a NAND ROM so there's an internal bootstrap at least
+ ROM_REGION( 0x10800000, "maincpu", ROMREGION_ERASEFF ) // SNC7320A header in ROM
+ ROM_LOAD( "mx35lf2ge4ad.u1", 0x000000, 0x10800000, CRC(b0ad2e03) SHA1(ec2d5254b2a3e183389bcf1cbb50ceb08f9c7cd3) )
+ROM_END
+
} // anonymous namespace
CONS( 2020, tamapix, 0, 0, tamapix, tamapix, tamagotchi_pix_state, empty_init, "Bandai", "Tamagotchi Pix", MACHINE_NO_SOUND | MACHINE_NOT_WORKING )
@@ -154,5 +159,8 @@ CONS( 2020, tamapix, 0, 0, tamapix, tamapix, tamagotchi
// "Muscat A 2022 01 15" on PCB
CONS( 2022, precur2w, 0, 0, precur2w, tamapix, precur2w_state, empty_init, "Bandai", "Delicious Party PreCure Heart Cure Watch & Heart Fruit Pendant Cover Special Set (Japan)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING )
+// キミもポケモン博士! スマホロトムPad
+CONS( 2022, rotom800, 0, 0, precur2w, tamapix, precur2w_state, empty_init, "Bandai", "Kimi mo Pokemon Hakase! Rotom Pad (Japan)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING )
+
// わんだふるぷりきゅあ! どうぶつおせわがた~っぷり あつめておせわしよ キラニコトランク
// Wonderful Precure! Dōbutsu Osewa ga Ta~ppuri Atsumete Osewa Shiyo♥ Kiraniko Trunk (c)2024 Bandai
diff --git a/src/mame/tvgames/generalplus_gpl16250.cpp b/src/mame/tvgames/generalplus_gpl16250.cpp
index 24a231fb295..e43e55a0e57 100644
--- a/src/mame/tvgames/generalplus_gpl16250.cpp
+++ b/src/mame/tvgames/generalplus_gpl16250.cpp
@@ -152,12 +152,6 @@ void gcm394_game_state::base(machine_config &config)
SPEAKER(config, "speaker", 2).front();
}
-void gcm394_game_state::base_alt_irq(machine_config &config)
-{
- gcm394_game_state::base(config);
- m_maincpu->set_alt_periodic_irq(true);
-}
-
void gcm394_game_state::machine_start()
{
space(0).specific(m_memory);
diff --git a/src/mame/tvgames/generalplus_gpl16250.h b/src/mame/tvgames/generalplus_gpl16250.h
index 6a533948cb6..dc75dc4b170 100644
--- a/src/mame/tvgames/generalplus_gpl16250.h
+++ b/src/mame/tvgames/generalplus_gpl16250.h
@@ -29,7 +29,6 @@ public:
}
void base(machine_config &config) ATTR_COLD;
- void base_alt_irq(machine_config &config) ATTR_COLD;
void cs_map_base(address_map &map) ATTR_COLD;
diff --git a/src/mame/tvgames/generalplus_gpl16250_rom.cpp b/src/mame/tvgames/generalplus_gpl16250_rom.cpp
index 971a20692b2..641803bef97 100644
--- a/src/mame/tvgames/generalplus_gpl16250_rom.cpp
+++ b/src/mame/tvgames/generalplus_gpl16250_rom.cpp
@@ -406,7 +406,9 @@ static INPUT_PORTS_START( beijuehh )
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN )
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT )
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT )
- PORT_BIT( 0x0e00, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_UNKNOWN ) // this one must be kept in this state or the machine will freeze after a few seconds?
PORT_BIT( 0xe000, IP_ACTIVE_LOW, IPT_UNKNOWN )
@@ -602,6 +604,11 @@ void beijuehh_game_state::beijuehh(machine_config &config)
m_maincpu->portb_out().set(FUNC(beijuehh_game_state::beijuehh_portb_w));
m_maincpu->portd_out().set(FUNC(beijuehh_game_state::beijuehh_portd_w));
+
+ // beijuehh and bornkidh have a protection function that runs in the timebase interrupt
+ // for beijuehh it causes freezes in xracer3, in bornkidh it runs at all times and even
+ // freezes the menus. disable the timebase interrupts in the core until this is understood.
+ m_maincpu->disable_timebase_interrupts();
}
@@ -823,7 +830,7 @@ CONS(2009, smartfpf, smartfp, 0, base, smartfp, gcm394_game_state, empty_init,
CONS(2008, fpsport, 0, 0, base, base, gcm394_game_state, empty_init, "Fisher-Price", "3-in-1 Smart Sports! (US)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
// uses a barcode card scanner device with custom cards
-CONS(200?, dressmtv, 0, 0, base_alt_irq, dressmtv, gcm394_game_state, empty_init, "Takara Tomy", "Disney Princess Dress Mania TV (Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND )
+CONS(200?, dressmtv, 0, 0, base, dressmtv, gcm394_game_state, empty_init, "Takara Tomy", "Disney Princess Dress Mania TV (Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND )
// These are ports of the 'Family Sport' games to GPL16250 type hardware, but they don't seem to use many unSP 2.0 instructions.
// The menu style is close to 'm505neo' but the game selection is closer to 'dnv200fs' (but without the Sports titles removed, and with a few other extras not found on that unit)
diff --git a/src/mame/tvgames/generalplus_gpl16250_spi.cpp b/src/mame/tvgames/generalplus_gpl16250_spi.cpp
index 20b6ffc6575..cb71cfb9544 100644
--- a/src/mame/tvgames/generalplus_gpl16250_spi.cpp
+++ b/src/mame/tvgames/generalplus_gpl16250_spi.cpp
@@ -175,6 +175,18 @@ ROM_START( jspodred )
ROM_LOAD16_WORD_SWAP( "gpr5l322.sfrom1", 0x0000, 0x400000, CRC(5bd08294) SHA1(3a4a76b7b30c0dcf8184cb94d75819c382c1c668) )
ROM_END
+ROM_START( wildking )
+ ROM_REGION16_BE( 0x40000, "maincpu:internal", ROMREGION_ERASE00 )
+ //ROM_LOAD16_WORD_SWAP( "internal.rom", 0x00000, 0x40000, NO_DUMP ) // used as bootstrap only (if it exists at all)
+
+ ROM_REGION(0x1000000, "maincpu", ROMREGION_ERASE00)
+ ROM_LOAD16_WORD_SWAP( "mx25l12835f.sfrom1", 0x0000, 0x1000000, CRC(bc4cace6) SHA1(1fc2e28b194a59ddb1ed9a63978064d2d0a6ab8c) )
+
+ // there was an SD card slot, but the "Power Up Cartridge" included was just a piece of plastic, not a real card
+ // other software may be available for the unit however.
+ROM_END
+
+
ROM_START( pokegach )
ROM_REGION16_BE( 0x40000, "maincpu:internal", ROMREGION_ERASE00 )
@@ -331,6 +343,8 @@ CONS(2013, anpaneng, 0, 0, generalplus_gpspispi, gcm394, generalplus_gps
// 甲虫王者ムシキング むしとりバトルずかん (JS Pod on PCB)
CONS(201?, jspodred, 0, 0, generalplus_gpspispi, gcm394, generalplus_gpspispi_game_state, init_spi, "Sega Toys", "Kouchuu Ouja Mushiking: Mushitori Battle Zukan (Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
+CONS(201?, wildking, 0, 0, generalplus_gpspispi, gcm394, generalplus_gpspispi_game_state, init_spi, "Sega Toys", "Wild King (Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
+
CONS(2015, bkrankp, 0, 0, generalplus_gpspispi_bkrankp, gcm394, generalplus_gpspispi_bkrankp_game_state, init_spi, "Bandai", "Karaoke Ranking Party (Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
CONS(2015, pokegach, 0, 0, generalplus_gpspispi_bkrankp, gcm394, generalplus_gpspispi_bkrankp_game_state, init_spi, "Tomy", "Pokegacha (20150902, Japan)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
diff --git a/src/mame/tvgames/generalplus_gpl32612.cpp b/src/mame/tvgames/generalplus_gpl32612.cpp
index c599fff06e8..19ed645ec97 100644
--- a/src/mame/tvgames/generalplus_gpl32612.cpp
+++ b/src/mame/tvgames/generalplus_gpl32612.cpp
@@ -498,6 +498,14 @@ ROM_START( jpaddp )
ROM_LOAD( "mx25l6406e.sfrom1", 0x0000, 0x800000, CRC(4e482f10) SHA1(e393090a98324fb33374d2203ef7763e1e15b361) )
ROM_END
+ROM_START( jpad )
+ ROM_REGION( 0x800000, "spi", ROMREGION_ERASE00 )
+ ROM_LOAD( "mx25l6406e.sfrom1", 0x0000, 0x800000, CRC(be2d7c59) SHA1(9b205b1a35e26720726fecac2d4523ef9a6e4d9d) )
+
+ DISK_REGION( "sdcard" ) // 2GB SD Card (might just be user data)
+ DISK_IMAGE( "jewel", 0, SHA1(6b39a2617ebbf9b2bebbf5ae118ea032072c011e) )
+ROM_END
+
ROM_START( dinopc )
ROM_REGION16_BE( 0x40000, "maincpu:internal", ROMREGION_ERASE00 )
ROM_LOAD16_WORD_SWAP( "internal.rom", 0x00000, 0x40000, NO_DUMP ) // used as bootstrap only?
@@ -691,6 +699,8 @@ CONS( 201?, segcarsh, 0, 0, gpl32612, gpl32612, generalpl
// uses glob, has GPSPI header
CONS( 201?, jpaddp, 0, 0, gpl32612, gpl32612, generalplus_gpl32612_game_state, empty_init, "Sega Toys", "Jewel Pad Diamond Premium (Japan)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
+CONS( 201?, jpad, 0, 0, gpl32612, gpl32612, generalplus_gpl32612_game_state, empty_init, "Sega Toys", "Jewel Pad (Japan)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
+
// uses GPL32600A
// マウスでバトル!! 恐竜図鑑パソコン
CONS( 2020, dinopc, 0, 0, gpl32612, gpl32612, generalplus_gpl32612_game_state, empty_init, "Sega Toys", "Mouse de Battle!! Kyouryuu Zukan PC (Japan)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)