mirror of
https://github.com/holub/mame
synced 2025-06-03 19:36:26 +03:00
Rewrite ARM IOMD/VIDC20 chips into own devices, merged implementations from ssfindo.cpp & riscpc.cpp [Angelo Salese] #6047
* riscpc now enters in desktop mode with a valid nvram; * adds preliminary sound for ppcar;
This commit is contained in:
parent
2eae516ff4
commit
f58c3ea264
@ -82,7 +82,6 @@ if (MACHINES["ACORN_VIDC"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/akiko.h,MACHINES["AKIKO"] = true
|
||||
@ -95,6 +94,17 @@ if (MACHINES["AKIKO"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
--------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/arm_iomd.h,MACHINES["ARM_IOMD"] = true
|
||||
--------------------------------------------------
|
||||
|
||||
if (MACHINES["ARM_IOMD"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/machine/arm_iomd.cpp",
|
||||
MAME_DIR .. "src/devices/machine/arm_iomd.h",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
|
@ -30,6 +30,7 @@
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(ACORN_VIDC10, acorn_vidc10_device, "acorn_vidc10", "Acorn VIDC10")
|
||||
DEFINE_DEVICE_TYPE(ACORN_VIDC10_LCD, acorn_vidc10_lcd_device, "acorn_vidc10_lcd", "Acorn VIDC10 with LCD monitor")
|
||||
DEFINE_DEVICE_TYPE(ARM_VIDC20, arm_vidc20_device, "arm_vidc20", "ARM VIDC20")
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
@ -51,25 +52,23 @@ void acorn_vidc10_device::regs_map(address_map &map)
|
||||
}
|
||||
|
||||
|
||||
acorn_vidc10_device::acorn_vidc10_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
|
||||
acorn_vidc10_device::acorn_vidc10_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, type, tag, owner, clock)
|
||||
, device_memory_interface(mconfig, *this)
|
||||
, device_palette_interface(mconfig, *this)
|
||||
, device_video_interface(mconfig, *this)
|
||||
, m_space_config("regs_space", ENDIANNESS_LITTLE, 32, 8, 0, address_map_constructor(FUNC(acorn_vidc10_device::regs_map), this))
|
||||
, m_bpp_mode(0)
|
||||
, m_crtc_interlace(0)
|
||||
, m_sound_frequency_latch(0)
|
||||
, m_sound_mode(false)
|
||||
, m_dac(*this, "dac%u", 0)
|
||||
, m_lspeaker(*this, "lspeaker")
|
||||
, m_rspeaker(*this, "rspeaker")
|
||||
, m_dac(*this, "dac%u", 0)
|
||||
, m_vblank_cb(*this)
|
||||
, m_sound_drq_cb(*this)
|
||||
, m_pixel_clock(0)
|
||||
, m_bpp_mode(0)
|
||||
, m_crtc_interlace(0)
|
||||
, m_cursor_enable(false)
|
||||
, m_sound_frequency_latch(0)
|
||||
, m_sound_frequency_test_bit(false)
|
||||
, m_sound_mode(false)
|
||||
|
||||
{
|
||||
std::fill(std::begin(m_crtc_regs), std::end(m_crtc_regs), 0);
|
||||
std::fill(std::begin(m_stereo_image), std::end(m_stereo_image), 0);
|
||||
@ -78,12 +77,21 @@ acorn_vidc10_device::acorn_vidc10_device(const machine_config &mconfig, device_t
|
||||
acorn_vidc10_device::acorn_vidc10_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: acorn_vidc10_device(mconfig, ACORN_VIDC10, tag, owner, clock)
|
||||
{
|
||||
m_space_config = address_space_config("regs_space", ENDIANNESS_LITTLE, 32, 8, 0, address_map_constructor(FUNC(acorn_vidc10_device::regs_map), this));
|
||||
m_pal_4bpp_base = 0x100;
|
||||
m_pal_cursor_base = 0x10;
|
||||
m_pal_border_base = 0x110;
|
||||
}
|
||||
|
||||
|
||||
acorn_vidc10_lcd_device::acorn_vidc10_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
acorn_vidc10_lcd_device::acorn_vidc10_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: acorn_vidc10_device(mconfig, ACORN_VIDC10_LCD, tag, owner, clock)
|
||||
{
|
||||
m_space_config = address_space_config("regs_space", ENDIANNESS_LITTLE, 32, 8, 0, address_map_constructor(FUNC(acorn_vidc10_lcd_device::regs_map), this));
|
||||
// TODO: confirm being identical to raster version
|
||||
m_pal_4bpp_base = 0x100;
|
||||
m_pal_cursor_base = 0x10;
|
||||
m_pal_border_base = 0x110;
|
||||
}
|
||||
|
||||
device_memory_interface::space_config_vector acorn_vidc10_device::memory_space_config() const
|
||||
@ -118,7 +126,7 @@ void acorn_vidc10_lcd_device::device_add_mconfig(machine_config &config)
|
||||
// TODO: verify !Configure with automatic type detection, there must be an ID telling this is a LCD machine.
|
||||
}
|
||||
|
||||
uint32_t acorn_vidc10_device::palette_entries() const
|
||||
u32 acorn_vidc10_device::palette_entries() const
|
||||
{
|
||||
return 0x100+0x10+4; // 8bpp + 1/2/4bpp + 2bpp for cursor
|
||||
}
|
||||
@ -160,8 +168,9 @@ void acorn_vidc10_device::device_start()
|
||||
save_item(NAME(m_sound_frequency_test_bit));
|
||||
save_item(NAME(m_cursor_enable));
|
||||
save_pointer(NAME(m_crtc_regs), CRTC_VCER+1);
|
||||
m_data_vram = auto_alloc_array_clear(machine(), u8, m_data_vram_size);
|
||||
m_cursor_vram = auto_alloc_array_clear(machine(), u8, m_cursor_vram_size);
|
||||
save_pointer(NAME(m_crtc_raw_horz), 2);
|
||||
m_data_vram = make_unique_clear<u8[]>(m_data_vram_size);
|
||||
m_cursor_vram = make_unique_clear<u8[]>(m_cursor_vram_size);
|
||||
save_pointer(NAME(m_data_vram), m_data_vram_size);
|
||||
save_pointer(NAME(m_cursor_vram), m_cursor_vram_size);
|
||||
save_pointer(NAME(m_stereo_image), m_sound_max_channels);
|
||||
@ -174,8 +183,8 @@ void acorn_vidc10_device::device_start()
|
||||
// TODO: manual mentions a format difference between VIDC10 revisions
|
||||
for (int rawval = 0; rawval < 256; rawval++)
|
||||
{
|
||||
uint8_t chord = rawval >> 5;
|
||||
uint8_t point = (rawval & 0x1e) >> 1;
|
||||
u8 chord = rawval >> 5;
|
||||
u8 point = (rawval & 0x1e) >> 1;
|
||||
bool sign = rawval & 1;
|
||||
int16_t result = ((16+point)<<chord)-16;
|
||||
|
||||
@ -184,6 +193,8 @@ void acorn_vidc10_device::device_start()
|
||||
|
||||
m_ulaw_lookup[rawval] = result*8;
|
||||
}
|
||||
|
||||
// saved for debugging purposes
|
||||
save_pointer(NAME(m_ulaw_lookup), 256);
|
||||
}
|
||||
|
||||
@ -195,8 +206,6 @@ void acorn_vidc10_device::device_start()
|
||||
void acorn_vidc10_device::device_reset()
|
||||
{
|
||||
m_cursor_enable = false;
|
||||
memset(m_data_vram, 0, m_data_vram_size);
|
||||
memset(m_cursor_vram, 0, m_cursor_vram_size);
|
||||
memset(m_stereo_image, 4, m_sound_max_channels);
|
||||
for (int ch=0;ch<m_sound_max_channels;ch++)
|
||||
refresh_stereo_image(ch);
|
||||
@ -232,9 +241,15 @@ inline void acorn_vidc10_device::screen_vblank_line_update()
|
||||
m_video_timer->adjust((vline > 2) ? screen().time_until_pos(vline) : attotime::never);
|
||||
}
|
||||
|
||||
void acorn_vidc10_device::screen_dynamic_res_change()
|
||||
u32 acorn_vidc10_device::get_pixel_clock()
|
||||
{
|
||||
const int32_t pixel_rate[4] = { 8000000, 12000000, 16000000, 24000000};
|
||||
return pixel_rate[m_pixel_clock];
|
||||
}
|
||||
|
||||
inline void acorn_vidc10_device::screen_dynamic_res_change()
|
||||
{
|
||||
const u32 pixel_clock = get_pixel_clock();
|
||||
|
||||
// sanity checks
|
||||
if (m_crtc_regs[CRTC_HCR] <= 1 || m_crtc_regs[CRTC_VCR] <= 1)
|
||||
@ -267,7 +282,7 @@ void acorn_vidc10_device::screen_dynamic_res_change()
|
||||
m_vidc_vblank_time);
|
||||
#endif
|
||||
|
||||
attoseconds_t const refresh = HZ_TO_ATTOSECONDS(pixel_rate[m_pixel_clock]) * m_crtc_regs[CRTC_HCR] * m_crtc_regs[CRTC_VCR];
|
||||
attoseconds_t const refresh = HZ_TO_ATTOSECONDS(pixel_clock) * m_crtc_regs[CRTC_HCR] * m_crtc_regs[CRTC_VCR];
|
||||
|
||||
screen().configure(m_crtc_regs[CRTC_HCR], m_crtc_regs[CRTC_VCR] * (m_crtc_interlace+1), visarea, refresh);
|
||||
}
|
||||
@ -279,13 +294,13 @@ void acorn_vidc10_device::screen_dynamic_res_change()
|
||||
WRITE32_MEMBER( acorn_vidc10_device::write )
|
||||
{
|
||||
// TODO: check against mem_mask not 32-bit wide
|
||||
uint8_t reg = data >> 24;
|
||||
uint32_t val = data & 0xffffff;
|
||||
|
||||
u8 reg = data >> 24;
|
||||
u32 val = data & 0xffffff;
|
||||
|
||||
this->space(AS_IO).write_dword(reg, val);
|
||||
}
|
||||
|
||||
inline void acorn_vidc10_device::update_4bpp_palette(uint16_t index, uint32_t paldata)
|
||||
inline void acorn_vidc10_device::update_4bpp_palette(u16 index, u32 paldata)
|
||||
{
|
||||
int r,g,b;
|
||||
|
||||
@ -331,20 +346,34 @@ WRITE32_MEMBER( acorn_vidc10_device::control_w )
|
||||
//m_test_mode = (data & 0xc100) != 0xc100;
|
||||
|
||||
//todo: vga/svga modes sets 0x1000?
|
||||
m_crtc_regs[CRTC_HDSR] = convert_crtc_hdisplay(0);
|
||||
m_crtc_regs[CRTC_HDER] = convert_crtc_hdisplay(1);
|
||||
screen_vblank_line_update();
|
||||
screen_dynamic_res_change();
|
||||
}
|
||||
|
||||
inline u32 acorn_vidc10_device::convert_crtc_hdisplay(u8 index)
|
||||
{
|
||||
const u8 x_step[4] = { 19, 11, 7, 5 };
|
||||
return (m_crtc_raw_horz[index]*2)+x_step[m_bpp_mode];
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( acorn_vidc10_device::crtc_w )
|
||||
{
|
||||
switch(offset)
|
||||
{
|
||||
case CRTC_HCR: m_crtc_regs[CRTC_HCR] = ((data >> 14)<<1)+2; break;
|
||||
// case CRTC_HSWR: m_crtc_regs[CRTC_HSWR] = (data >> 14)+1; break;
|
||||
case CRTC_HBSR: m_crtc_regs[CRTC_HBSR] = ((data >> 14)<<1)+1; break;
|
||||
case CRTC_HDSR: m_crtc_regs[CRTC_HDSR] = (data >> 14); break;
|
||||
case CRTC_HDER: m_crtc_regs[CRTC_HDER] = (data >> 14); break;
|
||||
case CRTC_HBER: m_crtc_regs[CRTC_HBER] = ((data >> 14)<<1)+1; break;
|
||||
case CRTC_HCR: m_crtc_regs[CRTC_HCR] = ((data >> 14)<<1)+2; break;
|
||||
// case CRTC_HSWR: m_crtc_regs[CRTC_HSWR] = (data >> 14)+1; break;
|
||||
case CRTC_HBSR: m_crtc_regs[CRTC_HBSR] = ((data >> 14)<<1)+1; break;
|
||||
case CRTC_HDSR:
|
||||
m_crtc_raw_horz[0] = (data >> 14);
|
||||
m_crtc_regs[CRTC_HDSR] = convert_crtc_hdisplay(0);
|
||||
break;
|
||||
case CRTC_HDER:
|
||||
m_crtc_raw_horz[1] = (data >> 14);
|
||||
m_crtc_regs[CRTC_HDER] = convert_crtc_hdisplay(1);
|
||||
break;
|
||||
case CRTC_HBER: m_crtc_regs[CRTC_HBER] = ((data >> 14)<<1)+1; break;
|
||||
case CRTC_HCSR: m_crtc_regs[CRTC_HCSR] = ((data >> 13) & 0x7ff) + 6; return;
|
||||
// case CRTC_HIR: // ...
|
||||
|
||||
@ -370,7 +399,7 @@ WRITE32_MEMBER( acorn_vidc10_device::crtc_w )
|
||||
screen_dynamic_res_change();
|
||||
}
|
||||
|
||||
inline void acorn_vidc10_device::refresh_stereo_image(uint8_t channel)
|
||||
inline void acorn_vidc10_device::refresh_stereo_image(u8 channel)
|
||||
{
|
||||
/*
|
||||
-111 full right
|
||||
@ -393,7 +422,7 @@ inline void acorn_vidc10_device::refresh_stereo_image(uint8_t channel)
|
||||
|
||||
WRITE32_MEMBER( acorn_vidc10_device::stereo_image_w )
|
||||
{
|
||||
uint8_t channel = (offset + 7) & 0x7;
|
||||
u8 channel = (offset + 7) & 0x7;
|
||||
m_stereo_image[channel] = data & 0x7;
|
||||
refresh_stereo_image(channel);
|
||||
}
|
||||
@ -410,8 +439,8 @@ WRITE32_MEMBER( acorn_vidc10_device::sound_frequency_w )
|
||||
// MEMC comms
|
||||
//**************************************************************************
|
||||
|
||||
void acorn_vidc10_device::write_dac(uint8_t channel, uint8_t data)
|
||||
{
|
||||
void acorn_vidc10_device::write_dac(u8 channel, u8 data)
|
||||
{
|
||||
int16_t res;
|
||||
res = m_ulaw_lookup[data];
|
||||
m_dac[channel & 7]->write(res);
|
||||
@ -424,7 +453,7 @@ void acorn_vidc10_device::refresh_sound_frequency()
|
||||
{
|
||||
// TODO: Range is between 3 and 256 usecs
|
||||
double sndhz = 1e6 / ((m_sound_frequency_latch & 0xff) + 2);
|
||||
sndhz /= 8.0;
|
||||
sndhz /= m_sound_internal_divider;
|
||||
m_sound_timer->adjust(attotime::zero, 0, attotime::from_hz(sndhz));
|
||||
//printf("VIDC: audio DMA start, sound freq %d, sndhz = %f\n", (m_crtc_regs[0xc0] & 0xff)-2, sndhz);
|
||||
}
|
||||
@ -436,9 +465,9 @@ void acorn_vidc10_device::refresh_sound_frequency()
|
||||
// Screen Update / VBlank / HBlank
|
||||
//**************************************************************************
|
||||
|
||||
void acorn_vidc10_device::draw(bitmap_rgb32 &bitmap, const rectangle &cliprect, u8 *vram, uint8_t bpp, int xstart, int ystart, int xsize, int ysize, bool is_cursor)
|
||||
void acorn_vidc10_device::draw(bitmap_rgb32 &bitmap, const rectangle &cliprect, u8 *vram, u8 bpp, int xstart, int ystart, int xsize, int ysize, bool is_cursor)
|
||||
{
|
||||
const u16 pen_base = (bpp == 3 ? 0 : 0x100) + (is_cursor == true ? 0x10 : 0);
|
||||
const u16 pen_base = (bpp == 3 ? 0 : m_pal_4bpp_base) + (is_cursor == true ? m_pal_cursor_base : 0);
|
||||
const u16 pen_masks[4] = { 1, 3, 0xf, 0xff };
|
||||
const u16 pen_mask = pen_masks[bpp];
|
||||
const u16 xchar_size = 1 << (3 - bpp);
|
||||
@ -476,14 +505,13 @@ u32 acorn_vidc10_device::screen_update(screen_device &screen, bitmap_rgb32 &bitm
|
||||
int xstart,ystart,xend,yend;
|
||||
int xsize,ysize;
|
||||
int calc_dxs = 0,calc_dxe = 0;
|
||||
const uint8_t x_step[4] = { 19, 11, 7, 5 };
|
||||
|
||||
/* border color */
|
||||
bitmap.fill(pen(0x110), cliprect);
|
||||
bitmap.fill(pen(m_pal_border_base), cliprect);
|
||||
|
||||
/* define X display area through BPP mode register */
|
||||
calc_dxs = (m_crtc_regs[CRTC_HDSR]*2)+x_step[m_bpp_mode & 3];
|
||||
calc_dxe = (m_crtc_regs[CRTC_HDER]*2)+x_step[m_bpp_mode & 3];
|
||||
calc_dxs = m_crtc_regs[CRTC_HDSR];
|
||||
calc_dxe = m_crtc_regs[CRTC_HDER];
|
||||
|
||||
/* now calculate display clip rectangle start/end areas */
|
||||
xstart = (calc_dxs)-m_crtc_regs[CRTC_HBSR];
|
||||
@ -501,7 +529,7 @@ u32 acorn_vidc10_device::screen_update(screen_device &screen, bitmap_rgb32 &bitm
|
||||
if (xsize <= 0 || ysize <= 0)
|
||||
return 0;
|
||||
|
||||
draw(bitmap, cliprect, m_data_vram, m_bpp_mode, xstart, ystart, xsize, ysize, false);
|
||||
draw(bitmap, cliprect, m_data_vram.get(), m_bpp_mode, xstart, ystart, xsize, ysize, false);
|
||||
if (m_cursor_enable == true)
|
||||
{
|
||||
xstart = m_crtc_regs[CRTC_HCSR] - m_crtc_regs[CRTC_HBSR];
|
||||
@ -509,7 +537,7 @@ u32 acorn_vidc10_device::screen_update(screen_device &screen, bitmap_rgb32 &bitm
|
||||
xsize = 32;
|
||||
ysize = m_crtc_regs[CRTC_VCER] - m_crtc_regs[CRTC_VCSR];
|
||||
if (ysize > 0)
|
||||
draw(bitmap, cliprect, m_cursor_vram, 1, xstart, ystart, xsize, ysize, true);
|
||||
draw(bitmap, cliprect, m_cursor_vram.get(), 1, xstart, ystart, xsize, ysize, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -518,6 +546,232 @@ u32 acorn_vidc10_device::screen_update(screen_device &screen, bitmap_rgb32 &bitm
|
||||
READ_LINE_MEMBER(acorn_vidc10_device::flyback_r )
|
||||
{
|
||||
int vert_pos = screen().vpos();
|
||||
bool flyback = (vert_pos <= m_crtc_regs[CRTC_VDSR] || vert_pos >= m_crtc_regs[CRTC_VDER]);
|
||||
return flyback;
|
||||
if (vert_pos <= m_crtc_regs[CRTC_VDSR] * (m_crtc_interlace+1))
|
||||
return true;
|
||||
|
||||
if (vert_pos >= m_crtc_regs[CRTC_VDER] * (m_crtc_interlace+1))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// VIDC20
|
||||
|
||||
void arm_vidc20_device::regs_map(address_map &map)
|
||||
{
|
||||
map(0x00, 0x0f).w(FUNC(arm_vidc20_device::vidc20_pal_data_display_w));
|
||||
map(0x10, 0x1f).w(FUNC(arm_vidc20_device::vidc20_pal_data_index_w));
|
||||
map(0x40, 0x7f).w(FUNC(arm_vidc20_device::vidc20_pal_data_cursor_w));
|
||||
map(0x80, 0x9f).w(FUNC(arm_vidc20_device::vidc20_crtc_w));
|
||||
map(0xb0, 0xb0).w(FUNC(arm_vidc20_device::vidc20_sound_frequency_w));
|
||||
map(0xb1, 0xb1).w(FUNC(arm_vidc20_device::vidc20_sound_control_w));
|
||||
map(0xd0, 0xdf).w(FUNC(arm_vidc20_device::fsynreg_w));
|
||||
map(0xe0, 0xef).w(FUNC(arm_vidc20_device::vidc20_control_w));
|
||||
}
|
||||
|
||||
arm_vidc20_device::arm_vidc20_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: acorn_vidc10_device(mconfig, ARM_VIDC20, tag, owner, clock)
|
||||
{
|
||||
m_space_config = address_space_config("regs_space", ENDIANNESS_LITTLE, 32, 8, -2, address_map_constructor(FUNC(arm_vidc20_device::regs_map), this));
|
||||
m_pal_4bpp_base = 0x000;
|
||||
m_pal_cursor_base = 0x100;
|
||||
m_pal_border_base = 0x100;
|
||||
}
|
||||
|
||||
|
||||
void arm_vidc20_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
acorn_vidc10_device::device_add_mconfig(config);
|
||||
// ...
|
||||
// TODO: for simplicity we may as well add separate DACs for 32-bit mode
|
||||
}
|
||||
|
||||
void arm_vidc20_device::device_config_complete()
|
||||
{
|
||||
if (!has_screen())
|
||||
return;
|
||||
|
||||
if (!screen().refresh_attoseconds())
|
||||
screen().set_raw(clock() * 2 / 3, 1024,0,735, 624/2,0,292); // RiscOS 3 default screen settings
|
||||
|
||||
if (!screen().has_screen_update())
|
||||
screen().set_screen_update(*this, FUNC(arm_vidc20_device::screen_update));
|
||||
}
|
||||
|
||||
u32 arm_vidc20_device::palette_entries() const
|
||||
{
|
||||
return 0x100+4; // 8bpp + 2bpp for cursor
|
||||
}
|
||||
|
||||
void arm_vidc20_device::device_start()
|
||||
{
|
||||
acorn_vidc10_device::device_start();
|
||||
|
||||
save_item(NAME(m_vco_r_modulo));
|
||||
save_item(NAME(m_vco_v_modulo));
|
||||
save_item(NAME(m_pal_data_index));
|
||||
save_item(NAME(m_dac_serial_mode));
|
||||
save_item(NAME(m_pixel_source));
|
||||
save_item(NAME(m_pixel_rate));
|
||||
}
|
||||
|
||||
void arm_vidc20_device::device_reset()
|
||||
{
|
||||
acorn_vidc10_device::device_reset();
|
||||
|
||||
// TODO: sensible defaults
|
||||
m_vco_r_modulo = 1;
|
||||
m_vco_v_modulo = 1;
|
||||
}
|
||||
|
||||
void arm_vidc20_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
acorn_vidc10_device::device_timer(timer, id, param, ptr);
|
||||
}
|
||||
|
||||
inline void arm_vidc20_device::update_8bpp_palette(u16 index, u32 paldata)
|
||||
{
|
||||
int r,g,b;
|
||||
|
||||
// TODO: ext hookup, supremacy plus other stuff according to the manual
|
||||
// ext = (paldata & 0x0f000000) >> 24;
|
||||
b = (paldata & 0x00ff0000) >> 16;
|
||||
g = (paldata & 0x0000ff00) >> 8;
|
||||
r = (paldata & 0x000000ff) >> 0;
|
||||
|
||||
set_pen_color(index, r, g, b );
|
||||
screen().update_partial(screen().vpos());
|
||||
}
|
||||
|
||||
WRITE32_MEMBER(arm_vidc20_device::vidc20_pal_data_display_w)
|
||||
{
|
||||
u8 ext_data = offset & 0xf;
|
||||
update_8bpp_palette(m_pal_data_index, (ext_data<<24) | data);
|
||||
m_pal_data_index ++;
|
||||
m_pal_data_index &= 0xff;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( arm_vidc20_device::vidc20_pal_data_index_w )
|
||||
{
|
||||
m_pal_data_index = data & 0xff;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( arm_vidc20_device::vidc20_pal_data_cursor_w )
|
||||
{
|
||||
u8 ext_data = offset & 0xf;
|
||||
u8 cursor_pal_index = (offset >> 4) & 3;
|
||||
update_8bpp_palette(m_pal_cursor_base + cursor_pal_index, (ext_data<<24) | data);
|
||||
}
|
||||
|
||||
u32 arm_vidc20_device::get_pixel_clock()
|
||||
{
|
||||
// RCLK source: passes thru a r-modulus and a phase frequency (PCOMP), the full story is interesting if you're into maths.
|
||||
// TODO: for now we just multiply source clock by 2, enough for ssfindo.cpp games.
|
||||
//printf("%d %02x %02x %d %d\n",this->clock(), 1 << m_pixel_rate, m_pixel_source, m_vco_v_modulo, m_vco_r_modulo);
|
||||
if (m_pixel_source == 2) // RCLK
|
||||
return (this->clock() << 1) >> m_pixel_rate;
|
||||
|
||||
// VCLK source is just an external connection
|
||||
// TODO: get clock from outside world, understand how the modulos are really used,
|
||||
// understand if SW do some VCO testing before setting CRTC params,
|
||||
// if there isn't a monitor ID mechanism that copes with this
|
||||
if (m_pixel_source == 0) // VCLK
|
||||
return (25175000);
|
||||
|
||||
throw emu_fatalerror("%s unhandled pixel source %02x selected",this->tag(), m_pixel_source);
|
||||
}
|
||||
|
||||
WRITE32_MEMBER(arm_vidc20_device::vidc20_crtc_w)
|
||||
{
|
||||
if (offset & 0x8)
|
||||
throw emu_fatalerror("%s accessing CRTC test register %02x, please call the ambulance",this->tag(),offset+0x80);
|
||||
|
||||
const u8 crtc_offset = (offset & 0x7) | ((offset & 0x10) >> 1);
|
||||
|
||||
switch(crtc_offset)
|
||||
{
|
||||
case CRTC_HCR: m_crtc_regs[CRTC_HCR] = (data&0x7ffc) + 8; break;
|
||||
case CRTC_HSWR: m_crtc_regs[CRTC_HSWR] = (data&0x7ffe) + 8; break;
|
||||
case CRTC_HBSR: m_crtc_regs[CRTC_HBSR] = (data&0x7ffe) + 12; break;
|
||||
case CRTC_HDSR: m_crtc_regs[CRTC_HDSR] = (data&0x7ffe) + 18; break;
|
||||
case CRTC_HDER: m_crtc_regs[CRTC_HDER] = (data&0x7ffe) + 18; break;
|
||||
case CRTC_HBER: m_crtc_regs[CRTC_HBER] = (data&0x7ffe) + 12; break;
|
||||
case CRTC_HCSR: m_crtc_regs[CRTC_HCSR] = (data&0x7fff) + 17; return;
|
||||
// case CRTC_HIR:
|
||||
case CRTC_VCR: m_crtc_regs[CRTC_VCR] = (data&0x3fff) + 2; break;
|
||||
case CRTC_VSWR: m_crtc_regs[CRTC_VSWR] = (data&0x3fff) + 1; break;
|
||||
case CRTC_VBSR: m_crtc_regs[CRTC_VBSR] = (data&0x3fff) + 1; break;
|
||||
case CRTC_VDSR: m_crtc_regs[CRTC_VDSR] = (data&0x3fff) + 1; break;
|
||||
case CRTC_VDER:
|
||||
m_crtc_regs[CRTC_VDER] = (data&0x3fff) + 1;
|
||||
screen_vblank_line_update();
|
||||
break;
|
||||
case CRTC_VBER: m_crtc_regs[CRTC_VBER] = (data&0x3fff) + 1; break;
|
||||
// TODO: bits 15-14 specific for duplex LCD mode
|
||||
case CRTC_VCSR:
|
||||
m_crtc_regs[CRTC_VCSR] = (data&0x3fff) + 1;
|
||||
return;
|
||||
case CRTC_VCER: m_crtc_regs[CRTC_VCER] = (data&0x3fff) + 1; return;
|
||||
}
|
||||
|
||||
screen_dynamic_res_change();
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( arm_vidc20_device::fsynreg_w )
|
||||
{
|
||||
m_vco_r_modulo = data & 0x3f;
|
||||
m_vco_v_modulo = (data >> 8) & 0x3f;
|
||||
// bits 15-14 and 7-6 are test bits
|
||||
|
||||
screen_dynamic_res_change();
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( arm_vidc20_device::vidc20_control_w )
|
||||
{
|
||||
// ---- --00: VCLK
|
||||
// ---- --01: HCLK
|
||||
// ---- --10: RCLK ("recommended" 24 MHz)
|
||||
// ---- --11: undefined, prolly same as RCLK
|
||||
m_pixel_source = data & 3;
|
||||
m_pixel_rate = (data & 0x1c) >> 2;
|
||||
// (data & 0x700) >> 8 FIFO load
|
||||
// BIT(data, 13) enables Duplex LCD mode
|
||||
// BIT(data, 14) power down
|
||||
// (data & 0xf0000) >> 16 test mode
|
||||
m_bpp_mode = (data & 0xe0) >> 5;
|
||||
m_crtc_interlace = BIT(data, 12);
|
||||
|
||||
screen_vblank_line_update();
|
||||
screen_dynamic_res_change();
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( arm_vidc20_device::vidc20_sound_control_w )
|
||||
{
|
||||
// TODO: VIDC10 mode, ext clock bit 0
|
||||
m_dac_serial_mode = BIT(data, 1);
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( arm_vidc20_device::vidc20_sound_frequency_w )
|
||||
{
|
||||
m_sound_frequency_latch = data & 0xff;
|
||||
if (m_sound_mode == true)
|
||||
refresh_sound_frequency();
|
||||
}
|
||||
|
||||
void arm_vidc20_device::write_dac32(u8 channel, u16 data)
|
||||
{
|
||||
m_dac[channel & 1]->write(data);
|
||||
}
|
||||
|
||||
bool arm_vidc20_device::get_dac_mode()
|
||||
{
|
||||
return m_dac_serial_mode;
|
||||
}
|
||||
|
||||
u32 arm_vidc20_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
// TODO: support for true color modes
|
||||
return acorn_vidc10_device::screen_update(screen, bitmap, cliprect);
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,7 +34,7 @@ class acorn_vidc10_device : public device_t,
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
acorn_vidc10_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
acorn_vidc10_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
// I/O operations
|
||||
DECLARE_WRITE32_MEMBER( write );
|
||||
@ -42,36 +42,60 @@ public:
|
||||
auto vblank() { return m_vblank_cb.bind(); }
|
||||
auto sound_drq() { return m_sound_drq_cb.bind(); }
|
||||
// MEMC comms
|
||||
void write_vram(uint32_t offset, uint8_t data) { m_data_vram[offset & (m_data_vram_mask)] = data; }
|
||||
void write_cram(uint32_t offset, uint8_t data) { m_cursor_vram[offset & (m_cursor_vram_mask)] = data; }
|
||||
void write_dac(uint8_t channel, uint8_t data);
|
||||
void clear_dac(uint8_t channel) { m_dac[channel & 7]->write(0); }
|
||||
void write_vram(u32 offset, u8 data) { m_data_vram[offset & (m_data_vram_mask)] = data; }
|
||||
void write_cram(u32 offset, u8 data) { m_cursor_vram[offset & (m_cursor_vram_mask)] = data; }
|
||||
void write_dac(u8 channel, u8 data);
|
||||
void clear_dac(u8 channel) { m_dac[channel & 7]->write(0); }
|
||||
void update_sound_mode(bool state) { m_sound_mode = state; refresh_sound_frequency(); }
|
||||
void set_cursor_enable(bool state) { m_cursor_enable = state; }
|
||||
uint32_t get_cursor_size() { return (m_crtc_regs[CRTC_VCER] - m_crtc_regs[CRTC_VCSR]) * (32/4); }
|
||||
|
||||
u32 get_cursor_size() { return (m_crtc_regs[CRTC_VCER] - m_crtc_regs[CRTC_VCSR]) * (32/4); }
|
||||
|
||||
protected:
|
||||
acorn_vidc10_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
// device-level overrides
|
||||
//virtual void device_validity_check(validity_checker &valid) const override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
virtual uint32_t palette_entries() const override;
|
||||
virtual u32 palette_entries() const override;
|
||||
virtual void device_config_complete() 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;
|
||||
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
virtual u32 get_pixel_clock();
|
||||
|
||||
private:
|
||||
const address_space_config m_space_config;
|
||||
|
||||
address_space_config m_space_config;
|
||||
void regs_map(address_map &map);
|
||||
|
||||
enum {
|
||||
CRTC_HCR = 0, CRTC_HSWR, CRTC_HBSR, CRTC_HDSR, CRTC_HDER, CRTC_HBER, CRTC_HCSR, CRTC_HIR,
|
||||
CRTC_VCR, CRTC_VSWR, CRTC_VBSR, CRTC_VDSR, CRTC_VDER, CRTC_VBER, CRTC_VCSR, CRTC_VCER
|
||||
};
|
||||
u32 m_crtc_regs[16];
|
||||
enum {
|
||||
TIMER_VIDEO = 1,
|
||||
TIMER_SOUND = 2
|
||||
};
|
||||
|
||||
inline void screen_vblank_line_update();
|
||||
inline void screen_dynamic_res_change();
|
||||
void refresh_sound_frequency();
|
||||
|
||||
u16 m_pal_4bpp_base;
|
||||
u16 m_pal_cursor_base;
|
||||
u16 m_pal_border_base;
|
||||
const double m_sound_internal_divider = 8.0;
|
||||
|
||||
u8 m_bpp_mode, m_crtc_interlace;
|
||||
u8 m_sound_frequency_latch;
|
||||
bool m_sound_mode;
|
||||
|
||||
required_device_array<dac_16bit_r2r_twos_complement_device, 8> m_dac;
|
||||
|
||||
private:
|
||||
required_device<speaker_device> m_lspeaker;
|
||||
required_device<speaker_device> m_rspeaker;
|
||||
required_device_array<dac_16bit_r2r_twos_complement_device, 8> m_dac;
|
||||
devcb_write_line m_vblank_cb;
|
||||
devcb_write_line m_sound_drq_cb;
|
||||
|
||||
@ -81,51 +105,38 @@ private:
|
||||
DECLARE_WRITE32_MEMBER( crtc_w );
|
||||
DECLARE_WRITE32_MEMBER( sound_frequency_w );
|
||||
DECLARE_WRITE32_MEMBER( control_w );
|
||||
|
||||
uint8_t m_pixel_clock, m_bpp_mode, m_crtc_interlace;
|
||||
|
||||
u8 m_pixel_clock;
|
||||
bool m_cursor_enable;
|
||||
//bool m_flyback;
|
||||
enum {
|
||||
TIMER_VIDEO = 1,
|
||||
TIMER_SOUND = 2
|
||||
};
|
||||
emu_timer *m_video_timer;
|
||||
emu_timer *m_sound_timer;
|
||||
|
||||
inline void screen_vblank_line_update();
|
||||
void screen_dynamic_res_change();
|
||||
|
||||
enum {
|
||||
CRTC_HCR = 0, CRTC_HSWR, CRTC_HBSR, CRTC_HDSR, CRTC_HDER, CRTC_HBER, CRTC_HCSR, CRTC_HIR,
|
||||
CRTC_VCR, CRTC_VSWR, CRTC_VBSR, CRTC_VDSR, CRTC_VDER, CRTC_VBER, CRTC_VCSR, CRTC_VCER
|
||||
};
|
||||
uint32_t m_crtc_regs[16];
|
||||
u8 *m_data_vram;
|
||||
u8 *m_cursor_vram;
|
||||
|
||||
std::unique_ptr<u8[]> m_data_vram;
|
||||
std::unique_ptr<u8[]> m_cursor_vram;
|
||||
// TODO: correct data vram size
|
||||
const u32 m_data_vram_mask = 0x1fffff;
|
||||
const u32 m_cursor_vram_mask = 0x7fff;
|
||||
const u32 m_data_vram_size = m_data_vram_mask+1;
|
||||
const u32 m_cursor_vram_size = m_cursor_vram_mask+1;
|
||||
bool m_cursor_enable;
|
||||
void draw(bitmap_rgb32 &bitmap, const rectangle &cliprect, u8 *vram, uint8_t bpp, int xstart, int ystart, int xsize, int ysize, bool is_cursor);
|
||||
inline void update_4bpp_palette(uint16_t index, uint32_t paldata);
|
||||
void draw(bitmap_rgb32 &bitmap, const rectangle &cliprect, u8 *vram, u8 bpp, int xstart, int ystart, int xsize, int ysize, bool is_cursor);
|
||||
inline void update_4bpp_palette(u16 index, u32 paldata);
|
||||
u32 m_crtc_raw_horz[2];
|
||||
inline u32 convert_crtc_hdisplay(u8 index);
|
||||
|
||||
u8 m_sound_frequency_latch;
|
||||
bool m_sound_frequency_test_bit;
|
||||
bool m_sound_mode;
|
||||
bool m_sound_frequency_test_bit;
|
||||
u8 m_stereo_image[8];
|
||||
const float m_sound_input_gain = 0.05f;
|
||||
const int m_sound_max_channels = 8;
|
||||
int16_t m_ulaw_lookup[256];
|
||||
void refresh_sound_frequency();
|
||||
inline void refresh_stereo_image(uint8_t channel);
|
||||
inline void refresh_stereo_image(u8 channel);
|
||||
};
|
||||
|
||||
class acorn_vidc10_lcd_device : public acorn_vidc10_device
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
acorn_vidc10_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
acorn_vidc10_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
protected:
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
};
|
||||
@ -134,6 +145,48 @@ protected:
|
||||
DECLARE_DEVICE_TYPE(ACORN_VIDC10, acorn_vidc10_device)
|
||||
DECLARE_DEVICE_TYPE(ACORN_VIDC10_LCD, acorn_vidc10_lcd_device)
|
||||
|
||||
class arm_vidc20_device : public acorn_vidc10_device
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
arm_vidc20_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
void write_dac32(u8 channel, u16 data);
|
||||
bool get_dac_mode();
|
||||
|
||||
protected:
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
void regs_map(address_map &map);
|
||||
virtual u32 palette_entries() const override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_config_complete() override;
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
virtual u32 get_pixel_clock() override;
|
||||
|
||||
const double m_sound_internal_divider = 1.0;
|
||||
|
||||
private:
|
||||
DECLARE_WRITE32_MEMBER( vidc20_pal_data_display_w );
|
||||
DECLARE_WRITE32_MEMBER( vidc20_pal_data_index_w );
|
||||
DECLARE_WRITE32_MEMBER( vidc20_pal_data_cursor_w );
|
||||
DECLARE_WRITE32_MEMBER( vidc20_crtc_w );
|
||||
DECLARE_WRITE32_MEMBER( vidc20_control_w );
|
||||
DECLARE_WRITE32_MEMBER( vidc20_sound_frequency_w );
|
||||
DECLARE_WRITE32_MEMBER( vidc20_sound_control_w );
|
||||
DECLARE_WRITE32_MEMBER( fsynreg_w );
|
||||
|
||||
u8 m_pal_data_index;
|
||||
inline void update_8bpp_palette(u16 index, u32 paldata);
|
||||
bool m_dac_serial_mode;
|
||||
u8 m_pixel_source;
|
||||
u8 m_pixel_rate;
|
||||
u8 m_vco_r_modulo;
|
||||
u8 m_vco_v_modulo;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(ARM_VIDC20, arm_vidc20_device)
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
|
767
src/devices/machine/arm_iomd.cpp
Normal file
767
src/devices/machine/arm_iomd.cpp
Normal file
@ -0,0 +1,767 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Angelo Salese
|
||||
/**************************************************************************************************
|
||||
|
||||
ARM IOMD device emulation
|
||||
|
||||
ARM7 SoC or stand-alone device, upgraded version(s) of the IOC found in Acorn Archimedes.
|
||||
|
||||
TODO:
|
||||
- IOCR / IOLINES hookups can be further improved, also DDR bits needs verifying;
|
||||
- word-boundary accesses for 8-bit ports;
|
||||
- split into different types, add quick notes about where they diverges do in this header;
|
||||
- keyboard/mouse interface hookup is wrong for PS/2 and unimplemented for quadrature.
|
||||
I guess we can use connectors over a custom handling, with a terminal mock for testing it
|
||||
without the overhead of everything else.
|
||||
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "arm_iomd.h"
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
//**************************************************************************
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(ARM_IOMD, arm_iomd_device, "arm_iomd", "ARM IOMD controller")
|
||||
// TODO: ssfindo.cpp actually uses a Cirrus Logic 7500FE, is it rebadged?
|
||||
DEFINE_DEVICE_TYPE(ARM7500FE_IOMD, arm7500fe_iomd_device, "arm_7500FE_SoC", "ARM 7500FE SoC")
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// arm_iomd_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
void arm_iomd_device::base_map(address_map &map)
|
||||
{
|
||||
// I/O
|
||||
map(0x000, 0x003).rw(FUNC(arm_iomd_device::iocr_r), FUNC(arm_iomd_device::iocr_w));
|
||||
map(0x004, 0x007).rw(FUNC(arm_iomd_device::kbddat_r), FUNC(arm_iomd_device::kbddat_w));
|
||||
map(0x008, 0x00b).rw(FUNC(arm_iomd_device::kbdcr_r), FUNC(arm_iomd_device::kbdcr_w));
|
||||
|
||||
// interrupt A/B/fiq + master clock controls
|
||||
map(0x010, 0x013).r(FUNC(arm_iomd_device::irqst_r<IRQA>));
|
||||
map(0x014, 0x017).rw(FUNC(arm_iomd_device::irqrq_r<IRQA>), FUNC(arm_iomd_device::irqrq_w<IRQA>));
|
||||
map(0x018, 0x01b).rw(FUNC(arm_iomd_device::irqmsk_r<IRQA>), FUNC(arm_iomd_device::irqmsk_w<IRQA>));
|
||||
|
||||
map(0x020, 0x023).r(FUNC(arm_iomd_device::irqst_r<IRQB>));
|
||||
map(0x024, 0x027).rw(FUNC(arm_iomd_device::irqrq_r<IRQB>), FUNC(arm_iomd_device::irqrq_w<IRQB>));
|
||||
map(0x028, 0x02b).rw(FUNC(arm_iomd_device::irqmsk_r<IRQB>), FUNC(arm_iomd_device::irqmsk_w<IRQB>));
|
||||
|
||||
// map(0x030, 0x033).r(FUNC(arm_iomd_device::fiqst_r));
|
||||
// map(0x034, 0x037).rw(FUNC(arm_iomd_device::fiqrq_r), FUNC(arm_iomd_device::fiqrq_w));
|
||||
// map(0x038, 0x03b).rw(FUNC(arm_iomd_device::fiqmsk_r), FUNC(arm_iomd_device::fiqmsk_w));
|
||||
|
||||
// timers
|
||||
map(0x040, 0x043).rw(FUNC(arm_iomd_device::tNlow_r<0>), FUNC(arm_iomd_device::tNlow_w<0>));
|
||||
map(0x044, 0x047).rw(FUNC(arm_iomd_device::tNhigh_r<0>), FUNC(arm_iomd_device::tNhigh_w<0>));
|
||||
map(0x048, 0x04b).w(FUNC(arm_iomd_device::tNgo_w<0>));
|
||||
map(0x04c, 0x04f).w(FUNC(arm_iomd_device::tNlatch_w<0>));
|
||||
|
||||
map(0x050, 0x053).rw(FUNC(arm_iomd_device::tNlow_r<1>), FUNC(arm_iomd_device::tNlow_w<1>));
|
||||
map(0x054, 0x057).rw(FUNC(arm_iomd_device::tNhigh_r<1>), FUNC(arm_iomd_device::tNhigh_w<1>));
|
||||
map(0x058, 0x05b).w(FUNC(arm_iomd_device::tNgo_w<1>));
|
||||
map(0x05c, 0x05f).w(FUNC(arm_iomd_device::tNlatch_w<1>));
|
||||
// ROM control
|
||||
// map(0x080, 0x083).rw(FUNC(arm_iomd_device::romcr_r<0>), FUNC(arm_iomd_device::romcr_w<0>));
|
||||
// map(0x084, 0x087).rw(FUNC(arm_iomd_device::romcr_r<1>), FUNC(arm_iomd_device::romcr_w<1>));
|
||||
// map(0x08c, 0x08f).rw(FUNC(arm_iomd_device::refcr_r), FUNC(arm_iomd_device::refcr_w));
|
||||
|
||||
// device identifiers
|
||||
map(0x094, 0x097).r(FUNC(arm_iomd_device::id_r<0>));
|
||||
map(0x098, 0x09b).r(FUNC(arm_iomd_device::id_r<1>));
|
||||
map(0x09c, 0x09f).r(FUNC(arm_iomd_device::version_r));
|
||||
// mouse
|
||||
// map(0x0a0, 0x0a3) // ...
|
||||
|
||||
// I/O control
|
||||
// map(0x0c4, 0x0c7).rw(FUNC(arm_iomd_device::iotcr_r), FUNC(arm_iomd_device::iotcr_w));
|
||||
// map(0x0c8, 0x0cb).rw(FUNC(arm_iomd_device::ectcr_r), FUNC(arm_iomd_device::ectcr_w));
|
||||
// sound DMA
|
||||
// TODO: IOMD actually have a sd1* register, rework this
|
||||
map(0x180, 0x183).rw(FUNC(arm_iomd_device::sdcur_r<0>), FUNC(arm_iomd_device::sdcur_w<0>));
|
||||
map(0x184, 0x187).rw(FUNC(arm_iomd_device::sdend_r<0>), FUNC(arm_iomd_device::sdend_w<0>));
|
||||
map(0x188, 0x18b).rw(FUNC(arm_iomd_device::sdcur_r<1>), FUNC(arm_iomd_device::sdcur_w<1>));
|
||||
map(0x18c, 0x18f).rw(FUNC(arm_iomd_device::sdend_r<1>), FUNC(arm_iomd_device::sdend_w<1>));
|
||||
map(0x190, 0x193).rw(FUNC(arm_iomd_device::sdcr_r), FUNC(arm_iomd_device::sdcr_w));
|
||||
map(0x194, 0x197).r(FUNC(arm_iomd_device::sdst_r));
|
||||
|
||||
// video DMA
|
||||
// map(0x1c0, 0x1c3).rw(FUNC(arm_iomd_device::curscur_r), FUNC(arm_iomd_device::curscur_w));
|
||||
map(0x1c4, 0x1c7).rw(FUNC(arm_iomd_device::cursinit_r), FUNC(arm_iomd_device::cursinit_w));
|
||||
|
||||
// map(0x1d0, 0x1d3).rw(FUNC(arm_iomd_device::vidcura_r), FUNC(arm_iomd_device::vidcura_w));
|
||||
map(0x1d4, 0x1d7).rw(FUNC(arm_iomd_device::vidend_r), FUNC(arm_iomd_device::vidend_w));
|
||||
// map(0x1d8, 0x1db).rw(FUNC(arm_iomd_device::vidstart_r), FUNC(arm_iomd_device::vidstart_w));
|
||||
map(0x1dc, 0x1df).rw(FUNC(arm_iomd_device::vidinita_r), FUNC(arm_iomd_device::vidinita_w));
|
||||
map(0x1e0, 0x1e3).rw(FUNC(arm_iomd_device::vidcr_r), FUNC(arm_iomd_device::vidcr_w));
|
||||
|
||||
// interrupt DMA
|
||||
map(0x1f0, 0x1f3).r(FUNC(arm_iomd_device::irqst_r<IRQDMA>));
|
||||
map(0x1f4, 0x1f7).rw(FUNC(arm_iomd_device::irqrq_r<IRQDMA>), FUNC(arm_iomd_device::irqrq_w<IRQDMA>));
|
||||
map(0x1f8, 0x1fb).rw(FUNC(arm_iomd_device::irqmsk_r<IRQDMA>), FUNC(arm_iomd_device::irqmsk_w<IRQDMA>));
|
||||
|
||||
// TODO: iomd2 has extra regs in 0x200-0x3ff area, others NOPs / mirrors?
|
||||
}
|
||||
|
||||
void arm_iomd_device::map(address_map &map)
|
||||
{
|
||||
arm_iomd_device::base_map(map);
|
||||
// map(0x088, 0x08b).rw(FUNC(arm_iomd_device::dramcr_r), FUNC(arm_iomd_device::dramcr_w));
|
||||
// VRAM control
|
||||
// map(0x08c, 0x08f).rw(FUNC(arm_iomd_device::vrefcr_r), FUNC(arm_iomd_device::vrefcr_w));
|
||||
// flyback line size
|
||||
// map(0x090, 0x093).rw(FUNC(arm_iomd_device::fsize_r), FUNC(arm_iomd_device::fsize_w));
|
||||
// quadrature mouse control
|
||||
// map(0x0a0, 0x0a3).rw(FUNC(arm_iomd_device::mousex_r), FUNC(arm_iomd_device::mousex_w));
|
||||
// map(0x0a4, 0x0a7).rw(FUNC(arm_iomd_device::mousey_r), FUNC(arm_iomd_device::mousey_w));
|
||||
// DACK timing control
|
||||
// map(0x0c0, 0x0c3).rw(FUNC(arm_iomd_device::dmatcr_r), FUNC(arm_iomd_device::dmatcr_w));
|
||||
// DMA external control
|
||||
// map(0x0cc, 0x0cf).rw(FUNC(arm_iomd_device::dmaext_r), FUNC(arm_iomd_device::dmaext_w));
|
||||
// I/O DMA, similar structure as sound DMA
|
||||
// map(0x100, 0x11f) ch 0
|
||||
// map(0x120, 0x13f) ch 1
|
||||
// map(0x140, 0x15f) ch 2
|
||||
// map(0x160, 0x17f) ch 3
|
||||
// sound DMA
|
||||
// map(0x1a0, 0x1bf) ch 1
|
||||
|
||||
}
|
||||
|
||||
arm_iomd_device::arm_iomd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, type, tag, owner, clock)
|
||||
, m_host_cpu(*this, finder_base::DUMMY_TAG)
|
||||
, m_vidc(*this, finder_base::DUMMY_TAG)
|
||||
, m_kbdc(*this, finder_base::DUMMY_TAG)
|
||||
, m_iocr_read_od_cb{{*this}, {*this}}
|
||||
, m_iocr_write_od_cb{{*this}, {*this}}
|
||||
, m_iocr_read_id_cb(*this)
|
||||
, m_iocr_write_id_cb(*this)
|
||||
{
|
||||
}
|
||||
|
||||
arm_iomd_device::arm_iomd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: arm_iomd_device(mconfig, ARM_IOMD, tag, owner, clock)
|
||||
{
|
||||
m_id = 0xd4e7;
|
||||
m_version = 0;
|
||||
}
|
||||
|
||||
void arm7500fe_iomd_device::map(address_map &map)
|
||||
{
|
||||
arm_iomd_device::base_map(map);
|
||||
|
||||
map(0x00c, 0x00f).rw(FUNC(arm7500fe_iomd_device::iolines_r), FUNC(arm7500fe_iomd_device::iolines_w));
|
||||
// master clock controls
|
||||
// map(0x01c, 0x01f).rw(FUNC(arm7500fe_iomd_device::susmode_r), FUNC(arm7500fe_iomd_device::susmode_w));
|
||||
// map(0x02c, 0x02f).w(FUNC(arm7500fe_iomd_device::stopmode_w));
|
||||
map(0x03c, 0x03f).rw(FUNC(arm7500fe_iomd_device::clkctl_r), FUNC(arm7500fe_iomd_device::clkctl_w));
|
||||
// interrupt C/D
|
||||
map(0x060, 0x063).r(FUNC(arm7500fe_iomd_device::irqst_r<IRQC>));
|
||||
map(0x064, 0x067).rw(FUNC(arm7500fe_iomd_device::irqrq_r<IRQC>), FUNC(arm7500fe_iomd_device::irqrq_w<IRQC>));
|
||||
map(0x068, 0x06b).rw(FUNC(arm7500fe_iomd_device::irqmsk_r<IRQC>), FUNC(arm7500fe_iomd_device::irqmsk_w<IRQC>));
|
||||
// map(0x06c, 0x06f).rw(FUNC(arm7500fe_iomd_device::vidmux_r), FUNC(arm7500fe_iomd_device::vidmux_w));
|
||||
map(0x070, 0x073).r(FUNC(arm7500fe_iomd_device::irqst_r<IRQD>));
|
||||
map(0x074, 0x077).rw(FUNC(arm7500fe_iomd_device::irqrq_r<IRQD>), FUNC(arm7500fe_iomd_device::irqrq_w<IRQD>));
|
||||
map(0x078, 0x07b).rw(FUNC(arm7500fe_iomd_device::irqmsk_r<IRQD>), FUNC(arm7500fe_iomd_device::irqmsk_w<IRQD>));
|
||||
|
||||
// PS/2 mouse
|
||||
// map(0x0a8, 0x0ab).rw(FUNC(arm7500fe_iomd_device::msedat_r), FUNC(arm7500fe_iomd_device::msedat_w));
|
||||
map(0x0ac, 0x0af).rw(FUNC(arm7500fe_iomd_device::msecr_r), FUNC(arm7500fe_iomd_device::msecr_w));
|
||||
// I/O control
|
||||
// map(0x0cc, 0x0cf).rw(FUNC(arm7500fe_iomd_device::astcr_r), FUNC(arm7500fe_iomd_device::astcr_w));
|
||||
// RAM control
|
||||
// map(0x0d0, 0x0d3).rw(FUNC(arm7500fe_iomd_device::dramctl_r), FUNC(arm7500fe_iomd_device::dramctl_w));
|
||||
// map(0x0d4, 0x0d7).rw(FUNC(arm7500fe_iomd_device::selfref_r), FUNC(arm7500fe_iomd_device::selfref_w));
|
||||
// A/D converter
|
||||
// map(0x0e0, 0x0e3).rw(FUNC(arm7500fe_iomd_device::atodicr_r), FUNC(arm7500fe_iomd_device::atodicr_w));
|
||||
// map(0x0e4, 0x0e7).r(FUNC(arm7500fe_iomd_device::atodsr_r));
|
||||
// map(0x0e8, 0x0eb).rw(FUNC(arm7500fe_iomd_device::atodcc_r), FUNC(arm7500fe_iomd_device::atodcc_w));
|
||||
// map(0x0ec, 0x0ef).r(FUNC(arm7500fe_iomd_device::atodcnt_r<0>));
|
||||
// map(0x0f0, 0x0f3).r(FUNC(arm7500fe_iomd_device::atodcnt_r<1>));
|
||||
// map(0x0f4, 0x0f7).r(FUNC(arm7500fe_iomd_device::atodcnt_r<2>));
|
||||
// map(0x0f8, 0x0fb).r(FUNC(arm7500fe_iomd_device::atodcnt_r<3>));
|
||||
// video DMA
|
||||
// map(0x1c8, 0x1cb).rw(FUNC(arm7500fe_iomd_device::vidcurb_r), FUNC(arm7500fe_iomd_device::vidcurb_w));
|
||||
// map(0x1e8, 0x1eb).rw(FUNC(arm7500fe_iomd_device::vidinitb_r), FUNC(arm7500fe_iomd_device::vidinitb_w));
|
||||
|
||||
}
|
||||
|
||||
arm7500fe_iomd_device::arm7500fe_iomd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: arm_iomd_device(mconfig, ARM7500FE_IOMD, tag, owner, clock)
|
||||
, m_iolines_read_cb(*this)
|
||||
, m_iolines_write_cb(*this)
|
||||
{
|
||||
m_id = 0xaa7c;
|
||||
m_version = 0;
|
||||
}
|
||||
|
||||
// vanilla ARM7500 m_id = 0x5b98; m_version = 0;
|
||||
// IOMD2 m_id = 0xd5e8; m_version = 1;
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_add_mconfig - device-specific machine
|
||||
// configuration addiitons
|
||||
//-------------------------------------------------
|
||||
|
||||
void arm_iomd_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
//DEVICE(config, ...);
|
||||
//TODO: keyboard and mouse interfaces at very least, also they differs by device type
|
||||
}
|
||||
|
||||
void arm7500fe_iomd_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
//DEVICE(config, ...);
|
||||
//TODO: above plus new sub-devices
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void arm_iomd_device::device_start()
|
||||
{
|
||||
for (devcb_read_line &cb : m_iocr_read_od_cb)
|
||||
cb.resolve_safe(1);
|
||||
|
||||
for (devcb_write_line &cb : m_iocr_write_od_cb)
|
||||
cb.resolve_safe();
|
||||
|
||||
m_iocr_read_id_cb.resolve_safe(1);
|
||||
m_iocr_write_id_cb.resolve_safe();
|
||||
|
||||
save_item(NAME(m_iocr_ddr));
|
||||
save_item(NAME(m_video_enable));
|
||||
save_item(NAME(m_vidinita));
|
||||
save_item(NAME(m_vidend));
|
||||
save_item(NAME(m_vidlast));
|
||||
save_item(NAME(m_videqual));
|
||||
save_item(NAME(m_cursor_enable));
|
||||
save_item(NAME(m_cursinit));
|
||||
save_pointer(NAME(m_irq_mask), IRQ_SOURCES_SIZE);
|
||||
save_pointer(NAME(m_irq_status), IRQ_SOURCES_SIZE);
|
||||
|
||||
m_host_space = &m_host_cpu->space(AS_PROGRAM);
|
||||
|
||||
m_timer[0] = timer_alloc(T0_TIMER);
|
||||
m_timer[1] = timer_alloc(T1_TIMER);
|
||||
save_pointer(NAME(m_timer_in), timer_ch_size);
|
||||
save_pointer(NAME(m_timer_out), timer_ch_size);
|
||||
save_pointer(NAME(m_timer_counter), timer_ch_size);
|
||||
save_pointer(NAME(m_timer_readinc), timer_ch_size);
|
||||
|
||||
save_item(NAME(m_sndcur));
|
||||
save_item(NAME(m_sndend));
|
||||
save_item(NAME(m_sound_dma_on));
|
||||
save_item(NAME(m_sndcur_buffer));
|
||||
save_item(NAME(m_snd_overrun));
|
||||
save_item(NAME(m_snd_int));
|
||||
|
||||
save_pointer(NAME(m_sndcur_reg), sounddma_ch_size);
|
||||
save_pointer(NAME(m_sndend_reg), sounddma_ch_size);
|
||||
save_pointer(NAME(m_sndstop_reg), sounddma_ch_size);
|
||||
save_pointer(NAME(m_sndlast_reg), sounddma_ch_size);
|
||||
save_pointer(NAME(m_sndbuffer_ok), sounddma_ch_size);
|
||||
|
||||
// TODO: jumps to EASI space at $0c0016xx for RiscPC if POR is on?
|
||||
}
|
||||
|
||||
void arm7500fe_iomd_device::device_start()
|
||||
{
|
||||
arm_iomd_device::device_start();
|
||||
|
||||
m_iolines_read_cb.resolve_safe(0xff);
|
||||
m_iolines_write_cb.resolve_safe();
|
||||
save_item(NAME(m_iolines_ddr));
|
||||
|
||||
save_item(NAME(m_cpuclk_divider));
|
||||
save_item(NAME(m_memclk_divider));
|
||||
save_item(NAME(m_ioclk_divider));
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void arm_iomd_device::device_reset()
|
||||
{
|
||||
int i;
|
||||
m_iocr_ddr = 0x0b;
|
||||
m_video_enable = false;
|
||||
// TODO: defaults for these
|
||||
m_vidinita = 0;
|
||||
m_vidend = 0;
|
||||
|
||||
for (i=0; i<IRQ_SOURCES_SIZE; i++)
|
||||
{
|
||||
m_irq_status[i] = 0;
|
||||
m_irq_mask[i] = 0;
|
||||
}
|
||||
|
||||
for (i=0; i<timer_ch_size; i++)
|
||||
m_timer[i]->adjust(attotime::never);
|
||||
|
||||
m_sound_dma_on = false;
|
||||
for (i=0; i<sounddma_ch_size; i++)
|
||||
m_sndbuffer_ok[i] = false;
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
void arm7500fe_iomd_device::device_reset()
|
||||
{
|
||||
arm_iomd_device::device_reset();
|
||||
|
||||
m_cpuclk_divider = m_ioclk_divider = m_memclk_divider = false;
|
||||
refresh_host_cpu_clocks();
|
||||
|
||||
m_iolines_ddr = 0xff;
|
||||
}
|
||||
|
||||
void arm_iomd_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
switch(id)
|
||||
{
|
||||
case T0_TIMER:
|
||||
case T1_TIMER:
|
||||
trigger_irq<IRQA>(id == T1_TIMER ? 0x40 : 0x20);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// READ/WRITE HANDLERS
|
||||
//**************************************************************************
|
||||
|
||||
// TODO: nINT1
|
||||
READ32_MEMBER( arm_iomd_device::iocr_r )
|
||||
{
|
||||
u8 res = 0;
|
||||
|
||||
res = m_iocr_read_id_cb() << 3;
|
||||
res|= m_iocr_read_od_cb[1]() << 1;
|
||||
res|= m_iocr_read_od_cb[0]() << 0;
|
||||
|
||||
return (m_vidc->flyback_r() << 7) | 0x34 | (res & m_iocr_ddr);
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( arm_iomd_device::iocr_w )
|
||||
{
|
||||
m_iocr_ddr = (data & 0x0b);
|
||||
m_iocr_write_id_cb(BIT(m_iocr_ddr,3));
|
||||
m_iocr_write_od_cb[1](BIT(m_iocr_ddr,1));
|
||||
m_iocr_write_od_cb[0](BIT(m_iocr_ddr,0));
|
||||
}
|
||||
|
||||
READ32_MEMBER( arm_iomd_device::kbddat_r )
|
||||
{
|
||||
if (m_kbdc.found())
|
||||
return m_kbdc->data_r();
|
||||
|
||||
logerror("%s attempted to read kbddat with no controller\n", this->tag());
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
READ32_MEMBER( arm_iomd_device::kbdcr_r )
|
||||
{
|
||||
if (m_kbdc.found())
|
||||
return m_kbdc->status_r();
|
||||
|
||||
logerror("%s attempted to read kbdcr with no controller\n", this->tag());
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( arm_iomd_device::kbddat_w )
|
||||
{
|
||||
if (m_kbdc.found())
|
||||
{
|
||||
m_kbdc->data_w(data & 0xff);
|
||||
return;
|
||||
}
|
||||
|
||||
logerror("%s attempted to write %02x on kbddat with no controller\n", this->tag(),data & 0xff);
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( arm_iomd_device::kbdcr_w )
|
||||
{
|
||||
if (m_kbdc.found())
|
||||
{
|
||||
m_kbdc->command_w(data & 0xff);
|
||||
return;
|
||||
}
|
||||
|
||||
logerror("%s attempted to write %02x on kbdcr with no controller\n", this->tag(),data & 0xff);
|
||||
}
|
||||
|
||||
READ32_MEMBER( arm7500fe_iomd_device::msecr_r )
|
||||
{
|
||||
// a7000p wants a TX empty otherwise it outright refuses to boot.
|
||||
return 0x80;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( arm7500fe_iomd_device::msecr_w )
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
READ32_MEMBER( arm7500fe_iomd_device::iolines_r )
|
||||
{
|
||||
return m_iolines_read_cb() & m_iolines_ddr;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( arm7500fe_iomd_device::iolines_w )
|
||||
{
|
||||
m_iolines_ddr = data;
|
||||
m_iolines_write_cb(m_iolines_ddr);
|
||||
}
|
||||
|
||||
// irqA is special since it has a force (7) and ignore (1) bits
|
||||
inline u8 arm_iomd_device::update_irqa_type(u8 data)
|
||||
{
|
||||
return (data & 0xfd) | 0x80;
|
||||
}
|
||||
|
||||
// interrupts
|
||||
|
||||
inline void arm_iomd_device::flush_irq(unsigned Which)
|
||||
{
|
||||
if (m_irq_status[Which] & m_irq_mask[Which])
|
||||
m_host_cpu->pulse_input_line(ARM7_IRQ_LINE, m_host_cpu->minimum_quantum_time());
|
||||
}
|
||||
|
||||
template <unsigned Which> inline void arm_iomd_device::trigger_irq(u8 irq_type)
|
||||
{
|
||||
m_irq_status[Which] |= irq_type;
|
||||
flush_irq(Which);
|
||||
}
|
||||
|
||||
template <unsigned Which> READ32_MEMBER( arm_iomd_device::irqst_r )
|
||||
{
|
||||
return m_irq_status[Which];
|
||||
}
|
||||
|
||||
template <unsigned Which> READ32_MEMBER( arm_iomd_device::irqrq_r )
|
||||
{
|
||||
return m_irq_status[Which] & m_irq_mask[Which];
|
||||
}
|
||||
|
||||
template <unsigned Which> READ32_MEMBER( arm_iomd_device::irqmsk_r )
|
||||
{
|
||||
return m_irq_mask[Which];
|
||||
}
|
||||
|
||||
template <unsigned Which> WRITE32_MEMBER( arm_iomd_device::irqrq_w )
|
||||
{
|
||||
u8 res = m_irq_status[Which] & ~data;
|
||||
if (Which == IRQA)
|
||||
res = update_irqa_type(res);
|
||||
m_irq_status[Which] = res;
|
||||
flush_irq(Which);
|
||||
}
|
||||
|
||||
template <unsigned Which> WRITE32_MEMBER( arm_iomd_device::irqmsk_w )
|
||||
{
|
||||
m_irq_mask[Which] = data & 0xff;
|
||||
flush_irq(Which);
|
||||
}
|
||||
|
||||
// master clock control
|
||||
inline void arm7500fe_iomd_device::refresh_host_cpu_clocks()
|
||||
{
|
||||
m_host_cpu->set_unscaled_clock(this->clock() >> (m_cpuclk_divider == false));
|
||||
}
|
||||
|
||||
READ32_MEMBER( arm7500fe_iomd_device::clkctl_r )
|
||||
{
|
||||
return (m_cpuclk_divider << 2) | (m_memclk_divider << 1) | (m_ioclk_divider);
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( arm7500fe_iomd_device::clkctl_w )
|
||||
{
|
||||
m_cpuclk_divider = BIT(data, 2);
|
||||
m_memclk_divider = BIT(data, 1);
|
||||
m_ioclk_divider = BIT(data, 0);
|
||||
refresh_host_cpu_clocks();
|
||||
}
|
||||
|
||||
// timers
|
||||
inline void arm_iomd_device::trigger_timer(unsigned Which)
|
||||
{
|
||||
int timer_count = m_timer_counter[Which];
|
||||
// TODO: it's actually a 2 MHz timer
|
||||
int val = timer_count / 2;
|
||||
|
||||
if(val==0)
|
||||
m_timer[Which]->adjust(attotime::never);
|
||||
else
|
||||
m_timer[Which]->adjust(attotime::from_usec(val), 0, attotime::from_usec(val));
|
||||
}
|
||||
|
||||
// TODO: live updates aren't really supported here
|
||||
template <unsigned Which> READ32_MEMBER( arm_iomd_device::tNlow_r )
|
||||
{
|
||||
return m_timer_out[Which] & 0xff;
|
||||
}
|
||||
|
||||
template <unsigned Which> READ32_MEMBER( arm_iomd_device::tNhigh_r )
|
||||
{
|
||||
return (m_timer_out[Which] >> 8) & 0xff;
|
||||
}
|
||||
|
||||
template <unsigned Which> WRITE32_MEMBER( arm_iomd_device::tNlow_w )
|
||||
{
|
||||
m_timer_in[Which] = (m_timer_in[Which] & 0xff00) | (data & 0xff);
|
||||
}
|
||||
|
||||
template <unsigned Which> WRITE32_MEMBER( arm_iomd_device::tNhigh_w )
|
||||
{
|
||||
m_timer_in[Which] = (m_timer_in[Which] & 0x00ff) | ((data & 0xff) << 8);
|
||||
}
|
||||
|
||||
template <unsigned Which> WRITE32_MEMBER( arm_iomd_device::tNgo_w )
|
||||
{
|
||||
m_timer_counter[Which] = m_timer_in[Which];
|
||||
trigger_timer(Which);
|
||||
}
|
||||
|
||||
template <unsigned Which> WRITE32_MEMBER( arm_iomd_device::tNlatch_w )
|
||||
{
|
||||
m_timer_readinc[Which] ^=1;
|
||||
m_timer_out[Which] = m_timer_counter[Which];
|
||||
if(m_timer_readinc[Which])
|
||||
{
|
||||
m_timer_counter[Which]--;
|
||||
if(m_timer_counter[Which] < 0)
|
||||
m_timer_counter[Which] += m_timer_in[Which];
|
||||
}
|
||||
}
|
||||
|
||||
// device identifiers
|
||||
template <unsigned Nibble> READ32_MEMBER( arm_iomd_device::id_r )
|
||||
{
|
||||
return (m_id >> (Nibble*8)) & 0xff;
|
||||
}
|
||||
|
||||
READ32_MEMBER( arm_iomd_device::version_r )
|
||||
{
|
||||
return m_version;
|
||||
}
|
||||
|
||||
DECLARE_READ32_MEMBER( version_r );
|
||||
|
||||
// sound DMA
|
||||
|
||||
template <unsigned Which> READ32_MEMBER( arm_iomd_device::sdcur_r ) { return m_sndcur_reg[Which]; }
|
||||
template <unsigned Which> WRITE32_MEMBER( arm_iomd_device::sdcur_w ) { COMBINE_DATA(&m_sndcur_reg[Which]); }
|
||||
template <unsigned Which> READ32_MEMBER( arm_iomd_device::sdend_r )
|
||||
{
|
||||
return (m_sndstop_reg[Which] << 31) | (m_sndlast_reg[Which] << 30) | (m_sndend_reg[Which] & 0x00fffff0);
|
||||
}
|
||||
|
||||
template <unsigned Which> WRITE32_MEMBER( arm_iomd_device::sdend_w )
|
||||
{
|
||||
COMBINE_DATA(&m_sndend_reg[Which]);
|
||||
m_sndend_reg[Which] &= 0x00fffff0;
|
||||
m_sndstop_reg[Which] = BIT(data, 31);
|
||||
m_sndlast_reg[Which] = BIT(data, 30);
|
||||
}
|
||||
|
||||
READ32_MEMBER( arm_iomd_device::sdcr_r )
|
||||
{
|
||||
return (m_sound_dma_on << 5) | dmaid_size;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( arm_iomd_device::sdcr_w )
|
||||
{
|
||||
m_sound_dma_on = BIT(data, 5);
|
||||
|
||||
m_vidc->update_sound_mode(m_sound_dma_on);
|
||||
if (m_sound_dma_on)
|
||||
{
|
||||
m_sndcur_buffer = 0;
|
||||
sounddma_swap_buffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
// TODO: bit 7 resets sound DMA
|
||||
}
|
||||
|
||||
READ32_MEMBER( arm_iomd_device::sdst_r )
|
||||
{
|
||||
return (m_snd_overrun << 2) | (m_snd_int << 1) | m_sndcur_buffer;
|
||||
}
|
||||
|
||||
// video DMA
|
||||
READ32_MEMBER( arm_iomd_device::cursinit_r )
|
||||
{
|
||||
return m_cursinit;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( arm_iomd_device::cursinit_w )
|
||||
{
|
||||
COMBINE_DATA(&m_cursinit);
|
||||
m_cursinit &= 0x1ffffff0;
|
||||
m_cursor_enable = true;
|
||||
m_vidc->set_cursor_enable(m_cursor_enable);
|
||||
}
|
||||
|
||||
READ32_MEMBER( arm_iomd_device::vidcr_r )
|
||||
{
|
||||
// bit 6: DRAM mode
|
||||
// bits 4-0: qword transfer
|
||||
return 0x40 | (m_video_enable << 5) | dmaid_size;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( arm_iomd_device::vidcr_w )
|
||||
{
|
||||
m_video_enable = BIT(data, 5);
|
||||
if (m_video_enable == false)
|
||||
{
|
||||
m_cursor_enable = false;
|
||||
m_vidc->set_cursor_enable(m_cursor_enable);
|
||||
}
|
||||
|
||||
if (data & 0x80)
|
||||
throw emu_fatalerror("%s VIDCR LCD dual panel mode enabled", this->tag());
|
||||
}
|
||||
|
||||
READ32_MEMBER( arm_iomd_device::vidend_r )
|
||||
{
|
||||
return (m_vidend & 0x00fffff0);
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( arm_iomd_device::vidend_w )
|
||||
{
|
||||
COMBINE_DATA(&m_vidend);
|
||||
m_vidend &= 0x00fffff0;
|
||||
}
|
||||
|
||||
READ32_MEMBER( arm_iomd_device::vidinita_r )
|
||||
{
|
||||
return (m_vidlast << 30) | (m_videqual << 29) | (m_vidinita & 0x1ffffff0);
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( arm_iomd_device::vidinita_w )
|
||||
{
|
||||
COMBINE_DATA(&m_vidinita);
|
||||
m_vidinita &= 0x1ffffff0;
|
||||
m_vidlast = BIT(data, 30);
|
||||
m_videqual = BIT(data, 29);
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// IRQ/DRQ/Reset signals
|
||||
//**************************************************************************
|
||||
|
||||
WRITE_LINE_MEMBER( arm_iomd_device::vblank_irq )
|
||||
{
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
trigger_irq<IRQA>(0x08);
|
||||
if (m_video_enable == true)
|
||||
{
|
||||
// TODO: much more complex, last/end regs, start regs and eventually LCD hooks
|
||||
u32 src = m_vidinita;
|
||||
u32 size = m_vidend;
|
||||
|
||||
// TODO: vidcur can be readback, support it once anything makes use of the 0x1d0 reg for obvious reasons
|
||||
// (and using m_ prefix is intentional too)
|
||||
for (u32 m_vidcur = 0; m_vidcur<size; m_vidcur++)
|
||||
{
|
||||
m_vidc->write_vram(m_vidcur, m_host_space->read_byte(src));
|
||||
src++;
|
||||
src &= 0x1fffffff;
|
||||
}
|
||||
|
||||
if (m_cursor_enable == true)
|
||||
{
|
||||
src = m_cursinit;
|
||||
size = m_vidc->get_cursor_size();
|
||||
|
||||
// TODO: same as above
|
||||
for (u32 m_curscur = 0; m_curscur<size; m_curscur++)
|
||||
{
|
||||
m_vidc->write_cram(m_curscur, m_host_space->read_byte(src));
|
||||
src++;
|
||||
src &= 0x1fffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void arm_iomd_device::sounddma_swap_buffer()
|
||||
{
|
||||
m_sndcur = m_sndcur_reg[m_sndcur_buffer];
|
||||
m_sndend = m_sndcur + (m_sndend_reg[m_sndcur_buffer] + 0x10);
|
||||
m_sndbuffer_ok[m_sndcur_buffer] = true;
|
||||
|
||||
// TODO: actual condition for int
|
||||
m_snd_overrun = false;
|
||||
m_snd_int = false;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( arm_iomd_device::sound_drq )
|
||||
{
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
if (m_vidc->get_dac_mode() == true)
|
||||
{
|
||||
for (int ch=0;ch<2;ch++)
|
||||
m_vidc->write_dac32(ch, (m_host_space->read_word(m_sndcur + ch*2)));
|
||||
|
||||
m_sndcur += 4;
|
||||
|
||||
if (m_sndcur >= m_sndend)
|
||||
{
|
||||
// TODO: interrupt bit
|
||||
|
||||
m_vidc->update_sound_mode(m_sound_dma_on);
|
||||
if (m_sound_dma_on)
|
||||
{
|
||||
m_sndbuffer_ok[m_sndcur_buffer] = false;
|
||||
m_sndcur_buffer ^= 1;
|
||||
m_snd_overrun = (m_sndbuffer_ok[m_sndcur_buffer] == false);
|
||||
sounddma_swap_buffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( arm_iomd_device::keyboard_irq )
|
||||
{
|
||||
printf("IRQ %d\n",state);
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
trigger_irq<IRQB>(0x80);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( arm_iomd_device::keyboard_reset )
|
||||
{
|
||||
printf("RST %d\n",state);
|
||||
}
|
||||
|
||||
|
211
src/devices/machine/arm_iomd.h
Normal file
211
src/devices/machine/arm_iomd.h
Normal file
@ -0,0 +1,211 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Angelo Salese
|
||||
/***************************************************************************
|
||||
|
||||
ARM IOMD device emulation
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MAME_MACHINE_ARM_IOMD_H
|
||||
#define MAME_MACHINE_ARM_IOMD_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpu/arm7/arm7.h"
|
||||
#include "cpu/arm7/arm7core.h"
|
||||
#include "machine/acorn_vidc.h"
|
||||
#include "machine/at_keybc.h"
|
||||
#include "bus/pc_kbd/pc_kbdc.h"
|
||||
#include "bus/pc_kbd/keyboards.h"
|
||||
|
||||
//**************************************************************************
|
||||
// INTERFACE CONFIGURATION MACROS
|
||||
//**************************************************************************
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> arm_iomd_device
|
||||
|
||||
class arm_iomd_device : public device_t
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
arm_iomd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
arm_iomd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
template <unsigned N> auto iocr_read_od() { return m_iocr_read_od_cb[N].bind(); }
|
||||
template <unsigned N> auto iocr_write_od() { return m_iocr_write_od_cb[N].bind(); }
|
||||
auto iocr_read_id() { return m_iocr_read_id_cb.bind(); }
|
||||
auto iocr_write_id() { return m_iocr_write_id_cb.bind(); }
|
||||
// IRQA
|
||||
DECLARE_WRITE_LINE_MEMBER( vblank_irq );
|
||||
// IRQB
|
||||
DECLARE_WRITE_LINE_MEMBER( keyboard_irq );
|
||||
// DRQs
|
||||
DECLARE_WRITE_LINE_MEMBER( sound_drq );
|
||||
// Reset
|
||||
DECLARE_WRITE_LINE_MEMBER( keyboard_reset );
|
||||
|
||||
// I/O operations
|
||||
virtual void map(address_map &map);
|
||||
template<class T> void set_host_cpu_tag(T &&tag) { m_host_cpu.set_tag(std::forward<T>(tag)); }
|
||||
template<class T> void set_vidc_tag(T &&tag) { m_vidc.set_tag(std::forward<T>(tag)); }
|
||||
template<class T> void set_kbdc_tag(T &&tag) { m_kbdc.set_tag(std::forward<T>(tag)); }
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
//virtual void device_validity_check(validity_checker &valid) const override;
|
||||
virtual void device_add_mconfig(machine_config &config) 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;
|
||||
|
||||
void base_map(address_map &map);
|
||||
u16 m_id;
|
||||
u8 m_version;
|
||||
|
||||
enum {
|
||||
IRQA = 0,
|
||||
IRQB,
|
||||
IRQC,
|
||||
IRQD,
|
||||
IRQDMA,
|
||||
IRQ_SOURCES_SIZE
|
||||
};
|
||||
template <unsigned Which> DECLARE_READ32_MEMBER( irqst_r );
|
||||
template <unsigned Which> DECLARE_READ32_MEMBER( irqrq_r );
|
||||
template <unsigned Which> DECLARE_WRITE32_MEMBER( irqrq_w );
|
||||
template <unsigned Which> DECLARE_READ32_MEMBER( irqmsk_r );
|
||||
template <unsigned Which> DECLARE_WRITE32_MEMBER( irqmsk_w );
|
||||
|
||||
// TODO: convert to ARM7 device instead, enums shouldn't be public
|
||||
required_device<cpu_device> m_host_cpu;
|
||||
required_device<arm_vidc20_device> m_vidc;
|
||||
optional_device<ps2_keyboard_controller_device> m_kbdc;
|
||||
address_space *m_host_space; /**< reference to the host cpu space for DMA ops */
|
||||
private:
|
||||
u8 m_iocr_ddr;
|
||||
|
||||
devcb_read_line m_iocr_read_od_cb[2];
|
||||
devcb_write_line m_iocr_write_od_cb[2];
|
||||
devcb_read_line m_iocr_read_id_cb;
|
||||
devcb_write_line m_iocr_write_id_cb;
|
||||
|
||||
DECLARE_READ32_MEMBER( iocr_r );
|
||||
DECLARE_WRITE32_MEMBER( iocr_w );
|
||||
|
||||
DECLARE_READ32_MEMBER( kbddat_r );
|
||||
DECLARE_WRITE32_MEMBER( kbddat_w );
|
||||
DECLARE_READ32_MEMBER( kbdcr_r );
|
||||
DECLARE_WRITE32_MEMBER( kbdcr_w );
|
||||
|
||||
u32 m_vidinita, m_vidend;
|
||||
bool m_vidlast, m_videqual;
|
||||
bool m_video_enable;
|
||||
DECLARE_READ32_MEMBER( vidcr_r );
|
||||
DECLARE_WRITE32_MEMBER( vidcr_w );
|
||||
DECLARE_READ32_MEMBER( vidend_r );
|
||||
DECLARE_WRITE32_MEMBER( vidend_w );
|
||||
DECLARE_READ32_MEMBER( vidinita_r );
|
||||
DECLARE_WRITE32_MEMBER( vidinita_w );
|
||||
u32 m_cursinit;
|
||||
bool m_cursor_enable;
|
||||
DECLARE_READ32_MEMBER( cursinit_r );
|
||||
DECLARE_WRITE32_MEMBER( cursinit_w );
|
||||
|
||||
static constexpr int sounddma_ch_size = 2;
|
||||
u32 m_sndcur, m_sndend;
|
||||
u32 m_sndcur_reg[sounddma_ch_size], m_sndend_reg[sounddma_ch_size];
|
||||
bool m_sndstop_reg[sounddma_ch_size], m_sndlast_reg[sounddma_ch_size];
|
||||
bool m_sndbuffer_ok[sounddma_ch_size];
|
||||
bool m_sound_dma_on;
|
||||
u8 m_sndcur_buffer;
|
||||
bool m_snd_overrun, m_snd_int;
|
||||
inline void sounddma_swap_buffer();
|
||||
template <unsigned Which> DECLARE_READ32_MEMBER( sdcur_r );
|
||||
template <unsigned Which> DECLARE_WRITE32_MEMBER( sdcur_w );
|
||||
template <unsigned Which> DECLARE_READ32_MEMBER( sdend_r );
|
||||
template <unsigned Which> DECLARE_WRITE32_MEMBER( sdend_w );
|
||||
DECLARE_READ32_MEMBER( sdcr_r );
|
||||
DECLARE_WRITE32_MEMBER( sdcr_w );
|
||||
DECLARE_READ32_MEMBER( sdst_r );
|
||||
|
||||
u8 m_irq_status[IRQ_SOURCES_SIZE], m_irq_mask[IRQ_SOURCES_SIZE];
|
||||
inline u8 update_irqa_type(u8 data);
|
||||
inline void flush_irq(unsigned Which);
|
||||
template <unsigned Which> inline void trigger_irq(u8 irq_type);
|
||||
|
||||
static constexpr int timer_ch_size = 2;
|
||||
enum {
|
||||
T0_TIMER = 1,
|
||||
T1_TIMER
|
||||
};
|
||||
inline void trigger_timer(unsigned Which);
|
||||
u16 m_timer_in[2];
|
||||
u16 m_timer_out[2];
|
||||
int m_timer_counter[2];
|
||||
u8 m_timer_readinc[2];
|
||||
emu_timer *m_timer[2];
|
||||
|
||||
template <unsigned Which> DECLARE_READ32_MEMBER( tNlow_r );
|
||||
template <unsigned Which> DECLARE_READ32_MEMBER( tNhigh_r );
|
||||
template <unsigned Which> DECLARE_WRITE32_MEMBER( tNlow_w );
|
||||
template <unsigned Which> DECLARE_WRITE32_MEMBER( tNhigh_w );
|
||||
template <unsigned Which> DECLARE_WRITE32_MEMBER( tNgo_w );
|
||||
template <unsigned Which> DECLARE_WRITE32_MEMBER( tNlatch_w );
|
||||
|
||||
template <unsigned Nibble> DECLARE_READ32_MEMBER( id_r );
|
||||
DECLARE_READ32_MEMBER( version_r );
|
||||
|
||||
// used in vidcr_r / sndcr_r, documentation hints this is a purged idea during chip development, to be checked out
|
||||
static constexpr u8 dmaid_size = 0x10; // qword transfer
|
||||
// constexpr u8 dmaid_mask = 0x1f;
|
||||
};
|
||||
|
||||
class arm7500fe_iomd_device : public arm_iomd_device
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
arm7500fe_iomd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
virtual void map(address_map &map) override;
|
||||
auto iolines_read() { return m_iolines_read_cb.bind(); }
|
||||
auto iolines_write() { return m_iolines_write_cb.bind(); }
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
private:
|
||||
devcb_read8 m_iolines_read_cb;
|
||||
devcb_write8 m_iolines_write_cb;
|
||||
|
||||
bool m_cpuclk_divider, m_memclk_divider, m_ioclk_divider;
|
||||
inline void refresh_host_cpu_clocks();
|
||||
DECLARE_READ32_MEMBER( clkctl_r );
|
||||
DECLARE_WRITE32_MEMBER( clkctl_w );
|
||||
|
||||
u8 m_iolines_ddr;
|
||||
DECLARE_READ32_MEMBER( iolines_r );
|
||||
DECLARE_WRITE32_MEMBER( iolines_w );
|
||||
|
||||
DECLARE_READ32_MEMBER( msecr_r );
|
||||
DECLARE_WRITE32_MEMBER( msecr_w );
|
||||
};
|
||||
|
||||
// device type definition
|
||||
DECLARE_DEVICE_TYPE(ARM_IOMD, arm_iomd_device)
|
||||
DECLARE_DEVICE_TYPE(ARM7500FE_IOMD, arm7500fe_iomd_device)
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
//**************************************************************************
|
||||
|
||||
|
||||
#endif // MAME_MACHINE_ARM_IOMD_H
|
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,7 @@
|
||||
Tomasz Slanina analog[at]op.pl
|
||||
|
||||
TODO:
|
||||
- move PS7500 stuff to machine/ps7500.c
|
||||
- Correct IOMD type (CL-PS7500 -> ARM7500FE?)
|
||||
- 24c01 eeprom (IOLINES)
|
||||
- timing
|
||||
- unknown reads/writes
|
||||
@ -128,136 +128,48 @@ Notes:
|
||||
#include "cpu/arm7/arm7.h"
|
||||
#include "cpu/arm7/arm7core.h"
|
||||
#include "machine/i2cmem.h"
|
||||
#include "machine/acorn_vidc.h"
|
||||
#include "machine/arm_iomd.h"
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
#include "speaker.h"
|
||||
|
||||
enum
|
||||
{
|
||||
IOCR=0,
|
||||
KBDDAT,
|
||||
KBDCR,
|
||||
IOLINES,
|
||||
IRQSTA,
|
||||
IRQRQA,
|
||||
IRQMSKA,
|
||||
SUSMODE,
|
||||
IRQSTB,
|
||||
IRQRQB,
|
||||
IRQMSKB,
|
||||
STOPMODE,
|
||||
FIQST,
|
||||
FIQRQ,
|
||||
FIQMSK,
|
||||
CLKCTL,
|
||||
T0low,
|
||||
T0high,
|
||||
T0GO,
|
||||
T0LAT,
|
||||
T1low,
|
||||
T1high,
|
||||
T1GO,
|
||||
T1LAT,
|
||||
IRQSTC,
|
||||
IRQRQC,
|
||||
IRQMSKC,
|
||||
VIDMUX,
|
||||
IRQSTD,
|
||||
IRQRQD,
|
||||
IRQMSKD,
|
||||
|
||||
ROMCR0=32,
|
||||
ROMCR1,
|
||||
|
||||
REFCR=35,
|
||||
|
||||
ID0=37,
|
||||
ID1,
|
||||
VERSION,
|
||||
|
||||
MSEDAT=42,
|
||||
MSECR,
|
||||
|
||||
IOTCR=49,
|
||||
ECTCR,
|
||||
ASTCR,
|
||||
DRAMCR,
|
||||
SELREF,
|
||||
|
||||
ATODICR=56,
|
||||
ATODSR,
|
||||
ATODCC,
|
||||
ATODCNT1,
|
||||
ATODCNT2,
|
||||
ATODCNT3,
|
||||
ATODCNT4,
|
||||
|
||||
SD0CURA=96,
|
||||
SD0ENDA,
|
||||
SD0CURB,
|
||||
SD0ENDB,
|
||||
SD0CR,
|
||||
SD0ST,
|
||||
|
||||
CURSCUR=112,
|
||||
CURSINIT,
|
||||
VIDCURB,
|
||||
|
||||
VIDCURA=116,
|
||||
VIDEND,
|
||||
VIDSTART,
|
||||
VIDINITA,
|
||||
VIDCR,
|
||||
|
||||
VIDINITB=122,
|
||||
|
||||
DMAST=124,
|
||||
DMARQ,
|
||||
DMASK,
|
||||
MAXIO=128
|
||||
};
|
||||
|
||||
|
||||
class ssfindo_state : public driver_device
|
||||
{
|
||||
public:
|
||||
ssfindo_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_palette(*this, "palette"),
|
||||
m_i2cmem(*this, "i2cmem"),
|
||||
m_vram(*this, "vram"),
|
||||
m_flashrom(*this, "flash"),
|
||||
m_io_ps7500(*this, "PS7500") { }
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_vidc(*this, "vidc")
|
||||
, m_iomd(*this, "iomd")
|
||||
, m_i2cmem(*this, "i2cmem")
|
||||
, m_flashrom(*this, "flash")
|
||||
{ }
|
||||
|
||||
void ssfindo(machine_config &config);
|
||||
void ppcar(machine_config &config);
|
||||
void tetfight(machine_config &config);
|
||||
|
||||
void init_ssfindo();
|
||||
void init_ppcar();
|
||||
void init_tetfight();
|
||||
|
||||
private:
|
||||
protected:
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<arm_vidc20_device> m_vidc;
|
||||
required_device<arm7500fe_iomd_device> m_iomd;
|
||||
optional_device<i2cmem_device> m_i2cmem;
|
||||
|
||||
required_shared_ptr<uint32_t> m_vram;
|
||||
|
||||
required_region_ptr<uint16_t> m_flashrom;
|
||||
|
||||
void init_common();
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
required_ioport m_io_ps7500;
|
||||
typedef void (ssfindo_state::*speedup_func)();
|
||||
speedup_func m_speedup;
|
||||
|
||||
// driver init configuration
|
||||
uint32_t m_flashType;
|
||||
int m_iocr_hack;
|
||||
|
||||
// common
|
||||
uint32_t m_PS7500_IO[MAXIO];
|
||||
uint32_t m_PS7500_FIFO[256];
|
||||
emu_timer *m_PS7500timer0;
|
||||
emu_timer *m_PS7500timer1;
|
||||
bool m_i2cmem_clock;
|
||||
private:
|
||||
|
||||
// ssfindo and ppcar
|
||||
uint32_t m_flashAdr;
|
||||
@ -265,11 +177,6 @@ private:
|
||||
uint32_t m_adrLatch;
|
||||
uint32_t m_flashN;
|
||||
|
||||
// common
|
||||
DECLARE_WRITE32_MEMBER(FIFO_w);
|
||||
DECLARE_READ32_MEMBER(PS7500_IO_r);
|
||||
DECLARE_WRITE32_MEMBER(PS7500_IO_w);
|
||||
|
||||
// ssfindo and ppcar
|
||||
DECLARE_READ32_MEMBER(io_r);
|
||||
DECLARE_WRITE32_MEMBER(io_w);
|
||||
@ -282,124 +189,93 @@ private:
|
||||
// ppcar
|
||||
DECLARE_READ32_MEMBER(randomized_r);
|
||||
|
||||
// tetfight
|
||||
DECLARE_READ32_MEMBER(tetfight_unk_r);
|
||||
DECLARE_WRITE32_MEMBER(tetfight_unk_w);
|
||||
|
||||
void init_common();
|
||||
virtual void machine_reset() override;
|
||||
|
||||
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
|
||||
INTERRUPT_GEN_MEMBER(interrupt);
|
||||
TIMER_CALLBACK_MEMBER(PS7500_Timer0_callback);
|
||||
TIMER_CALLBACK_MEMBER(PS7500_Timer1_callback);
|
||||
|
||||
typedef void (ssfindo_state::*speedup_func)();
|
||||
speedup_func m_speedup;
|
||||
|
||||
void PS7500_startTimer0();
|
||||
void PS7500_startTimer1();
|
||||
void PS7500_reset();
|
||||
void ssfindo_speedups();
|
||||
void ppcar_speedups();
|
||||
|
||||
void ppcar_map(address_map &map);
|
||||
void ssfindo_map(address_map &map);
|
||||
void tetfight_map(address_map &map);
|
||||
|
||||
DECLARE_READ8_MEMBER(iolines_r);
|
||||
DECLARE_WRITE8_MEMBER(iolines_w);
|
||||
bool m_flash_bank_select;
|
||||
};
|
||||
|
||||
|
||||
uint32_t ssfindo_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
class tetfight_state : public ssfindo_state
|
||||
{
|
||||
int s,x,y;
|
||||
public:
|
||||
tetfight_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: ssfindo_state(mconfig, type, tag)
|
||||
{}
|
||||
|
||||
if( m_PS7500_IO[VIDCR]&0x20) //video DMA enabled
|
||||
{
|
||||
s=( (m_PS7500_IO[VIDINITA]&0x1fffffff)-0x10000000)/4;
|
||||
void init_tetfight();
|
||||
void tetfight(machine_config &config);
|
||||
|
||||
if(s>=0 && s<(0x10000000/4))
|
||||
{
|
||||
for(y=0;y<256;y++)
|
||||
for(x=0;x<320;x+=4)
|
||||
{
|
||||
bitmap.pix16(y, x+0) = m_vram[s]&0xff;
|
||||
bitmap.pix16(y, x+1) = (m_vram[s]>>8)&0xff;
|
||||
bitmap.pix16(y, x+2) = (m_vram[s]>>16)&0xff;
|
||||
bitmap.pix16(y, x+3) = (m_vram[s]>>24)&0xff;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
}
|
||||
protected:
|
||||
|
||||
return 0;
|
||||
}
|
||||
private:
|
||||
bool m_i2cdata_hack;
|
||||
|
||||
WRITE32_MEMBER(ssfindo_state::FIFO_w)
|
||||
void tetfight_map(address_map &map);
|
||||
|
||||
DECLARE_READ_LINE_MEMBER(iocr_od0_r);
|
||||
DECLARE_READ_LINE_MEMBER(iocr_od1_r);
|
||||
DECLARE_WRITE_LINE_MEMBER(iocr_od0_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(iocr_od1_w);
|
||||
DECLARE_READ32_MEMBER(tetfight_unk_r);
|
||||
DECLARE_WRITE32_MEMBER(tetfight_unk_w);
|
||||
};
|
||||
|
||||
//TODO: eeprom 24c01 & 24c02
|
||||
// TODO: untangle, kill hacks
|
||||
READ8_MEMBER(ssfindo_state::iolines_r)
|
||||
{
|
||||
m_PS7500_FIFO[data>>28]=data;
|
||||
|
||||
if(!(data>>28))
|
||||
{
|
||||
m_palette->set_pen_color(m_PS7500_FIFO[1]&0xff, data&0xff,(data>>8)&0xff,(data>>16)&0xff);
|
||||
m_PS7500_FIFO[1]++; //autoinc
|
||||
}
|
||||
}
|
||||
TIMER_CALLBACK_MEMBER(ssfindo_state::PS7500_Timer0_callback)
|
||||
{
|
||||
m_PS7500_IO[IRQSTA]|=0x20;
|
||||
if(m_PS7500_IO[IRQMSKA]&0x20)
|
||||
{
|
||||
m_maincpu->pulse_input_line(ARM7_IRQ_LINE, m_maincpu->minimum_quantum_time());
|
||||
}
|
||||
}
|
||||
|
||||
void ssfindo_state::PS7500_startTimer0()
|
||||
{
|
||||
int val=((m_PS7500_IO[T0low]&0xff)|((m_PS7500_IO[T0high]&0xff)<<8))>>1;
|
||||
|
||||
if(val==0)
|
||||
m_PS7500timer0->adjust(attotime::never);
|
||||
if(m_flashType == 1)
|
||||
return 0;
|
||||
else
|
||||
m_PS7500timer0->adjust(attotime::from_usec(val ), 0, attotime::from_usec(val ));
|
||||
return machine().rand();
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(ssfindo_state::PS7500_Timer1_callback)
|
||||
WRITE8_MEMBER(ssfindo_state::iolines_w)
|
||||
{
|
||||
m_PS7500_IO[IRQSTA]|=0x40;
|
||||
if(m_PS7500_IO[IRQMSKA]&0x40)
|
||||
{
|
||||
m_maincpu->pulse_input_line(ARM7_IRQ_LINE, m_maincpu->minimum_quantum_time());
|
||||
}
|
||||
if(data&0xc0)
|
||||
m_adrLatch=0;
|
||||
|
||||
if(m_maincpu->pc() == 0xbac0 && m_flashType == 1)
|
||||
m_flashN=data&1;
|
||||
|
||||
m_flash_bank_select = BIT(data, 0);
|
||||
}
|
||||
|
||||
void ssfindo_state::PS7500_startTimer1()
|
||||
// inverted compared to riscpc.cpp
|
||||
// TODO: simplify hookup over i2cmem having AND 1 on state for a writeline (?)
|
||||
READ_LINE_MEMBER(tetfight_state::iocr_od1_r)
|
||||
{
|
||||
int val=((m_PS7500_IO[T1low]&0xff)|((m_PS7500_IO[T1high]&0xff)<<8))>>1;
|
||||
if(val==0)
|
||||
m_PS7500timer1->adjust(attotime::never);
|
||||
else
|
||||
m_PS7500timer1->adjust(attotime::from_usec(val ), 0, attotime::from_usec(val ));
|
||||
// TODO: completely get rid of this speedup fn or move anywhere else
|
||||
//if (m_speedup) (this->*m_speedup)();
|
||||
return (m_i2cmem->read_sda() ? 1 : 0); //eeprom read
|
||||
}
|
||||
|
||||
INTERRUPT_GEN_MEMBER(ssfindo_state::interrupt)
|
||||
READ_LINE_MEMBER(tetfight_state::iocr_od0_r)
|
||||
{
|
||||
m_PS7500_IO[IRQSTA]|=0x08;
|
||||
if(m_PS7500_IO[IRQMSKA]&0x08)
|
||||
{
|
||||
device.execute().pulse_input_line(ARM7_IRQ_LINE, device.execute().minimum_quantum_time());
|
||||
}
|
||||
return (m_i2cmem_clock == true ? 1 : 0); //eeprom read
|
||||
}
|
||||
|
||||
void ssfindo_state::PS7500_reset()
|
||||
WRITE_LINE_MEMBER(tetfight_state::iocr_od1_w)
|
||||
{
|
||||
m_PS7500_IO[IOCR] = 0x3f;
|
||||
m_PS7500_IO[VIDCR] = 0;
|
||||
|
||||
m_PS7500timer0->adjust( attotime::never);
|
||||
m_PS7500timer1->adjust( attotime::never);
|
||||
// TODO: i2c cares about the order of this!?
|
||||
// tetfight reaches PC=0x106c if initialization has success
|
||||
// rpc700 doesn't like above and go into supervisor mode even with a valid NVRAM
|
||||
// both wants clock first then data, not sure where the issue actually is
|
||||
m_i2cdata_hack = state == true;
|
||||
//m_i2cmem->write_sda(state == true ? 1 : 0);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(tetfight_state::iocr_od0_w)
|
||||
{
|
||||
m_i2cmem_clock = state;
|
||||
m_i2cmem->write_scl(state == true ? 1 : 0);
|
||||
m_i2cmem->write_sda(m_i2cdata_hack == true ? 1 : 0);
|
||||
}
|
||||
|
||||
void ssfindo_state::ssfindo_speedups()
|
||||
{
|
||||
@ -417,138 +293,15 @@ void ssfindo_state::ppcar_speedups()
|
||||
m_maincpu->spin_until_time(attotime::from_usec(20));
|
||||
}
|
||||
|
||||
|
||||
READ32_MEMBER(ssfindo_state::PS7500_IO_r)
|
||||
{
|
||||
switch(offset)
|
||||
{
|
||||
case MSECR:
|
||||
return machine().rand();
|
||||
|
||||
case IOLINES: //TODO: eeprom 24c01
|
||||
#if 0
|
||||
osd_printf_debug("IOLINESR %i @%x\n", offset, m_maincpu->pc());
|
||||
#endif
|
||||
|
||||
if(m_flashType == 1)
|
||||
return 0;
|
||||
else
|
||||
return machine().rand();
|
||||
|
||||
case IRQSTA:
|
||||
return (m_PS7500_IO[offset] & (~2)) | 0x80;
|
||||
|
||||
case IRQRQA:
|
||||
return (m_PS7500_IO[IRQSTA] & m_PS7500_IO[IRQMSKA]) | 0x80;
|
||||
|
||||
case IOCR: //TODO: nINT1, OD[n] p.81
|
||||
if (m_speedup) (this->*m_speedup)();
|
||||
|
||||
if( m_iocr_hack)
|
||||
{
|
||||
return (m_io_ps7500->read() & 0x80) | 0x34 | (m_i2cmem->read_sda() ? 0x03 : 0x00); //eeprom read
|
||||
}
|
||||
|
||||
return (m_io_ps7500->read() & 0x80) | 0x37;
|
||||
|
||||
case VIDCR:
|
||||
return (m_PS7500_IO[offset] | 0x50) & 0xfffffff0;
|
||||
|
||||
case T1low:
|
||||
case T0low:
|
||||
case T1high:
|
||||
case T0high:
|
||||
case IRQMSKA:
|
||||
case VIDEND:
|
||||
case VIDSTART:
|
||||
case VIDINITA: //TODO: bits 29 ("equal") and 30 (last bit) p.105
|
||||
|
||||
return m_PS7500_IO[offset];
|
||||
|
||||
|
||||
}
|
||||
return machine().rand();//m_PS7500_IO[offset];
|
||||
}
|
||||
|
||||
WRITE32_MEMBER(ssfindo_state::PS7500_IO_w)
|
||||
{
|
||||
uint32_t temp=m_PS7500_IO[offset];
|
||||
|
||||
COMBINE_DATA(&temp);
|
||||
|
||||
switch(offset)
|
||||
{
|
||||
case IOLINES: //TODO: eeprom 24c01
|
||||
m_PS7500_IO[offset]=data;
|
||||
if(data&0xc0)
|
||||
m_adrLatch=0;
|
||||
|
||||
if(m_maincpu->pc() == 0xbac0 && m_flashType == 1)
|
||||
{
|
||||
m_flashN=data&1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
logerror("IOLINESW %i = %x @%x\n",offset,data,m_maincpu->pc());
|
||||
#endif
|
||||
break;
|
||||
|
||||
case IRQRQA:
|
||||
m_PS7500_IO[IRQSTA]&=~temp;
|
||||
break;
|
||||
|
||||
case IRQMSKA:
|
||||
m_PS7500_IO[IRQMSKA]=(temp&(~2))|0x80;
|
||||
break;
|
||||
|
||||
case T1GO:
|
||||
PS7500_startTimer1();
|
||||
break;
|
||||
|
||||
case T0GO:
|
||||
PS7500_startTimer0();
|
||||
break;
|
||||
|
||||
case VIDEND:
|
||||
case VIDSTART:
|
||||
COMBINE_DATA(&m_PS7500_IO[offset]);
|
||||
m_PS7500_IO[offset]&=0xfffffff0; // qword align
|
||||
break;
|
||||
|
||||
case IOCR:
|
||||
//popmessage("IOLINESW %i = %x @%x\n",offset,data,m_maincpu->pc());
|
||||
COMBINE_DATA(&m_PS7500_IO[offset]);
|
||||
// TODO: correct hook-up
|
||||
m_i2cmem->write_scl((data & 0x01) ? 1 : 0);
|
||||
m_i2cmem->write_sda((data & 0x02) ? 1 : 0);
|
||||
break;
|
||||
|
||||
case REFCR:
|
||||
case DRAMCR:
|
||||
case SD0CR:
|
||||
case ROMCR0:
|
||||
case VIDMUX:
|
||||
case CLKCTL:
|
||||
case T1low:
|
||||
case T0low:
|
||||
case T1high:
|
||||
case T0high:
|
||||
case VIDCR:
|
||||
case VIDINITA: //TODO: bit 30 (last bit) p.105
|
||||
COMBINE_DATA(&m_PS7500_IO[offset]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
READ32_MEMBER(ssfindo_state::io_r)
|
||||
{
|
||||
int adr=m_flashAdr*0x200+(m_flashOffset);
|
||||
|
||||
|
||||
switch(m_flashType)
|
||||
{
|
||||
case 0:
|
||||
if(m_PS7500_IO[IOLINES]&1) //bit 0 of IOLINES = flash select ( 5/6 or 3/2 )
|
||||
//bit 0 of IOLINES = flash select ( 5/6 or 3/2 )
|
||||
if (m_flash_bank_select)
|
||||
adr+=0x400000;
|
||||
break;
|
||||
|
||||
@ -609,7 +362,7 @@ READ32_MEMBER(ssfindo_state::randomized_r)
|
||||
void ssfindo_state::ssfindo_map(address_map &map)
|
||||
{
|
||||
map(0x00000000, 0x000fffff).rom();
|
||||
map(0x03200000, 0x032001ff).rw(FUNC(ssfindo_state::PS7500_IO_r), FUNC(ssfindo_state::PS7500_IO_w));
|
||||
map(0x03200000, 0x032001ff).m(m_iomd, FUNC(arm7500fe_iomd_device::map));
|
||||
map(0x03012e60, 0x03012e67).noprw();
|
||||
map(0x03012fe0, 0x03012fe3).w(FUNC(ssfindo_state::debug_w));
|
||||
map(0x03012ff0, 0x03012ff3).noprw();
|
||||
@ -621,14 +374,14 @@ void ssfindo_state::ssfindo_map(address_map &map)
|
||||
map(0x03243000, 0x03243003).portr("DSW").nopw();
|
||||
map(0x0324f000, 0x0324f003).r(FUNC(ssfindo_state::SIMPLEIO_r));
|
||||
map(0x03245000, 0x03245003).nopw(); /* sound ? */
|
||||
map(0x03400000, 0x03400003).w(FUNC(ssfindo_state::FIFO_w));
|
||||
map(0x10000000, 0x11ffffff).ram().share("vram");
|
||||
map(0x03400000, 0x037fffff).w(m_vidc, FUNC(arm_vidc20_device::write));
|
||||
map(0x10000000, 0x11ffffff).ram();
|
||||
}
|
||||
|
||||
void ssfindo_state::ppcar_map(address_map &map)
|
||||
{
|
||||
map(0x00000000, 0x000fffff).rom();
|
||||
map(0x03200000, 0x032001ff).rw(FUNC(ssfindo_state::PS7500_IO_r), FUNC(ssfindo_state::PS7500_IO_w));
|
||||
map(0x03200000, 0x032001ff).m(m_iomd, FUNC(arm7500fe_iomd_device::map));
|
||||
map(0x03012b00, 0x03012bff).r(FUNC(ssfindo_state::randomized_r)).nopw();
|
||||
map(0x03012e60, 0x03012e67).nopw();
|
||||
map(0x03012ff8, 0x03012ffb).portr("IN0").nopw();
|
||||
@ -636,43 +389,52 @@ void ssfindo_state::ppcar_map(address_map &map)
|
||||
map(0x03340000, 0x03340007).nopw();
|
||||
map(0x03341000, 0x0334101f).nopw();
|
||||
map(0x033c0000, 0x033c0003).r(FUNC(ssfindo_state::io_r)).w(FUNC(ssfindo_state::io_w));
|
||||
map(0x03400000, 0x03400003).w(FUNC(ssfindo_state::FIFO_w));
|
||||
map(0x03400000, 0x037fffff).w(m_vidc, FUNC(arm_vidc20_device::write));
|
||||
map(0x08000000, 0x08ffffff).ram();
|
||||
map(0x10000000, 0x10ffffff).ram().share("vram");
|
||||
map(0x10000000, 0x10ffffff).ram();
|
||||
}
|
||||
|
||||
READ32_MEMBER(ssfindo_state::tetfight_unk_r)
|
||||
READ32_MEMBER(tetfight_state::tetfight_unk_r)
|
||||
{
|
||||
//sound status ?
|
||||
return machine().rand();
|
||||
}
|
||||
|
||||
WRITE32_MEMBER(ssfindo_state::tetfight_unk_w)
|
||||
WRITE32_MEMBER(tetfight_state::tetfight_unk_w)
|
||||
{
|
||||
//sound latch ?
|
||||
}
|
||||
|
||||
void ssfindo_state::tetfight_map(address_map &map)
|
||||
void tetfight_state::tetfight_map(address_map &map)
|
||||
{
|
||||
map(0x00000000, 0x001fffff).rom();
|
||||
map(0x03200000, 0x032001ff).rw(FUNC(ssfindo_state::PS7500_IO_r), FUNC(ssfindo_state::PS7500_IO_w));
|
||||
map(0x03400000, 0x03400003).w(FUNC(ssfindo_state::FIFO_w));
|
||||
map(0x03200000, 0x032001ff).m(m_iomd, FUNC(arm7500fe_iomd_device::map));
|
||||
map(0x03240000, 0x03240003).portr("IN0");
|
||||
map(0x03240004, 0x03240007).portr("IN1");
|
||||
map(0x03240008, 0x0324000b).portr("DSW2");
|
||||
map(0x03240020, 0x03240023).rw(FUNC(ssfindo_state::tetfight_unk_r), FUNC(ssfindo_state::tetfight_unk_w));
|
||||
map(0x10000000, 0x14ffffff).ram().share("vram");
|
||||
map(0x03240020, 0x03240023).rw(FUNC(tetfight_state::tetfight_unk_r), FUNC(tetfight_state::tetfight_unk_w));
|
||||
map(0x03400000, 0x037fffff).w(m_vidc, FUNC(arm_vidc20_device::write));
|
||||
map(0x10000000, 0x14ffffff).ram();
|
||||
}
|
||||
|
||||
void ssfindo_state::machine_start()
|
||||
{
|
||||
// TODO: convert to exact flash device
|
||||
save_item(NAME(m_flashAdr));
|
||||
save_item(NAME(m_flashOffset));
|
||||
save_item(NAME(m_adrLatch));
|
||||
save_item(NAME(m_flashN));
|
||||
save_item(NAME(m_i2cmem_clock));
|
||||
save_item(NAME(m_flash_bank_select));
|
||||
}
|
||||
|
||||
void ssfindo_state::machine_reset()
|
||||
{
|
||||
PS7500_reset();
|
||||
// ...
|
||||
}
|
||||
|
||||
static INPUT_PORTS_START( ssfindo )
|
||||
PORT_START("PS7500")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_VBLANK("screen")
|
||||
|
||||
// TODO: incomplete structs
|
||||
PORT_START("IN0")
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_UNUSED ) // IPT_START2 ??
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
|
||||
@ -698,31 +460,28 @@ static INPUT_PORTS_START( ssfindo )
|
||||
PORT_DIPNAME( 0x02, 0x02, DEF_STR( Free_Play ) )
|
||||
PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x80, 0x80, DEF_STR( Service_Mode ) )
|
||||
PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x04, 0x04, "DSW 2" )
|
||||
PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x08, 0x08, "DSW 3" )
|
||||
PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x10, 0x010, "DSW 4" )
|
||||
PORT_DIPNAME( 0x10, 0x10, "DSW 4" )
|
||||
PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x20, 0x20, "DSW 5" )
|
||||
PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x40, 0x040, "DSW 6" )
|
||||
PORT_DIPNAME( 0x40, 0x40, "DSW 6" )
|
||||
PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x80, 0x80, DEF_STR( Service_Mode ) )
|
||||
PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
static INPUT_PORTS_START( ppcar )
|
||||
PORT_START("PS7500")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_VBLANK("screen")
|
||||
|
||||
PORT_START("IN0")
|
||||
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_COIN1 )
|
||||
|
||||
@ -737,9 +496,6 @@ static INPUT_PORTS_START( ppcar )
|
||||
INPUT_PORTS_END
|
||||
|
||||
static INPUT_PORTS_START( tetfight )
|
||||
PORT_START("PS7500")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_VBLANK("screen")
|
||||
|
||||
PORT_START("IN0")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
|
||||
@ -798,42 +554,46 @@ INPUT_PORTS_END
|
||||
|
||||
void ssfindo_state::ssfindo(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
ARM7(config, m_maincpu, 54000000); // guess...
|
||||
ARM7(config, m_maincpu, 54000000);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &ssfindo_state::ssfindo_map);
|
||||
m_maincpu->set_vblank_int("screen", FUNC(ssfindo_state::interrupt));
|
||||
|
||||
I2C_24C01(config, m_i2cmem);
|
||||
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_refresh_hz(60);
|
||||
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
|
||||
screen.set_size(320, 256);
|
||||
screen.set_visarea(0, 319, 0, 239);
|
||||
screen.set_screen_update(FUNC(ssfindo_state::screen_update));
|
||||
screen.set_palette(m_palette);
|
||||
SCREEN(config, "screen", SCREEN_TYPE_RASTER);
|
||||
|
||||
PALETTE(config, m_palette).set_entries(256);
|
||||
ARM_VIDC20(config, m_vidc, 24_MHz_XTAL);
|
||||
m_vidc->set_screen("screen");
|
||||
m_vidc->vblank().set(m_iomd, FUNC(arm_iomd_device::vblank_irq));
|
||||
m_vidc->sound_drq().set(m_iomd, FUNC(arm_iomd_device::sound_drq));
|
||||
|
||||
ARM7500FE_IOMD(config, m_iomd, 54000000);
|
||||
m_iomd->set_host_cpu_tag(m_maincpu);
|
||||
m_iomd->set_vidc_tag(m_vidc);
|
||||
m_iomd->iolines_read().set(FUNC(ssfindo_state::iolines_r));
|
||||
m_iomd->iolines_write().set(FUNC(ssfindo_state::iolines_w));
|
||||
}
|
||||
|
||||
void ssfindo_state::ppcar(machine_config &config)
|
||||
{
|
||||
ssfindo(config);
|
||||
|
||||
/* basic machine hardware */
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &ssfindo_state::ppcar_map);
|
||||
|
||||
config.device_remove("i2cmem");
|
||||
}
|
||||
|
||||
void ssfindo_state::tetfight(machine_config &config)
|
||||
void tetfight_state::tetfight(machine_config &config)
|
||||
{
|
||||
ppcar(config);
|
||||
|
||||
/* basic machine hardware */
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &ssfindo_state::tetfight_map);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &tetfight_state::tetfight_map);
|
||||
|
||||
I2C_24C02(config, m_i2cmem);
|
||||
|
||||
m_iomd->iocr_read_od<0>().set(FUNC(tetfight_state::iocr_od0_r));
|
||||
m_iomd->iocr_read_od<1>().set(FUNC(tetfight_state::iocr_od1_r));
|
||||
m_iomd->iocr_write_od<0>().set(FUNC(tetfight_state::iocr_od0_w));
|
||||
m_iomd->iocr_write_od<1>().set(FUNC(tetfight_state::iocr_od1_w));
|
||||
}
|
||||
|
||||
ROM_START( ssfindo )
|
||||
@ -909,11 +669,11 @@ ROM_END
|
||||
void ssfindo_state::init_common()
|
||||
{
|
||||
m_speedup = nullptr;
|
||||
m_PS7500timer0 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ssfindo_state::PS7500_Timer0_callback),this));
|
||||
m_PS7500timer1 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ssfindo_state::PS7500_Timer1_callback),this));
|
||||
//m_PS7500timer0 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ssfindo_state::PS7500_Timer0_callback),this));
|
||||
//m_PS7500timer1 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ssfindo_state::PS7500_Timer1_callback),this));
|
||||
|
||||
save_item(NAME(m_PS7500_IO));
|
||||
save_item(NAME(m_PS7500_FIFO));
|
||||
//save_item(NAME(m_PS7500_IO));
|
||||
//save_item(NAME(m_PS7500_FIFO));
|
||||
}
|
||||
|
||||
void ssfindo_state::init_ssfindo()
|
||||
@ -921,12 +681,6 @@ void ssfindo_state::init_ssfindo()
|
||||
init_common();
|
||||
m_flashType = 0;
|
||||
m_speedup = &ssfindo_state::ssfindo_speedups;
|
||||
m_iocr_hack = 0;
|
||||
|
||||
save_item(NAME(m_flashAdr));
|
||||
save_item(NAME(m_flashOffset));
|
||||
save_item(NAME(m_adrLatch));
|
||||
save_item(NAME(m_flashN));
|
||||
}
|
||||
|
||||
void ssfindo_state::init_ppcar()
|
||||
@ -936,13 +690,12 @@ void ssfindo_state::init_ppcar()
|
||||
m_speedup = &ssfindo_state::ppcar_speedups;
|
||||
}
|
||||
|
||||
void ssfindo_state::init_tetfight()
|
||||
void tetfight_state::init_tetfight()
|
||||
{
|
||||
init_common();
|
||||
m_flashType = 0;
|
||||
m_iocr_hack = 1;
|
||||
}
|
||||
|
||||
GAME( 1999, ssfindo, 0, ssfindo, ssfindo, ssfindo_state, init_ssfindo, ROT0, "Icarus", "See See Find Out", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1999, ppcar, 0, ppcar, ppcar, ssfindo_state, init_ppcar, ROT0, "Icarus", "Pang Pang Car", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 2001, tetfight,0, tetfight, tetfight, ssfindo_state, init_tetfight, ROT0, "Sego", "Tetris Fighters", MACHINE_NO_SOUND | MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 2001, tetfight,0, tetfight, tetfight, tetfight_state, init_tetfight, ROT0, "Sego", "Tetris Fighters", MACHINE_NO_SOUND | MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE )
|
||||
|
Loading…
Reference in New Issue
Block a user