mirror of
https://github.com/holub/mame
synced 2025-04-16 13:34:55 +03:00
More MC68EZ328 work for palmm100 and iqunlim (#10696) [Ryan Holtz]
* palm/palm.cpp: Promoted palmm100 to working. Split Palm LCD into a separate device. * machine/mc68328.cpp: Improved LCD controller emulation. Fixed reported Coverity issues * vidoe/mc68328lcd.cpp: Added a generic device to handle MC68328-style LCD output signals. * vtech/iqunlim.cpp: Hooked up MC68EZ328 device. Clones promoted to working --------------------- 3Com Palm m100 [Ryan Holtz]
This commit is contained in:
parent
14c680e940
commit
3178442049
@ -689,6 +689,18 @@ if (VIDEOS["MB_VCU"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
--------------------------------------------------
|
||||
--
|
||||
--@src/devices/video/mc68328lcd.h,VIDEOS["MC68328LCD"] = true
|
||||
--------------------------------------------------
|
||||
|
||||
if (VIDEOS["MC68328LCD"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/video/mc68328lcd.cpp",
|
||||
MAME_DIR .. "src/devices/video/mc68328lcd.h",
|
||||
}
|
||||
end
|
||||
|
||||
--------------------------------------------------
|
||||
--
|
||||
--@src/devices/video/mc6845.h,VIDEOS["MC6845"] = true
|
||||
|
@ -373,7 +373,7 @@ void mc68328_base_device::device_start()
|
||||
m_spim = timer_alloc(FUNC(mc68328_base_device::spim_tick), this);
|
||||
m_lcd_scan = timer_alloc(FUNC(mc68328_base_device::lcd_scan_tick), this);
|
||||
|
||||
m_lcd_line_buffer = std::make_unique<u16[]>(1024 / 8); // 1024px wide, up to 8 pixels per word
|
||||
m_lcd_line_buffer = std::make_unique<u16[]>(1024 / 16); // 1024px wide, up to 16 pixels per word
|
||||
|
||||
register_state_save();
|
||||
}
|
||||
@ -466,6 +466,7 @@ void mc68328_base_device::device_reset()
|
||||
m_umisc = 0x0000;
|
||||
|
||||
m_lssa = 0x00000000;
|
||||
m_lssa_end = 0x00000000;
|
||||
m_lvpw = 0xff;
|
||||
m_lxmax = 0x03ff;
|
||||
m_lymax = 0x01ff;
|
||||
@ -480,6 +481,7 @@ void mc68328_base_device::device_reset()
|
||||
m_lckcon = 0x40;
|
||||
m_lposr = 0x00;
|
||||
m_lfrcm = 0xb9;
|
||||
m_lcd_update_pending = true;
|
||||
|
||||
m_hmsr = 0x00000000;
|
||||
m_alarm = 0x00000000;
|
||||
@ -496,6 +498,7 @@ void mc68328_base_device::device_reset()
|
||||
m_spim->adjust(attotime::never);
|
||||
m_lcd_scan->adjust(attotime::never);
|
||||
m_lcd_sysmem_ptr = 0;
|
||||
m_lssa_end = 0;
|
||||
m_lcd_line_bit = 0;
|
||||
m_lcd_line_word = 0;
|
||||
m_lsclk = false;
|
||||
@ -647,6 +650,7 @@ void mc68328_base_device::register_state_save()
|
||||
save_item(NAME(m_umisc));
|
||||
|
||||
save_item(NAME(m_lssa));
|
||||
save_item(NAME(m_lssa_end));
|
||||
save_item(NAME(m_lvpw));
|
||||
save_item(NAME(m_lxmax));
|
||||
save_item(NAME(m_lymax));
|
||||
@ -659,11 +663,9 @@ void mc68328_base_device::register_state_save()
|
||||
save_item(NAME(m_lacdrc));
|
||||
save_item(NAME(m_lpxcd));
|
||||
save_item(NAME(m_lckcon));
|
||||
save_item(NAME(m_llbar));
|
||||
save_item(NAME(m_lotcr));
|
||||
save_item(NAME(m_lposr));
|
||||
save_item(NAME(m_lfrcm));
|
||||
save_item(NAME(m_lgpmr));
|
||||
save_item(NAME(m_lcd_update_pending));
|
||||
|
||||
save_item(NAME(m_hmsr));
|
||||
save_item(NAME(m_alarm));
|
||||
@ -723,6 +725,10 @@ void mc68328_device::register_state_save()
|
||||
save_item(NAME(m_wcn));
|
||||
|
||||
save_item(NAME(m_spisr));
|
||||
|
||||
save_item(NAME(m_llbar));
|
||||
save_item(NAME(m_lotcr));
|
||||
save_item(NAME(m_lgpmr));
|
||||
}
|
||||
|
||||
void mc68ez328_device::register_state_save()
|
||||
@ -1374,31 +1380,31 @@ void mc68328_base_device::isr_msw_w(offs_t offset, u16 data, u16 mem_mask) // 0x
|
||||
{
|
||||
LOGMASKED(LOG_INTS, "%s: isr_msw_w: ISR(MSW) = %04x\n", machine().describe_context(), data);
|
||||
// Clear edge-triggered IRQ1
|
||||
if ((m_icr & ICR_ET1) == ICR_ET1 && (data & INT_IRQ1_MASK) == INT_IRQ1_MASK)
|
||||
if ((m_icr & ICR_ET1) == ICR_ET1 && ((data << 16) & INT_IRQ1_MASK) == INT_IRQ1_MASK)
|
||||
{
|
||||
m_isr &= ~INT_IRQ1_MASK;
|
||||
}
|
||||
|
||||
// Clear edge-triggered IRQ2
|
||||
if ((m_icr & ICR_ET2) == ICR_ET2 && (data & INT_IRQ2_MASK) == INT_IRQ2_MASK)
|
||||
if ((m_icr & ICR_ET2) == ICR_ET2 && ((data << 16) & INT_IRQ2_MASK) == INT_IRQ2_MASK)
|
||||
{
|
||||
m_isr &= ~INT_IRQ2_MASK;
|
||||
}
|
||||
|
||||
// Clear edge-triggered IRQ3
|
||||
if ((m_icr & ICR_ET3) == ICR_ET3 && (data & INT_IRQ3_MASK) == INT_IRQ3_MASK)
|
||||
if ((m_icr & ICR_ET3) == ICR_ET3 && ((data << 16) & INT_IRQ3_MASK) == INT_IRQ3_MASK)
|
||||
{
|
||||
m_isr &= ~INT_IRQ3_MASK;
|
||||
}
|
||||
|
||||
// Clear edge-triggered IRQ6
|
||||
if ((m_icr & ICR_ET6) == ICR_ET6 && (data & INT_IRQ6_MASK) == INT_IRQ6_MASK)
|
||||
if ((m_icr & ICR_ET6) == ICR_ET6 && ((data << 16) & INT_IRQ6_MASK) == INT_IRQ6_MASK)
|
||||
{
|
||||
m_isr &= ~INT_IRQ6_MASK;
|
||||
}
|
||||
|
||||
// Clear edge-triggered IRQ7
|
||||
if ((data & INT_IRQ7_MASK) == INT_IRQ7_MASK)
|
||||
if (((data << 16) & INT_IRQ7_MASK) == INT_IRQ7_MASK)
|
||||
{
|
||||
m_isr &= ~INT_IRQ7_MASK;
|
||||
}
|
||||
@ -3081,12 +3087,38 @@ u16 mc68328_base_device::umisc_r() // 0x908
|
||||
// LCD hardware - Shared and Standard MC68328
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc68328_device::lcd_update_info()
|
||||
{
|
||||
if (!m_lcd_update_pending)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const u32 sysclk_divisor = VCO_DIVISORS[(m_pllcr & PLLCR_SYSCLK_SEL) >> PLLCR_SYSCLK_SHIFT];
|
||||
attotime lcd_dma_duration = attotime::from_ticks(lcd_get_line_word_count() * sysclk_divisor, clock());
|
||||
attotime lcd_scan_duration = lcd_get_line_rate();
|
||||
attotime lcd_frame_duration = (lcd_scan_duration + lcd_dma_duration) * (m_lymax + 1);
|
||||
LOGMASKED(LOG_LCD, "lxmax %d, lymax %d, divisor %d, lrra %02x, lpxcd %02x\n", m_lxmax, m_lymax + 1, sysclk_divisor, m_lpxcd + 1);
|
||||
|
||||
constexpr u8 BIT_WIDTHS[4] = { 1, 2, 4, 0xff };
|
||||
if (!m_lcd_info_changed_cb.isnull())
|
||||
{
|
||||
m_lcd_info_changed_cb(lcd_frame_duration.as_hz(), lcd_get_width(), m_lymax + 1, BIT_WIDTHS[(m_lpicf & LPICF_PBSIZ) >> LPICF_PBSIZ_SHIFT], BIT_WIDTHS[m_lpicf & LPICF_GS]);
|
||||
}
|
||||
|
||||
m_lcd_update_pending = false;
|
||||
}
|
||||
|
||||
u16 mc68328_device::lcd_get_lxmax_mask()
|
||||
{
|
||||
constexpr u16 LXMAX_MASK = 0x03ff;
|
||||
return LXMAX_MASK;
|
||||
}
|
||||
|
||||
int mc68328_device::lcd_get_width()
|
||||
{
|
||||
return (m_lxmax & lcd_get_lxmax_mask()) + 1;
|
||||
}
|
||||
|
||||
u32 mc68328_device::lcd_get_line_word_count()
|
||||
{
|
||||
return m_lvpw != m_llbar ? (m_llbar + 1) : m_llbar;
|
||||
@ -3119,7 +3151,9 @@ void mc68328_base_device::fill_lcd_dma_buffer()
|
||||
{
|
||||
if (m_lcd_sysmem_ptr == m_lssa)
|
||||
{
|
||||
lcd_update_info();
|
||||
m_out_flm_cb(BIT(m_lpolcf, LPOLCF_FLMPOL_BIT) ? 0 : 1);
|
||||
m_lssa_end = m_lssa + ((m_lvpw * (m_lymax + 1)) << 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3138,9 +3172,7 @@ void mc68328_base_device::fill_lcd_dma_buffer()
|
||||
}
|
||||
|
||||
m_lcd_sysmem_ptr += m_lvpw << 1;
|
||||
|
||||
const u32 screen_max_addr = m_lssa + ((m_lvpw * (m_lymax + 1)) << 1);
|
||||
if (m_lcd_sysmem_ptr >= screen_max_addr)
|
||||
if (m_lcd_sysmem_ptr >= m_lssa_end)
|
||||
{
|
||||
m_lcd_sysmem_ptr = m_lssa;
|
||||
}
|
||||
@ -3245,7 +3277,7 @@ void mc68328_base_device::lvpw_w(u8 data) // 0xa05
|
||||
{
|
||||
LOGMASKED(LOG_LCD, "%s: lvpw_w: LVPW = %02x\n", machine().describe_context(), data);
|
||||
m_lvpw = data;
|
||||
LOGMASKED(LOG_LCD, "%s: Virtual Page Width: %d words\n", machine().describe_context(), m_lvpw << 1);
|
||||
LOGMASKED(LOG_LCD, "%s: Virtual Page Width: %d words\n", machine().describe_context(), m_lvpw);
|
||||
}
|
||||
|
||||
u8 mc68328_base_device::lvpw_r() // 0xa05
|
||||
@ -3256,9 +3288,10 @@ u8 mc68328_base_device::lvpw_r() // 0xa05
|
||||
|
||||
void mc68328_base_device::lxmax_w(u16 data) // 0xa08
|
||||
{
|
||||
m_lcd_update_pending = m_lcd_update_pending || (m_lxmax != (data & lcd_get_lxmax_mask()));
|
||||
LOGMASKED(LOG_LCD, "%s: lxmax_w: LXMAX = %04x\n", machine().describe_context(), data);
|
||||
m_lxmax = data & lcd_get_lxmax_mask();
|
||||
LOGMASKED(LOG_LCD, "%s: Width: %d\n", machine().describe_context(), (data & 0x03ff) + 1);
|
||||
LOGMASKED(LOG_LCD, "%s: Width: %d\n", machine().describe_context(), lcd_get_width());
|
||||
}
|
||||
|
||||
u16 mc68328_base_device::lxmax_r() // 0xa08
|
||||
@ -3269,6 +3302,7 @@ u16 mc68328_base_device::lxmax_r() // 0xa08
|
||||
|
||||
void mc68328_base_device::lymax_w(u16 data) // 0xa0a
|
||||
{
|
||||
m_lcd_update_pending = m_lcd_update_pending || (m_lxmax != (data & LYMAX_MASK));
|
||||
LOGMASKED(LOG_LCD, "%s: lymax_w: LYMAX = %04x\n", machine().describe_context(), data);
|
||||
m_lymax = data & LYMAX_MASK;
|
||||
LOGMASKED(LOG_LCD, "%s: Height: %d\n", machine().describe_context(), (data & 0x03ff) + 1);
|
||||
@ -3420,18 +3454,13 @@ void mc68328_device::lckcon_w(u8 data) // 0xa27
|
||||
const u16 old = m_lckcon;
|
||||
m_lckcon = data;
|
||||
|
||||
lcd_update_info();
|
||||
if (BIT(old, LCKCON_LCDON_BIT) && !BIT(m_lckcon, LCKCON_LCDON_BIT))
|
||||
{
|
||||
m_lcd_scan->adjust(attotime::never);
|
||||
}
|
||||
else if (!BIT(old, LCKCON_LCDON_BIT) && BIT(m_lckcon, LCKCON_LCDON_BIT))
|
||||
{
|
||||
const u32 sysclk_divisor = VCO_DIVISORS[(m_pllcr & PLLCR_SYSCLK_SEL) >> PLLCR_SYSCLK_SHIFT];
|
||||
attotime lcd_dma_duration = attotime::from_ticks(m_llbar, clock() / sysclk_divisor);
|
||||
attotime lcd_scan_duration = get_pixclk_rate() * (m_lxmax + 1);
|
||||
attotime lcd_frame_duration = (lcd_scan_duration + lcd_dma_duration) * (m_lymax + 1);
|
||||
m_lcd_info_changed_cb(lcd_frame_duration.as_hz(), m_lxmax + 1, m_lymax + 1);
|
||||
|
||||
m_lcd_scan->adjust(attotime::never);
|
||||
m_lcd_sysmem_ptr = m_lssa;
|
||||
fill_lcd_dma_buffer();
|
||||
@ -3517,24 +3546,52 @@ u16 mc68328_device::lgpmr_r() // 0xa32
|
||||
// LCD hardware - EZ variant
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc68ez328_device::lcd_update_info()
|
||||
{
|
||||
if (!m_lcd_update_pending)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const u32 sysclk_divisor = VCO_DIVISORS[(m_pllcr & PLLCR_SYSCLK_SEL) >> PLLCR_SYSCLK_SHIFT];
|
||||
attotime lcd_dma_duration = attotime::from_ticks(lcd_get_line_word_count() * sysclk_divisor, clock());
|
||||
attotime lcd_scan_duration = lcd_get_line_rate();
|
||||
attotime lcd_frame_duration = (lcd_scan_duration + lcd_dma_duration) * (m_lymax + 1) * 2;
|
||||
|
||||
constexpr u8 BIT_WIDTHS[4] = { 1, 2, 4, 0xff };
|
||||
if (!m_lcd_info_changed_cb.isnull())
|
||||
{
|
||||
m_lcd_info_changed_cb(lcd_frame_duration.as_hz(), lcd_get_width(), m_lymax + 1, BIT_WIDTHS[(m_lpicf & LPICF_PBSIZ) >> LPICF_PBSIZ_SHIFT], BIT_WIDTHS[m_lpicf & LPICF_GS]);
|
||||
}
|
||||
|
||||
m_lcd_update_pending = false;
|
||||
}
|
||||
|
||||
u16 mc68ez328_device::lcd_get_lxmax_mask()
|
||||
{
|
||||
constexpr u16 LXMAX_MASK = 0x03f0;
|
||||
return LXMAX_MASK;
|
||||
}
|
||||
|
||||
int mc68ez328_device::lcd_get_width()
|
||||
{
|
||||
return m_lxmax & lcd_get_lxmax_mask();
|
||||
}
|
||||
|
||||
u32 mc68ez328_device::lcd_get_line_word_count()
|
||||
{
|
||||
const u32 pixels_per_word = 16 / lcd_get_panel_bit_size();
|
||||
return ((m_lxmax & lcd_get_lxmax_mask()) + 16) / pixels_per_word;
|
||||
const u32 pixels_per_word = 16 / (1 << (m_lpicf & LPICF_GS));
|
||||
const u32 data = (m_lxmax & lcd_get_lxmax_mask()) / pixels_per_word;
|
||||
return data;
|
||||
}
|
||||
|
||||
attotime mc68ez328_device::lcd_get_line_rate()
|
||||
{
|
||||
const u32 pixclk_divisor = VCO_DIVISORS[(m_pllcr & PLLCR_PIXCLK_SEL) >> PLLCR_PIXCLK_SHIFT];
|
||||
const u32 pxcd = (m_lpxcd & LPXCD_MASK) + 1;
|
||||
const u32 lrra_factor = 6 + m_lrra + (m_lxmax & lcd_get_lxmax_mask()) + 16;
|
||||
return attotime::from_ticks(lrra_factor * pxcd * pixclk_divisor, clock());
|
||||
const u32 lrra_factor = 6 + m_lrra + (m_lxmax & lcd_get_lxmax_mask()) * 4;
|
||||
const u32 ticks = lrra_factor * pxcd * pixclk_divisor;
|
||||
return attotime::from_ticks(ticks, clock());
|
||||
}
|
||||
|
||||
u8 mc68ez328_device::lcd_get_panel_bit_size()
|
||||
@ -3556,6 +3613,7 @@ void mc68ez328_device::lpicf_w(u8 data) // 0xa20
|
||||
LOGMASKED(LOG_LCD, "%s: lpicf_w: LPICF = %02x\n", machine().describe_context(), data);
|
||||
LOGMASKED(LOG_LCD, "%s: Grayscale Mode: %d\n", machine().describe_context(), GS_NAMES[data & LPICF_GS]);
|
||||
LOGMASKED(LOG_LCD, "%s: Bus Size: %s\n", machine().describe_context(), PBSIZ_NAMES[(data & LPICF_PBSIZ) >> LPICF_PBSIZ_SHIFT]);
|
||||
m_lcd_update_pending = m_lcd_update_pending || (m_lpicf != data);
|
||||
m_lpicf = data;
|
||||
}
|
||||
|
||||
@ -3569,18 +3627,13 @@ void mc68ez328_device::lckcon_w(u8 data) // 0xa27
|
||||
const u16 old = m_lckcon;
|
||||
m_lckcon = data;
|
||||
|
||||
lcd_update_info();
|
||||
if (BIT(old, LCKCON_LCDON_BIT) && !BIT(m_lckcon, LCKCON_LCDON_BIT))
|
||||
{
|
||||
m_lcd_scan->adjust(attotime::never);
|
||||
}
|
||||
else if (!BIT(old, LCKCON_LCDON_BIT) && BIT(m_lckcon, LCKCON_LCDON_BIT))
|
||||
{
|
||||
const u32 sysclk_divisor = VCO_DIVISORS[(m_pllcr & PLLCR_SYSCLK_SEL) >> PLLCR_SYSCLK_SHIFT];
|
||||
attotime lcd_dma_duration = attotime::from_ticks(m_llbar, clock() / sysclk_divisor);
|
||||
attotime lcd_scan_duration = get_pixclk_rate() * (m_lxmax + 1);
|
||||
attotime lcd_frame_duration = (lcd_scan_duration + lcd_dma_duration) * (m_lymax + 1);
|
||||
m_lcd_info_changed_cb(lcd_frame_duration.as_hz(), m_lxmax + 1, m_lymax + 1);
|
||||
|
||||
m_lcd_scan->adjust(attotime::never);
|
||||
m_lcd_sysmem_ptr = m_lssa;
|
||||
fill_lcd_dma_buffer();
|
||||
@ -3590,6 +3643,7 @@ void mc68ez328_device::lckcon_w(u8 data) // 0xa27
|
||||
void mc68ez328_device::lrra_w(u8 data) // 0xa29
|
||||
{
|
||||
LOGMASKED(LOG_LCD, "%s: lrra_w: LRRA = %02x\n", machine().describe_context(), data);
|
||||
m_lcd_update_pending = m_lcd_update_pending || (m_lrra != data);
|
||||
m_lrra = data;
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@
|
||||
class mc68328_base_device : public m68000_device
|
||||
{
|
||||
public:
|
||||
typedef device_delegate<void (double, int, int)> lcd_info_changed_delegate;
|
||||
typedef device_delegate<void (double, int, int, u8, u8)> lcd_info_changed_delegate;
|
||||
|
||||
template <int Line> auto out_port_a() { return m_out_port_a_cb[Line].bind(); }
|
||||
template <int Line> auto out_port_b() { return m_out_port_b_cb[Line].bind(); }
|
||||
@ -124,10 +124,10 @@ public:
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(irq5_w);
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<lcd_info_changed_delegate::supports_callback<T>::value> set_lcd_info_changed(T &&callback, const char *name)
|
||||
template <typename... T>
|
||||
void set_lcd_info_changed(T &&... args)
|
||||
{
|
||||
m_lcd_info_changed_cb.set(std::forward<T>(callback), name);
|
||||
m_lcd_info_changed_cb.set(std::forward<T>(args)...);
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -346,11 +346,6 @@ protected:
|
||||
|
||||
LYMAX_MASK = 0x03ff,
|
||||
|
||||
LGPMR_PAL2 = 0x0007,
|
||||
LGPMR_PAL3 = 0x0070,
|
||||
LGPMR_PAL0 = 0x0700,
|
||||
LGPMR_PAL1 = 0x7000,
|
||||
|
||||
RTCCTL_38_4_BIT = 5,
|
||||
RTCCTL_ENABLE_BIT = 7,
|
||||
RTCCTL_MASK = 0x00a0,
|
||||
@ -706,6 +701,7 @@ protected:
|
||||
|
||||
// $(FF)FFFA00
|
||||
u32 m_lssa; // Screen Starting Address Register
|
||||
u32 m_lssa_end; // Screen Starting Address Register, buffer end address (not memory-mapped)
|
||||
u8 m_lvpw; // Virtual Page Width Register
|
||||
u16 m_lxmax; // Screen Width Register
|
||||
u16 m_lymax; // Screen Height Register
|
||||
@ -718,11 +714,9 @@ protected:
|
||||
u8 m_lacdrc; // ACD (M) Rate Control Register
|
||||
u8 m_lpxcd; // Pixel Clock Divider Register
|
||||
u8 m_lckcon; // Clocking Control Register
|
||||
u8 m_llbar; // Last Buffer Address Register
|
||||
u8 m_lotcr; // Octet Terminal Count Register
|
||||
u8 m_lposr; // Panning Offset Register
|
||||
u8 m_lfrcm; // Frame Rate Control Modulation Register
|
||||
u16 m_lgpmr; // Gray Palette Mapping Register
|
||||
bool m_lcd_update_pending;
|
||||
|
||||
// $(FF)FFFB00
|
||||
u32 m_hmsr; // RTC Hours Minutes Seconds Register
|
||||
@ -751,7 +745,9 @@ protected:
|
||||
template<int Timer> void update_gptimer_state();
|
||||
template<int Timer> TIMER_CALLBACK_MEMBER(timer_tick);
|
||||
|
||||
virtual void lcd_update_info() = 0;
|
||||
virtual u16 lcd_get_lxmax_mask() = 0;
|
||||
virtual int lcd_get_width() = 0;
|
||||
virtual u32 lcd_get_line_word_count() = 0;
|
||||
virtual attotime lcd_get_line_rate() = 0;
|
||||
virtual u8 lcd_get_panel_bit_size() = 0;
|
||||
@ -865,6 +861,11 @@ private:
|
||||
PWMC_IRQEN = 0x4000,
|
||||
PWMC_PWMIRQ = 0x8000,
|
||||
|
||||
LGPMR_PAL2 = 0x0007,
|
||||
LGPMR_PAL3 = 0x0070,
|
||||
LGPMR_PAL0 = 0x0700,
|
||||
LGPMR_PAL1 = 0x7000,
|
||||
|
||||
WCTLR_WDRST = 0x0008,
|
||||
WCTLR_LOCK = 0x0004,
|
||||
WCTLR_FI = 0x0002,
|
||||
@ -1005,6 +1006,11 @@ private:
|
||||
// $(FF)FFF700
|
||||
u16 m_spisr; // SPIS Register
|
||||
|
||||
// $(FF)FFFA00
|
||||
u8 m_llbar; // Last Buffer Address Register
|
||||
u8 m_lotcr; // Octet Terminal Count Register
|
||||
u16 m_lgpmr; // Gray Palette Mapping Register
|
||||
|
||||
void internal_map(address_map &map);
|
||||
void cpu_space_map(address_map &map);
|
||||
|
||||
@ -1020,7 +1026,9 @@ private:
|
||||
virtual timer_regs &get_timer_regs(int timer) override;
|
||||
virtual u32 get_timer_int(int timer) override;
|
||||
|
||||
virtual void lcd_update_info() override;
|
||||
virtual u16 lcd_get_lxmax_mask() override;
|
||||
virtual int lcd_get_width() override;
|
||||
virtual u32 lcd_get_line_word_count() override;
|
||||
virtual attotime lcd_get_line_rate() override;
|
||||
virtual u8 lcd_get_panel_bit_size() override;
|
||||
@ -1225,7 +1233,9 @@ private:
|
||||
virtual timer_regs &get_timer_regs(int timer) override;
|
||||
virtual u32 get_timer_int(int timer) override;
|
||||
|
||||
virtual void lcd_update_info() override;
|
||||
virtual u16 lcd_get_lxmax_mask() override;
|
||||
virtual int lcd_get_width() override;
|
||||
virtual u32 lcd_get_line_word_count() override;
|
||||
virtual attotime lcd_get_line_rate() override;
|
||||
virtual u8 lcd_get_panel_bit_size() override;
|
||||
|
149
src/devices/video/mc68328lcd.cpp
Normal file
149
src/devices/video/mc68328lcd.cpp
Normal file
@ -0,0 +1,149 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ryan Holtz
|
||||
/******************************************************************************
|
||||
|
||||
Generic LCD emulation for use with MC68328/MC68EZ328 devices
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "mc68328lcd.h"
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(MC68328_LCD, mc68328_lcd_device, "mc68328_lcd", "MC68328-compatible LCD Controller")
|
||||
|
||||
mc68328_lcd_device::mc68328_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, MC68328_LCD, tag, owner, clock)
|
||||
, device_palette_interface(mconfig, *this)
|
||||
, device_video_interface(mconfig, *this)
|
||||
{
|
||||
}
|
||||
|
||||
void mc68328_lcd_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_lcd_first_line));
|
||||
save_item(NAME(m_lcd_line_pulse));
|
||||
save_item(NAME(m_lcd_shift_clk));
|
||||
save_item(NAME(m_lcd_data));
|
||||
save_item(NAME(m_lcd_scan_x));
|
||||
save_item(NAME(m_lcd_scan_y));
|
||||
save_item(NAME(m_bus_width));
|
||||
save_item(NAME(m_bpp));
|
||||
|
||||
palette_init();
|
||||
}
|
||||
|
||||
void mc68328_lcd_device::device_reset()
|
||||
{
|
||||
m_lcd_first_line = true;
|
||||
m_lcd_line_pulse = false;
|
||||
m_lcd_shift_clk = false;
|
||||
m_lcd_data = 0;
|
||||
m_lcd_scan_x = 0;
|
||||
m_lcd_scan_y = 0;
|
||||
m_bus_width = 4;
|
||||
m_bpp = 1;
|
||||
}
|
||||
|
||||
void mc68328_lcd_device::palette_init()
|
||||
{
|
||||
constexpr u8 LCD_OFF_R = 0xbd;
|
||||
constexpr u8 LCD_OFF_G = 0xbd;
|
||||
constexpr u8 LCD_OFF_B = 0xaa;
|
||||
constexpr u8 LCD_ON_R = 0x40;
|
||||
constexpr u8 LCD_ON_G = 0x40;
|
||||
constexpr u8 LCD_ON_B = 0x40;
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
const float lerp_factor = i / 15.f;
|
||||
const u8 blend_r = (u8)(LCD_OFF_R * (1.f - lerp_factor) + LCD_ON_R * lerp_factor);
|
||||
const u8 blend_g = (u8)(LCD_OFF_G * (1.f - lerp_factor) + LCD_ON_G * lerp_factor);
|
||||
const u8 blend_b = (u8)(LCD_OFF_B * (1.f - lerp_factor) + LCD_ON_B * lerp_factor);
|
||||
set_pen_color(i, blend_r, blend_g, blend_b);
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(mc68328_lcd_device::flm_w)
|
||||
{
|
||||
m_lcd_first_line = state;
|
||||
}
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(mc68328_lcd_device::llp_w)
|
||||
{
|
||||
const int old = m_lcd_line_pulse;
|
||||
m_lcd_line_pulse = state;
|
||||
if (!state && old)
|
||||
{
|
||||
if (m_lcd_first_line)
|
||||
{
|
||||
m_lcd_scan_y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_lcd_scan_y++;
|
||||
}
|
||||
m_lcd_scan_x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(mc68328_lcd_device::lsclk_w)
|
||||
{
|
||||
const int old = m_lcd_shift_clk;
|
||||
m_lcd_shift_clk = state;
|
||||
if (state && !old)
|
||||
{
|
||||
for (u8 i = 0; i < m_bus_width && m_lcd_scan_x < m_lcd_bitmap.width() && m_lcd_scan_y < m_lcd_bitmap.height(); i += m_bpp)
|
||||
{
|
||||
u8 value = 0;
|
||||
switch (m_bpp)
|
||||
{
|
||||
case 1:
|
||||
value = BIT(m_lcd_data, (m_bus_width - 1) - i) * 15;
|
||||
break;
|
||||
case 2:
|
||||
value = ((m_lcd_data >> ((m_bus_width - 2) - i)) & 3) * 5;
|
||||
break;
|
||||
case 4:
|
||||
value = m_lcd_data & 15;
|
||||
break;
|
||||
}
|
||||
if (m_lcd_scan_x < m_lcd_bitmap.width() && m_lcd_scan_y < m_lcd_bitmap.height())
|
||||
{
|
||||
m_lcd_bitmap.pix(m_lcd_scan_y, m_lcd_scan_x) = pen_color(value);
|
||||
}
|
||||
m_lcd_scan_x++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mc68328_lcd_device::ld_w(u8 data)
|
||||
{
|
||||
m_lcd_data = data;
|
||||
}
|
||||
|
||||
void mc68328_lcd_device::lcd_info_changed(double refresh_hz, int width, int height, u8 bus_width, u8 bpp)
|
||||
{
|
||||
if (has_screen())
|
||||
{
|
||||
screen().set_refresh_hz(refresh_hz);
|
||||
}
|
||||
m_lcd_bitmap.resize(width, height);
|
||||
m_bus_width = bus_width;
|
||||
m_bpp = bpp;
|
||||
m_lcd_scan_x = 0;
|
||||
m_lcd_scan_y = 0;
|
||||
}
|
||||
|
||||
void mc68328_lcd_device::video_update(bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
bitmap.fill(pen_color(0));
|
||||
if (m_lcd_bitmap.valid())
|
||||
{
|
||||
u32 *src = &m_lcd_bitmap.pix(0);
|
||||
u32 *dst = &bitmap.pix(0);
|
||||
const int word_count = std::min(bitmap.width() * bitmap.height(), m_lcd_bitmap.width() * m_lcd_bitmap.height());
|
||||
std::copy_n(src, word_count, dst);
|
||||
}
|
||||
}
|
53
src/devices/video/mc68328lcd.h
Normal file
53
src/devices/video/mc68328lcd.h
Normal file
@ -0,0 +1,53 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ryan Holtz
|
||||
/******************************************************************************
|
||||
|
||||
Generic LCD emulation for use with MC68328/MC68EZ328 devices
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef MAME_VIDEO_MC68328LCD_H
|
||||
#define MAME_VIDEO_MC68328LCD_H
|
||||
|
||||
#pragma once
|
||||
|
||||
class mc68328_lcd_device : public device_t,
|
||||
public device_palette_interface,
|
||||
public device_video_interface
|
||||
{
|
||||
public:
|
||||
mc68328_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(flm_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(llp_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(lsclk_w);
|
||||
void ld_w(u8 data);
|
||||
void lcd_info_changed(double refresh_hz, int width, int height, u8 bus_width, u8 bpp);
|
||||
|
||||
void video_update(bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_palette_interface overrides
|
||||
virtual uint32_t palette_entries() const noexcept override { return 16; }
|
||||
|
||||
void palette_init();
|
||||
|
||||
bitmap_rgb32 m_lcd_bitmap;
|
||||
bool m_lcd_first_line;
|
||||
bool m_lcd_line_pulse;
|
||||
bool m_lcd_shift_clk;
|
||||
u8 m_lcd_data;
|
||||
u16 m_lcd_scan_x;
|
||||
u16 m_lcd_scan_y;
|
||||
u8 m_bus_width;
|
||||
u8 m_bpp;
|
||||
};
|
||||
|
||||
// device type definition
|
||||
DECLARE_DEVICE_TYPE(MC68328_LCD, mc68328_lcd_device)
|
||||
|
||||
#endif // MAME_VIDEO_MC68328LCD_H
|
@ -16,9 +16,9 @@
|
||||
#include "machine/mc68328.h"
|
||||
#include "machine/ram.h"
|
||||
#include "sound/dac.h"
|
||||
#include "video/mc68328lcd.h"
|
||||
#include "video/sed1375.h"
|
||||
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
#include "speaker.h"
|
||||
|
||||
@ -50,12 +50,6 @@ protected:
|
||||
|
||||
offs_t dasm_override(std::ostream &stream, offs_t pc, const util::disasm_interface::data_buffer &opcodes, const util::disasm_interface::data_buffer ¶ms);
|
||||
|
||||
void flm_out(int state);
|
||||
void llp_out(int state);
|
||||
virtual void lsclk_out(int state);
|
||||
void ld_out(u8 data);
|
||||
void lcd_info_changed(double refresh_hz, int width, int height);
|
||||
|
||||
virtual int spi_from_hw();
|
||||
|
||||
required_device<mc68328_base_device> m_maincpu;
|
||||
@ -66,16 +60,6 @@ protected:
|
||||
required_ioport m_io_penb;
|
||||
|
||||
u16 m_spim_data;
|
||||
|
||||
bitmap_rgb32 m_lcd_bitmap;
|
||||
int m_lcd_first_line;
|
||||
int m_lcd_line_pulse;
|
||||
int m_lcd_shift_clk;
|
||||
u8 m_lcd_data;
|
||||
int m_lcd_scan_x;
|
||||
int m_lcd_scan_y;
|
||||
|
||||
static const int EXTRA_ARTWORK_HEIGHT = 60;
|
||||
};
|
||||
|
||||
class palm_state : public palm_base_state
|
||||
@ -83,7 +67,7 @@ class palm_state : public palm_base_state
|
||||
public:
|
||||
palm_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: palm_base_state(mconfig, type, tag)
|
||||
, m_palette(*this, "palette")
|
||||
, m_lcdctrl(*this, "lcdctrl")
|
||||
, m_io_portd(*this, "PORTD")
|
||||
{ }
|
||||
|
||||
@ -105,7 +89,6 @@ protected:
|
||||
void mem_map(address_map &map);
|
||||
|
||||
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
void init_palette(palette_device &palette) const;
|
||||
|
||||
void check_pen_adc_read();
|
||||
void adc_vcc_y_w(int state);
|
||||
@ -115,8 +98,6 @@ protected:
|
||||
void adc_csn_w(int state);
|
||||
int power_nmi_r();
|
||||
|
||||
virtual void lsclk_out(int state) override;
|
||||
|
||||
enum : int
|
||||
{
|
||||
PORTF_Y_VCCN_BIT = 0,
|
||||
@ -126,7 +107,7 @@ protected:
|
||||
PORTF_ADC_CSN_BIT = 7
|
||||
};
|
||||
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<mc68328_lcd_device> m_lcdctrl;
|
||||
required_ioport m_io_portd;
|
||||
|
||||
u8 m_port_f_latch;
|
||||
@ -137,23 +118,23 @@ protected:
|
||||
bool m_adc_gnd_y;
|
||||
};
|
||||
|
||||
class palmiiic_state : public palm_base_state
|
||||
class palmez_base_state : public palm_base_state
|
||||
{
|
||||
public:
|
||||
palmiiic_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: palm_base_state(mconfig, type, tag)
|
||||
, m_sed1375(*this, "lcdctrl")
|
||||
, m_rows(*this, "ROW%u", 0u)
|
||||
{ }
|
||||
|
||||
void palmiiic(machine_config &config);
|
||||
|
||||
DECLARE_INPUT_CHANGED_MEMBER(button_check);
|
||||
|
||||
protected:
|
||||
palmez_base_state(const machine_config &mconfig, device_type type, const char *tag, const u8 hardware_id)
|
||||
: palm_base_state(mconfig, type, tag)
|
||||
, m_rows(*this, "ROW%u", 0u)
|
||||
, m_hardware_id(hardware_id)
|
||||
{ }
|
||||
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
void palmez_base(machine_config &config);
|
||||
|
||||
void mem_map(address_map &map);
|
||||
|
||||
void adc_enable_w(int state);
|
||||
@ -167,18 +148,55 @@ protected:
|
||||
void spi_to_hw(int state);
|
||||
virtual int spi_from_hw() override;
|
||||
|
||||
required_device<sed1375_device> m_sed1375;
|
||||
required_ioport_array<3> m_rows;
|
||||
|
||||
u8 m_key_row_mask;
|
||||
u8 m_key_col_mask;
|
||||
bool m_port_d_hardware_id;
|
||||
|
||||
bool m_hardware_id_asserted;
|
||||
const u8 m_hardware_id;
|
||||
|
||||
bool m_adc_enabled;
|
||||
u8 m_adc_cmd_bit_count;
|
||||
u8 m_adc_response_bit_count;
|
||||
u8 m_adc_cmd;
|
||||
};
|
||||
|
||||
class palmiiic_state : public palmez_base_state
|
||||
{
|
||||
public:
|
||||
palmiiic_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: palmez_base_state(mconfig, type, tag, 0x09)
|
||||
, m_sed1375(*this, "lcdctrl")
|
||||
{ }
|
||||
|
||||
void palmiiic(machine_config &config);
|
||||
|
||||
protected:
|
||||
void mem_map(address_map &map);
|
||||
|
||||
required_device<sed1375_device> m_sed1375;
|
||||
};
|
||||
|
||||
class palmm100_state : public palmez_base_state
|
||||
{
|
||||
public:
|
||||
palmm100_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: palmez_base_state(mconfig, type, tag, 0x05)
|
||||
, m_lcdctrl(*this, "lcdctrl")
|
||||
{ }
|
||||
|
||||
void palmm100(machine_config &config);
|
||||
|
||||
protected:
|
||||
template <int Line> int hardware_subid_r();
|
||||
|
||||
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
|
||||
required_device<mc68328_lcd_device> m_lcdctrl;
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
MACHINE HARDWARE
|
||||
***************************************************************************/
|
||||
@ -188,13 +206,6 @@ protected:
|
||||
void palm_base_state::machine_start()
|
||||
{
|
||||
save_item(NAME(m_spim_data));
|
||||
|
||||
save_item(NAME(m_lcd_first_line));
|
||||
save_item(NAME(m_lcd_line_pulse));
|
||||
save_item(NAME(m_lcd_shift_clk));
|
||||
save_item(NAME(m_lcd_data));
|
||||
save_item(NAME(m_lcd_scan_x));
|
||||
save_item(NAME(m_lcd_scan_y));
|
||||
}
|
||||
|
||||
void palm_base_state::machine_reset()
|
||||
@ -205,13 +216,6 @@ void palm_base_state::machine_reset()
|
||||
memcpy(m_ram->pointer(), bios, 0x20000);
|
||||
|
||||
m_spim_data = 0xffff;
|
||||
|
||||
m_lcd_first_line = 1;
|
||||
m_lcd_line_pulse = 0;
|
||||
m_lcd_shift_clk = 0;
|
||||
m_lcd_data = 0;
|
||||
m_lcd_scan_x = 0;
|
||||
m_lcd_scan_y = 0;
|
||||
}
|
||||
|
||||
INPUT_CHANGED_MEMBER(palm_base_state::pen_check)
|
||||
@ -227,6 +231,7 @@ int palm_base_state::spi_from_hw()
|
||||
return out_state;
|
||||
}
|
||||
|
||||
|
||||
// First-generation Palm hardware ("IDT")
|
||||
|
||||
void palm_state::machine_start()
|
||||
@ -254,6 +259,12 @@ void palm_state::machine_reset()
|
||||
m_adc_gnd_y = false;
|
||||
}
|
||||
|
||||
u32 palm_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
m_lcdctrl->video_update(bitmap, cliprect);
|
||||
return 0;
|
||||
}
|
||||
|
||||
INPUT_CHANGED_MEMBER(palm_state::button_check)
|
||||
{
|
||||
const u8 button_state = m_io_portd->read();
|
||||
@ -310,9 +321,10 @@ int palm_state::power_nmi_r()
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Palm IIIc hardware ("Austin")
|
||||
|
||||
void palmiiic_state::machine_start()
|
||||
// Basic 68EZ328-based Palm hardware
|
||||
|
||||
void palmez_base_state::machine_start()
|
||||
{
|
||||
palm_base_state::machine_start();
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
@ -320,28 +332,31 @@ void palmiiic_state::machine_start()
|
||||
|
||||
save_item(NAME(m_key_row_mask));
|
||||
save_item(NAME(m_key_col_mask));
|
||||
save_item(NAME(m_port_d_hardware_id));
|
||||
|
||||
save_item(NAME(m_hardware_id_asserted));
|
||||
|
||||
save_item(NAME(m_adc_enabled));
|
||||
save_item(NAME(m_adc_cmd_bit_count));
|
||||
save_item(NAME(m_adc_response_bit_count));
|
||||
save_item(NAME(m_adc_cmd));
|
||||
}
|
||||
|
||||
void palmiiic_state::machine_reset()
|
||||
void palmez_base_state::machine_reset()
|
||||
{
|
||||
palm_base_state::machine_reset();
|
||||
|
||||
m_key_row_mask = 0;
|
||||
m_key_col_mask = 0;
|
||||
|
||||
m_port_d_hardware_id = false;
|
||||
m_hardware_id_asserted = false;
|
||||
|
||||
m_adc_enabled = false;
|
||||
m_adc_cmd_bit_count = 8;
|
||||
m_adc_response_bit_count = 0;
|
||||
m_adc_cmd = 0;
|
||||
}
|
||||
|
||||
INPUT_CHANGED_MEMBER(palmiiic_state::button_check)
|
||||
INPUT_CHANGED_MEMBER(palmez_base_state::button_check)
|
||||
{
|
||||
const u8 button_state = m_rows[param]->read();
|
||||
for (int bit = 0; bit < 4; bit++)
|
||||
@ -350,7 +365,7 @@ INPUT_CHANGED_MEMBER(palmiiic_state::button_check)
|
||||
}
|
||||
}
|
||||
|
||||
void palmiiic_state::adc_enable_w(int state)
|
||||
void palmez_base_state::adc_enable_w(int state)
|
||||
{
|
||||
const bool was_enabled = m_adc_enabled;
|
||||
m_adc_enabled = !state;
|
||||
@ -362,46 +377,39 @@ void palmiiic_state::adc_enable_w(int state)
|
||||
}
|
||||
|
||||
template <int Line>
|
||||
void palmiiic_state::kbd_row_w(int state)
|
||||
void palmez_base_state::kbd_row_w(int state)
|
||||
{
|
||||
m_key_row_mask &= ~(1 << Line);
|
||||
m_key_row_mask |= !state << Line;
|
||||
}
|
||||
|
||||
template <int Line>
|
||||
void palmiiic_state::kbd_col_w(int state)
|
||||
void palmez_base_state::kbd_col_w(int state)
|
||||
{
|
||||
m_key_col_mask &= ~(1 << Line);
|
||||
m_key_col_mask |= state << Line;
|
||||
}
|
||||
|
||||
template <int Line>
|
||||
int palmiiic_state::kbd_scan_r()
|
||||
int palmez_base_state::kbd_scan_r()
|
||||
{
|
||||
int state = 0;
|
||||
if (m_port_d_hardware_id)
|
||||
if (m_hardware_id_asserted)
|
||||
{
|
||||
state = BIT(~0x09, Line);
|
||||
return BIT(~m_hardware_id, Line);
|
||||
}
|
||||
else
|
||||
|
||||
int state = 0;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
if (BIT(m_key_row_mask, i))
|
||||
{
|
||||
if (BIT(m_key_row_mask, i))
|
||||
{
|
||||
state |= BIT(m_rows[i]->read(), Line);
|
||||
}
|
||||
state |= BIT(m_rows[i]->read(), Line);
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
void palmiiic_state::hardware_id_req_w(int state)
|
||||
{
|
||||
m_port_d_hardware_id = !state;
|
||||
}
|
||||
|
||||
void palmiiic_state::spi_to_hw(int state)
|
||||
void palmez_base_state::spi_to_hw(int state)
|
||||
{
|
||||
if (m_adc_enabled && m_adc_cmd_bit_count > 0)
|
||||
{
|
||||
@ -411,7 +419,7 @@ void palmiiic_state::spi_to_hw(int state)
|
||||
}
|
||||
}
|
||||
|
||||
int palmiiic_state::spi_from_hw()
|
||||
int palmez_base_state::spi_from_hw()
|
||||
{
|
||||
int state = palm_base_state::spi_from_hw();
|
||||
if (m_adc_enabled && m_adc_cmd_bit_count == 0)
|
||||
@ -451,84 +459,26 @@ int palmiiic_state::spi_from_hw()
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
LCD HARDWARE
|
||||
***************************************************************************/
|
||||
|
||||
void palm_state::init_palette(palette_device &palette) const
|
||||
void palmez_base_state::hardware_id_req_w(int state)
|
||||
{
|
||||
palette.set_pen_color(0, 0xbd, 0xbd, 0xaa);
|
||||
palette.set_pen_color(1, 0x40, 0x40, 0x40);
|
||||
m_hardware_id_asserted = !state;
|
||||
}
|
||||
|
||||
void palm_base_state::flm_out(int state)
|
||||
{
|
||||
m_lcd_first_line = state;
|
||||
}
|
||||
|
||||
void palm_base_state::llp_out(int state)
|
||||
{
|
||||
const int old = m_lcd_line_pulse;
|
||||
m_lcd_line_pulse = state;
|
||||
if (!state && old)
|
||||
{
|
||||
m_lcd_scan_x = 0;
|
||||
if (m_lcd_first_line)
|
||||
{
|
||||
m_lcd_scan_y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_lcd_scan_y++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Palm m100 ("Brad") hardware
|
||||
|
||||
void palm_base_state::lsclk_out(int state)
|
||||
u32 palmm100_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
m_lcd_shift_clk = state;
|
||||
}
|
||||
|
||||
void palm_state::lsclk_out(int state)
|
||||
{
|
||||
const int old = m_lcd_shift_clk;
|
||||
palm_base_state::lsclk_out(state);
|
||||
if (state && !old)
|
||||
{
|
||||
for (u8 i = 0; i < 4; i++)
|
||||
{
|
||||
m_lcd_bitmap.pix(m_lcd_scan_y, m_lcd_scan_x) = m_palette->pen_color(BIT(m_lcd_data, 3 - i));
|
||||
m_lcd_scan_x++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void palm_base_state::ld_out(u8 data)
|
||||
{
|
||||
m_lcd_data = data;
|
||||
}
|
||||
|
||||
void palm_base_state::lcd_info_changed(double refresh_hz, int width, int height)
|
||||
{
|
||||
m_screen->set_refresh_hz(refresh_hz);
|
||||
m_screen->set_size(width, height + EXTRA_ARTWORK_HEIGHT);
|
||||
m_screen->set_visarea(0, width - 1, 0, (height + EXTRA_ARTWORK_HEIGHT) - 1);
|
||||
m_lcd_bitmap.resize(width, height);
|
||||
}
|
||||
|
||||
u32 palm_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
bitmap.fill(m_palette->pen_color(0));
|
||||
if (m_lcd_bitmap.valid())
|
||||
{
|
||||
u32 *src = &m_lcd_bitmap.pix(0);
|
||||
u32 *dst = &bitmap.pix(0);
|
||||
std::copy_n(src, m_lcd_bitmap.width() * m_lcd_bitmap.height(), dst);
|
||||
}
|
||||
m_lcdctrl->video_update(bitmap, cliprect);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <int Line> int palmm100_state::hardware_subid_r()
|
||||
{
|
||||
return BIT(~0x00, Line);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
ADDRESS MAPS
|
||||
***************************************************************************/
|
||||
@ -538,10 +488,15 @@ void palm_state::mem_map(address_map &map)
|
||||
map(0xc00000, 0xe07fff).rom().region("bios", 0);
|
||||
}
|
||||
|
||||
void palmiiic_state::mem_map(address_map &map)
|
||||
void palmez_base_state::mem_map(address_map &map)
|
||||
{
|
||||
map(0x00c00000, 0x00e07fff).rom().region("bios", 0);
|
||||
map(0x10c00000, 0x10e07fff).rom().region("bios", 0);
|
||||
}
|
||||
|
||||
void palmiiic_state::mem_map(address_map &map)
|
||||
{
|
||||
palmez_base_state::mem_map(map);
|
||||
map(0x1f000000, 0x1f01ffff).m(m_sed1375, FUNC(sed1375_device::map));
|
||||
}
|
||||
|
||||
@ -575,7 +530,7 @@ static INPUT_PORTS_START(palm)
|
||||
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_UNUSED)
|
||||
INPUT_PORTS_END
|
||||
|
||||
static INPUT_PORTS_START(palmez)
|
||||
static INPUT_PORTS_START(palmiiic)
|
||||
PORT_INCLUDE(palm_base)
|
||||
|
||||
PORT_START("ROW0")
|
||||
@ -597,9 +552,29 @@ static INPUT_PORTS_START(palmez)
|
||||
PORT_BIT(0xf8, IP_ACTIVE_HIGH, IPT_UNUSED)
|
||||
INPUT_PORTS_END
|
||||
|
||||
static INPUT_PORTS_START(palmm100)
|
||||
PORT_INCLUDE(palm_base)
|
||||
|
||||
PORT_START("ROW0")
|
||||
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Button 1") PORT_CODE(KEYCODE_F) PORT_CHANGED_MEMBER(DEVICE_SELF, palmm100_state, button_check, 0)
|
||||
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Button 2") PORT_CODE(KEYCODE_G) PORT_CHANGED_MEMBER(DEVICE_SELF, palmm100_state, button_check, 0)
|
||||
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON4) PORT_NAME("Button 3") PORT_CODE(KEYCODE_J) PORT_CHANGED_MEMBER(DEVICE_SELF, palmm100_state, button_check, 0)
|
||||
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_BUTTON5) PORT_NAME("Button 4") PORT_CODE(KEYCODE_K) PORT_CHANGED_MEMBER(DEVICE_SELF, palmm100_state, button_check, 0)
|
||||
PORT_BIT(0xf0, IP_ACTIVE_HIGH, IPT_UNUSED)
|
||||
|
||||
PORT_START("ROW1")
|
||||
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON6) PORT_NAME("Down") PORT_CODE(KEYCODE_H) PORT_CHANGED_MEMBER(DEVICE_SELF, palmm100_state, button_check, 1)
|
||||
PORT_BIT(0xfd, IP_ACTIVE_HIGH, IPT_UNUSED)
|
||||
|
||||
PORT_START("ROW2")
|
||||
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON7) PORT_NAME("Power") PORT_CODE(KEYCODE_D) PORT_CHANGED_MEMBER(DEVICE_SELF, palmm100_state, button_check, 2)
|
||||
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON8) PORT_NAME("Up") PORT_CODE(KEYCODE_Y) PORT_CHANGED_MEMBER(DEVICE_SELF, palmm100_state, button_check, 2)
|
||||
PORT_BIT(0xfc, IP_ACTIVE_HIGH, IPT_UNUSED)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
MACHINE DRIVERS
|
||||
MACHINE/DEVICE DRIVERS
|
||||
***************************************************************************/
|
||||
|
||||
void palm_state::palm_base(machine_config &config)
|
||||
@ -626,24 +601,23 @@ void palm_state::palm_base(machine_config &config)
|
||||
m_maincpu->in_port_d<6>().set_ioport(m_io_penb).bit(6);
|
||||
m_maincpu->in_port_d<7>().set_ioport(m_io_penb).bit(7);
|
||||
|
||||
//m_maincpu->in_port_f().set(FUNC(palm_state::port_f_in)); Port F latch
|
||||
|
||||
m_maincpu->out_pwm().set("dac", FUNC(dac_bit_interface::write));
|
||||
m_maincpu->in_spim().set(FUNC(palm_state::spi_from_hw));
|
||||
m_maincpu->out_flm().set(FUNC(palm_state::flm_out));
|
||||
m_maincpu->out_llp().set(FUNC(palm_state::llp_out));
|
||||
m_maincpu->out_lsclk().set(FUNC(palm_state::lsclk_out));
|
||||
m_maincpu->out_ld().set(FUNC(palm_state::ld_out));
|
||||
m_maincpu->set_lcd_info_changed(FUNC(palm_state::lcd_info_changed));
|
||||
|
||||
m_maincpu->out_flm().set(m_lcdctrl, FUNC(mc68328_lcd_device::flm_w));
|
||||
m_maincpu->out_llp().set(m_lcdctrl, FUNC(mc68328_lcd_device::llp_w));
|
||||
m_maincpu->out_lsclk().set(m_lcdctrl, FUNC(mc68328_lcd_device::lsclk_w));
|
||||
m_maincpu->out_ld().set(m_lcdctrl, FUNC(mc68328_lcd_device::ld_w));
|
||||
m_maincpu->set_lcd_info_changed(m_lcdctrl, FUNC(mc68328_lcd_device::lcd_info_changed));
|
||||
|
||||
/* video hardware */
|
||||
SCREEN(config, m_screen, SCREEN_TYPE_LCD);
|
||||
m_screen->set_refresh_hz(60);
|
||||
m_screen->set_size(160, 160);
|
||||
m_screen->set_visarea(0, 159, 0, 159);
|
||||
m_screen->set_size(160, 220);
|
||||
m_screen->set_visarea(0, 160 - 1, 0, 220 - 1);
|
||||
m_screen->set_screen_update(FUNC(palm_state::screen_update));
|
||||
|
||||
PALETTE(config, m_palette, FUNC(palm_state::init_palette), 2);
|
||||
MC68328_LCD(config, m_lcdctrl, 0);
|
||||
|
||||
/* audio hardware */
|
||||
SPEAKER(config, "speaker").front_center();
|
||||
@ -685,11 +659,6 @@ void palmiiic_state::palmiiic(machine_config &config)
|
||||
m_maincpu->out_pwm().set("dac", FUNC(dac_bit_interface::write));
|
||||
m_maincpu->in_spim().set(FUNC(palmiiic_state::spi_from_hw));
|
||||
m_maincpu->out_spim().set(FUNC(palmiiic_state::spi_to_hw));
|
||||
m_maincpu->out_flm().set(FUNC(palmiiic_state::flm_out));
|
||||
m_maincpu->out_llp().set(FUNC(palmiiic_state::llp_out));
|
||||
m_maincpu->out_lsclk().set(FUNC(palmiiic_state::lsclk_out));
|
||||
m_maincpu->out_ld().set(FUNC(palmiiic_state::ld_out));
|
||||
m_maincpu->set_lcd_info_changed(FUNC(palmiiic_state::lcd_info_changed));
|
||||
|
||||
/* internal ram */
|
||||
RAM(config, RAM_TAG).set_default_size("8M");
|
||||
@ -708,6 +677,73 @@ void palmiiic_state::palmiiic(machine_config &config)
|
||||
DAC_1BIT(config, "dac", 0).add_route(ALL_OUTPUTS, "speaker", 0.25);
|
||||
}
|
||||
|
||||
void palmm100_state::palmm100(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
MC68EZ328(config, m_maincpu, 32768*506); /* 16.580608 MHz */
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &palmm100_state::mem_map);
|
||||
m_maincpu->set_dasm_override(FUNC(palmm100_state::dasm_override));
|
||||
|
||||
m_maincpu->out_port_b<1>().set(FUNC(palmm100_state::kbd_row_w<0>));
|
||||
m_maincpu->out_port_b<3>().set(FUNC(palmm100_state::kbd_row_w<1>));
|
||||
m_maincpu->out_port_b<6>().set(FUNC(palmm100_state::kbd_row_w<2>));
|
||||
|
||||
m_maincpu->out_port_d<0>().set(FUNC(palmm100_state::kbd_col_w<0>));
|
||||
m_maincpu->out_port_d<1>().set(FUNC(palmm100_state::kbd_col_w<1>));
|
||||
m_maincpu->out_port_d<2>().set(FUNC(palmm100_state::kbd_col_w<2>));
|
||||
m_maincpu->out_port_d<3>().set(FUNC(palmm100_state::kbd_col_w<3>));
|
||||
|
||||
m_maincpu->out_port_g<2>().set(FUNC(palmm100_state::hardware_id_req_w));
|
||||
m_maincpu->out_port_g<5>().set(FUNC(palmm100_state::adc_enable_w));
|
||||
|
||||
m_maincpu->in_port_d<0>().set(FUNC(palmm100_state::kbd_scan_r<0>));
|
||||
m_maincpu->in_port_d<1>().set(FUNC(palmm100_state::kbd_scan_r<1>));
|
||||
m_maincpu->in_port_d<2>().set(FUNC(palmm100_state::kbd_scan_r<2>));
|
||||
m_maincpu->in_port_d<3>().set(FUNC(palmm100_state::kbd_scan_r<3>));
|
||||
m_maincpu->in_port_d<4>().set_constant(1); // Active-low, indicates hotsync/dock button press
|
||||
m_maincpu->in_port_d<6>().set_constant(1); // Active-low, indicates external adapter installed
|
||||
m_maincpu->in_port_d<7>().set_constant(1); // Active-low, indicates pending power failure
|
||||
|
||||
m_maincpu->in_port_e<0>().set(FUNC(palmm100_state::hardware_subid_r<0>));
|
||||
m_maincpu->in_port_e<1>().set(FUNC(palmm100_state::hardware_subid_r<1>));
|
||||
m_maincpu->in_port_e<2>().set(FUNC(palmm100_state::hardware_subid_r<2>));
|
||||
m_maincpu->in_port_e<3>().set(FUNC(palmm100_state::hardware_subid_r<3>));
|
||||
m_maincpu->in_port_e<4>().set(FUNC(palmm100_state::hardware_subid_r<4>));
|
||||
m_maincpu->in_port_e<5>().set(FUNC(palmm100_state::hardware_subid_r<5>));
|
||||
m_maincpu->in_port_e<6>().set(FUNC(palmm100_state::hardware_subid_r<6>));
|
||||
m_maincpu->in_port_e<7>().set(FUNC(palmm100_state::hardware_subid_r<7>));
|
||||
|
||||
m_maincpu->in_port_f<0>().set_constant(1); // Active-high, indicates LCD is at full power
|
||||
m_maincpu->in_port_f<6>().set_constant(1); // Active-high, indicates battery enabled
|
||||
m_maincpu->in_port_f<7>().set_constant(1); // Active-low, determines sync port attachment
|
||||
|
||||
m_maincpu->out_pwm().set("dac", FUNC(dac_bit_interface::write));
|
||||
m_maincpu->in_spim().set(FUNC(palmm100_state::spi_from_hw));
|
||||
m_maincpu->out_spim().set(FUNC(palmm100_state::spi_to_hw));
|
||||
|
||||
m_maincpu->out_flm().set(m_lcdctrl, FUNC(mc68328_lcd_device::flm_w));
|
||||
m_maincpu->out_llp().set(m_lcdctrl, FUNC(mc68328_lcd_device::llp_w));
|
||||
m_maincpu->out_lsclk().set(m_lcdctrl, FUNC(mc68328_lcd_device::lsclk_w));
|
||||
m_maincpu->out_ld().set(m_lcdctrl, FUNC(mc68328_lcd_device::ld_w));
|
||||
m_maincpu->set_lcd_info_changed(m_lcdctrl, FUNC(mc68328_lcd_device::lcd_info_changed));
|
||||
|
||||
/* internal ram */
|
||||
RAM(config, RAM_TAG).set_default_size("2M");
|
||||
|
||||
/* video hardware */
|
||||
SCREEN(config, m_screen, SCREEN_TYPE_LCD);
|
||||
m_screen->set_refresh_hz(60);
|
||||
m_screen->set_size(160, 220);
|
||||
m_screen->set_visarea(0, 160 - 1, 0, 220 - 1);
|
||||
m_screen->set_screen_update(FUNC(palmm100_state::screen_update));
|
||||
|
||||
MC68328_LCD(config, m_lcdctrl, 0);
|
||||
|
||||
/* audio hardware */
|
||||
SPEAKER(config, "speaker").front_center();
|
||||
DAC_1BIT(config, "dac", 0).add_route(ALL_OUTPUTS, "speaker", 0.25);
|
||||
}
|
||||
|
||||
void palm_state::pilot1k(machine_config &config)
|
||||
{
|
||||
palm_base(config);
|
||||
@ -951,22 +987,22 @@ ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
||||
COMP( 1996, pilot1k, 0, 0, pilot1k, palm, palm_state, empty_init, "U.S. Robotics", "Pilot 1000", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1996, pilot5k, pilot1k, 0, pilot5k, palm, palm_state, empty_init, "U.S. Robotics", "Pilot 5000", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1997, palmpers, pilot1k, 0, pilot5k, palm, palm_state, empty_init, "U.S. Robotics", "Palm Pilot Personal", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1997, palmpro, pilot1k, 0, palmpro, palm, palm_state, empty_init, "U.S. Robotics", "Palm Pilot Pro", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1998, palmiii, pilot1k, 0, palmiii, palm, palm_state, empty_init, "3Com", "Palm III", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1998, palmiiic, pilot1k, 0, palmiiic, palmez, palmiiic_state, empty_init, "3Com", "Palm IIIc", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 2000, palmm100, pilot1k, 0, palmiii, palm, palm_state, empty_init, "3Com", "Palm m100", MACHINE_NOT_WORKING )
|
||||
COMP( 2000, palmm130, pilot1k, 0, palmiii, palm, palm_state, empty_init, "3Com", "Palm m130", MACHINE_NOT_WORKING )
|
||||
COMP( 2001, palmm505, pilot1k, 0, palmiii, palm, palm_state, empty_init, "3Com", "Palm m505", MACHINE_NOT_WORKING )
|
||||
COMP( 2001, palmm515, pilot1k, 0, palmiii, palm, palm_state, empty_init, "3Com", "Palm m515", MACHINE_NOT_WORKING )
|
||||
COMP( 1999, palmv, pilot1k, 0, palmv, palm, palm_state, empty_init, "3Com", "Palm V", MACHINE_NOT_WORKING )
|
||||
COMP( 1999, palmvx, pilot1k, 0, palmvx, palm, palm_state, empty_init, "3Com", "Palm Vx", MACHINE_NOT_WORKING )
|
||||
COMP( 2001, visor, pilot1k, 0, palmvx, palm, palm_state, empty_init, "Handspring", "Visor Edge", MACHINE_NOT_WORKING )
|
||||
COMP( 19??, spt1500, pilot1k, 0, palmvx, palm, palm_state, empty_init, "Symbol", "SPT 1500", MACHINE_NOT_WORKING )
|
||||
COMP( 19??, spt1700, pilot1k, 0, palmvx, palm, palm_state, empty_init, "Symbol", "SPT 1700", MACHINE_NOT_WORKING )
|
||||
COMP( 19??, spt1740, pilot1k, 0, palmvx, palm, palm_state, empty_init, "Symbol", "SPT 1740", MACHINE_NOT_WORKING )
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
||||
COMP( 1996, pilot1k, 0, 0, pilot1k, palm, palm_state, empty_init, "U.S. Robotics", "Pilot 1000", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1996, pilot5k, pilot1k, 0, pilot5k, palm, palm_state, empty_init, "U.S. Robotics", "Pilot 5000", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1997, palmpers, pilot1k, 0, pilot5k, palm, palm_state, empty_init, "U.S. Robotics", "Palm Pilot Personal", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1997, palmpro, pilot1k, 0, palmpro, palm, palm_state, empty_init, "U.S. Robotics", "Palm Pilot Pro", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1998, palmiii, pilot1k, 0, palmiii, palm, palm_state, empty_init, "3Com", "Palm III", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1998, palmiiic, pilot1k, 0, palmiiic, palmiiic, palmiiic_state, empty_init, "3Com", "Palm IIIc", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 2000, palmm100, pilot1k, 0, palmm100, palmm100, palmm100_state, empty_init, "3Com", "Palm m100", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_GRAPHICS )
|
||||
COMP( 2000, palmm130, pilot1k, 0, palmiii, palm, palm_state, empty_init, "3Com", "Palm m130", MACHINE_NOT_WORKING )
|
||||
COMP( 2001, palmm505, pilot1k, 0, palmiii, palm, palm_state, empty_init, "3Com", "Palm m505", MACHINE_NOT_WORKING )
|
||||
COMP( 2001, palmm515, pilot1k, 0, palmiii, palm, palm_state, empty_init, "3Com", "Palm m515", MACHINE_NOT_WORKING )
|
||||
COMP( 1999, palmv, pilot1k, 0, palmv, palm, palm_state, empty_init, "3Com", "Palm V", MACHINE_NOT_WORKING )
|
||||
COMP( 1999, palmvx, pilot1k, 0, palmvx, palm, palm_state, empty_init, "3Com", "Palm Vx", MACHINE_NOT_WORKING )
|
||||
COMP( 2001, visor, pilot1k, 0, palmvx, palm, palm_state, empty_init, "Handspring", "Visor Edge", MACHINE_NOT_WORKING )
|
||||
COMP( 19??, spt1500, pilot1k, 0, palmvx, palm, palm_state, empty_init, "Symbol", "SPT 1500", MACHINE_NOT_WORKING )
|
||||
COMP( 19??, spt1700, pilot1k, 0, palmvx, palm, palm_state, empty_init, "Symbol", "SPT 1700", MACHINE_NOT_WORKING )
|
||||
COMP( 19??, spt1740, pilot1k, 0, palmvx, palm, palm_state, empty_init, "Symbol", "SPT 1740", MACHINE_NOT_WORKING )
|
||||
|
||||
#include "palm_dbg.ipp"
|
||||
|
@ -52,42 +52,116 @@ A4 = MAX232
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "screen.h"
|
||||
#include "cpu/m68000/m68000.h"
|
||||
#include "bus/generic/slot.h"
|
||||
#include "machine/mc68328.h"
|
||||
#include "machine/ram.h"
|
||||
#include "video/mc68328lcd.h"
|
||||
|
||||
#include "bus/generic/carts.h"
|
||||
#include "bus/generic/slot.h"
|
||||
|
||||
#include "screen.h"
|
||||
#include "softlist_dev.h"
|
||||
|
||||
#define LOG_CARD_A_READ (1 << 1u)
|
||||
#define LOG_CARD_A_WRITE (1 << 2u)
|
||||
#define LOG_CARD_B_READ (1 << 3u)
|
||||
#define LOG_CARD_B_WRITE (1 << 4u)
|
||||
#define LOG_ALL (LOG_CARD_A_READ | LOG_CARD_A_WRITE | LOG_CARD_B_READ | LOG_CARD_B_WRITE)
|
||||
|
||||
#define VERBOSE (LOG_ALL)
|
||||
#include "logmacro.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class iqunlim_state : public driver_device
|
||||
{
|
||||
public:
|
||||
iqunlim_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_ram(*this, RAM_TAG),
|
||||
m_lcdctrl(*this, "lcdctrl"),
|
||||
m_screen(*this, "screen"),
|
||||
m_cart(*this, "cartslot")
|
||||
{ }
|
||||
{ }
|
||||
|
||||
void iqunlim(machine_config &config);
|
||||
|
||||
private:
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<generic_slot_device> m_cart;
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
void mem_map(address_map &map);
|
||||
|
||||
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
|
||||
void card4x_w(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff);
|
||||
uint16_t card4x_r(offs_t offset, uint16_t mem_mask = 0xffff);
|
||||
void card5x_w(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff);
|
||||
uint16_t card5x_r(offs_t offset, uint16_t mem_mask = 0xffff);
|
||||
|
||||
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(cart_load);
|
||||
|
||||
virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
void iqunlim_mem(address_map &map);
|
||||
required_device<mc68ez328_device> m_maincpu;
|
||||
required_device<ram_device> m_ram;
|
||||
required_device<mc68328_lcd_device> m_lcdctrl;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<generic_slot_device> m_cart;
|
||||
};
|
||||
|
||||
void iqunlim_state::machine_start()
|
||||
{
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
space.install_ram(0x00000000, m_ram->size() - 1, m_ram->pointer());
|
||||
}
|
||||
|
||||
void iqunlim_state::machine_reset()
|
||||
{
|
||||
// Copy ROM vectors into RAM
|
||||
memcpy(m_ram->pointer(), memregion("maincpu")->base(), 0x8);
|
||||
}
|
||||
|
||||
void iqunlim_state::mem_map(address_map &map)
|
||||
{
|
||||
map(0x02000000, 0x023fffff).rom().region("maincpu", 0); // 68EZ328 /CSA0 pin selects System ROM after bootup
|
||||
map(0x03000000, 0x0307ffff).ram(); // Region used by the internal flash memory
|
||||
map(0x04000000, 0x04ffffff).rw(FUNC(iqunlim_state::card4x_r), FUNC(iqunlim_state::card4x_w)); // Region used by Card B
|
||||
map(0x05000000, 0x05ffffff).rw(FUNC(iqunlim_state::card5x_r), FUNC(iqunlim_state::card5x_w)); // Region used by Card A
|
||||
}
|
||||
|
||||
uint32_t iqunlim_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
m_lcdctrl->video_update(bitmap, cliprect);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void iqunlim_state::iqunlim_mem(address_map &map)
|
||||
uint16_t iqunlim_state::card4x_r(offs_t offset, uint16_t mem_mask)
|
||||
{
|
||||
map.unmap_value_high();
|
||||
map(0x000000, 0x1FFFFF).rom();
|
||||
uint16_t data = 0;
|
||||
LOGMASKED(LOG_CARD_B_READ, "card4x_read[%08x]: %04x\n", offset << 1, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
void iqunlim_state::card4x_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
LOGMASKED(LOG_CARD_B_WRITE, "card4x_write[%08x]: %04x\n", offset << 1, data);
|
||||
}
|
||||
|
||||
uint16_t iqunlim_state::card5x_r(offs_t offset, uint16_t mem_mask)
|
||||
{
|
||||
uint16_t data = 0xffff;
|
||||
if (m_cart)
|
||||
{
|
||||
data = m_cart->read16_rom(offset, mem_mask);
|
||||
}
|
||||
LOGMASKED(LOG_CARD_A_READ, "card5x_read[%08x]: %04x\n", offset << 1, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
void iqunlim_state::card5x_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
LOGMASKED(LOG_CARD_A_WRITE, "card5x_write[%08x]: %04x\n", offset << 1, data);
|
||||
}
|
||||
|
||||
static INPUT_PORTS_START( iqunlim )
|
||||
@ -107,16 +181,25 @@ DEVICE_IMAGE_LOAD_MEMBER(iqunlim_state::cart_load)
|
||||
void iqunlim_state::iqunlim(machine_config &config)
|
||||
{
|
||||
// Basic machine hardware
|
||||
M68000(config, m_maincpu, XTAL(32'000'000)/2); // DragonBall EZ (MC68EZ328, 68k core) (Is the xtal correct? This was from the other hardware)
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &iqunlim_state::iqunlim_mem);
|
||||
MC68EZ328(config, m_maincpu, 32768*506);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &iqunlim_state::mem_map);
|
||||
|
||||
m_maincpu->out_flm().set(m_lcdctrl, FUNC(mc68328_lcd_device::flm_w));
|
||||
m_maincpu->out_llp().set(m_lcdctrl, FUNC(mc68328_lcd_device::llp_w));
|
||||
m_maincpu->out_lsclk().set(m_lcdctrl, FUNC(mc68328_lcd_device::lsclk_w));
|
||||
m_maincpu->out_ld().set(m_lcdctrl, FUNC(mc68328_lcd_device::ld_w));
|
||||
m_maincpu->set_lcd_info_changed(m_lcdctrl, FUNC(mc68328_lcd_device::lcd_info_changed));
|
||||
|
||||
RAM(config, RAM_TAG).set_default_size("2M");
|
||||
|
||||
// Video hardware
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_refresh_hz(50);
|
||||
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); // Not accurate
|
||||
screen.set_size(512, 256);
|
||||
screen.set_visarea(0, 512-1, 0, 256-1);
|
||||
screen.set_screen_update(FUNC(iqunlim_state::screen_update));
|
||||
SCREEN(config, m_screen, SCREEN_TYPE_LCD);
|
||||
m_screen->set_refresh_hz(60);
|
||||
m_screen->set_size(480, 260);
|
||||
m_screen->set_visarea(0, 480 - 1, 0, 260 - 1);
|
||||
m_screen->set_screen_update(FUNC(iqunlim_state::screen_update));
|
||||
|
||||
MC68328_LCD(config, m_lcdctrl, 0);
|
||||
|
||||
GENERIC_CARTSLOT(config, m_cart, generic_plain_slot, "iqunlim_cart");
|
||||
m_cart->set_width(GENERIC_ROM16_WIDTH);
|
||||
@ -135,5 +218,7 @@ ROM_START( iqunlimgr )
|
||||
ROM_LOAD16_WORD_SWAP( "27-06126-007.bin", 0x000000, 0x400000, CRC(2e99cfef) SHA1(790869ffcf7fd666def8ff57fce0691062b3cec5) )
|
||||
ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
COMP( 1995, iqunlim, 0, 0, iqunlim, iqunlim, iqunlim_state, empty_init, "VTech / Integrated Systems Inc.", "IQ Unlimited", MACHINE_IS_SKELETON) // COPYRIGHT 1995 INTERGRATED SYSTEMS, INC.
|
||||
COMP( 1995, iqunlimgr, iqunlim, 0, iqunlim, iqunlim, iqunlim_state, empty_init, "VTech / Integrated Systems Inc.", "IQ Unlimited (Germany)", MACHINE_IS_SKELETON) // COPYRIGHT 1995 INTERGRATED SYSTEMS, INC.
|
||||
|
Loading…
Reference in New Issue
Block a user