summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
diff options
context:
space:
mode:
author mamehaze <140764005+mamehaze@users.noreply.github.com>2026-05-19 20:44:10 +0100
committer GitHub <noreply@github.com>2026-05-19 21:44:10 +0200
commitf125c7a141c26513ca3210276b45e781920b4f16 (patch)
tree5c064d112dea32f8e395a08490d448fd2927e4ce /src/devices
parent46dbf56bb9507a5c403189175451d370aad7ac6e (diff)
gpl951xx - more aggressive template use (#15352)
- generalplus_gpl951xx_soc - use templates for timebase and timers, add more timers [David Haywood] - generalplus_gpl951xx_soc - basic 'manual' ADC mode support [David Haywood] - generalplus_gpl951xx_soc - provide address when required in autocmd mode for spifc, to prevent wrong addresses being written [David Haywood] - generalplus_gpl951xx_soc - add stub logging more registers [David Haywood] - gpl_renderer - port improved linemap code from spg_renderer so that other BPPs can be handled [David Haywood] - generalplus_gpl951xx_rtc - allow setting / reading of timer registers [David Haywood] - generalplus_gpl951xx.cpp - various cleanups driver-side, including template use [David Haywood]
Diffstat (limited to 'src/devices')
-rw-r--r--src/devices/machine/generalplus_gpl162xx_soc.cpp10
-rw-r--r--src/devices/machine/generalplus_gpl162xx_soc_video.cpp19
-rw-r--r--src/devices/machine/generalplus_gpl951xx_rtc.cpp114
-rw-r--r--src/devices/machine/generalplus_gpl951xx_rtc.h20
-rw-r--r--src/devices/machine/generalplus_gpl951xx_soc.cpp602
-rw-r--r--src/devices/machine/generalplus_gpl951xx_soc.h89
-rw-r--r--src/devices/machine/generalplus_gpl_chx.cpp42
-rw-r--r--src/devices/machine/generalplus_gpl_chx.h3
-rw-r--r--src/devices/machine/generalplus_gpl_dma.cpp7
-rw-r--r--src/devices/machine/generalplus_gpl_timebase.cpp163
-rw-r--r--src/devices/machine/generalplus_gpl_timebase.h28
-rw-r--r--src/devices/machine/generic_spi_flash.cpp12
-rw-r--r--src/devices/machine/gpl_renderer.cpp131
-rw-r--r--src/devices/machine/gpl_renderer.h2
14 files changed, 777 insertions, 465 deletions
diff --git a/src/devices/machine/generalplus_gpl162xx_soc.cpp b/src/devices/machine/generalplus_gpl162xx_soc.cpp
index 3dbc7c4f554..9ddda8f8479 100644
--- a/src/devices/machine/generalplus_gpl162xx_soc.cpp
+++ b/src/devices/machine/generalplus_gpl162xx_soc.cpp
@@ -577,13 +577,13 @@ u16 sunplus_gcm394_base_device::int_status2_r()
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::int_status2_r\n", machine().describe_context());
u16 ret = 0;
- if (m_gpl_timebase->timebasea_irq_flag())
+ if (m_gpl_timebase->timebase_irq_flag<0>())
ret |= 0x0100;
- if (m_gpl_timebase->timebaseb_irq_flag())
+ if (m_gpl_timebase->timebase_irq_flag<1>())
ret |= 0x0200;
- if (m_gpl_timebase->timebasec_irq_flag())
+ if (m_gpl_timebase->timebase_irq_flag<2>())
ret |= 0x0400;
return ret;
@@ -693,7 +693,7 @@ void sunplus_gcm394_base_device::mint_ctrl_w(u16 data)
void sunplus_gcm394_base_device::update_interrupts(int state)
{
- if ((m_gpl_timebase->timebasea_irq_flag() && !m_disable_timebase_interrupts) || (m_gpl_timebase->timebaseb_irq_flag() && !m_disable_timebase_interrupts))
+ if ((m_gpl_timebase->timebase_irq_flag<0>() && !m_disable_timebase_interrupts) || (m_gpl_timebase->timebase_irq_flag<1>() && !m_disable_timebase_interrupts))
{
set_state_unsynced(UNSP_IRQ7_LINE, ASSERT_LINE);
}
@@ -702,7 +702,7 @@ void sunplus_gcm394_base_device::update_interrupts(int state)
set_state_unsynced(UNSP_IRQ7_LINE, CLEAR_LINE);
}
- if ((m_gpl_timebase->timebasec_irq_flag() && !m_disable_timebase_interrupts) || (m_rtc_int_status & 0x0100))
+ if ((m_gpl_timebase->timebase_irq_flag<2>() && !m_disable_timebase_interrupts) || (m_rtc_int_status & 0x0100))
{
set_state_unsynced(UNSP_IRQ6_LINE, ASSERT_LINE);
}
diff --git a/src/devices/machine/generalplus_gpl162xx_soc_video.cpp b/src/devices/machine/generalplus_gpl162xx_soc_video.cpp
index 76c94326008..031587fa8bb 100644
--- a/src/devices/machine/generalplus_gpl162xx_soc_video.cpp
+++ b/src/devices/machine/generalplus_gpl162xx_soc_video.cpp
@@ -282,7 +282,7 @@ void gcm394_base_video_device::device_reset()
for (int i=0;i<0x100 * 0x10;i++)
m_paletteram[i] = machine().rand()&0x7fff;
- m_707f = 0x0000;
+ m_707f = 0x0001;
m_703a_palettebank = 0x0000;
m_video_irq_enable = 0x0000;
m_video_irq_status = 0x0000;
@@ -883,7 +883,22 @@ u16 gcm394_base_video_device::ppu_enable_r()
}
void gcm394_base_video_device::ppu_enable_w(u16 data)
{
- LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::ppu_enable_w %04x\n", machine().describe_context(), data);
+ u8 save_rom = (data & 0x8000) >> 15;
+ u8 unused = (data & 0x7000) >> 12;
+ u8 fb_mono = (data & 0x0c00) >> 10;
+ u8 spr25d = (data & 0x0200) >> 9;
+ u8 fb_format = (data & 0x0100) >> 8;
+ u8 fb_en = (data & 0x0080) >> 7;
+ u8 free_adr = (data & 0x0040) >> 6;
+ u8 vga_nointl = (data & 0x0020) >> 5;
+ u8 vga_en = (data & 0x0010) >> 4;
+ u8 tx_botup = (data & 0x0008) >> 3;
+ u8 tx_direct = (data & 0x0004) >> 2;
+ u8 tchar = (data & 0x0002) >> 1;
+ u8 ppu_en = (data & 0x0001) >> 0;
+
+ LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::ppu_enable_w %04x (save_rom %01x, unused %01x, fb_mono %01x, spr25d %01x, fb_format %01x, fb_en %01x, free_adr %01x, vga_nointl %01x, vga_en %01x, tx_botup %01x, tx_direct %01x, tchar %01x, ppu_en %01x)\n",
+ machine().describe_context(), data, save_rom, unused, fb_mono, spr25d, fb_format, fb_en, free_adr, vga_nointl, vga_en, tx_botup, tx_direct, tchar, ppu_en);
m_707f = data;
m_renderer->set_video_reg_7f(data);
diff --git a/src/devices/machine/generalplus_gpl951xx_rtc.cpp b/src/devices/machine/generalplus_gpl951xx_rtc.cpp
index da303406d4a..da0414f5f46 100644
--- a/src/devices/machine/generalplus_gpl951xx_rtc.cpp
+++ b/src/devices/machine/generalplus_gpl951xx_rtc.cpp
@@ -6,7 +6,7 @@
#define LOG_RTC (1U << 1)
-#define VERBOSE (0)
+#define VERBOSE (LOG_RTC)
#include "logmacro.h"
@@ -36,10 +36,6 @@ inline void gpl951xx_rtc_device::writebyte(offs_t address, uint8_t data)
space().write_byte(address, data);
}
-void gpl951xx_rtc_device::device_validity_check(validity_checker &valid) const
-{
-}
-
void gpl951xx_rtc_device::device_start()
{
save_item(NAME(m_rtc_addr));
@@ -48,6 +44,15 @@ void gpl951xx_rtc_device::device_start()
save_item(NAME(m_reg40));
save_item(NAME(m_reg50));
+
+ save_item(NAME(m_loadcnt));
+ save_item(NAME(m_alarmdat));
+ save_item(NAME(m_timerval));
+
+ // not on reset? (should be saved as NV?)
+ m_loadcnt = 0;
+ m_alarmdat = 0;
+ m_timerval = 0;
}
void gpl951xx_rtc_device::device_reset()
@@ -60,24 +65,75 @@ void gpl951xx_rtc_device::device_reset()
m_reg50 = 0;
}
+// Reg00
+//
+// 4 Rtcclken
+// 3 Rtcrst
+// 2 Timerdir
+// 1 SWreset
+// 0 Busy
+
u8 gpl951xx_rtc_device::reg00_r()
{
LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg00_r\n", machine().describe_context());
return 0x00;
}
+// Reg01
+//
+// 3 Slow_clk
+// 2 Reserved
+// 1 Strong
+// 0 Reserved
+
u8 gpl951xx_rtc_device::reg01_r()
{
LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg01_r\n", machine().describe_context());
return 0x01;
}
+// Reg02
+//
+// 'reliable'
+
+u8 gpl951xx_rtc_device::reg02_r()
+{
+ LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg02_r\n", machine().describe_context());
+ return m_reg02;
+}
+
+void gpl951xx_rtc_device::reg02_w(u8 data)
+{
+ LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg02_w %02x\n", machine().describe_context(), data);
+ m_reg02 = data;
+}
+
+// Reg40
+//
+// 3 HalfSecint
+// 2 Rtcwakeup
+// 1 Alarmint
+// 0 Secint
+
+u8 gpl951xx_rtc_device::reg40_r()
+{
+ LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg40_r\n", machine().describe_context());
+ return m_reg40;
+}
+
void gpl951xx_rtc_device::reg40_w(u8 data)
{
LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg40_w %02x\n", machine().describe_context(), data);
m_reg40 = data;
}
+// Reg50
+//
+// 3 HalfSecint_en
+// 2 Rtcwakeup_en
+// 1 Alarmint_en
+// 0 Secint_en
+
u8 gpl951xx_rtc_device::reg50_r()
{
LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg50_r\n", machine().describe_context());
@@ -90,13 +146,49 @@ void gpl951xx_rtc_device::reg50_w(u8 data)
m_reg50 = data;
}
+void gpl951xx_rtc_device::loadcnt_w(offs_t offset, u8 data)
+{
+ u64 bits = (u64)0xff << (8 * offset);
+ u64 databits = (u64)data << (8 * offset);
+ m_loadcnt = m_loadcnt & ~bits;
+ m_loadcnt |= databits;
+
+ LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::loadcnt_w (offset %02x) %02x (loadcnt is now %08x%08x)\n", machine().describe_context(), offset, data, (u32)(m_loadcnt >> 32), (u32)(m_loadcnt & 0xffffffff));
+
+ // TODO: not sure this is how it's reloaded
+ if (offset == 5)
+ m_timerval = m_loadcnt;
+}
+
+void gpl951xx_rtc_device::alarmdat_w(offs_t offset, u8 data)
+{
+ u64 bits = (u64)0xff << (8 * offset);
+ u64 databits = (u64)data << (8 * offset);
+ m_alarmdat = m_alarmdat & ~bits;
+ m_alarmdat |= databits;
+
+ LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::alarmdat_w (offset %02x) %02x (alarmdat is now %08x%08x)\n", machine().describe_context(), offset, data, (u32)(m_loadcnt >> 32), (u32)(m_loadcnt & 0xffffffff));
+}
+
+u8 gpl951xx_rtc_device::timerval_r(offs_t offset)
+{
+ LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::timerval_r (offset %02x)\n", machine().describe_context(), offset);
+ return m_timerval >> (offset * 8);
+}
+
void gpl951xx_rtc_device::rtc_regs(address_map &map)
{
if (!has_configured_map(0))
{
map(0x00, 0x00).r(FUNC(gpl951xx_rtc_device::reg00_r));
map(0x01, 0x01).r(FUNC(gpl951xx_rtc_device::reg01_r));
- map(0x40, 0x40).w(FUNC(gpl951xx_rtc_device::reg40_w));
+ map(0x02, 0x02).rw(FUNC(gpl951xx_rtc_device::reg02_r), FUNC(gpl951xx_rtc_device::reg02_w));
+
+ map(0x10, 0x15).w(FUNC(gpl951xx_rtc_device::loadcnt_w));
+ map(0x20, 0x25).w(FUNC(gpl951xx_rtc_device::alarmdat_w));
+ map(0x30, 0x35).r(FUNC(gpl951xx_rtc_device::timerval_r));
+
+ map(0x40, 0x40).rw(FUNC(gpl951xx_rtc_device::reg40_r), FUNC(gpl951xx_rtc_device::reg40_w));
map(0x50, 0x50).rw(FUNC(gpl951xx_rtc_device::reg50_r), FUNC(gpl951xx_rtc_device::reg50_w));
// 0x80 - 0x8f reserved
map(0x90, 0xff).ram();
@@ -149,3 +241,13 @@ void gpl951xx_rtc_device::rtc_request_w(u16 data)
if (data & 2)
m_read_dat = readbyte(m_rtc_addr);
}
+
+TIMER_DEVICE_CALLBACK_MEMBER( gpl951xx_rtc_device::rtc_cb )
+{
+ m_timerval++;
+}
+
+void gpl951xx_rtc_device::device_add_mconfig(machine_config &config)
+{
+ TIMER(config, "rtc_timer").configure_periodic(FUNC(gpl951xx_rtc_device::rtc_cb), attotime::from_hz(32768));
+}
diff --git a/src/devices/machine/generalplus_gpl951xx_rtc.h b/src/devices/machine/generalplus_gpl951xx_rtc.h
index 11d011fe21b..209e25cd371 100644
--- a/src/devices/machine/generalplus_gpl951xx_rtc.h
+++ b/src/devices/machine/generalplus_gpl951xx_rtc.h
@@ -5,6 +5,8 @@
#pragma once
+#include "machine/timer.h"
+
class gpl951xx_rtc_device : public device_t,
public device_memory_interface
{
@@ -22,7 +24,7 @@ public:
void rtc_request_w(u16 data);
protected:
- virtual void device_validity_check(validity_checker &valid) const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
virtual space_config_vector memory_space_config() const override;
@@ -33,20 +35,36 @@ private:
inline uint8_t readbyte(offs_t address);
inline void writebyte(offs_t address, uint8_t data);
+ TIMER_DEVICE_CALLBACK_MEMBER(rtc_cb);
+
u8 reg00_r();
u8 reg01_r();
+ u8 reg02_r();
+ void reg02_w(u8 data);
+ u8 reg40_r();
void reg40_w(u8 data);
u8 reg50_r();
void reg50_w(u8 data);
+ void loadcnt_w(offs_t offset, u8 data);
+ void alarmdat_w(offs_t offset, u8 data);
+ u8 timerval_r(offs_t offset);
+
u8 m_rtc_addr;
u8 m_read_dat;
u8 m_write_dat;
+ u8 m_reg02;
+
u8 m_reg40;
u8 m_reg50;
+
+ // these are 48-bit registers
+ u64 m_loadcnt;
+ u64 m_alarmdat;
+ u64 m_timerval;
};
DECLARE_DEVICE_TYPE(GPL951XX_RTC, gpl951xx_rtc_device)
diff --git a/src/devices/machine/generalplus_gpl951xx_soc.cpp b/src/devices/machine/generalplus_gpl951xx_soc.cpp
index efea49eee48..ee6840ad0b5 100644
--- a/src/devices/machine/generalplus_gpl951xx_soc.cpp
+++ b/src/devices/machine/generalplus_gpl951xx_soc.cpp
@@ -1,6 +1,17 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
+// known SoCs
+//
+// GPL95100UA
+// GPL95101UA (101 model again has fewer features)
+//
+// 'B' models have different timer e/f behavior amongst other changes
+// GPL95100UB / GPL95100UB1 (unclear what difference is between UB and UB1)
+// GPL95101UB / GPL95101UB1 (101 models have fewer features than 100)
+//
+
+
#include "emu.h"
#include "generalplus_gpl951xx_soc.h"
@@ -8,7 +19,7 @@
#define LOG_TFT (1U << 2)
#define LOG_OTHER (1U << 3)
-#define VERBOSE (LOG_SPIFC | LOG_TFT | LOG_OTHER)
+#define VERBOSE (LOG_SPIFC | LOG_OTHER)
#include "logmacro.h"
@@ -123,6 +134,14 @@ void generalplus_gpl951xx_device::spifc_cmd_w(u16 data)
m_spi_reset(1);
m_spi_out_cmd(data & 0x00ff);
+ if (!(m_spifc_para & 0x1000))
+ {
+ m_spi_out((m_spifc_addr >> 16) & 0xff);
+ m_spi_out((m_spifc_addr >> 8) & 0xff);
+ m_spi_out((m_spifc_addr >> 0) & 0xff);
+
+ }
+
// how does byte count work? the FIFO is apparently in words
for (int i = 0; i < m_spifc_rx_bc; i++)
{
@@ -359,10 +378,8 @@ void generalplus_gpl951xx_device::device_start()
unsp_20_device::device_start();
save_item(NAME(m_byteswap));
- save_item(NAME(m_timerg_ctrl));
- save_item(NAME(m_timerg_preload));
- save_item(NAME(m_timerh_ctrl));
- save_item(NAME(m_timerh_preload));
+ save_item(NAME(m_timer_ctrl));
+ save_item(NAME(m_timer_preload));
save_item(NAME(m_spifc_ctrl));
save_item(NAME(m_spifc_ctrl2));
save_item(NAME(m_spifc_addr));
@@ -386,18 +403,25 @@ void generalplus_gpl951xx_device::device_start()
save_item(NAME(m_int_priority_3));
save_item(NAME(m_misc_int_ctrl));
save_item(NAME(m_pllchange));
+ save_item(NAME(m_tft_rgb_ctrl));
+ save_item(NAME(m_madc_ctrl));
+ save_item(NAME(m_madc_data));
}
void generalplus_gpl951xx_device::device_reset()
{
unsp_20_device::device_reset();
m_spg_video->reset();
+ m_spg_video->set_disallow_resolution_control();
m_byteswap = 0;
- m_timerg_ctrl = 0;
- m_timerg_preload = 0;
- m_timerh_ctrl = 0;
- m_timerh_preload = 0;
+
+ for (int i = 0; i < 8; i++)
+ {
+ m_timer_ctrl[i] = 0;
+ m_timer_preload[i] = 0;
+ }
+
m_spifc_ctrl = 0;
m_spifc_ctrl2 = 0;
m_spifc_addr = 0;
@@ -418,6 +442,7 @@ void generalplus_gpl951xx_device::device_reset()
m_int_priority_3 = 0;
m_misc_int_ctrl = 0;
m_pllchange = 0;
+ m_tft_rgb_ctrl = 0;
for (int i = 0; i < 6; i++)
{
@@ -436,174 +461,126 @@ void generalplus_gpl951xx_device::dac_0_w(uint16_t data)
m_dac0->write(data);
}
-TIMER_DEVICE_CALLBACK_MEMBER( generalplus_gpl951xx_device::timer_g_cb )
-{
- m_timerg_ctrl |= 0x8000;
- update_interrupts(1);
- m_gpl_chx->process_cha_fifo(); // is cha hardwired to timerg overflow?
-}
-
void generalplus_gpl951xx_device::dac_1_w(uint16_t data)
{
m_dac1->write(data);
}
-TIMER_DEVICE_CALLBACK_MEMBER( generalplus_gpl951xx_device::timer_h_cb )
-{
- m_timerh_ctrl |= 0x8000;
- update_interrupts(1);
- m_gpl_chx->process_chb_fifo(); // is chb hardwired to timerh overflow?
-}
-
-u16 generalplus_gpl951xx_device::timerg_preload_r()
-{
- logerror("%s: timerg_preload_r\n", machine().describe_context());
- return m_timerg_preload;
-}
+// Other timers are more generic
+// although timers e and f have different behavior depending on SoC
-void generalplus_gpl951xx_device::timerg_preload_w(u16 data)
+template<int Timer>
+u16 generalplus_gpl951xx_device::timer_ctrl_r()
{
- logerror("%s: timerg_preload_w %04x\n", machine().describe_context(), data);
- m_timerg_preload = data;
-}
-
-// P_TimerG_Ctrl
-
-// 15 TMGIF/C
-// 14 TMGIE
-// 13 TMGEN
-// 12
-// 11 EXT0SEL[1]
-// 10 EXT0SEL[0]
-// 9 EXT1SEL[1]
-// 8 EXT1SEL[0]
-// 7
-// 6 SRCBSEL[2]
-// 5 SRCBSEL[1]
-// 4 SRCBSEL[0]
-// 3 SRCASEL[3]
-// 2 SRCASEL[2]
-// 1 SRCASEL[1]
-// 0 SRCASEL[0]
-
-u16 generalplus_gpl951xx_device::timerg_ctrl_r()
-{
- logerror("%s: timerg_ctrl_r\n", machine().describe_context());
- u16 ret = m_timerg_ctrl;
- return ret;
+ logerror("%s: timer%c_ctrl_r\n", machine().describe_context(), 'a'+Timer);
+ return m_timer_ctrl[Timer];
}
-void generalplus_gpl951xx_device::timerg_ctrl_w(u16 data)
+template<int Timer>
+void generalplus_gpl951xx_device::timer_ctrl_w(u16 data)
{
- u8 tmgif_clear = (data & 0x8000) >> 15;
- u8 tmgie = (data & 0x4000) >> 14;
- u8 tmgen = (data & 0x2000) >> 13;
+ u8 tmxif_clear = (data & 0x8000) >> 15;
+ u8 tmxie = (data & 0x4000) >> 14;
+ u8 tmxen = (data & 0x2000) >> 13;
u8 ext0sel = (data & 0x0c00) >> 10;
u8 ext1sel = (data & 0x0300) >> 8;
u8 srcbsel = (data & 0x0070) >> 4;
u8 srcasel = (data & 0x000f) >> 0;
- logerror("%s: timerg_ctrl_w %04x (tmgif_clear %01x) (interrupt enabled %01x) (timer enabled %01x) (ext0sel %01x) (ext1sel %01x) (srcbsel %s) (srcasel %s)\n", machine().describe_context(), data, tmgif_clear, tmgie, tmgen, ext0sel, ext1sel, m_srcb[srcbsel], m_srca[srcasel]);
+ logerror("%s: timer%c_ctrl_w %04x (tmxif_clear %01x) (interrupt enabled %01x) (timer enabled %01x) (ext0sel %01x) (ext1sel %01x) (srcbsel %01x) (srcasel %01x)\n", machine().describe_context(), 'a'+Timer, data, tmxif_clear, tmxie, tmxen, ext0sel, ext1sel, m_srcb[srcbsel], m_srca[srcasel]);
if (data & 0x8000)
{
- m_timerg_ctrl &= 0x7fff;
+ m_timer_ctrl[Timer] &= 0x7fff;
}
- if ((data & 0x2000) != (m_timerg_ctrl & 0x2000))
+ if ((data & 0x2000) != (m_timer_ctrl[Timer] & 0x2000))
{
if (data & 0x2000)
{
- m_timer_g->adjust(attotime::zero, 0, attotime::from_hz(8000));
+ // currently hardcoded, need to figure out how to use the preload and timer source registers properly!
+ if (Timer == 6)
+ m_timer[Timer]->adjust(attotime::zero, 0, attotime::from_hz(8000));
+ else if (Timer == 3)
+ m_timer[Timer]->adjust(attotime::zero, 0, attotime::from_hz(20000));
+ else
+ m_timer[Timer]->adjust(attotime::zero, 0, attotime::from_hz(1000));
}
else
{
- m_timer_g->adjust(attotime::never);
+ m_timer[Timer]->adjust(attotime::never);
}
+
}
- m_timerg_ctrl = (m_timerg_ctrl & 0x8000) | (data & 0x7fff);
+ m_timer_ctrl[Timer] = (m_timer_ctrl[Timer] & 0x8000) | (data & 0x7fff);
update_interrupts(1);
}
-u16 generalplus_gpl951xx_device::timerh_preload_r()
+template<int Timer>
+u16 generalplus_gpl951xx_device::timer_preload_r()
{
- logerror("%s: timerh_preload_r\n", machine().describe_context());
- return m_timerh_preload;
+ logerror("%s: timer%c_preload_r\n", machine().describe_context(), 'a'+Timer);
+ return m_timer_preload[Timer];
}
-void generalplus_gpl951xx_device::timerh_preload_w(u16 data)
+template<int Timer>
+void generalplus_gpl951xx_device::timer_preload_w(u16 data)
{
- logerror("%s: timerh_preload_w %04x\n", machine().describe_context(), data);
- m_timerh_preload = data;
+ logerror("%s: timer%c_preload_w %04x\n", machine().describe_context(), 'a'+Timer, data);
+ m_timer_preload[Timer] = data;
}
-// P_TimerH_Ctrl
-// 15 TMHIF/C
-// 14 TMHIE
-// 13 TMHEN
-// 12
-//
-// 11 EXT0SEL[1]
-// 10 EXT0SEL[0]
-// 9 EXT1SEL[1]
-// 8 EXT1SEL[0]
+
+// P_Timerx_CCPB_Ctrl
//
-// 7
-// 6 SRCBSEL[2]
-// 5 SRCBSEL[1]
-// 4 SRCBSEL[0]
+// 15 CCPBxEN[1] - 00 = CCPB Mode Disabled, 01 = Capture Enabled, 10 = Comparison Enabled, 11 = PWM/BAM Enabled
+// 14 CCPBxEN[0]
+// 13
+// 12
//
-// 3 SRCASEL[3]
-// 2 SRCASEL[2]
-// 1 SRCASEL[1]
-// 0 SRCASEL[0]
+// 11
+// 10
+// 9 CAPxSEL[1] - 00 = every falling, 01 = every rising, 10/11 = reserved
+// 8 CAPxSEL[0]
+//
+// 7
+// 6
+// 5 CMPxSEL[1] - 00 = high pulse on CCPB, 01 = low pulse on CCPB, 10 = unaffected on CCPB, 11 = reserved
+// 4 CMPxSEL[0]
+//
+// 3
+// 2
+// 1 PWMxSEL[1] - 00 = PWM mode/NRO output, 01 = PWM mode/NRZ output, 10 = BAM mode/NRO output, 11 = BAM mode/NRZ output
+// 0 PWMxSEL[0]
-u16 generalplus_gpl951xx_device::timerh_ctrl_r()
+template<int Timer>
+void generalplus_gpl951xx_device::timer_ccpb_ctrl_w(u16 data)
{
- u16 ret = m_timerh_ctrl;
- logerror("%s: timerh_ctrl_r (returning %04x)\n", machine().describe_context(), ret);
- return ret;
+ logerror("%s: timer%c_ccpb_ctrl_w %04x\n", machine().describe_context(), 'a'+Timer, data);
}
-void generalplus_gpl951xx_device::timerh_ctrl_w(u16 data)
+template<int Timer>
+u16 generalplus_gpl951xx_device::timer_upcount_r()
{
- u8 tmhif_clear = (data & 0x8000) >> 15;
- u8 tmhie = (data & 0x4000) >> 14;
- u8 tmhen = (data & 0x2000) >> 13;
- u8 ext0sel = (data & 0x0c00) >> 10;
- u8 ext1sel = (data & 0x0300) >> 8;
- u8 srcbsel = (data & 0x0070) >> 4;
- u8 srcasel = (data & 0x000f) >> 0;
+ logerror("%s: timera_upcount_r\n", machine().describe_context(), 'a'+Timer);
+ return machine().rand();
+}
- logerror("%s: timerh_ctrl_w %04x (tmhif_clear %01x) (interrupt enabled %01x) (timer enabled %01x) (ext0sel %01x) (ext1sel %01x) (srcbsel %01x) (srcasel %01x)\n", machine().describe_context(), data, tmhif_clear, tmhie, tmhen, ext0sel, ext1sel, m_srcb[srcbsel], m_srca[srcasel]);
- if (data & 0x8000)
- {
- logerror("cleared timerh flag\n");
- m_timerh_ctrl &= 0x7fff;
- }
- if ((data & 0x2000) != (m_timerh_ctrl & 0x2000))
- {
- logerror("changed\n");
- if (data & 0x2000)
- {
- logerror("started timerh\n");
- m_timer_h->adjust(attotime::zero, 0, attotime::from_hz(1000));
- }
- else
- {
- m_timer_h->adjust(attotime::never);
- }
-
- }
-
- m_timerh_ctrl = (m_timerh_ctrl & 0x8000) | (data & 0x7fff);
- update_interrupts(1);
+u16 generalplus_gpl951xx_device::i2c_ctrl_r()
+{
+ logerror("%s: i2c_ctrl_r\n", machine().describe_context());
+ return machine().rand();
}
+u16 generalplus_gpl951xx_device::i2c_status_r()
+{
+ logerror("%s: i2c_status_r\n", machine().describe_context());
+ return machine().rand();
+}
// TFT
@@ -706,6 +683,89 @@ void generalplus_gpl951xx_device::tft_memmode_wcmd_w(u16 data)
m_memmode_wcmd = data;
}
+
+u16 generalplus_gpl951xx_device::tft_rgb_ctrl_r()
+{
+ LOGMASKED(LOG_TFT, "%s: tft_rgb_ctrl_r\n", machine().describe_context());
+ return m_tft_rgb_ctrl;
+}
+
+void generalplus_gpl951xx_device::tft_rgb_ctrl_w(u16 data)
+{
+ LOGMASKED(LOG_TFT, "%s: tft_rgb_ctrl_w %04x\n", machine().describe_context(), data);
+ m_tft_rgb_ctrl = data;
+}
+
+void generalplus_gpl951xx_device::tft_v_width_w(u16 data)
+{
+ LOGMASKED(LOG_TFT, "%s: tft_v_width_w %04x\n", machine().describe_context(), data);
+}
+
+void generalplus_gpl951xx_device::tft_vsync_setup_w(u16 data)
+{
+ LOGMASKED(LOG_TFT, "%s: tft_vsync_setup_w %04x\n", machine().describe_context(), data);
+}
+
+void generalplus_gpl951xx_device::tft_v_start_w(u16 data)
+{
+ LOGMASKED(LOG_TFT, "%s: tft_v_start_w %04x\n", machine().describe_context(), data);
+}
+
+void generalplus_gpl951xx_device::tft_v_end_w(u16 data)
+{
+ LOGMASKED(LOG_TFT, "%s: tft_v_end_w %04x\n", machine().describe_context(), data);
+}
+
+void generalplus_gpl951xx_device::tft_h_width_w(u16 data)
+{
+ LOGMASKED(LOG_TFT, "%s: tft_h_width_w %04x\n", machine().describe_context(), data);
+}
+
+void generalplus_gpl951xx_device::tft_hsync_setup_w(u16 data)
+{
+ LOGMASKED(LOG_TFT, "%s: tft_hsync_setup_w %04x\n", machine().describe_context(), data);
+}
+
+void generalplus_gpl951xx_device::tft_h_start_w(u16 data)
+{
+ LOGMASKED(LOG_TFT, "%s: tft_h_start_w %04x\n", machine().describe_context(), data);
+}
+
+void generalplus_gpl951xx_device::tft_h_end_w(u16 data)
+{
+ LOGMASKED(LOG_TFT, "%s: tft_h_end_w %04x\n", machine().describe_context(), data);
+}
+
+void generalplus_gpl951xx_device::tft_v_show_start_w(u16 data)
+{
+ LOGMASKED(LOG_TFT, "%s: tft_v_show_start_w %04x\n", machine().describe_context(), data);
+}
+
+void generalplus_gpl951xx_device::tft_v_show_end_w(u16 data)
+{
+ LOGMASKED(LOG_TFT, "%s: tft_v_show_end_w %04x\n", machine().describe_context(), data);
+}
+
+void generalplus_gpl951xx_device::tft_h_show_start_w(u16 data)
+{
+ LOGMASKED(LOG_TFT, "%s: tft_h_show_start_w %04x\n", machine().describe_context(), data);
+}
+
+void generalplus_gpl951xx_device::tft_h_show_end_w(u16 data)
+{
+ LOGMASKED(LOG_TFT, "%s: tft_h_show_end_w %04x\n", machine().describe_context(), data);
+}
+
+void generalplus_gpl951xx_device::free_height_w(u16 data)
+{
+ LOGMASKED(LOG_TFT, "%s: free_height_w %04x\n", machine().describe_context(), data);
+}
+
+void generalplus_gpl951xx_device::free_width_w(u16 data)
+{
+ LOGMASKED(LOG_TFT, "%s: free_width_w %04x\n", machine().describe_context(), data);
+}
+
//
u16 generalplus_gpl951xx_device::spi_bank_r()
@@ -720,28 +780,104 @@ void generalplus_gpl951xx_device::spi_bank_w(u16 data)
m_spi_bank = data;
}
-TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_a_cb)
+template<int Timer>
+TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_cb)
{
-}
+ m_timer_ctrl[Timer] |= 0x8000;
+ update_interrupts(1);
-TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_b_cb)
-{
+ if (Timer == 6)
+ m_gpl_chx->process_cha_fifo(); // is cha hardwired to timerg overflow?
+ else if (Timer == 7)
+ m_gpl_chx->process_chb_fifo(); // is cha hardwired to timerh overflow?
}
-TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_c_cb)
+
+TIMER_DEVICE_CALLBACK_MEMBER( generalplus_gpl951xx_device::adc_timer_cb )
{
+ m_madc_ctrl |= 0x8000;
+ m_madc_ctrl |= 0x0080; // apparently always set after the first ADC operation, no way to clear?
}
-TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_d_cb)
+
+// P_MADC_Ctrl
+//
+// 15 ADCRIF/C - ADC Ready Interrupt Flag/Clear
+// 14 ADCRIEN - ADC Interrupt Enable
+// 13
+// 12
+//
+// 11
+// 10
+// 9
+// 8
+//
+// 7 CNVRDY - Conversion Ready
+// 6 STRCNV - Manual Start Conversion
+// 5 MIASE - ADC Conversion Error Flag 1
+// 4 ASIME - ADC Conversion Error Flag 2
+//
+// 3 CHSEL - ADC Channel Selection (manual mode)
+// 2
+// 1
+// 0
+
+u16 generalplus_gpl951xx_device::madc_ctrl_r()
{
+ logerror("%s: madc_ctrl_r\n", machine().describe_context());
+ return m_madc_ctrl;
}
-TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_e_cb)
+void generalplus_gpl951xx_device::madc_ctrl_w(u16 data)
{
+ logerror("%s: madc_ctrl_w %04x\n", machine().describe_context(), data);
+
+ if (data & 0x8000)
+ {
+ // clear IRQ flag
+ data = data &~ 0x8000;
+ }
+
+ if (data & 0x0010)
+ {
+ // clear Error Flag 2
+ data = data &~ 0x0010;
+ }
+
+ if (data & 0x0020)
+ {
+ // clear Error Flag 1
+ data = data &~ 0x0020;
+ }
+
+ if (data & 0x0040) // Manual start
+ {
+ data = data & ~0x0040;
+ data = data & ~0x0080;
+
+ u8 channel = data & 0x0007;
+
+ logerror("manual ADC conversion on port %s\n", m_adc_channels[channel]);
+
+ if (channel < 6)
+ {
+ m_madc_data = m_adc_in[channel]();
+ }
+ else
+ {
+ m_madc_data = 0x0000;
+ }
+
+ m_adc_timer->adjust(attotime::from_usec(10));
+ }
+
+ m_madc_ctrl = data;
}
-TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_f_cb)
+u16 generalplus_gpl951xx_device::madc_data_r()
{
+ logerror("%s: madc_data_r\n", machine().describe_context());
+ return m_madc_data;
}
@@ -988,13 +1124,13 @@ u16 generalplus_gpl951xx_device::int_status2_r()
LOGMASKED(LOG_OTHER, "%s: generalplus_gpl951xx_device::int_status2_r\n", machine().describe_context());
u16 ret = 0;
- if (m_gpl_timebase->timebasea_irq_flag())
+ if (m_gpl_timebase->timebase_irq_flag<0>())
ret |= 0x0100;
- if (m_gpl_timebase->timebaseb_irq_flag())
+ if (m_gpl_timebase->timebase_irq_flag<1>())
ret |= 0x0200;
- if (m_gpl_timebase->timebasec_irq_flag())
+ if (m_gpl_timebase->timebase_irq_flag<2>())
ret |= 0x0400;
return ret;
@@ -1033,12 +1169,18 @@ u16 generalplus_gpl951xx_device::int_status3_r()
u16 ret = 0;
LOGMASKED(LOG_OTHER, "%s: generalplus_gpl951xx_device::int_status3_r\n", machine().describe_context());
- if (m_timerh_ctrl & 0x8000)
+ if (m_timer_ctrl[7] & 0x8000)
ret |= 0x8000;
- if (m_timerg_ctrl & 0x8000)
+ if (m_timer_ctrl[6] & 0x8000)
ret |= 0x4000;
+ if (m_timer_ctrl[1] & 0x8000)
+ ret |= 0x0200;
+
+ if (m_timer_ctrl[0] & 0x8000)
+ ret |= 0x0100;
+
return ret;
}
@@ -1048,18 +1190,36 @@ void generalplus_gpl951xx_device::int_status3_w(u16 data)
// bit 2 (SPU Beat Interrupt) is listed as R/W for GPL95, but not GPL162? (verify)
}
+u16 generalplus_gpl951xx_device::int_priority_1_r()
+{
+ LOGMASKED(LOG_OTHER, "%s: generalplus_gpl951xx_device::int_priority_1_r\n", machine().describe_context());
+ return m_int_priority_1;
+}
+
void generalplus_gpl951xx_device::int_priority_1_w(u16 data)
{
LOGMASKED(LOG_OTHER, "%s: generalplus_gpl951xx_device::int_priority_1_w %04x\n", machine().describe_context(), data);
m_int_priority_1 = data;
}
+u16 generalplus_gpl951xx_device::int_priority_2_r()
+{
+ LOGMASKED(LOG_OTHER, "%s: generalplus_gpl951xx_device::int_priority_2_r\n", machine().describe_context());
+ return m_int_priority_2;
+}
+
void generalplus_gpl951xx_device::int_priority_2_w(u16 data)
{
LOGMASKED(LOG_OTHER, "%s: generalplus_gpl951xx_device::int_priority_2_w %04x\n", machine().describe_context(), data);
m_int_priority_2 = data;
}
+u16 generalplus_gpl951xx_device::int_priority_3_r()
+{
+ LOGMASKED(LOG_OTHER, "%s: generalplus_gpl951xx_device::int_priority_3_r\n", machine().describe_context());
+ return m_int_priority_3;
+}
+
void generalplus_gpl951xx_device::int_priority_3_w(u16 data)
{
LOGMASKED(LOG_OTHER, "%s: generalplus_gpl951xx_device::int_priority_3_w %04x\n", machine().describe_context(), data);
@@ -1150,15 +1310,15 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
map(0x007042, 0x007042).rw(m_spg_video, FUNC(gcm394_base_video_device::sprite_7042_extra_r), FUNC(gcm394_base_video_device::sprite_7042_extra_w)); // 7042 - SControl
//
map(0x007050, 0x007050).w(FUNC(generalplus_gpl951xx_device::tft_ctrl_w)); // 7050 - TFT_Ctrl
- // 7051 - TFT_V_Width
- // 7052 - TFT_VSync_Setup
- // 7053 - TFT_V_Start
- // 7054 - TFT_V_End
- // 7055 - TFT_H_Width
- // 7056 - TFT_HSync_Setup
- // 7057 - TFT_H_Start
- // 7058 - TFT_H_End
- // 7059 - TFT_RGB_Ctrl
+ map(0x007051, 0x007051).w(FUNC(generalplus_gpl951xx_device::tft_v_width_w)); // 7051 - TFT_V_Width
+ map(0x007052, 0x007052).w(FUNC(generalplus_gpl951xx_device::tft_vsync_setup_w)); // 7052 - TFT_VSync_Setup
+ map(0x007053, 0x007053).w(FUNC(generalplus_gpl951xx_device::tft_v_start_w)); // 7053 - TFT_V_Start
+ map(0x007054, 0x007054).w(FUNC(generalplus_gpl951xx_device::tft_v_end_w)); // 7054 - TFT_V_End
+ map(0x007055, 0x007055).w(FUNC(generalplus_gpl951xx_device::tft_h_width_w)); // 7055 - TFT_H_Width
+ map(0x007056, 0x007056).w(FUNC(generalplus_gpl951xx_device::tft_hsync_setup_w)); // 7056 - TFT_HSync_Setup
+ map(0x007057, 0x007057).w(FUNC(generalplus_gpl951xx_device::tft_h_start_w)); // 7057 - TFT_H_Start
+ map(0x007058, 0x007058).w(FUNC(generalplus_gpl951xx_device::tft_h_end_w)); // 7058 - TFT_H_End
+ map(0x007059, 0x007059).rw(FUNC(generalplus_gpl951xx_device::tft_rgb_ctrl_r), FUNC(generalplus_gpl951xx_device::tft_rgb_ctrl_w)); // 7059 - TFT_RGB_Ctrl
map(0x00705a, 0x00705a).r(FUNC(generalplus_gpl951xx_device::tft_status_r)); // 705a - TFT_Status
map(0x00705b, 0x00705b).w(FUNC(generalplus_gpl951xx_device::tft_memmode_wcmd_w)); // 705b - TFT_MemMode_WCmd
// 705c - TFT_MemMode_RCmd
@@ -1176,10 +1336,10 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
// 7069 - US_Hoffset
// 706a - US_Voffset
//
- // 706c - TFT_V_Show_Start
- // 706d - TFT_V_Show_End
- // 706e - TFT_H_Show_Start
- // 706f - TFT_H_Show_End
+ map(0x00706c, 0x00706c).w(FUNC(generalplus_gpl951xx_device::tft_v_show_start_w)); // 706c - TFT_V_Show_Start
+ map(0x00706d, 0x00706d).w(FUNC(generalplus_gpl951xx_device::tft_v_show_end_w)); // 706d - TFT_V_Show_End
+ map(0x00706e, 0x00706e).w(FUNC(generalplus_gpl951xx_device::tft_h_show_start_w)); // 706e - TFT_H_Show_Start
+ map(0x00706f, 0x00706f).w(FUNC(generalplus_gpl951xx_device::tft_h_show_end_w)); // 706f - TFT_H_Show_End
//
map(0x007070, 0x007070).w(m_spg_video, FUNC(gcm394_base_video_device::video_dma_source_w)); // 7070 - SPDMA_Source
map(0x007071, 0x007071).w(m_spg_video, FUNC(gcm394_base_video_device::video_dma_dest_w)); // 7071 - SPDMA_Target
@@ -1207,8 +1367,8 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
// 70b8 - Tx3_N_PTRH
// 70b9 - Tx3_A_PTRH
//
- // 70db - Free_Height
- // 70dc - Free_Width
+ map(0x0070db, 0x0070db).w(FUNC(generalplus_gpl951xx_device::free_height_w)); // 70db - Free_Height
+ map(0x0070dc, 0x0070dc).w(FUNC(generalplus_gpl951xx_device::free_width_w)); // 70dc - Free_Width
//
map(0x0070e0, 0x0070e0).r(m_spg_video, FUNC(gcm394_base_video_device::video_70e0_prng_r)); // 70e0 - Random0 (15-bit)
// 70e1 - Random1 (15-bit)
@@ -1299,9 +1459,9 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
map(0x0078a0, 0x0078a0).rw(FUNC(generalplus_gpl951xx_device::int_status1_r), FUNC(generalplus_gpl951xx_device::int_status1_w)); // 78a0 - INT_Status1
map(0x0078a1, 0x0078a1).rw(FUNC(generalplus_gpl951xx_device::int_status2_r), FUNC(generalplus_gpl951xx_device::int_status2_w)); // 78a1 - INT_Status2
map(0x0078a2, 0x0078a2).rw(FUNC(generalplus_gpl951xx_device::int_status3_r), FUNC(generalplus_gpl951xx_device::int_status3_w)); // 78a2 - INT_Status3
- map(0x0078a3, 0x0078a3).w(FUNC(generalplus_gpl951xx_device::int_priority_1_w)); // 78a3 - INT_Priority1
- map(0x0078a4, 0x0078a4).w(FUNC(generalplus_gpl951xx_device::int_priority_2_w)); // 78a4 - INT_Priority2
- map(0x0078a5, 0x0078a5).w(FUNC(generalplus_gpl951xx_device::int_priority_3_w)); // 78a5 - INT_Priority3
+ map(0x0078a3, 0x0078a3).rw(FUNC(generalplus_gpl951xx_device::int_priority_1_r), FUNC(generalplus_gpl951xx_device::int_priority_1_w)); // 78a3 - INT_Priority1
+ map(0x0078a4, 0x0078a4).rw(FUNC(generalplus_gpl951xx_device::int_priority_2_r), FUNC(generalplus_gpl951xx_device::int_priority_2_w)); // 78a4 - INT_Priority2
+ map(0x0078a5, 0x0078a5).rw(FUNC(generalplus_gpl951xx_device::int_priority_3_r), FUNC(generalplus_gpl951xx_device::int_priority_3_w)); // 78a5 - INT_Priority3
map(0x0078a6, 0x0078a6).w(FUNC(generalplus_gpl951xx_device::mint_ctrl_w)); // 78a6 - MINT_Ctrl
// 78a7 - IOAB_KCIEN
// 78a8 - IOC_KCIEN
@@ -1318,27 +1478,30 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
map(0x0078b8, 0x0078b8).w(m_gpl_timebase, FUNC(gpl_timebase_device::timebase_reset_w)); // 78b8 - TimeBase_Reset
- // 78c0 - I2C_Ctrl
- // 78c1 - I2C_Status
+ map(0x0078c0, 0x0078c0).r(FUNC(generalplus_gpl951xx_device::i2c_ctrl_r)); // 78c0 - I2C_Ctrl
+ map(0x0078c1, 0x0078c1).r(FUNC(generalplus_gpl951xx_device::i2c_status_r)); // 78c1 - I2C_Status
// 78c2 - I2C_Address
// 78c3 - I2C_Data
// 78c4 - I2C_Debounce
// 78c5 - I2C_Clk
// 78c6 - I2C_MISC
- map(0x0078e0, 0x0078e0).rw(FUNC(generalplus_gpl951xx_device::timerg_ctrl_r), FUNC(generalplus_gpl951xx_device::timerg_ctrl_w)); // 78e0 - timerg_Ctrl
+ // Timer G
+ map(0x0078e0, 0x0078e0).rw(FUNC(generalplus_gpl951xx_device::timer_ctrl_r<6>), FUNC(generalplus_gpl951xx_device::timer_ctrl_w<6>)); // 78e0 - timerg_Ctrl
// 78e1
- map(0x0078e2, 0x0078e2).rw(FUNC(generalplus_gpl951xx_device::timerg_preload_r), FUNC(generalplus_gpl951xx_device::timerg_preload_w)); // 78e2 - timerg_Preload
+ map(0x0078e2, 0x0078e2).rw(FUNC(generalplus_gpl951xx_device::timer_preload_r<6>), FUNC(generalplus_gpl951xx_device::timer_preload_w<6>)); // 78e2 - timerg_Preload
// 78e3
- // 78e4 - TimerG_UpCount
+ map(0x0078e4, 0x0078e4).r(FUNC(generalplus_gpl951xx_device::timer_upcount_r<6>)); // 78e4 - TimerG_UpCount
// 78e5
// 78e6
// 78e7
- map(0x0078e8, 0x0078e8).rw(FUNC(generalplus_gpl951xx_device::timerh_ctrl_r), FUNC(generalplus_gpl951xx_device::timerh_ctrl_w)); // timerh_Ctrl
+
+ // Timer H
+ map(0x0078e8, 0x0078e8).rw(FUNC(generalplus_gpl951xx_device::timer_ctrl_r<7>), FUNC(generalplus_gpl951xx_device::timer_ctrl_w<7>)); // timerh_Ctrl
// 78e9
- map(0x0078ea, 0x0078ea).rw(FUNC(generalplus_gpl951xx_device::timerh_preload_r), FUNC(generalplus_gpl951xx_device::timerh_preload_w)); // 78ea - timerh_Preload
+ map(0x0078ea, 0x0078ea).rw(FUNC(generalplus_gpl951xx_device::timer_preload_r<7>), FUNC(generalplus_gpl951xx_device::timer_preload_w<7>)); // 78ea - timerh_Preload
// 78eb
- // 78ec - TimerH_UpCount
+ map(0x0078ec, 0x0078ec).r(FUNC(generalplus_gpl951xx_device::timer_upcount_r<7>)); // 78ec - TimerH_UpCount
// 78ed
// 78ee
// 78ef
@@ -1383,8 +1546,8 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
// 7945 - SPI0_Misc
// 79a0 - ADC_Setup
- // 79a1 - MADC_Ctrl
- // 79a2 - MADC_Data
+ map(0x0079a1, 0x0079a1).rw(FUNC(generalplus_gpl951xx_device::madc_ctrl_r), FUNC(generalplus_gpl951xx_device::madc_ctrl_w)); // 79a1 - MADC_Ctrl
+ map(0x0079a2, 0x0079a2).r(FUNC(generalplus_gpl951xx_device::madc_data_r)); // 79a2 - MADC_Data
// 79a3 - ASADC_Ctrl
// 79a4 - ASDAC_Data
// 79a5
@@ -1420,43 +1583,48 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
// 79fa
// 79fb - RTC_ClkDiv
- // 7a00 - TimerA_Ctrl
- // 7a01 - TimerA_CCPB_Ctrl
- // 7a02 - TimerA_Preload
+ // Timer A
+ map(0x007a00, 0x007a00).rw(FUNC(generalplus_gpl951xx_device::timer_ctrl_r<0>), FUNC(generalplus_gpl951xx_device::timer_ctrl_w<0>)); // 7a00 - TimerA_Ctrl
+ map(0x007a01, 0x007a01).w(FUNC(generalplus_gpl951xx_device::timer_ccpb_ctrl_w<0>)); // 7a01 - TimerA_CCPB_Ctrl
+ map(0x007a02, 0x007a02).rw(FUNC(generalplus_gpl951xx_device::timer_preload_r<0>), FUNC(generalplus_gpl951xx_device::timer_preload_w<0>)); // 7a02 - TimerA_Preload
// 7a03 - TimerA_CCPB_Reg
- // 7a04 - TimerA_UpCount
+ map(0x007a04, 0x007a04).r(FUNC(generalplus_gpl951xx_device::timer_upcount_r<0>)); // 7a04 - TimerA_UpCount
- // 7a08 - TimerB_Ctrl
- // 7a09 - TimerB_CCPB_Ctrl
- // 7a0a - TimerB_Preload
+ // Timer B
+ map(0x007a08, 0x007a08).rw(FUNC(generalplus_gpl951xx_device::timer_ctrl_r<1>), FUNC(generalplus_gpl951xx_device::timer_ctrl_w<1>)); // 7a08 - TimerB_Ctrl
+ map(0x007a09, 0x007a09).w(FUNC(generalplus_gpl951xx_device::timer_ccpb_ctrl_w<1>)); // 7a09 - TimerB_CCPB_Ctrl
+ map(0x007a0a, 0x007a0a).rw(FUNC(generalplus_gpl951xx_device::timer_preload_r<1>), FUNC(generalplus_gpl951xx_device::timer_preload_w<1>)); // 7a0a - TimerB_Preload
// 7a0b - TimerB_CCPB_Reg
- // 7a0c - TimerB_UpCount
+ map(0x007a0c, 0x007a0c).r(FUNC(generalplus_gpl951xx_device::timer_upcount_r<1>)); // 7a0c - TimerB_UpCount
- // 7a10 - TimerC_Ctrl
- // 7a11 - TimerC_CCPB_Ctrl
- // 7a12 - TimerC_Preload
+ // Timer C
+ map(0x007a10, 0x007a10).rw(FUNC(generalplus_gpl951xx_device::timer_ctrl_r<2>), FUNC(generalplus_gpl951xx_device::timer_ctrl_w<2>)); // 7a10 - TimerC_Ctrl
+ map(0x007a11, 0x007a11).w(FUNC(generalplus_gpl951xx_device::timer_ccpb_ctrl_w<2>)); // 7a11 - TimerC_CCPB_Ctrl
+ map(0x007a12, 0x007a12).rw(FUNC(generalplus_gpl951xx_device::timer_preload_r<2>), FUNC(generalplus_gpl951xx_device::timer_preload_w<2>)); // 7a12 - TimerC_Preload
// 7a13 - TimerC_CCPB_Reg
- // 7a14 - TimerC_UpCount
+ map(0x007a14, 0x007a14).r(FUNC(generalplus_gpl951xx_device::timer_upcount_r<2>)); // 7a14 - TimerC_UpCount
- // 7a18 - TimerD_Ctrl
- // 7a19 - TimerD_CCPB_Ctrl
- // 7a1a - TimerD_Preload
+ // Timer D
+ map(0x007a18, 0x007a18).rw(FUNC(generalplus_gpl951xx_device::timer_ctrl_r<3>), FUNC(generalplus_gpl951xx_device::timer_ctrl_w<3>)); // 7a18 - TimerD_Ctrl
+ map(0x007a19, 0x007a19).w(FUNC(generalplus_gpl951xx_device::timer_ccpb_ctrl_w<3>)); // 7a19 - TimerD_CCPB_Ctrl
+ map(0x007a1a, 0x007a1a).rw(FUNC(generalplus_gpl951xx_device::timer_preload_r<3>), FUNC(generalplus_gpl951xx_device::timer_preload_w<3>)); // 7a1a - TimerD_Preload
// 7a1b - TimerD_CCPB_Reg
- // 7a1c - TimerD_UpCount
-
- // 7a20 - TimerE_Ctrl
- // 7a21 - TimerF_Ctrl
- // 7a22 - TimerE_CCPB_Ctrl
- // 7a23 - TimerF_CCPB_Ctrl
- // 7a24 - TimerE_Preload
- // 7a25 - TimerF_Preload
- // 7a26 - TimerEF_CCPB4_Reg
- // 7a27 - TimerEF_CCPB5_Reg
- // 7a28 - TimerEF_CCPB6_Reg
- // 7a29 - TimerEF_CCPB7_Reg
- // 7a2a - TimerE_UpCount
- // 7a2b - TimerF_UpCount
- // 7a2c - TimerEF_CCPB_Se
+ map(0x007a1c, 0x007a1c).r(FUNC(generalplus_gpl951xx_device::timer_upcount_r<3>)); // 7a1c - TimerD_UpCount
+
+ // Timers E & F
+ map(0x007a20, 0x007a20).rw(FUNC(generalplus_gpl951xx_device::timer_ctrl_r<4>), FUNC(generalplus_gpl951xx_device::timer_ctrl_w<4>)); // 7a20 - TimerE_Ctrl
+ map(0x007a21, 0x007a21).rw(FUNC(generalplus_gpl951xx_device::timer_ctrl_r<5>), FUNC(generalplus_gpl951xx_device::timer_ctrl_w<5>)); // 7a21 - TimerF_Ctrl
+ map(0x007a22, 0x007a22).w(FUNC(generalplus_gpl951xx_device::timer_ccpb_ctrl_w<4>)); // 7a22 - TimerE_CCPB_Ctrl
+ map(0x007a23, 0x007a23).w(FUNC(generalplus_gpl951xx_device::timer_ccpb_ctrl_w<5>)); // 7a23 - TimerF_CCPB_Ctrl
+ map(0x007a24, 0x007a24).rw(FUNC(generalplus_gpl951xx_device::timer_preload_r<4>), FUNC(generalplus_gpl951xx_device::timer_preload_w<4>)); // 7a24 - TimerE_Preload
+ map(0x007a25, 0x007a25).rw(FUNC(generalplus_gpl951xx_device::timer_preload_r<5>), FUNC(generalplus_gpl951xx_device::timer_preload_w<5>)); // 7a25 - TimerF_Preload
+ // 7a26 - TimerEF_CCPB4_Reg (differs between GPL951xx models)
+ // 7a27 - TimerEF_CCPB5_Reg (differs between GPL951xx models)
+ // 7a28 - TimerEF_CCPB6_Reg (differs between GPL951xx models - doesn't exist on 'B')
+ // 7a29 - TimerEF_CCPB7_Reg (differs between GPL951xx models - doesn't exist on 'B')
+ map(0x007a2a, 0x007a2a).r(FUNC(generalplus_gpl951xx_device::timer_upcount_r<4>)); // 7a2a - TimerE_UpCount
+ map(0x007a2b, 0x007a2b).r(FUNC(generalplus_gpl951xx_device::timer_upcount_r<5>)); // 7a2b - TimerF_UpCount
+ // 7a2c - TimerEF_CCPB_Sel (differs between GPL951xx models - 2 bits on 'B', 4 bits on GPL95100UA/GPL95101UA)
// 7a40 - USBD_Config
// 7a41 - USBD_Function
@@ -1565,7 +1733,7 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map)
void generalplus_gpl951xx_device::update_interrupts(int state)
{
- if (m_gpl_timebase->timebasea_irq_flag() || m_gpl_timebase->timebaseb_irq_flag())
+ if (m_gpl_timebase->timebase_irq_flag<0>() || m_gpl_timebase->timebase_irq_flag<1>())
{
set_state_unsynced(UNSP_IRQ7_LINE, ASSERT_LINE);
}
@@ -1574,7 +1742,7 @@ void generalplus_gpl951xx_device::update_interrupts(int state)
set_state_unsynced(UNSP_IRQ7_LINE, CLEAR_LINE);
}
- if (m_gpl_timebase->timebasec_irq_flag())
+ if (m_gpl_timebase->timebase_irq_flag<2>())
{
set_state_unsynced(UNSP_IRQ6_LINE, ASSERT_LINE);
}
@@ -1583,8 +1751,15 @@ void generalplus_gpl951xx_device::update_interrupts(int state)
set_state_unsynced(UNSP_IRQ6_LINE, CLEAR_LINE);
}
- if (((m_timerg_ctrl & 0x8000) && (m_timerg_ctrl & 0x4000)) ||
- ((m_timerh_ctrl & 0x8000) && (m_timerh_ctrl & 0x4000)))
+ if (((m_timer_ctrl[7] & 0x8000) && (m_timer_ctrl[7] & 0x4000)) ||
+ ((m_timer_ctrl[6] & 0x8000) && (m_timer_ctrl[6] & 0x4000)) ||
+ ((m_timer_ctrl[5] & 0x8000) && (m_timer_ctrl[5] & 0x4000)) ||
+ ((m_timer_ctrl[4] & 0x8000) && (m_timer_ctrl[4] & 0x4000)) ||
+ ((m_timer_ctrl[3] & 0x8000) && (m_timer_ctrl[3] & 0x4000)) ||
+ ((m_timer_ctrl[2] & 0x8000) && (m_timer_ctrl[2] & 0x4000)) ||
+ ((m_timer_ctrl[1] & 0x8000) && (m_timer_ctrl[1] & 0x4000)) ||
+ ((m_timer_ctrl[0] & 0x8000) && (m_timer_ctrl[0] & 0x4000))
+ )
{
set_state_unsynced(UNSP_IRQ4_LINE, ASSERT_LINE);
}
@@ -1663,15 +1838,19 @@ void generalplus_gpl951xx_device::device_add_mconfig(machine_config &config)
m_spg_video->space_read_callback().set(FUNC(generalplus_gpl951xx_device::read_space));
m_spg_video->set_video_space(DEVICE_SELF, AS_PROGRAM);
- TIMER(config, "timer_a").configure_generic(FUNC(generalplus_gpl951xx_device::timer_a_cb));
- TIMER(config, "timer_b").configure_generic(FUNC(generalplus_gpl951xx_device::timer_b_cb));
- TIMER(config, "timer_c").configure_generic(FUNC(generalplus_gpl951xx_device::timer_c_cb));
- TIMER(config, "timer_d").configure_generic(FUNC(generalplus_gpl951xx_device::timer_d_cb));
- TIMER(config, "timer_e").configure_generic(FUNC(generalplus_gpl951xx_device::timer_e_cb));
- TIMER(config, "timer_f").configure_generic(FUNC(generalplus_gpl951xx_device::timer_f_cb));
+ TIMER(config, "timer_a").configure_generic(FUNC(generalplus_gpl951xx_device::timer_cb<0>));
+ TIMER(config, "timer_b").configure_generic(FUNC(generalplus_gpl951xx_device::timer_cb<1>));
+ TIMER(config, "timer_c").configure_generic(FUNC(generalplus_gpl951xx_device::timer_cb<2>));
+ TIMER(config, "timer_d").configure_generic(FUNC(generalplus_gpl951xx_device::timer_cb<3>));
+ // timers e and f are a little different
+ TIMER(config, "timer_e").configure_generic(FUNC(generalplus_gpl951xx_device::timer_cb<4>));
+ TIMER(config, "timer_f").configure_generic(FUNC(generalplus_gpl951xx_device::timer_cb<5>));
+
+ // timers g and h are for the cha/chb DAC (and can overflow trigger each other, not the above)
+ TIMER(config, "timer_g").configure_generic(FUNC(generalplus_gpl951xx_device::timer_cb<6>));
+ TIMER(config, "timer_h").configure_generic(FUNC(generalplus_gpl951xx_device::timer_cb<7>));
- TIMER(config, "timer_g").configure_generic(FUNC(generalplus_gpl951xx_device::timer_g_cb));
- TIMER(config, "timer_h").configure_generic(FUNC(generalplus_gpl951xx_device::timer_h_cb));
+ TIMER(config, "adc_timer").configure_generic(FUNC(generalplus_gpl951xx_device::adc_timer_cb));
GPL951XX_RTC(config, m_rtc, 0);
}
@@ -1688,8 +1867,9 @@ generalplus_gpl951xx_device::generalplus_gpl951xx_device(const machine_config &m
m_i80_data_out(*this),
m_port_in(*this, 0),
m_port_out(*this),
- m_timer_g(*this, "timer_g"),
- m_timer_h(*this, "timer_h"),
+ m_adc_in(*this, 0),
+ m_timer(*this, { "timer_a", "timer_b", "timer_c", "timer_d", "timer_e", "timer_f", "timer_g", "timer_h" }),
+ m_adc_timer(*this, "adc_timer"),
m_rtc(*this, "rtc"),
m_gpl_chx(*this, "gpl_chx"),
m_dac0(*this, "dac0"),
diff --git a/src/devices/machine/generalplus_gpl951xx_soc.h b/src/devices/machine/generalplus_gpl951xx_soc.h
index dd71bf4d1c4..b42112563db 100644
--- a/src/devices/machine/generalplus_gpl951xx_soc.h
+++ b/src/devices/machine/generalplus_gpl951xx_soc.h
@@ -57,6 +57,13 @@ public:
auto porte_out() { return m_port_out[4].bind(); }
auto portf_out() { return m_port_out[5].bind(); }
+ auto adc0_in() { return m_adc_in[0].bind(); }
+ auto adc1_in() { return m_adc_in[1].bind(); }
+ auto adc2_in() { return m_adc_in[2].bind(); }
+ auto adc3_in() { return m_adc_in[3].bind(); }
+ auto adc4_in() { return m_adc_in[4].bind(); }
+ auto adc5_in() { return m_adc_in[5].bind(); }
+
void recieve_spi_fifo_data(u8 data);
IRQ_CALLBACK_MEMBER(irq_vector_cb);
@@ -116,14 +123,15 @@ private:
void byte_swap_w(u16 data);
// Timers (different compared to GPL162xx)
- u16 timerg_ctrl_r();
- void timerg_ctrl_w(u16 data);
- u16 timerg_preload_r();
- void timerg_preload_w(u16 data);
- u16 timerh_ctrl_r();
- void timerh_ctrl_w(u16 data);
- u16 timerh_preload_r();
- void timerh_preload_w(u16 data);
+ template<int Timer> u16 timer_preload_r();
+ template<int Timer> void timer_preload_w(u16 data);
+ template<int Timer> u16 timer_ctrl_r();
+ template<int Timer> void timer_ctrl_w(u16 data);
+ template<int Timer> void timer_ccpb_ctrl_w(u16 data);
+ template<int Timer> u16 timer_upcount_r();
+
+ u16 i2c_ctrl_r();
+ u16 i2c_status_r();
void dac_0_w(uint16_t data);
void dac_1_w(uint16_t data);
@@ -178,6 +186,10 @@ private:
void int_priority_1_w(u16 data);
void int_priority_2_w(u16 data);
void int_priority_3_w(u16 data);
+ u16 int_priority_1_r();
+ u16 int_priority_2_r();
+ u16 int_priority_3_r();
+
void mint_ctrl_w(u16 data);
void update_interrupts(int state);
@@ -185,18 +197,34 @@ private:
void audioirq_w(int state);
void videoirq_w(int state);
+ u16 madc_ctrl_r();
+ void madc_ctrl_w(u16 data);
+ u16 madc_data_r();
+
+ u16 tft_rgb_ctrl_r();
+ void tft_rgb_ctrl_w(u16 data);
+
+ void tft_v_width_w(u16 data);
+ void tft_vsync_setup_w(u16 data);
+ void tft_v_start_w(u16 data);
+ void tft_v_end_w(u16 data);
+ void tft_h_width_w(u16 data);
+ void tft_hsync_setup_w(u16 data);
+ void tft_h_start_w(u16 data);
+ void tft_h_end_w(u16 data);
+ void tft_v_show_start_w(u16 data);
+ void tft_v_show_end_w(u16 data);
+ void tft_h_show_start_w(u16 data);
+ void tft_h_show_end_w(u16 data);
+ void free_height_w(u16 data);
+ void free_width_w(u16 data);
+
inline u16 read_space(offs_t offset);
inline void write_space(offs_t offset, u16 data);
- TIMER_DEVICE_CALLBACK_MEMBER(timer_g_cb);
- TIMER_DEVICE_CALLBACK_MEMBER(timer_h_cb);
+ template<int Timer> TIMER_DEVICE_CALLBACK_MEMBER(timer_cb);
- TIMER_DEVICE_CALLBACK_MEMBER(timer_a_cb);
- TIMER_DEVICE_CALLBACK_MEMBER(timer_b_cb);
- TIMER_DEVICE_CALLBACK_MEMBER(timer_c_cb);
- TIMER_DEVICE_CALLBACK_MEMBER(timer_d_cb);
- TIMER_DEVICE_CALLBACK_MEMBER(timer_e_cb);
- TIMER_DEVICE_CALLBACK_MEMBER(timer_f_cb);
+ TIMER_DEVICE_CALLBACK_MEMBER(adc_timer_cb);
u16 m_byteswap;
@@ -232,10 +260,20 @@ private:
"f: reserved"
};
- u16 m_timerg_preload;
- u16 m_timerg_ctrl;
- u16 m_timerh_preload;
- u16 m_timerh_ctrl;
+ const char* m_adc_channels[8] =
+ {
+ "LINEIN 0",
+ "LINEIN 1",
+ "LINEIN 2",
+ "LINEIN 3",
+ "LINEIN 4",
+ "LINEIN 5",
+ "1.2V bandgap",
+ "LDOV50"
+ };
+
+ u16 m_timer_preload[8];
+ u16 m_timer_ctrl[8];
u16 m_spifc_ctrl;
u16 m_spifc_ctrl2;
@@ -268,6 +306,11 @@ private:
u16 m_memmode_wcmd;
+ u16 m_tft_rgb_ctrl;
+
+ u16 m_madc_ctrl;
+ u16 m_madc_data;
+
// config
u8 *m_spiregion;
u32 m_spisize;
@@ -282,9 +325,11 @@ private:
devcb_read16::array<6> m_port_in;
devcb_write16::array<6> m_port_out;
+ devcb_read16::array<6> m_adc_in;
+
// devices
- required_device<timer_device> m_timer_g;
- required_device<timer_device> m_timer_h;
+ required_device_array<timer_device, 8> m_timer;
+ required_device<timer_device> m_adc_timer;
required_device<gpl951xx_rtc_device> m_rtc;
required_device<gpl_chx_device> m_gpl_chx;
required_device<dac_16bit_r2r_twos_complement_device> m_dac0;
diff --git a/src/devices/machine/generalplus_gpl_chx.cpp b/src/devices/machine/generalplus_gpl_chx.cpp
index 80fc90ee884..8c7ebc6b213 100644
--- a/src/devices/machine/generalplus_gpl_chx.cpp
+++ b/src/devices/machine/generalplus_gpl_chx.cpp
@@ -106,6 +106,8 @@ void gpl_chx_device::cha_ctrl_w(u16 data)
}
m_cha_ctrl = data;
+
+ //check_cha_fifo_empty();
}
// P_CHA_Data
@@ -219,6 +221,8 @@ void gpl_chx_device::chb_ctrl_w(u16 data)
}
m_chb_ctrl = data;
+
+ //check_chb_fifo_empty();
}
// P_CHB_Data
@@ -272,6 +276,20 @@ void gpl_chx_device::chb_fifo_w(u16 data)
}
}
+void gpl_chx_device::check_cha_fifo_empty()
+{
+ u8 emptyamount = (m_cha_fifo_reg & 0x00f0) >> 4;
+
+ if (m_cha_fifo_entries <= emptyamount)
+ {
+ if (m_cha_ctrl & 0x4000)
+ {
+ m_cha_ctrl |= 0x8000;
+ m_updateirqs_cb(1);
+ }
+ }
+}
+
void gpl_chx_device::process_cha_fifo()
{
if (!(m_cha_ctrl & 0x2000))
@@ -292,13 +310,18 @@ void gpl_chx_device::process_cha_fifo()
// trying to underflow the FIFO?
}
- u8 emptyamount = (m_cha_fifo_reg & 0x00f0) >> 4;
+ check_cha_fifo_empty();
+}
- if (m_cha_fifo_entries <= emptyamount)
+void gpl_chx_device::check_chb_fifo_empty()
+{
+ u8 emptyamount = (m_chb_fifo_reg & 0x00f0) >> 4;
+
+ if (m_chb_fifo_entries <= emptyamount)
{
- if (m_cha_ctrl & 0x4000)
+ if (m_chb_ctrl & 0x4000)
{
- m_cha_ctrl |= 0x8000;
+ m_chb_ctrl |= 0x8000;
m_updateirqs_cb(1);
}
}
@@ -324,16 +347,7 @@ void gpl_chx_device::process_chb_fifo()
// trying to underflow the FIFO?
}
- u8 emptyamount = (m_chb_fifo_reg & 0x00f0) >> 4;
-
- if (m_chb_fifo_entries <= emptyamount)
- {
- if (m_chb_ctrl & 0x4000)
- {
- m_chb_ctrl |= 0x8000;
- m_updateirqs_cb(1);
- }
- }
+ check_chb_fifo_empty();
}
void gpl_chx_device::device_add_mconfig(machine_config &config)
diff --git a/src/devices/machine/generalplus_gpl_chx.h b/src/devices/machine/generalplus_gpl_chx.h
index 041d16c765a..07cbcce8556 100644
--- a/src/devices/machine/generalplus_gpl_chx.h
+++ b/src/devices/machine/generalplus_gpl_chx.h
@@ -30,6 +30,9 @@ public:
u16 chb_fifo_r();
void chb_fifo_w(u16 data);
+ void check_cha_fifo_empty();
+ void check_chb_fifo_empty();
+
void process_cha_fifo();
void process_chb_fifo();
diff --git a/src/devices/machine/generalplus_gpl_dma.cpp b/src/devices/machine/generalplus_gpl_dma.cpp
index 98a77fb7133..f8b55db8307 100644
--- a/src/devices/machine/generalplus_gpl_dma.cpp
+++ b/src/devices/machine/generalplus_gpl_dma.cpp
@@ -202,7 +202,10 @@ void gpl_dma_device::trigger_systemm_dma(int channel)
else if ((mode & 0x50) == 0x10)
destdelta = -1;
- LOGMASKED(LOG_GCM394_SYSDMA, "%s:possible DMA operation with params mode:%04x source:%08x (word offset) dest:%08x (word offset) length:%08x (words)\n", machine().describe_context(), mode, source, dest, length );
+ static const char* tmode_names[4] = { "Memory to Memory", "Memory to IO", "IO to Memory", "Reserved" };
+ u8 td = (mode & 0x0c00) >> 10;
+
+ LOGMASKED(LOG_GCM394_SYSDMA, "%s:possible DMA operation with params mode:%04x (TD is %s) source:%08x (word offset) dest:%08x (word offset) length:%08x (words)\n", machine().describe_context(), mode, tmode_names[td], source, dest, length );
// wrlshunt transfers ROM to RAM, all RAM write addresses have 0x800000 in the destination set
@@ -214,7 +217,7 @@ void gpl_dma_device::trigger_systemm_dma(int channel)
u16 val;
if (mode & 0x1000)
{
- val = (m_space_read_cb(source) & 0xFF) | (m_space_read_cb(source) << 8);
+ val = (m_space_read_cb(source) & 0xff) | (m_space_read_cb(source) << 8);
i++;
}
else
diff --git a/src/devices/machine/generalplus_gpl_timebase.cpp b/src/devices/machine/generalplus_gpl_timebase.cpp
index 838ea14400f..ff0fddf2a04 100644
--- a/src/devices/machine/generalplus_gpl_timebase.cpp
+++ b/src/devices/machine/generalplus_gpl_timebase.cpp
@@ -14,39 +14,47 @@ DEFINE_DEVICE_TYPE(GPL_TIMEBASE, gpl_timebase_device, "gpl_timebase", "Generalpl
gpl_timebase_device::gpl_timebase_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, GPL_TIMEBASE, tag, owner, clock),
- m_timebase_a(*this, "timebase_a"),
- m_timebase_b(*this, "timebase_b"),
- m_timebase_c(*this, "timebase_c"),
+ m_timebasetimer(*this, { "timebase_a", "timebase_b", "timebase_c" }),
m_updateirqs_cb(*this)
{
}
void gpl_timebase_device::device_start()
{
- save_item(NAME(m_timebasea_ctrl));
- save_item(NAME(m_timebaseb_ctrl));
- save_item(NAME(m_timebasec_ctrl));
+ save_item(NAME(m_timebase_ctrl));
save_item(NAME(m_timebase_reset));
}
void gpl_timebase_device::device_reset()
{
- m_timebasea_ctrl = 0x0000;
- m_timebaseb_ctrl = 0x0000;
- m_timebasec_ctrl = 0x0000;
+ m_timebase_ctrl[0] = 0x0000;
+ m_timebase_ctrl[1] = 0x0000;
+ m_timebase_ctrl[2] = 0x0000;
m_timebase_reset = 0x0000;
}
+attotime gpl_timebase_device::get_timer_period(int timer, int ctrlval)
+{
+ int which = (timer << 2) | ctrlval;
+
+ if (which != 0) // timebase_a, fequency 0 is 'off'
+ {
+ int period = 1 << (which - 1);
+ return attotime::from_hz(period);
+ }
+
+ return attotime::never;
+}
// Timebase ('fixed' frequency timers)
// (each can select from 3 different frequencies, different for each timer)
-
-TIMER_DEVICE_CALLBACK_MEMBER( gpl_timebase_device::timebase_a_cb )
+template<u16 Timer>
+TIMER_DEVICE_CALLBACK_MEMBER( gpl_timebase_device::timebase_cb )
{
- // sets bit 15 in m_timebasec_ctrl, also visible (as read only) in P_INT_Status2, bit 8
+ // sets bit 15 in m_timebase_ctrl[2], also visible (as read only) in P_INT_Status2, bit 8
// uses IRQ7 (FIQ option not available)
- m_timebasea_ctrl |= 0x8000;
+ m_timebase_ctrl[Timer] |= 0x8000;
m_updateirqs_cb(1);
}
@@ -70,127 +78,34 @@ TIMER_DEVICE_CALLBACK_MEMBER( gpl_timebase_device::timebase_a_cb )
// 1 TMBAS[1]
// 0 TMBAS[0] 00 = Reserved, 01 = 1Hz, 10 = 2Hz, 11 = 4Hz
-u16 gpl_timebase_device::timebasea_ctrl_r()
-{
- LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebasea_ctrl_r\n", machine().describe_context());
- return m_timebasea_ctrl;
-}
-
-void gpl_timebase_device::timebasea_ctrl_w(u16 data)
-{
- LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebasea_ctrl_w %04x\n", machine().describe_context(), data);
-
- if (data & 0x8000)
- {
- m_timebasea_ctrl = data & 0x7fff;
- m_updateirqs_cb(1);
- }
- else
- {
- m_timebasea_ctrl = data;
- }
-
- if ((m_timebasea_ctrl & 0x6000) == 0x6000)
- {
- switch (m_timebasea_ctrl & 0x0003)
- {
- case 0x00: m_timebase_a->adjust(attotime::never); break; // invalid
- case 0x01: m_timebase_a->adjust(attotime::from_hz(1)); break;
- case 0x02: m_timebase_a->adjust(attotime::from_hz(2)); break;
- case 0x03: m_timebase_a->adjust(attotime::from_hz(4)); break;
- }
- }
- else
- {
- m_timebase_a->adjust(attotime::never);
- }
-}
-
-TIMER_DEVICE_CALLBACK_MEMBER( gpl_timebase_device::timebase_b_cb )
-{
- // sets bit 15 in m_timebaseb_ctrl, also visible (as read only) in P_INT_Status2, bit 9
- // uses IRQ7 (FIQ option not available)
- m_timebaseb_ctrl |= 0x8000;
- m_updateirqs_cb(1);
-}
-
-u16 gpl_timebase_device::timebaseb_ctrl_r()
+template<u16 Timer> u16 gpl_timebase_device::timebase_ctrl_r()
{
- LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebaseb_ctrl_r\n", machine().describe_context());
- return m_timebaseb_ctrl;
+ LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebase%c_ctrl_r\n", machine().describe_context(), 'a'+Timer);
+ return m_timebase_ctrl[Timer];
}
-void gpl_timebase_device::timebaseb_ctrl_w(u16 data)
+template<u16 Timer> void gpl_timebase_device::timebase_ctrl_w(u16 data)
{
- LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebaseb_ctrl_w %04x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebase%c_ctrl_w %04x\n", machine().describe_context(), 'a'+Timer, data);
if (data & 0x8000)
{
- m_timebaseb_ctrl = data & 0x7fff;
+ m_timebase_ctrl[Timer] = data & 0x7fff;
m_updateirqs_cb(1);
}
else
{
- m_timebaseb_ctrl = data;
+ m_timebase_ctrl[Timer] = data;
}
- if ((m_timebaseb_ctrl & 0x6000) == 0x6000)
+ if (m_timebase_ctrl[Timer] & 0x2000)
{
- switch (m_timebaseb_ctrl & 0x0003)
- {
- case 0x00: m_timebase_b->adjust(attotime::from_hz(8)); break;
- case 0x01: m_timebase_b->adjust(attotime::from_hz(16)); break;
- case 0x02: m_timebase_b->adjust(attotime::from_hz(32)); break;
- case 0x03: m_timebase_b->adjust(attotime::from_hz(64)); break;
- }
+ attotime period = get_timer_period(Timer, m_timebase_ctrl[Timer] & 0x0003);
+ m_timebasetimer[Timer]->adjust(period, 0, period);
}
else
{
- m_timebase_b->adjust(attotime::never);
- }
-}
-
-TIMER_DEVICE_CALLBACK_MEMBER( gpl_timebase_device::timebase_c_cb )
-{
- // sets bit 15 in m_timebasec_ctrl, also visible (as read only) in P_INT_Status2, bit 10
- // uses IRQ6 (FIQ option not available)
- m_timebasec_ctrl |= 0x8000;
- m_updateirqs_cb(1);
-}
-
-u16 gpl_timebase_device::timebasec_ctrl_r()
-{
- LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebasec_ctrl_r\n", machine().describe_context());
- return m_timebasec_ctrl;
-}
-
-void gpl_timebase_device::timebasec_ctrl_w(u16 data)
-{
- LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebasec_ctrl_w %04x\n", machine().describe_context(), data);
-
- if (data & 0x8000)
- {
- m_timebasec_ctrl = data & 0x7fff;
- m_updateirqs_cb(1);
- }
- else
- {
- m_timebasec_ctrl = data;
- }
-
- if ((m_timebasec_ctrl & 0x6000) == 0x6000)
- {
- switch (m_timebasec_ctrl & 0x0003)
- {
- case 0x00: m_timebase_c->adjust(attotime::from_hz(128)); break;
- case 0x01: m_timebase_c->adjust(attotime::from_hz(256)); break;
- case 0x02: m_timebase_c->adjust(attotime::from_hz(512)); break;
- case 0x03: m_timebase_c->adjust(attotime::from_hz(1024)); break;
- }
- }
- else
- {
- m_timebase_c->adjust(attotime::never);
+ m_timebasetimer[Timer]->adjust(attotime::never);
}
}
@@ -200,9 +115,17 @@ void gpl_timebase_device::timebase_reset_w(u16 data)
m_timebase_reset = data;
}
+u16 gpl_timebase_device::timebasea_ctrl_r() { return timebase_ctrl_r<0>(); }
+u16 gpl_timebase_device::timebaseb_ctrl_r() { return timebase_ctrl_r<1>(); }
+u16 gpl_timebase_device::timebasec_ctrl_r() { return timebase_ctrl_r<2>(); }
+
+void gpl_timebase_device::timebasea_ctrl_w(u16 data) { timebase_ctrl_w<0>(data); }
+void gpl_timebase_device::timebaseb_ctrl_w(u16 data) { timebase_ctrl_w<1>(data); }
+void gpl_timebase_device::timebasec_ctrl_w(u16 data) { timebase_ctrl_w<2>(data); }
+
void gpl_timebase_device::device_add_mconfig(machine_config &config)
{
- TIMER(config, "timebase_a").configure_generic(FUNC(gpl_timebase_device::timebase_a_cb));
- TIMER(config, "timebase_b").configure_generic(FUNC(gpl_timebase_device::timebase_b_cb));
- TIMER(config, "timebase_c").configure_generic(FUNC(gpl_timebase_device::timebase_c_cb));
+ TIMER(config, "timebase_a").configure_generic(FUNC(gpl_timebase_device::timebase_cb<0>));
+ TIMER(config, "timebase_b").configure_generic(FUNC(gpl_timebase_device::timebase_cb<1>));
+ TIMER(config, "timebase_c").configure_generic(FUNC(gpl_timebase_device::timebase_cb<2>));
}
diff --git a/src/devices/machine/generalplus_gpl_timebase.h b/src/devices/machine/generalplus_gpl_timebase.h
index a6ad4969009..bac4c1f3f15 100644
--- a/src/devices/machine/generalplus_gpl_timebase.h
+++ b/src/devices/machine/generalplus_gpl_timebase.h
@@ -12,19 +12,16 @@ class gpl_timebase_device : public device_t
public:
gpl_timebase_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- bool timebasea_irq_flag() { return m_timebasea_ctrl & 0x8000 ? true : false; }
- bool timebaseb_irq_flag() { return m_timebaseb_ctrl & 0x8000 ? true : false; }
- bool timebasec_irq_flag() { return m_timebasec_ctrl & 0x8000 ? true : false; }
+ template<u16 Timer> bool timebase_irq_flag() { return ((m_timebase_ctrl[Timer] & 0x8000) && (m_timebase_ctrl[Timer] & 0x4000)) ? true : false; }
auto updateirqs_callback() { return m_updateirqs_cb.bind(); }
u16 timebasea_ctrl_r();
- void timebasea_ctrl_w(u16 data);
-
u16 timebaseb_ctrl_r();
- void timebaseb_ctrl_w(u16 data);
-
u16 timebasec_ctrl_r();
+
+ void timebasea_ctrl_w(u16 data);
+ void timebaseb_ctrl_w(u16 data);
void timebasec_ctrl_w(u16 data);
void timebase_reset_w(u16 data);
@@ -35,19 +32,18 @@ protected:
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- TIMER_DEVICE_CALLBACK_MEMBER(timebase_a_cb);
- TIMER_DEVICE_CALLBACK_MEMBER(timebase_b_cb);
- TIMER_DEVICE_CALLBACK_MEMBER(timebase_c_cb);
+ template<u16 Timer> TIMER_DEVICE_CALLBACK_MEMBER(timebase_cb);
+
+ template<u16 Timer> u16 timebase_ctrl_r();
+ template<u16 Timer> void timebase_ctrl_w(u16 data);
+
- u16 m_timebasea_ctrl;
- u16 m_timebaseb_ctrl;
- u16 m_timebasec_ctrl;
+ attotime get_timer_period(int timer, int ctrlval);
+ u16 m_timebase_ctrl[3];
u16 m_timebase_reset;
- required_device<timer_device> m_timebase_a;
- required_device<timer_device> m_timebase_b;
- required_device<timer_device> m_timebase_c;
+ required_device_array<timer_device, 3> m_timebasetimer;
devcb_write_line m_updateirqs_cb;
};
diff --git a/src/devices/machine/generic_spi_flash.cpp b/src/devices/machine/generic_spi_flash.cpp
index cf2825b7b0d..10a819d3276 100644
--- a/src/devices/machine/generic_spi_flash.cpp
+++ b/src/devices/machine/generic_spi_flash.cpp
@@ -242,8 +242,16 @@ void generic_spi_flash_device::process_write_command(u8 data)
m_spi_addr = (m_spi_addr & 0xffff00) | (data); m_spi_state_step++;
break;
default:
- LOGMASKED(LOG_SPI, "Write SPI data %02x\n", data);
- m_spiptr[(m_spi_addr++) & (m_length - 1)] = data;
+
+ if (m_spi_statusreg & 0x02)
+ {
+ LOGMASKED(LOG_SPI, "Write SPI data %02x at %08x\n", data, m_spi_addr);
+ m_spiptr[(m_spi_addr++) & (m_length - 1)] = data;
+ }
+ else
+ {
+ LOGMASKED(LOG_SPI, "Write SPI data %02x at %08x (but write protect enabled)\n", data, m_spi_addr);
+ }
break;
}
}
diff --git a/src/devices/machine/gpl_renderer.cpp b/src/devices/machine/gpl_renderer.cpp
index f77c826819a..85126c6361e 100644
--- a/src/devices/machine/gpl_renderer.cpp
+++ b/src/devices/machine/gpl_renderer.cpp
@@ -226,101 +226,106 @@ void gpl_renderer_device::draw_tilestrip(bool read_from_csspace, uint32_t screen
}
}
-void gpl_renderer_device::draw_linemap(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t *scrollregs, uint16_t *tilemapregs, address_space &spc, uint16_t *paletteram)
+
+void gpl_renderer_device::draw_linemap(bool read_from_csspace, const rectangle &cliprect, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t *scrollregs, uint16_t *tilemapregs, address_space &spc, uint16_t *paletteram)
{
- uint32_t ctrl = tilemapregs[1];
+ // TODO, correct for segapet1 etc. but points at the wrong data for jak_s500
+ // (is the data on jak_s500 in the correct place?)
- if (0)
- {
- if (ctrl & 0x0010)
- popmessage("bitmap mode %08x with rowscroll\n", tilegfxdata_addr);
- else
- popmessage("bitmap mode %08x\n", tilegfxdata_addr);
- }
+ if ((scanline < cliprect.min_y) || (scanline >= cliprect.max_y))
+ return;
- // note, in interlace modes it appears every other line is unused? (480 entry table, but with blank values)
- // and furthermore the rowscroll and rowzoom tables only have 240 entries, not enough for every line
- // the end of the rowscroll table (entries 240-255) contain something else, maybe garbage data as it's offscreen, maybe not
uint32_t tilemap = tilemapregs[2];
uint32_t palette_map = tilemapregs[3];
- uint32_t linebase = spc.read_word(tilemap + scanline); // every other word is unused, but there are only enough entries for 240 lines then, sometimes to do with interlace mode?
- uint16_t palette = spc.read_word(palette_map + (scanline / 2));
+ //uint32_t xscroll = scrollregs[0];
+ uint32_t yscroll = scrollregs[1];
- if (scanline & 1)
- palette >>= 8;
- else
- palette &= 0xff;
+ int realline = (scanline + yscroll) & 0xff;
- if (!linebase)
- return;
- linebase = linebase | (palette << 16);
+ uint32_t tile = spc.read_word(tilemap + realline);
+ uint16_t palette = 0;
- int upperpalselect = 0;
- if (tilegfxdata_addr & 0x80000000)
- upperpalselect = 1;
+ palette = spc.read_word(palette_map + realline / 2);
+ if (scanline & 1)
+ palette >>= 8;
+ else
+ palette &= 0x00ff;
- tilegfxdata_addr &= 0x7ffffff;
+ int sourcebase = tile | (palette << 16);
+ sourcebase += tilegfxdata_addr;
- // this logic works for jak_s500 and the test modes to get the correct base, doesn't seem to work for jak_car2 ingame, maybe data is copied to wrong place?
- int gfxbase = (tilegfxdata_addr & 0x7ffffff) + (linebase & 0x7ffffff);
+ uint32_t ctrl = tilemapregs[1];
- for (int i = 0; i < 160; i++) // will have to be 320 for jak_car2 ingame, jak_s500 lines are wider than screen, and zoomed
+ if (ctrl & 0x80) // HiColor mode (rad_digi)
{
- uint16_t pix;
- const int addr = gfxbase & 0x7ffffff;
- if (addr < m_csbase)
- {
- pix = m_cpuspace->read_word(addr);
- }
- else
+ for (int i = 0; i < 320; i++)
{
- pix = m_cs_space->read_word(addr - m_csbase);
+ const uint16_t data = spc.read_word(sourcebase + i);
+
+ if (!(data & 0x8000))
+ {
+ m_linebuf[i] = data & 0x7fff;
+ }
}
- gfxbase++;
+ }
+ else
+ {
+ const uint32_t attr = tilemapregs[0];
+ const uint8_t bpp = attr & 0x0003;
+ const uint32_t nc_bpp = ((bpp)+1) << 1;
+ uint32_t palette_offset = (attr & 0x0f00) >> 4;
+ palette_offset >>= nc_bpp;
+ palette_offset <<= nc_bpp;
- int xx;
- uint16_t pal;
+ uint32_t bits = 0;
+ uint32_t nbits = 0;
- if ((scanline >= 0) && (scanline < 480))
+ for (int i = cliprect.min_x; i <= cliprect.max_x; i++)
{
- xx = i * 2;
-
- pal = (pix & 0xff) | 0x100;
-
- if (upperpalselect)
- pal |= 0x200;
-
- if (xx >= 0 && xx <= cliprect.max_x)
+ bits <<= nc_bpp;
+ if (nbits < nc_bpp)
{
- uint16_t rgb = paletteram[pal];
+ uint16_t b;
- if (!(rgb & 0x8000))
+ if (!read_from_csspace)
+ {
+ b = spc.read_word(sourcebase++ & 0x3fffff);
+ }
+ else
{
- m_linebuf[xx] = rgb;
+ const int addr = sourcebase & 0x7ffffff;
+ if (sourcebase < m_csbase)
+ {
+ b = m_cpuspace->read_word(addr & 0x3fffff);
+ }
+ else
+ {
+ b = m_cs_space->read_word(addr - m_csbase);
+ }
}
+ b = (b << 8) | (b >> 8);
+ bits |= b << (nc_bpp - nbits);
+ nbits += 16;
+
}
+ nbits -= nc_bpp;
- xx = (i * 2) + 1;
- pal = (pix >> 8) | 0x100;
+ uint32_t pal = palette_offset + (bits >> 16);
+ bits &= 0xffff;
- if (upperpalselect)
- pal |= 0x200;
+ uint16_t rgb = paletteram[pal];
- if (xx >= 0 && xx <= cliprect.max_x)
+ if (!(rgb & 0x8000))
{
- uint16_t rgb = paletteram[pal];
-
- if (!(rgb & 0x8000))
- {
- m_linebuf[xx] = rgb;
- }
+ m_linebuf[i] = rgb;
}
}
}
}
+
void gpl_renderer_device::draw_sprite(bool read_from_csspace, int extended_sprites_mode, uint32_t palbank, bool highres, const rectangle &cliprect, uint32_t scanline, int priority, uint32_t spritegfxdata_addr, uint32_t base_addr, address_space &spc, uint16_t *paletteram, uint16_t *spriteram)
{
uint32_t tilegfxdata_addr = spritegfxdata_addr;
@@ -543,7 +548,7 @@ void gpl_renderer_device::draw_page(bool read_from_csspace, uint32_t palbank, co
if (ctrl & 0x0001) // Bitmap / Linemap mode! (basically screen width tile mode)
{
- draw_linemap(cliprect, scanline, priority, tilegfxdata_addr_full, scrollregs, tilemapregs, spc, paletteram);
+ draw_linemap(read_from_csspace, cliprect, scanline, priority, tilegfxdata_addr_full, scrollregs, tilemapregs, spc, paletteram);
return;
}
diff --git a/src/devices/machine/gpl_renderer.h b/src/devices/machine/gpl_renderer.h
index f8920623d7a..a2afdf37cb9 100644
--- a/src/devices/machine/gpl_renderer.h
+++ b/src/devices/machine/gpl_renderer.h
@@ -66,7 +66,7 @@ private:
inline void draw_tilestrip(bool read_from_csspace, uint32_t screenwidth, uint32_t drawwidthmask, const rectangle &cliprect, uint32_t tile_h, uint32_t tile_w, uint32_t tilegfxdata_addr, uint32_t tile, uint32_t tile_scanline, int drawx, bool flip_y, uint32_t palette_offset, const uint32_t nc_bpp, const uint32_t bits_per_row, const uint32_t words_per_tile, address_space &spc, uint16_t *palette, uint8_t blendlevel);
inline void draw_tilestrip(bool read_from_csspace, uint32_t screenwidth, uint32_t drawwidthmask, bool blend, bool flip_x, const rectangle &cliprect, uint32_t tile_h, uint32_t tile_w, uint32_t tilegfxdata_addr, uint32_t tile, uint32_t tile_scanline, int drawx, bool flip_y, uint32_t palette_offset, const uint32_t nc_bpp, const uint32_t bits_per_row, const uint32_t words_per_tile, address_space &spc, uint16_t *paletteram, uint8_t blendlevel);
inline void draw_sprite(bool read_from_csspace, int extended_sprites_mode, uint32_t palbank, bool highres, const rectangle &cliprect, uint32_t scanline, int priority, uint32_t spritegfxdata_addr, uint32_t base_addr, address_space &spc, uint16_t *paletteram, uint16_t *spriteram);
- virtual void draw_linemap(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t *scrollregs, uint16_t *tilemapregs, address_space &spc, uint16_t *paletteram);
+ virtual void draw_linemap(bool read_from_csspace, const rectangle &cliprect, uint32_t scanline, int priority, uint32_t tilegfxdata_addr, uint16_t *scrollregs, uint16_t *tilemapregs, address_space &spc, uint16_t *paletteram);
inline uint8_t mix_channel(uint8_t a, uint8_t b, uint8_t alpha);
void update_vcmp_table();
void update_palette_lookup();