diff options
| author | 2026-05-08 13:27:01 +0200 | |
|---|---|---|
| committer | 2026-05-08 07:27:01 -0400 | |
| commit | c2ffdd5ec1b13c28c4e36049eee879d1b3fb7212 (patch) | |
| tree | b11ad51e9f1b420d85aea219528ccb4bf679a5d4 | |
| parent | bcc561afdf812eff00e2d7c1a069aec2a2c66694 (diff) | |
pixtermu: Make the system boot and LCD/touchscreen work (#15220)
* pixtermu: Split up the APB peripherals
* pixtermu: Implement the LH79524 timer
* pixtermu: Implement dummy SSP
* pixtermu: Make it boot and LCD/TS work
| -rw-r--r-- | scripts/src/machine.lua | 12 | ||||
| -rw-r--r-- | src/devices/machine/lh79524_timer.cpp | 168 | ||||
| -rw-r--r-- | src/devices/machine/lh79524_timer.h | 49 | ||||
| -rw-r--r-- | src/mame/mattel/pixtermu.cpp | 353 |
4 files changed, 553 insertions, 29 deletions
diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index d84f3d01041..9dcb61bb16d 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -2182,6 +2182,18 @@ end --------------------------------------------------- -- +--@src/devices/machine/lh79524_timer.h,MACHINES["LH79524"] = true +--------------------------------------------------- + +if MACHINES["LH79524"] then + files { + MAME_DIR .. "src/devices/machine/lh79524_timer.cpp", + MAME_DIR .. "src/devices/machine/lh79524_timer.h", + } +end + +--------------------------------------------------- +-- --@src/devices/machine/locomo.h,MACHINES["LOCOMO"] = true --------------------------------------------------- diff --git a/src/devices/machine/lh79524_timer.cpp b/src/devices/machine/lh79524_timer.cpp new file mode 100644 index 00000000000..d0656f010e5 --- /dev/null +++ b/src/devices/machine/lh79524_timer.cpp @@ -0,0 +1,168 @@ +// license:BSD-3-Clause +// copyright-holders:Myrtle Shah +/***************************************************************************** + + LH79524 Timer + +*****************************************************************************/ + +#include "emu.h" +#include "lh79524_timer.h" + + +DEFINE_DEVICE_TYPE(LH79524_TIMER, lh79524_timer_device, "lh79524_timer", "LH79524 Timer") + + +lh79524_timer_device::lh79524_timer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, LH79524_TIMER, tag, owner, clock) + , m_irq_cb(*this) { +} + +void lh79524_timer_device::set_timer_index(int index) { + timer_index = index; +} + + +void lh79524_timer_device::device_start() { + m_tick_timer = timer_alloc(FUNC(lh79524_timer_device::timer_update), this); + + save_item(NAME(m_control)); + save_item(NAME(m_cap_control)); + save_item(NAME(m_inten)); + save_item(NAME(m_status)); + save_item(NAME(m_cnt)); + save_item(NAME(m_cmp0)); + save_item(NAME(m_cmp1)); +} + +void lh79524_timer_device::device_reset() { + m_control = 0; + m_cap_control = 0; + m_inten = 0; + m_status = 0; + m_cnt = 0; + m_cmp0 = 0; + m_cmp1 = 0; + + m_tick_timer->adjust(attotime::never); + + update_interrupt(); +} + +void lh79524_timer_device::update_interrupt() { + if ((m_status & 0x7) & (m_inten & 0x7)) { + m_irq_cb(ASSERT_LINE); + } else { + m_irq_cb(CLEAR_LINE); + } + +} + +void lh79524_timer_device::device_clock_changed() { + if (BIT(m_control, 1)) { + uint32_t hclk_div_value = (m_control >> 2) & 0x7; + m_tick_timer->adjust(attotime::from_hz(clock() / (2U << hclk_div_value)), 0, attotime::from_hz(clock() / (2U << hclk_div_value))); + } else { + m_tick_timer->adjust(attotime::never); + } +} + +TIMER_CALLBACK_MEMBER(lh79524_timer_device::timer_update) { + if (!BIT(m_control, 1)) + return; + + bool tc = (timer_index == 0) ? BIT(m_cap_control, 14) : BIT(m_control, 13); + + uint16_t limit = tc ? m_cmp1 : 0xffff; + + if (m_cnt == m_cmp0) { + m_status |= 0x0002; + } + + if (m_cnt == m_cmp1) { + m_status |= 0x0004; + } + + if (m_cnt == limit) { + m_cnt = 0; + m_status |= 0x0001; + } else { + m_cnt++; + } + + update_interrupt(); +} + +uint32_t lh79524_timer_device::read(offs_t offset, uint32_t mem_mask) { + offs_t addr = offset << 2; + if (timer_index >= 1 && addr >= 0x04) { + addr += 0x04; + } + switch (addr) { + case 0x00: + return m_control; + case 0x04: + return m_cap_control; + case 0x08: + return m_inten; + case 0x0c: + return m_status; + case 0x10: + return m_cnt; + case 0x14: + return m_cmp0; + case 0x18: + return m_cmp1; + default: + logerror("[%s] %s: unknown read %x\n", tag(), machine().describe_context(), offset << 2); + } + + return 0; +} + +void lh79524_timer_device::write(offs_t offset, uint32_t data, uint32_t mem_mask) { + offs_t addr = offset << 2; + if (timer_index >= 1 && addr >= 0x04) { + addr += 0x04; + } + switch (addr) { + case 0x00: + if (data & 0x1) { + m_cnt = 0; + data &= ~0x1; + } + COMBINE_DATA(&m_control); + lh79524_timer_device::device_clock_changed(); + break; + case 0x04: + COMBINE_DATA(&m_cap_control); + break; + case 0x08: + COMBINE_DATA(&m_inten); + update_interrupt(); + break; + case 0x0c: + if (BIT(mem_mask, 0) && BIT(data, 0)) { + m_status &= ~0x1; + } + if (BIT(mem_mask, 1) && BIT(data, 1)) { + m_status &= ~0x2; + } + if (BIT(mem_mask, 2) && BIT(data, 2)) { + m_status &= ~0x4; + } + update_interrupt(); + break; + case 0x10: + COMBINE_DATA(&m_cnt); + break; + case 0x14: + COMBINE_DATA(&m_cmp0); + break; + case 0x18: + COMBINE_DATA(&m_cmp1); + break; + default: + logerror("[%s] %s: unknown write %x = %x\n", tag(), machine().describe_context(), offset << 2, data); + } +} diff --git a/src/devices/machine/lh79524_timer.h b/src/devices/machine/lh79524_timer.h new file mode 100644 index 00000000000..b6959a83bf6 --- /dev/null +++ b/src/devices/machine/lh79524_timer.h @@ -0,0 +1,49 @@ +// license:BSD-3-Clause +// copyright-holders:Myrtle Shah + + +#ifndef MAME_MACHINE_LH79524_TIMER_H +#define MAME_MACHINE_LH79524_TIMER_H + +#pragma once + +class lh79524_timer_device : public device_t +{ +public: + lh79524_timer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + void set_timer_index(int index); + + void write(offs_t offset, uint32_t data, uint32_t mem_mask); + uint32_t read(offs_t offset, uint32_t mem_mask); + auto irq_cb() { return m_irq_cb.bind(); } + +protected: + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + virtual void device_clock_changed() override; + + TIMER_CALLBACK_MEMBER(timer_update); + +private: + void update_interrupt(); + + devcb_write_line m_irq_cb; + + emu_timer *m_tick_timer; + + int timer_index; + + uint32_t m_control; + uint32_t m_cap_control; + uint32_t m_inten; + uint32_t m_status; + uint32_t m_cnt; + uint32_t m_cmp0; + uint32_t m_cmp1; + + // TODO: compare +}; + +DECLARE_DEVICE_TYPE(LH79524_TIMER, lh79524_timer_device) + +#endif // MAME_MACHINE_LH79524_TIMER_H diff --git a/src/mame/mattel/pixtermu.cpp b/src/mame/mattel/pixtermu.cpp index 46e89ca28f6..f66559c727b 100644 --- a/src/mame/mattel/pixtermu.cpp +++ b/src/mame/mattel/pixtermu.cpp @@ -2,12 +2,12 @@ // copyright-holders:QUFB /****************************************************************************** - Skeleton driver for Pixter Multi-Media. + WIP driver for Pixter Multi-Media. - Currently hangs after reset: - - - If executing boot ROM, with boot configuration set to load NOR Flash or SRAM, it will reach an infinite loop at 0x1f0; - - If executing nCS1 ROM, it will wait indefinitely due to unimplemented timer controls; + - The boot ROM is ignored, boot directly from NOR flash + - The buttons are not implemented, only the touchscreen input + - Audio and SSP DMA is not implemented, the SSP DMA interrupt is fired on Vblank to maintain progress + - The soft buttons below the touchscreen are just drawn as rectangles References: @@ -48,8 +48,14 @@ #include "bus/generic/slot.h" #include "cpu/arm7/arm7.h" +#include "machine/lh79524_timer.h" +#include "machine/vic_pl192.h" + #include "softlist_dev.h" +#include "emupal.h" +#include "screen.h" + namespace { class pixter_multimedia_state : public driver_device @@ -57,39 +63,84 @@ class pixter_multimedia_state : public driver_device public: pixter_multimedia_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) + , m_palette(*this, "palette") + , m_screen(*this, "screen") + , m_touch(*this, { "TOUCHX", "TOUCHY", "TOUCH" }) , m_cart(*this, "cartslot") , m_maincpu(*this, "maincpu") , m_ndcs0(*this, "ndcs0") , m_internal_sram(*this, "internal_sram") - , m_apb(*this, "apb", 0x27000, ENDIANNESS_LITTLE) + , m_timers(*this, "timer%u", 0U) + , m_vic(*this, "vic") + , m_clkrst(*this, "clkrst", 0x1000, ENDIANNESS_LITTLE) + , m_bootctl(*this, "bootctl", 0x1000, ENDIANNESS_LITTLE) + , m_lcdc(*this, "lcdc", 0x1000, ENDIANNESS_LITTLE) + , m_adc(*this, "adc", 0x100, ENDIANNESS_LITTLE) + , m_dma(*this, "dma", 0x100, ENDIANNESS_LITTLE) , m_remap_view(*this, "remap") { } void pixter_multimedia(machine_config &config); private: - // Remap Control, mapped at 0xfffe2008, offset 0x22008/4 - static inline constexpr uint32_t APB_REMAP = 34818; - // Power-up Boot Configuration, mapped at 0xfffe6000, offset 0x26000/4 - static inline constexpr uint32_t APB_PBC = 38912; - // nCS1 Override, mapped at 0xfffe6004, offset 0x26004/4 - static inline constexpr uint32_t APB_CS1OV = 38913; - // External Peripheral Mapping, mapped at 0xfffe6008, offset 0x26008/4 - static inline constexpr uint32_t APB_EPM = 38914; + // Remap Control, mapped at 0xfffe2008, offset 0x0008/4 + static inline constexpr uint32_t CLKRST_REMAP = 2; + // Power-up Boot Configuration, mapped at 0xfffe6000, offset 0x0000/4 + static inline constexpr uint32_t BOOTCTL_PBC = 0; + // nCS1 Override, mapped at 0xfffe6004, offset 0x0004/4 + static inline constexpr uint32_t BOOTCTL_CS1OV = 1; + // External Peripheral Mapping, mapped at 0xfffe6008, offset 0x0008/4 + static inline constexpr uint32_t BOOTCTL_EPM = 2; virtual void machine_start() override ATTR_COLD; virtual void machine_reset() override ATTR_COLD; DEVICE_IMAGE_LOAD_MEMBER(cart_load); void arm7_map(address_map &map) ATTR_COLD; - void apb_bridge_w(offs_t offset, uint32_t data, uint32_t mem_mask); + void clkrst_w(offs_t offset, uint32_t data, uint32_t mem_mask); + void bootctl_w(offs_t offset, uint32_t data, uint32_t mem_mask); + + void lcdc_w(offs_t offset, uint32_t data, uint32_t mem_mask); + uint32_t lcdc_r(offs_t offset); + + uint32_t adc_r(offs_t offset); + void adc_w(offs_t offset, uint32_t data, uint32_t mem_mask); + + void dma_w(offs_t offset, uint32_t data, uint32_t mem_mask); + + uint32_t ssp_r(offs_t offset); + void ssp_w(offs_t offset, uint32_t data, uint32_t mem_mask); + + uint32_t gpioab_r(offs_t offset); + uint32_t gpiogh_r(offs_t offset); + uint32_t gpioij_r(offs_t offset); + + + int adc_count; + void apb_remap(uint32_t data); + uint32_t screen_update_pixtermu(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + void screen_vblank(int state); + + required_device<palette_device> m_palette; + required_device<screen_device> m_screen; + + required_ioport_array<3> m_touch; + required_device<generic_slot_device> m_cart; required_device<arm7_cpu_device> m_maincpu; required_shared_ptr<uint32_t> m_ndcs0; required_shared_ptr<uint32_t> m_internal_sram; - memory_share_creator<uint32_t> m_apb; + required_device_array<lh79524_timer_device, 3> m_timers; + required_device<vic_pl190_device> m_vic; + + memory_share_creator<uint32_t> m_clkrst; + memory_share_creator<uint32_t> m_bootctl; + memory_share_creator<uint32_t> m_lcdc; + memory_share_creator<uint32_t> m_adc; + memory_share_creator<uint32_t> m_dma; + memory_view m_remap_view; }; @@ -97,7 +148,7 @@ void pixter_multimedia_state::apb_remap(uint32_t data) { // User's Guide - 1.6 Memory Interface Architecture if (data == 0) { - m_remap_view.select((m_apb[APB_PBC] & 0b0100) && (m_apb[APB_CS1OV] & 0b1) ? 0 : 3); + m_remap_view.select((m_bootctl[BOOTCTL_PBC] & 0b0100) && (m_bootctl[BOOTCTL_CS1OV] & 0b1) ? 0 : 3); } else if (data < 3) { m_remap_view.select(data); } else { @@ -122,12 +173,15 @@ void pixter_multimedia_state::machine_start() void pixter_multimedia_state::machine_reset() { - m_apb[APB_PBC] = 0b0000; // Boot from NOR Flash or SRAM, 16-bit data bus width, nBLEx LOW for reads - m_apb[APB_CS1OV] = 0b0; // nCS1 is routed for normal operation - m_apb[APB_EPM] = 0b1111; // All external devices are accessible following reset + m_bootctl[BOOTCTL_PBC] = 0b0000; // Boot from NOR Flash or SRAM, 16-bit data bus width, nBLEx LOW for reads + m_bootctl[BOOTCTL_CS1OV] = 0b0; // nCS1 is routed for normal operation + m_bootctl[BOOTCTL_EPM] = 0b1111; // All external devices are accessible following reset + + m_clkrst[CLKRST_REMAP] = 0b00; // Map nCS1 + + adc_count = 0; - m_apb[APB_REMAP] = 0b00; // Map nCS1 - apb_remap(m_apb[APB_REMAP]); + apb_remap(m_clkrst[CLKRST_REMAP]); } DEVICE_IMAGE_LOAD_MEMBER(pixter_multimedia_state::cart_load) @@ -197,28 +251,241 @@ void pixter_multimedia_state::arm7_map(address_map &map) // Boot ROM map(0x8000'0000, 0x8000'1fff).rom().region("bootrom", 0); - // APB Bridge - map(0xfffc'0000, 0xfffe'6fff).ram().share("apb").w(FUNC(pixter_multimedia_state::apb_bridge_w)); + // APB Peripherals + // ADC + map(0xfffc'3000, 0xfffc'30ff).ram().share("adc").r(FUNC(pixter_multimedia_state::adc_r)).w(FUNC(pixter_multimedia_state::adc_w)); + // Timers + map(0xfffc'4000, 0xfffc'402f).rw(m_timers[0], FUNC(lh79524_timer_device::read), FUNC(lh79524_timer_device::write)); + map(0xfffc'4030, 0xfffc'404f).rw(m_timers[1], FUNC(lh79524_timer_device::read), FUNC(lh79524_timer_device::write)); + map(0xfffc'4050, 0xfffc'406f).rw(m_timers[2], FUNC(lh79524_timer_device::read), FUNC(lh79524_timer_device::write)); + // SSP + map(0xfffc'6000, 0xfffc'602f).r(FUNC(pixter_multimedia_state::ssp_r)).w(FUNC(pixter_multimedia_state::ssp_w)); + + // GPIO I/J + map(0xfffd'b000, 0xfffd'b00f).r(FUNC(pixter_multimedia_state::gpioij_r)); + // GPIO G/H + map(0xfffd'c000, 0xfffd'c00f).r(FUNC(pixter_multimedia_state::gpiogh_r)); + // GPIO A/B + map(0xfffd'f000, 0xfffd'f00f).r(FUNC(pixter_multimedia_state::gpioab_r)); + // DMA + map(0xfffe'1000, 0xfffe'10ff).ram().share("dma").w(FUNC(pixter_multimedia_state::dma_w)); + + // Reset Clock and Power Controller + map(0xfffe'2000, 0xfffe'2fff).ram().share("clkrst").w(FUNC(pixter_multimedia_state::clkrst_w)); + // Boot Controller + map(0xfffe'6000, 0xfffe'6fff).ram().share("bootctl").w(FUNC(pixter_multimedia_state::bootctl_w)); + + // External Memory Control map(0xffff'1000, 0xffff'1fff).ram(); // Color LCD Control - map(0xffff'4000, 0xffff'4fff).ram(); + map(0xffff'4000, 0xffff'4fff).ram().share("lcdc").w(FUNC(pixter_multimedia_state::lcdc_w)).r(FUNC(pixter_multimedia_state::lcdc_r)); // USB Device map(0xffff'5000, 0xffff'5fff).ram(); // Interrupt Vector Control - map(0xffff'f000, 0xffff'ffff).ram(); + map(0xffff'f000, 0xffff'ffff).m(m_vic, FUNC(vic_pl190_device::map)); // interrupt controller } -void pixter_multimedia_state::apb_bridge_w(offs_t offset, uint32_t data, uint32_t mem_mask) +void pixter_multimedia_state::clkrst_w(offs_t offset, uint32_t data, uint32_t mem_mask) { - if (offset == m_apb[APB_REMAP]) { + if (offset == CLKRST_REMAP) { apb_remap(data); } - COMBINE_DATA(&m_apb[offset]); + COMBINE_DATA(&m_clkrst[offset]); +} + +void pixter_multimedia_state::bootctl_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_bootctl[offset]); +} + + +void pixter_multimedia_state::lcdc_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + offs_t addr = offset << 2; + if (addr >= 0x200 && addr <= 0x3fc) { + unsigned base = ((addr - 0x200) >> 2) * 2; + for (int j = 0; j < 2; j++) { + uint16_t ibgr1555 = data >> (16 * j); + uint16_t i = ((ibgr1555 >> 15) & 0x1) << 2; + uint16_t b = ((ibgr1555 >> 10) & 0x1F) << 3 | i; + uint16_t g = ((ibgr1555 >> 5) & 0x1F) << 3 | i; + uint16_t r = ((ibgr1555 >> 0) & 0x1F) << 3 | i; + + m_palette->set_pen_color(base + j, r, g, b); + } + } + COMBINE_DATA(&m_lcdc[offset]); +} + +uint32_t pixter_multimedia_state::lcdc_r(offs_t offset) +{ + return m_lcdc[offset]; +} + +uint32_t pixter_multimedia_state::ssp_r(offs_t offset) +{ + switch (offset << 2) { + case 0x0C: // status + return 1; + default: + return 0; + } +} + +void pixter_multimedia_state::ssp_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ +} + +uint32_t pixter_multimedia_state::adc_r(offs_t offset) +{ + switch (offset << 2) { + case 0x08: { // result + if (adc_count > 0) + --adc_count; + unsigned index = ((m_adc[0x10 >> 2] & 0xF) - adc_count); + unsigned hc = m_adc[(0x24 >> 2) + index], lc = m_adc[(0x64 >> 2) + index]; + unsigned result = 0x3ff; + if (hc == 0xFF80 && lc == 0x1080) { // touch or no touch + result = m_touch[2]->read() ? 0 : 0x3ff; + } else if (hc == 0xFFA0 && lc == 0x1080) { + result = 0; + } else if (hc == 0xFF91 && lc == 0x0015) { // Y position + result = (m_touch[1]->read() * 1023) / 176; + } else if (hc == 0xFF82 && lc == 0x00A2) { // X position + result = 1023 - ((8 + m_touch[0]->read()) * 1023) / 176; + } + // At least one extra channel is used for battery + return (result << 6) | (index & 0xF); + } + case 0x1C: // IRQ status + return (m_touch[2]->read() ? 8 : 0) | 4; + case 0x20: // FIFO status + if (adc_count == 16) + return 8; + else if (adc_count == 0) + return 4; + else + return 0; + default: + return m_adc[offset]; + } +} + +void pixter_multimedia_state::adc_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + switch (offset << 2) { + case 0x14: + if(data & 0x4) { // start conversion + adc_count = (m_adc[0x10 >> 2] & 0xF) + 1; + }; + return; + default: + break; + } + COMBINE_DATA(&m_adc[offset]); +} + +uint32_t pixter_multimedia_state::gpioab_r(offs_t offset) +{ + switch (offset << 2) { + case 0x04: // port B data + return 0xFF; + default: + return 0; + } +} + +uint32_t pixter_multimedia_state::gpiogh_r(offs_t offset) +{ + // Some of these GPIO are likely used for the buttons, which aren't implemented right now + switch (offset << 2) { + case 0x00: // port G data + return 0x00; + case 0x04: // port H data + return 0x00; + default: + return 0; + } +} + + +uint32_t pixter_multimedia_state::gpioij_r(offs_t offset) +{ + switch (offset << 2) { + case 0x00: // port I data + return 0xFF; + default: + return 0; + } +} + +void pixter_multimedia_state::dma_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + switch (offset << 2) { + case 0xF4: // interrupt clear + if (data & 0x2) { + m_dma[0xF8 >> 2] &= ~0x2; + } + break; + default: + COMBINE_DATA(&m_dma[offset]); + break; + } + m_vic->irq_w<21>(((m_dma[0xF0 >> 2] & 0x2) & (m_dma[0xF8 >> 2] & 0x2)) ? ASSERT_LINE : CLEAR_LINE); +} + +uint32_t pixter_multimedia_state::screen_update_pixtermu(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + if (!BIT(m_lcdc[0x01C>>2], 1)) + return 0; + const uint32_t base = (m_lcdc[0x010>>2] >> 2) & 0xfffff; + + for (int y = 0; y < 160; y++) { + for (int x = 0; x < 160; x++) { + int pixel = (y * 162 + x + 1); + uint8_t ind = m_ndcs0[base + pixel / 4] >> ((pixel % 4) * 8); + bitmap.pix(y, x) = ind; + } + } + + // HACK: draw the soft buttons where the touchscreen extends below the LCD as white squares + // The label that is used in the physical hardware probably needs to be scanned + for (int i = 0; i < 9; i++) { + int x0 = (160 * i) / 9; + int y0 = 160; + for (int y = (y0 + 2); y <= (y0 + 14); y++) { + for (int x = (x0 + 2); x <= (x0 + 14); x++) { + bitmap.pix(y, x) = 0xFF; + } + } + } + + return 0; +} + +void pixter_multimedia_state::screen_vblank(int state) +{ + // Triggering this on vblank is definitely wrong, but it's the best place to set this right now... + // The correct solution is to implement the SSP and DMA that drives the audio DAC. But without + // this interrupt the system won't run. + m_dma[0xF8 >> 2] |= 0x2; + m_vic->irq_w<21>(((m_dma[0xF0 >> 2] & 0x2) & (m_dma[0xF8 >> 2] & 0x2)) ? ASSERT_LINE : CLEAR_LINE); } static INPUT_PORTS_START( pixter_multimedia ) + + PORT_START("TOUCHX") + PORT_BIT(0x3ff, 80, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_MINMAX(0,159) PORT_SENSITIVITY(45) PORT_KEYDELTA(13) + + PORT_START("TOUCHY") + PORT_BIT(0x3ff, 80, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_MINMAX(0,171) PORT_SENSITIVITY(45) PORT_KEYDELTA(13) + + PORT_START("TOUCH") + PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Touch") + PORT_BIT(0xfffe, IP_ACTIVE_HIGH, IPT_UNUSED) + INPUT_PORTS_END void pixter_multimedia_state::pixter_multimedia(machine_config &config) @@ -227,12 +494,40 @@ void pixter_multimedia_state::pixter_multimedia(machine_config &config) ARM7(config, m_maincpu, 76'205'000); m_maincpu->set_addrmap(AS_PROGRAM, &pixter_multimedia_state::arm7_map); + PL190_VIC(config, m_vic, 0); + m_vic->out_irq_cb().set_inputline(m_maincpu, arm7_cpu_device::ARM7_IRQ_LINE); + m_vic->out_fiq_cb().set_inputline(m_maincpu, arm7_cpu_device::ARM7_FIRQ_LINE); + + for (int i=0; i<3; i++) { + LH79524_TIMER(config, m_timers[i], 76'205'000); + m_timers[i]->set_timer_index(i); + } + + m_timers[0]->irq_cb().set(m_vic, FUNC(vic_pl190_device::irq_w<4>)); + m_timers[1]->irq_cb().set(m_vic, FUNC(vic_pl190_device::irq_w<5>)); + m_timers[2]->irq_cb().set(m_vic, FUNC(vic_pl190_device::irq_w<6>)); + GENERIC_CARTSLOT(config, m_cart, generic_plain_slot, "pixter_cart"); m_cart->set_endian(ENDIANNESS_LITTLE); m_cart->set_width(GENERIC_ROM32_WIDTH); m_cart->set_device_load(FUNC(pixter_multimedia_state::cart_load)); m_cart->set_must_be_loaded(false); + PALETTE(config, m_palette).set_format(palette_device::IRGB_1555, 256); + + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + m_screen->set_palette("palette"); + + m_screen->set_refresh_hz(60); + m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500) /* not accurate */); + // The LCD is 160x160 but this is a hack to draw the softbuttons below it + m_screen->set_size(160, 176); + m_screen->set_visarea(0, 160-1, 0, 176-1); + m_screen->set_screen_update(FUNC(pixter_multimedia_state::screen_update_pixtermu)); + + m_screen->screen_vblank().set(FUNC(pixter_multimedia_state::screen_vblank)); + + SOFTWARE_LIST(config, "cart_list").set_original("pixter_cart"); } |
