summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
diff options
context:
space:
mode:
author mamehaze <140764005+mamehaze@users.noreply.github.com>2026-05-13 17:40:50 +0100
committer GitHub <noreply@github.com>2026-05-13 18:40:50 +0200
commitb66dcb71a2a699526f2ffd9261c20d9ab4876fc4 (patch)
tree80cfaaa63fec0099b0ce65beb6c9b2303f8c99ba /src/devices
parent53ae362496ad8b8800a057c3c274e65033f574f9 (diff)
Current Plug & Play / Handhelds PR / GPL951xx milestone (9 new sets, 3 softlist entries) (#15334)
- continued work on GPL951xx and GPL162xx further documenting registers / differences - created stub device for GPL951xx RTC allowing some sets to boot a bit further - added LCDC to GPL951xx based games (all of them have one) and allow bftetris to render graphics as it programs it directly - added 'timebase' timers to GPL951xx and GPL162xx emulation, which was also required by bftetris and others. Discovered that bornkidh and beijuehh have a protection function in the timebase interrupt that needs studying (disabled it in those cases for now) - added 'scheduler' interrupt to GPL162xx instead of unknown timer hack, used by smartfp - moved some code out into devices - split GPL951xx and GPL162xx implementations as despite similarities there are many differences and sharing a base doesn't make much sense - removed some hacks (dressmtv doesn't boot to title anymore, but that will be addressed later) - moved a few files around (GPL951xx has no TV out, so moved those out of tvgames) New working systems ------------------- TV Joy Pro 15-in-1 (2500) [Team Europe, David Haywood] TV Joy Pro 30-in-1 (2501) [Team Europe, David Haywood] New clones marked not working ----------------------------- Punirunes (HXR-1 PCB) [Team Europe] New systems marked not working ------------------------------ Popstar Karaoke [Team Europe, David Haywood] Wild King (Japan) [Team Europe, David Haywood] Jewel Pad (Japan) [Team Europe, David Haywood] Kimi mo Pokemon Hakase! Rotom Pad (Japan) [Team Europe] Popstarz Karaoke (GK8000) [Team Europe] Mini Arcade Machine 240-in-1 (translucent case) [Team Europe, David Haywood] New software list items marked not working ------------------------------------------ popstar_cart.xml: Popstar Karaoke - 5 Songs [Team Europe, David Haywood] Popstar Karaoke Vol. 1 [Team Europe, David Haywood] Popstar Karaoke Vol. 2 [Team Europe, David Haywood]
Diffstat (limited to 'src/devices')
-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
12 files changed, 2279 insertions, 618 deletions
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