diff options
author | AJR <ajrhacker@users.noreply.github.com> | 2019-11-08 09:33:43 -0500 |
---|---|---|
committer | AJR <ajrhacker@users.noreply.github.com> | 2019-11-08 09:34:50 -0500 |
commit | 576e9ee12e2399312d78b629975018711cf6fd97 (patch) | |
tree | 48fc55cf566b55cc3b9b38bc659c35c2c1693241 /src/devices/cpu | |
parent | 8801bb8f8d22f8b48a2df68a8616d4af300bb514 (diff) |
st2xxx: Calculate LCD frame rate and emulate related interrupt (nw)
st2204: Fix logic mistake in psg_w (nw)
Diffstat (limited to 'src/devices/cpu')
-rw-r--r-- | src/devices/cpu/m6502/st2204.cpp | 14 | ||||
-rw-r--r-- | src/devices/cpu/m6502/st2204.h | 1 | ||||
-rw-r--r-- | src/devices/cpu/m6502/st2205u.cpp | 11 | ||||
-rw-r--r-- | src/devices/cpu/m6502/st2205u.h | 1 | ||||
-rw-r--r-- | src/devices/cpu/m6502/st2xxx.cpp | 44 | ||||
-rw-r--r-- | src/devices/cpu/m6502/st2xxx.h | 7 |
6 files changed, 75 insertions, 3 deletions
diff --git a/src/devices/cpu/m6502/st2204.cpp b/src/devices/cpu/m6502/st2204.cpp index 55c837fb8d6..829ff74ac08 100644 --- a/src/devices/cpu/m6502/st2204.cpp +++ b/src/devices/cpu/m6502/st2204.cpp @@ -77,6 +77,7 @@ void st2204_device::device_start() intf->irq_service = false; init_base_timer(0x0020); + init_lcd_timer(0x0040); m_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2204_device::t0_interrupt), this)); m_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2204_device::t1_interrupt), this)); @@ -404,7 +405,7 @@ void st2204_device::st2xxx_tclk_stop() void st2204_device::psg_w(offs_t offset, u8 data) { if (BIT(offset, 0)) - m_psg[offset >> 1] = u16(data << 8) | (m_psg[offset >> 1] & 0x0ff); + m_psg[offset >> 1] = u16(data & 0x0f) << 8 | (m_psg[offset >> 1] & 0x0ff); else m_psg[offset >> 1] = data | (m_psg[offset >> 1] & 0xf00); } @@ -419,6 +420,17 @@ void st2204_device::dac_w(u8 data) // TODO } +unsigned st2204_device::st2xxx_lfr_clocks() const +{ + // ST2202 datasheet suggests 1/4 as many clocks in 4-bit mode; this seems too fast for GameKing 3 (TODO: double-check this) + unsigned lcdcks = ((m_lxmax + m_lfra) * 2 + 3) * 8 * (m_lymax ? m_lymax : 256); + + if (BIT(m_lckr, 4)) + return lcdcks * std::max((m_lckr & 0x0f) * 2, 1); + else + return lcdcks * std::max(((m_lckr & 0x0c) >> 2) * 2, 1); +} + u8 st2204_device::dmsl_r() { return m_dms & 0xff; diff --git a/src/devices/cpu/m6502/st2204.h b/src/devices/cpu/m6502/st2204.h index 8cca3c57085..6c5772b7ecf 100644 --- a/src/devices/cpu/m6502/st2204.h +++ b/src/devices/cpu/m6502/st2204.h @@ -50,6 +50,7 @@ protected: virtual u8 st2xxx_lctr_mask() const override { return 0xff; } virtual u8 st2xxx_lckr_mask() const override { return 0x1f; } virtual u8 st2xxx_lpwm_mask() const override { return 0x3f; } + virtual unsigned st2xxx_lfr_clocks() const override; virtual u8 st2xxx_bctr_mask() const override { return 0x87; } void common_map(address_map &map); diff --git a/src/devices/cpu/m6502/st2205u.cpp b/src/devices/cpu/m6502/st2205u.cpp index 100169584a9..c6036fbe21d 100644 --- a/src/devices/cpu/m6502/st2205u.cpp +++ b/src/devices/cpu/m6502/st2205u.cpp @@ -62,6 +62,7 @@ void st2205u_device::device_start() intf->ram = make_unique_clear<u8[]>(0x8000); init_base_timer(0x0040); + init_lcd_timer(0x0080); save_item(NAME(m_btc)); save_item(NAME(m_tc_12bit)); @@ -349,6 +350,16 @@ void st2205u_device::st2xxx_tclk_stop() { } +unsigned st2205u_device::st2xxx_lfr_clocks() const +{ + unsigned lcdcks = ((m_lxmax * 2 + m_lfra * 4) + 5) * (m_lymax ? m_lymax : 256) * ((m_lctr & 0x03) == 0 ? 2 : 4); + + if ((m_lckr & 0x30) == 0x00 || (m_lckr & 0x30) == 0x30) + return lcdcks * std::max(((m_lckr & 0x0c) >> 2) * 8, 4); + else + return lcdcks * std::max((m_lckr & 0x0f) * 2, 1); +} + u8 st2205u_device::lvctr_r() { return m_lvctr | 0x01; diff --git a/src/devices/cpu/m6502/st2205u.h b/src/devices/cpu/m6502/st2205u.h index edde62aea71..f8ee13649d1 100644 --- a/src/devices/cpu/m6502/st2205u.h +++ b/src/devices/cpu/m6502/st2205u.h @@ -49,6 +49,7 @@ protected: virtual u8 st2xxx_lctr_mask() const override { return 0xef; } virtual u8 st2xxx_lckr_mask() const override { return 0x3f; } virtual u8 st2xxx_lpwm_mask() const override { return 0xff; } + virtual unsigned st2xxx_lfr_clocks() const override; virtual u8 st2xxx_bctr_mask() const override { return 0xb7; } private: diff --git a/src/devices/cpu/m6502/st2xxx.cpp b/src/devices/cpu/m6502/st2xxx.cpp index 62fd8871f85..47d6b6778b4 100644 --- a/src/devices/cpu/m6502/st2xxx.cpp +++ b/src/devices/cpu/m6502/st2xxx.cpp @@ -30,7 +30,8 @@ #define LOG_IRQ (1 << 1U) #define LOG_BT (1 << 2U) -//#define VERBOSE (LOG_IRQ | LOG_BT) +#define LOG_LCDC (1 << 3U) +//#define VERBOSE (LOG_IRQ | LOG_BT | LOG_LCDC) #include "logmacro.h" st2xxx_device::st2xxx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal_map, int data_bits, bool has_banked_ram) @@ -66,6 +67,8 @@ st2xxx_device::st2xxx_device(const machine_config &mconfig, device_type type, co , m_lfra(0) , m_lac(0) , m_lpwm(0) + , m_lcd_ireq(0) + , m_lcd_timer(nullptr) , m_bctr(0) { program_config.m_internal_map = std::move(internal_map); @@ -123,6 +126,20 @@ void st2xxx_device::init_base_timer(u16 ireq) assert(m_bt_ireq != 0); } +TIMER_CALLBACK_MEMBER(st2xxx_device::lcd_interrupt) +{ + m_ireq |= m_lcd_ireq; + update_irq_state(); +} + +void st2xxx_device::init_lcd_timer(u16 ireq) +{ + m_lcd_ireq = ireq; + assert(m_lcd_ireq != 0); + + m_lcd_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2xxx_device::lcd_interrupt), this)); +} + void st2xxx_device::save_common_registers() { mi_st2xxx *intf = downcast<mi_st2xxx *>(mintf.get()); @@ -228,6 +245,7 @@ void st2xxx_device::device_reset() m_lfra = 0; m_lac = 0; m_lpwm = 0; + m_lcd_timer->adjust(attotime::never); // reset UART and BRG m_bctr = 0; @@ -676,6 +694,7 @@ u8 st2xxx_device::lxmax_r() void st2xxx_device::lxmax_w(u8 data) { m_lxmax = data; + lfr_recalculate_period(); } u8 st2xxx_device::lymax_r() @@ -686,6 +705,7 @@ u8 st2xxx_device::lymax_r() void st2xxx_device::lymax_w(u8 data) { m_lymax = data; + lfr_recalculate_period(); } u8 st2xxx_device::lpan_r() @@ -705,17 +725,37 @@ u8 st2xxx_device::lctr_r() void st2xxx_device::lctr_w(u8 data) { - m_lctr = data & st2xxx_lctr_mask(); + data &= st2xxx_lctr_mask(); + u8 old_lctr = std::exchange(m_lctr, data); + + if ((old_lctr & 0xbf) != (m_lctr & 0xbf)) + lfr_recalculate_period(); } void st2xxx_device::lckr_w(u8 data) { m_lckr = data & st2xxx_lckr_mask(); + lfr_recalculate_period(); } void st2xxx_device::lfra_w(u8 data) { m_lfra = data & 0x3f; + lfr_recalculate_period(); +} + +void st2xxx_device::lfr_recalculate_period() +{ + if (!BIT(m_lctr, 7)) + { + unsigned clocks = st2xxx_lfr_clocks(); + assert(clocks != 0); + attotime period = cycles_to_attotime(clocks); + LOGMASKED(LOG_LCDC, "LCD frame rate = %f Hz (PC = $%04X)\n", period.as_hz(), PPC); + m_lcd_timer->adjust(period, 0, period); + } + else + m_lcd_timer->adjust(attotime::never); } u8 st2xxx_device::lac_r() diff --git a/src/devices/cpu/m6502/st2xxx.h b/src/devices/cpu/m6502/st2xxx.h index e72e5c36d95..9dbdef3ba24 100644 --- a/src/devices/cpu/m6502/st2xxx.h +++ b/src/devices/cpu/m6502/st2xxx.h @@ -99,6 +99,7 @@ protected: virtual u8 st2xxx_lctr_mask() const = 0; virtual u8 st2xxx_lckr_mask() const = 0; virtual u8 st2xxx_lpwm_mask() const = 0; + virtual unsigned st2xxx_lfr_clocks() const = 0; virtual u8 st2xxx_bctr_mask() const = 0; class mi_st2xxx : public memory_interface { @@ -117,6 +118,7 @@ protected: }; void init_base_timer(u16 ireq); + void init_lcd_timer(u16 ireq); void save_common_registers(); u8 read_vector(u16 adr) { return downcast<mi_st2xxx &>(*mintf).read_vector(adr); } @@ -126,6 +128,7 @@ protected: u8 acknowledge_irq(); TIMER_CALLBACK_MEMBER(bt_interrupt); + TIMER_CALLBACK_MEMBER(lcd_interrupt); u8 pdata_r(offs_t offset); void pdata_w(offs_t offset, u8 data); @@ -201,6 +204,7 @@ protected: void lctr_w(u8 data); void lckr_w(u8 data); void lfra_w(u8 data); + void lfr_recalculate_period(); u8 lac_r(); void lac_w(u8 data); u8 lpwm_r(); @@ -260,6 +264,9 @@ protected: u8 m_lfra; u8 m_lac; u8 m_lpwm; + u16 m_lcd_ireq; + emu_timer *m_lcd_timer; + u8 m_bctr; u8 m_brs; u8 m_bdiv; |