iphone2g wip (nw) (#6226)

* iphone2g wip (nw)

* fixup

* fixup

* fixup

* iphone2g: hacky spi and non-existent timers (nw)
This commit is contained in:
Melissa Goad 2020-01-29 09:13:48 -06:00 committed by GitHub
parent a5783544e8
commit e6595b06a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 478 additions and 10 deletions

View File

@ -3130,6 +3130,18 @@ if (MACHINES["V3021"]~=null) then
}
end
---------------------------------------------------
--
--@src/devices/machine/vic_pl192.h,MACHINES["VIC_PL192"] = true
---------------------------------------------------
if (MACHINES["VIC_PL192"]~=null) then
files {
MAME_DIR .. "src/devices/machine/vic_pl192.cpp",
MAME_DIR .. "src/devices/machine/vic_pl192.h",
}
end
---------------------------------------------------
--
--@src/devices/machine/wd_fdc.h,MACHINES["WD_FDC"] = true

View File

@ -672,6 +672,7 @@ MACHINES["UPD71071"] = true
MACHINES["UPD765"] = true
MACHINES["FDC_PLL"] = true
MACHINES["V3021"] = true
MACHINES["VIC_PL192"] = true
MACHINES["WD_FDC"] = true
MACHINES["WD1000"] = true
MACHINES["WD1010"] = true

View File

@ -42,7 +42,7 @@ TODO:
#define LOG_COPRO_UNKNOWN (1 << 4)
#define LOG_COPRO_RESERVED (1 << 5)
#define VERBOSE (0)
#define VERBOSE (0) //(LOG_MMU | LOG_COPRO_READS | LOG_COPRO_WRITES)
#include "logmacro.h"
#define PRINT_HAPYFSH2 (0)
@ -726,7 +726,6 @@ void arm946es_cpu_device::device_start()
save_item(NAME(DTCM));
}
void arm7_cpu_device::state_export(const device_state_entry &entry)
{
switch (entry.index())
@ -787,6 +786,11 @@ void arm7_cpu_device::device_reset()
m_impstate.cache_dirty = true;
}
void arm1176jzf_s_cpu_device::device_reset()
{
arm7_cpu_device::device_reset();
m_control = 0x00050078;
}
#define UNEXECUTED() \
m_r[eR15] += 4; \
@ -1413,7 +1417,7 @@ WRITE32_MEMBER( arm7_cpu_device::arm7_rt_w_callback )
#if ARM7_MMU_ENABLE_HACK
if (((data & COPRO_CTRL_MMU_EN) != 0) && ((COPRO_CTRL & COPRO_CTRL_MMU_EN) == 0))
{
>m_mmu_enable_addr = R15;
m_mmu_enable_addr = R15;
}
if (((data & COPRO_CTRL_MMU_EN) == 0) && ((COPRO_CTRL & COPRO_CTRL_MMU_EN) != 0))
{
@ -1778,6 +1782,44 @@ void arm7_cpu_device::arm7_dt_w_callback(uint32_t insn, uint32_t *prn)
}
}
READ32_MEMBER( arm1176jzf_s_cpu_device::arm7_rt_r_callback )
{
uint32_t opcode = offset;
uint8_t crn = (opcode & INSN_COPRO_CREG) >> INSN_COPRO_CREG_SHIFT;
uint8_t op1 = (opcode & INSN_COPRO_OP1) >> INSN_COPRO_OP1_SHIFT;
uint8_t op2 = (opcode & INSN_COPRO_OP2) >> INSN_COPRO_OP2_SHIFT;
uint8_t crm = opcode & INSN_COPRO_OP3;
uint8_t cpnum = (opcode & INSN_COPRO_CPNUM) >> INSN_COPRO_CPNUM_SHIFT;
uint32_t data = 0;
// printf("arm7946: copro %d write %x to cReg %d op2 %d op3 %d (mask %08x)\n", cpnum, data, cReg, op2, op3, mem_mask);
if (cpnum == 15)
{
if(crn == 0 && op1 == 0 && crm == 0 && op2 == 0) data = 0x410FB767; //ARM1176JZF-S Main ID.
if(crn == 1 && op1 == 0 && crm == 0 && op2 == 0) data = m_control;
}
return data;
}
WRITE32_MEMBER( arm1176jzf_s_cpu_device::arm7_rt_w_callback )
{
uint32_t opcode = offset;
uint8_t crn = (opcode & INSN_COPRO_CREG) >> INSN_COPRO_CREG_SHIFT;
uint8_t op1 = (opcode & INSN_COPRO_OP1) >> INSN_COPRO_OP1_SHIFT;
uint8_t op2 = (opcode & INSN_COPRO_OP2) >> INSN_COPRO_OP2_SHIFT;
uint8_t crm = opcode & INSN_COPRO_OP3;
uint8_t cpnum = (opcode & INSN_COPRO_CPNUM) >> INSN_COPRO_CPNUM_SHIFT;
// printf("arm7946: copro %d write %x to cReg %d op2 %d op3 %d (mask %08x)\n", cpnum, data, cReg, op2, op3, mem_mask);
if (cpnum == 15)
{
LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback: CP15 CRn %02x Op1 %02x CRm %02x Op2 %02x data %08x\n", crn, op1, crm, op2, data);
if(crn == 1 && op1 == 0 && crm == 0 && op2 == 0) m_control = data;
}
}
/***************************************************************************
* Default Memory Handlers

View File

@ -179,7 +179,7 @@ protected:
uint32_t m_domainAccessControl;
uint8_t m_decoded_access_control[16];
uint8_t m_archRev; // ARM architecture revision (3, 4, and 5 are valid)
uint8_t m_archRev; // ARM architecture revision (3, 4, 5, and 6 are valid)
uint32_t m_archFlags; // architecture flags
uint32_t m_vectorbase;
@ -674,6 +674,12 @@ class arm1176jzf_s_cpu_device : public arm11_cpu_device
public:
// construction/destruction
arm1176jzf_s_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual DECLARE_READ32_MEMBER( arm7_rt_r_callback ) override;
virtual DECLARE_WRITE32_MEMBER( arm7_rt_w_callback ) override;
protected:
virtual void device_reset() override;
};
class igs036_cpu_device : public arm946es_cpu_device

View File

@ -356,12 +356,14 @@ static const int sRegisterTable[ARM7_NUM_MODES][18] =
#define INSN_RD_SHIFT 12
#define INSN_COND_SHIFT 28
#define INSN_COPRO_OP1 ((uint32_t) 0x00e00000u)
#define INSN_COPRO_N ((uint32_t) 0x00100000u)
#define INSN_COPRO_CREG ((uint32_t) 0x000f0000u)
#define INSN_COPRO_AREG ((uint32_t) 0x0000f000u)
#define INSN_COPRO_CPNUM ((uint32_t) 0x00000f00u)
#define INSN_COPRO_OP2 ((uint32_t) 0x000000e0u)
#define INSN_COPRO_OP3 ((uint32_t) 0x0000000fu)
#define INSN_COPRO_OP1_SHIFT 21
#define INSN_COPRO_N_SHIFT 20
#define INSN_COPRO_CREG_SHIFT 16
#define INSN_COPRO_AREG_SHIFT 12

View File

@ -0,0 +1,130 @@
// license:BSD-3-Clause
// copyright-holders:Melissa Goad
// ARM PrimeCell PL192 VIC emulation
#include "emu.h"
#include "machine/bankdev.h"
#include "machine/vic_pl192.h"
#define LOG_GENERAL (1U << 0)
#define VERBOSE (LOG_GENERAL)
#include "logmacro.h"
void vic_pl192_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
if(u32 intrs = (raw_intr | soft_intr) & intr_en)
{
if(intrs & intr_select) m_out_fiq_func(1);
else m_out_fiq_func(0);
if(intrs & ~intr_select) m_out_irq_func(1);
else m_out_irq_func(0);
}
}
void vic_pl192_device::set_irq_line(int irq, int state)
{
u32 mask = (1 << irq);
if(state)
{
raw_intr |= mask;
}
else
{
raw_intr &= ~mask;
}
timer_set(attotime::zero, TIMER_CHECK_IRQ);
}
void vic_pl192_device::map(address_map &map)
{
map(0x000, 0x003).lr32([this](offs_t offset){ return raw_intr & ~intr_select; }, "irq_status"); //IRQ_STATUS
map(0x004, 0x007).lr32([this](offs_t offset){ return raw_intr & intr_select; }, "fiq_status"); //FIQ_STATUS
map(0x008, 0x00b).lr32([this](offs_t offset){ return raw_intr; }, "raw_intr");
map(0x00c, 0x00f).lrw32(NAME([this](offs_t offset){ return intr_select; }), NAME([this](offs_t offset, u32 data){ intr_select = data; timer_set(attotime::zero, TIMER_CHECK_IRQ); }));
map(0x010, 0x013).lrw32(NAME([this](offs_t offset){ return intr_en; }), NAME([this](offs_t offset, u32 data){ intr_en = data; timer_set(attotime::zero, TIMER_CHECK_IRQ); }));
map(0x014, 0x017).lw32([this](u32 data){ intr_en &= ~data; }, "intr_en_clear");
map(0x018, 0x01b).lrw32(NAME([this](offs_t offset){ return soft_intr; }), NAME([this](offs_t offset, u32 data){ soft_intr = data; timer_set(attotime::zero, TIMER_CHECK_IRQ); }));
map(0x01c, 0x01f).lw32([this](u32 data){ soft_intr &= ~data; }, "soft_intr_clear");
map(0x020, 0x020).lrw8(NAME([this](offs_t offset){ return protection; }), NAME([this](offs_t offset, u8 data){ protection = data & 1; })).umask32(0x000000ff);
map(0x024, 0x025).lrw8(NAME([this](offs_t offset){ return sw_priority_mask; }), NAME([this](offs_t offset, u16 data){ sw_priority_mask = data; })).umask32(0x0000ffff);
map(0x028, 0x028).lrw8(NAME([this](offs_t offset){ return daisy_priority; }), NAME([this](offs_t offset, u8 data){ daisy_priority = data & 0xf; })).umask32(0x000000ff);
map(0x100, 0x17f).lrw32(NAME([this](offs_t offset){ return vectaddr[(offset & 0x7c) >> 2]; }), NAME([this](offs_t offset, u32 data){ vectaddr[(offset & 0x7c) >> 2] = data; }));
map(0x200, 0x27f).lrw8(NAME([this](offs_t offset){ return vectprio[(offset & 0x7c) >> 2]; }), NAME([this](offs_t offset, u32 data){ vectprio[(offset & 0x7c) >> 2] = data & 0xf; }));
map(0xf00, 0xf03).lrw32(NAME([this](offs_t offset){ return vicaddress; }), NAME([this](offs_t offset, u32 data){ vectaddr[(offset & 0x7c) >> 2] = data; }));
map(0xfe0, 0xfe0).lr8([this](offs_t offset){ return periph_id[0]; }, "periph_id0").umask32(0x000000ff);
map(0xfe4, 0xfe4).lr8([this](offs_t offset){ return periph_id[1]; }, "periph_id1").umask32(0x000000ff);
map(0xfe8, 0xfe8).lr8([this](offs_t offset){ return periph_id[2]; }, "periph_id2").umask32(0x000000ff);
map(0xfec, 0xfec).lr8([this](offs_t offset){ return periph_id[3]; }, "periph_id3").umask32(0x000000ff);
map(0xff0, 0xff0).lr8([this](offs_t offset){ return pcell_id[0]; }, "pcell_id0").umask32(0x000000ff);
map(0xff4, 0xff4).lr8([this](offs_t offset){ return pcell_id[1]; }, "pcell_id1").umask32(0x000000ff);
map(0xff8, 0xff8).lr8([this](offs_t offset){ return pcell_id[2]; }, "pcell_id2").umask32(0x000000ff);
map(0xffc, 0xffc).lr8([this](offs_t offset){ return pcell_id[3]; }, "pcell_id3").umask32(0x000000ff);
}
device_memory_interface::space_config_vector vic_pl192_device::memory_space_config() const
{
return space_config_vector{
std::make_pair(0, &m_mmio_config)
};
}
void vic_pl192_device::device_resolve_objects()
{
// resolve callbacks
m_out_irq_func.resolve_safe();
m_out_fiq_func.resolve_safe();
}
void vic_pl192_device::device_start()
{
save_item(NAME(raw_intr));
save_item(NAME(intr_select));
save_item(NAME(intr_en));
save_item(NAME(soft_intr));
save_item(NAME(vectaddr));
save_item(NAME(vicaddress));
save_item(NAME(protection));
save_item(NAME(sw_priority_mask));
save_item(NAME(daisy_priority));
save_item(NAME(vectprio));
}
void vic_pl192_device::device_reset()
{
raw_intr = intr_select = intr_en = soft_intr = vicaddress = protection = 0;
sw_priority_mask = 0xffff;
daisy_priority = 0xf;
for(int i = 0; i < 32; i++)
{
vectaddr[i] = 0;
}
for(int i = 0; i < 32; i++)
{
vectprio[i] = 0xf;
}
}
DEFINE_DEVICE_TYPE(PL192_VIC, vic_pl192_device, "vic_pl192", "ARM PL192 VIC")
vic_pl192_device::vic_pl192_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, device_memory_interface(mconfig, *this)
, m_mmio_config("mmio", ENDIANNESS_LITTLE, 32, 32, 0)
, m_out_irq_func(*this)
, m_out_fiq_func(*this)
, periph_id{0x92, 0x11, 0x04, 0x00}
, pcell_id{0x0d, 0xf0, 0x05, 0xb1}
{
}
vic_pl192_device::vic_pl192_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: vic_pl192_device(mconfig, PL192_VIC, tag, owner, clock)
{
}

View File

@ -0,0 +1,51 @@
// license:BSD-3-Clause
// copyright-holders:Melissa Goad
// ARM PrimeCell PL192 VIC emulation
#ifndef MAME_MACHINE_VIC_PL192_H
#define MAME_MACHINE_VIC_PL192_H
class vic_pl192_device : public device_t, public device_memory_interface
{
public:
vic_pl192_device(const machine_config &mconfig, const char* tag, device_t *owner, uint32_t clock = 0);
auto out_irq_cb() { return m_out_irq_func.bind(); }
auto out_fiq_cb() { return m_out_fiq_func.bind(); }
template<unsigned IRQ>
DECLARE_WRITE_LINE_MEMBER( irq_w ) { set_irq_line(IRQ, state); }
void map(address_map &map);
protected:
vic_pl192_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_resolve_objects() override;
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
virtual space_config_vector memory_space_config() const override;
private:
static constexpr device_timer_id TIMER_CHECK_IRQ = 0;
void set_irq_line(int irq, int state);
address_space_config m_mmio_config;
devcb_write_line m_out_irq_func;
devcb_write_line m_out_fiq_func;
u32 raw_intr, intr_select, intr_en, soft_intr, vectaddr[32], vicaddress;
int protection;
u16 sw_priority_mask;
u8 daisy_priority, vectprio[32];
u8 periph_id[4], pcell_id[4];
};
DECLARE_DEVICE_TYPE(PL192_VIC, vic_pl192_device)
#endif // MAME_MACHINE_VIC_PL192_H

View File

@ -10,14 +10,212 @@
#include "emu.h"
#include "cpu/arm7/arm7.h"
#include "cpu/arm7/arm7core.h"
#include "machine/bankdev.h"
#include "machine/vic_pl192.h"
#include "screen.h"
class iphone2g_spi_device : public device_t, public device_memory_interface
{
public:
iphone2g_spi_device(const machine_config &mconfig, const char* tag, device_t *owner, uint32_t clock = 0);
auto out_irq_cb() { return m_out_irq_func.bind(); }
void map(address_map &map);
protected:
iphone2g_spi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_resolve_objects() override;
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
virtual space_config_vector memory_space_config() const override;
private:
static constexpr device_timer_id TIMER_SEND_IRQ = 0;
address_space_config m_mmio_config;
devcb_write_line m_out_irq_func;
u8 cmd, tx_data;
u32 ctrl;
u16 status;
};
DECLARE_DEVICE_TYPE(IPHONE2G_SPI, iphone2g_spi_device)
void iphone2g_spi_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
m_out_irq_func(1);
}
void iphone2g_spi_device::map(address_map &map)
{
map(0x00,0x03).lrw32(NAME([this](offs_t offset){ return ctrl; }), NAME([this](offs_t offset, u32 data){
if(data & 1)
{
status |= 0xfff2;
cmd = tx_data;
timer_set(attotime::from_hz(1'000), TIMER_SEND_IRQ);
}
ctrl = data;
}));
map(0x08, 0x09).lr16([this](offs_t offset){ return status; }, "status").umask32(0x0000ffff);
map(0x10, 0x10).lrw8(NAME([this](offs_t offset){ return tx_data; }), NAME([this](offs_t offset, u8 data){ tx_data = data; })).umask32(0x000000ff);
map(0x20, 0x20).lr8([this](offs_t offset){
// FIXME: make this less hacky
switch(cmd)
{
case 0x95: return 0x01;
case 0xda: return 0x71;
case 0xdb: return 0xc2;
case 0xdc: return 0x00;
}
return 0;
}, "rx_data");
}
device_memory_interface::space_config_vector iphone2g_spi_device::memory_space_config() const
{
return space_config_vector{
std::make_pair(0, &m_mmio_config)
};
}
void iphone2g_spi_device::device_resolve_objects()
{
// resolve callbacks
m_out_irq_func.resolve_safe();
}
void iphone2g_spi_device::device_start()
{
save_item(NAME(cmd));
save_item(NAME(ctrl));
save_item(NAME(tx_data));
save_item(NAME(status));
}
void iphone2g_spi_device::device_reset()
{
cmd = ctrl= status = tx_data = 0;
}
DEFINE_DEVICE_TYPE(IPHONE2G_SPI, iphone2g_spi_device, "iphone2g_spi", "iPhone 2G SPI controller")
iphone2g_spi_device::iphone2g_spi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, device_memory_interface(mconfig, *this)
, m_mmio_config("mmio", ENDIANNESS_LITTLE, 32, 32, 0)
, m_out_irq_func(*this)
{
}
iphone2g_spi_device::iphone2g_spi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: iphone2g_spi_device(mconfig, IPHONE2G_SPI, tag, owner, clock)
{
}
class iphone2g_timer_device : public device_t, public device_memory_interface
{
public:
iphone2g_timer_device(const machine_config &mconfig, const char* tag, device_t *owner, uint32_t clock = 0);
auto out_irq_cb() { return m_out_irq_func.bind(); }
void map(address_map &map);
void timer_map(address_map &map);
protected:
iphone2g_timer_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_resolve_objects() override;
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
virtual space_config_vector memory_space_config() const override;
private:
static constexpr device_timer_id TIMER_TICK = 0;
address_space_config m_mmio_config;
devcb_write_line m_out_irq_func;
struct timer
{
u16 config;
u8 state;
u32 count_buffer[2], count;
} timers[7];
u64 ticks;
};
DECLARE_DEVICE_TYPE(IPHONE2G_TIMER, iphone2g_timer_device)
void iphone2g_timer_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
m_out_irq_func(1);
}
void iphone2g_timer_device::map(address_map &map)
{
}
device_memory_interface::space_config_vector iphone2g_timer_device::memory_space_config() const
{
return space_config_vector{
std::make_pair(0, &m_mmio_config)
};
}
void iphone2g_timer_device::device_resolve_objects()
{
// resolve callbacks
m_out_irq_func.resolve_safe();
}
void iphone2g_timer_device::device_start()
{
}
void iphone2g_timer_device::device_reset()
{
}
DEFINE_DEVICE_TYPE(IPHONE2G_TIMER, iphone2g_timer_device, "iphone2g_timer", "iPhone 2G timers")
iphone2g_timer_device::iphone2g_timer_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, device_memory_interface(mconfig, *this)
, m_mmio_config("mmio", ENDIANNESS_LITTLE, 32, 32, 0)
, m_out_irq_func(*this)
{
}
iphone2g_timer_device::iphone2g_timer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: iphone2g_timer_device(mconfig, IPHONE2G_SPI, tag, owner, clock)
{
}
class iphone2g_state : public driver_device
{
public:
iphone2g_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_vic0(*this, "vic0"),
m_vic1(*this, "vic1"),
m_spi(*this, {"spi0", "spi1", "spi2"}),
m_timers(*this, "timers"),
m_ram(*this, "ram"),
m_bios(*this, "bios"),
m_screen(*this, "screen")
@ -33,7 +231,11 @@ protected:
private:
required_device<cpu_device> m_maincpu;
required_shared_ptr<uint32_t> m_ram;
required_device<vic_pl192_device> m_vic0;
required_device<vic_pl192_device> m_vic1;
required_device_array<iphone2g_spi_device, 3> m_spi;
required_device<iphone2g_timer_device> m_timers;
optional_shared_ptr<uint32_t> m_ram;
required_region_ptr<uint32_t> m_bios;
required_device<screen_device> m_screen;
@ -62,15 +264,19 @@ READ32_MEMBER(iphone2g_state::clock1_r)
void iphone2g_state::mem_map(address_map &map)
{
map(0x00000000, 0x07FFFFFF).mirror(0x18000000).ram().share("ram"); /* DRAM */
map(0x20000000, 0x2000FFFF).rom().region("bios", 0); /* BIOS */
map(0x22000000, 0x224FFFFF).ram(); /* SRAM */
map(0x3C500000, 0x3C500FFF).r(FUNC(iphone2g_state::clock1_r)).nopw();
map(0x00000000, 0x0000ffff).mirror(0x20000000).rom().region("bios", 0); /* BIOS */
map(0x22000000, 0x224fffff).ram(); /* SRAM */
map(0x38e00000, 0x38e00fff).m(m_vic0, FUNC(vic_pl192_device::map));
map(0x38e01000, 0x38e01fff).m(m_vic1, FUNC(vic_pl192_device::map));
map(0x3c300000, 0x3c3000ff).m(m_spi[0], FUNC(iphone2g_spi_device::map));
map(0x3c500000, 0x3c500fff).r(FUNC(iphone2g_state::clock1_r)).nopw();
map(0x3ce00000, 0x3ce000ff).m(m_spi[1], FUNC(iphone2g_spi_device::map));
map(0x3d200000, 0x3d2000ff).m(m_spi[2], FUNC(iphone2g_spi_device::map));
}
void iphone2g_state::machine_start()
{
std::copy_n(m_bios.target(), m_bios.length(), m_ram.target());
//std::copy_n(m_bios.target(), m_bios.length(), m_ram.target());
}
void iphone2g_state::machine_reset()
@ -83,6 +289,24 @@ void iphone2g_state::iphone2g(machine_config &config)
ARM1176JZF_S(config, m_maincpu, XTAL(12'000'000) * 103 / 3); //412 MHz, downclocked from 600 MHz
m_maincpu->set_addrmap(AS_PROGRAM, &iphone2g_state::mem_map);
PL192_VIC(config, m_vic0);
m_vic0->out_irq_cb().set_inputline("maincpu", ARM7_IRQ_LINE);
m_vic0->out_fiq_cb().set_inputline("maincpu", ARM7_FIRQ_LINE);
IPHONE2G_SPI(config, m_spi[0], XTAL(12'000'000));
m_spi[0]->out_irq_cb().set(m_vic0, FUNC(vic_pl192_device::irq_w<0x09>));
IPHONE2G_SPI(config, m_spi[1], XTAL(12'000'000));
m_spi[1]->out_irq_cb().set(m_vic0, FUNC(vic_pl192_device::irq_w<0x0a>));
IPHONE2G_SPI(config, m_spi[2], XTAL(12'000'000));
m_spi[2]->out_irq_cb().set(m_vic0, FUNC(vic_pl192_device::irq_w<0x0b>));
IPHONE2G_TIMER(config, m_timers, XTAL(12'000'000));
m_timers->out_irq_cb().set(m_vic0, FUNC(vic_pl192_device::irq_w<0x07>));
PL192_VIC(config, m_vic1);
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(XTAL(12'000'000), 320, 0, 320, 480, 0, 480); //Complete guess
m_screen->set_screen_update(FUNC(iphone2g_state::screen_update));