// license:BSD-3-Clause
// copyright-holders:Barry Rodewald
/*
* Data East Pinball / Sega Pinball Dot Matrix Display
*
* Type 3: 192x64
* 68000 @ 12MHz
* 68B45 CRTC
*/
#include "emu.h"
#include "decodmd3.h"
#include "rendlay.h"
#include "screen.h"
DEFINE_DEVICE_TYPE(DECODMD3, decodmd_type3_device, "decodmd3", "Data East Pinball Dot Matrix Display Type 3")
WRITE8_MEMBER( decodmd_type3_device::data_w )
{
m_latch = data;
}
READ8_MEMBER( decodmd_type3_device::busy_r )
{
uint8_t ret = 0x00;
ret = (m_status & 0x0f) << 3;
if(m_busy)
return 0x80 | ret;
else
return 0x00 | ret;
}
WRITE8_MEMBER( decodmd_type3_device::ctrl_w )
{
if(!(m_ctrl & 0x01) && (data & 0x01))
{
m_cpu->set_input_line(M68K_IRQ_1,ASSERT_LINE);
m_busy = true;
m_command = m_latch;
}
if((m_ctrl & 0x02) && !(data & 0x02))
{
m_cpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero);
logerror("DMD3: Reset\n");
}
m_ctrl = data;
}
READ16_MEMBER( decodmd_type3_device::status_r )
{
return m_status;
}
WRITE16_MEMBER( decodmd_type3_device::status_w )
{
m_status = data & 0x0f;
}
READ16_MEMBER( decodmd_type3_device::latch_r )
{
// clear IRQ?
m_cpu->set_input_line(M68K_IRQ_1,CLEAR_LINE);
m_busy = false;
return m_command;
}
TIMER_DEVICE_CALLBACK_MEMBER(decodmd_type3_device::dmd_irq)
{
m_cpu->set_input_line(M68K_IRQ_2, HOLD_LINE);
}
WRITE16_MEMBER( decodmd_type3_device::crtc_address_w )
{
if(ACCESSING_BITS_8_15)
{
m_mc6845->address_w(space,offset,data >> 8);
m_crtc_index = data >> 8;
}
}
READ16_MEMBER( decodmd_type3_device::crtc_status_r )
{
if(ACCESSING_BITS_8_15)
return m_mc6845->register_r(space,offset);
else
return 0xff;
}
WRITE16_MEMBER( decodmd_type3_device::crtc_register_w )
{
if(ACCESSING_BITS_8_15)
{
if(m_crtc_index == 9) // hack!!
data -= 0x100;
m_mc6845->register_w(space,offset,data >> 8);
m_crtc_reg[m_crtc_index] = data >> 8;
}
}
MC6845_UPDATE_ROW( decodmd_type3_device::crtc_update_row )
{
uint8_t *RAM = m_ram->pointer();
uint8_t intensity;
uint16_t addr = ((ma & 0x7ff) << 2) | ((ra & 0x02) << 12);
addr += ((ra & 0x01) * 24);
for (int x = 0; x < 192; x += 16)
{
for (int dot = 0; dot < 8; dot++)
{
intensity = ((RAM[addr + 1] >> (7-dot) & 0x01) << 1) | (RAM[addr + 0x801] >> (7-dot) & 0x01);
bitmap.pix32(y, x + dot) = rgb_t(0x3f * intensity, 0x2a * intensity, 0x00);
}
for (int dot = 8; dot < 16; dot++)
{
intensity = ((RAM[addr] >> (15-dot) & 0x01) << 1) | (RAM[addr + 0x800] >> (15-dot) & 0x01);
bitmap.pix32(y, x + dot) = rgb_t(0x3f * intensity, 0x2a * intensity, 0x00);
}
addr += 2;
}
}
void decodmd_type3_device::decodmd3_map(address_map &map)
{
map(0x00000000, 0x000fffff).bankr("dmdrom");
map(0x00800000, 0x0080ffff).bankrw("dmdram");
map(0x00c00010, 0x00c00011).rw(FUNC(decodmd_type3_device::crtc_status_r), FUNC(decodmd_type3_device::crtc_address_w));
map(0x00c00012, 0x00c00013).w(FUNC(decodmd_type3_device::crtc_register_w));
map(0x00c00020, 0x00c00021).rw(FUNC(decodmd_type3_device::latch_r), FUNC(decodmd_type3_device::status_w));
}
MACHINE_CONFIG_START(decodmd_type3_device::device_add_mconfig)
/* basic machine hardware */
MCFG_DEVICE_ADD("dmdcpu", M68000, XTAL(12'000'000))
MCFG_DEVICE_PROGRAM_MAP(decodmd3_map)
MCFG_QUANTUM_TIME(attotime::from_hz(60))
MCFG_TIMER_DRIVER_ADD_PERIODIC("irq_timer", decodmd_type3_device, dmd_irq, attotime::from_hz(150))
MCFG_MC6845_ADD("dmd6845", MC6845, nullptr, XTAL(12'000'000) / 4) // TODO: confirm clock speed
MCFG_MC6845_SHOW_BORDER_AREA(false)
MCFG_MC6845_CHAR_WIDTH(16)
MCFG_MC6845_UPDATE_ROW_CB(decodmd_type3_device, crtc_update_row)
MCFG_DEFAULT_LAYOUT(layout_lcd)
MCFG_SCREEN_ADD("dmd",RASTER)
MCFG_SCREEN_SIZE(192, 64)
MCFG_SCREEN_VISIBLE_AREA(0, 192-1, 0, 64-1)
MCFG_SCREEN_UPDATE_DEVICE("dmd6845", mc6845_device, screen_update)
MCFG_SCREEN_REFRESH_RATE(60)
MCFG_RAM_ADD(RAM_TAG)
MCFG_RAM_DEFAULT_SIZE("64K")
MACHINE_CONFIG_END
decodmd_type3_device::decodmd_type3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, DECODMD3, tag, owner, clock),
m_cpu(*this,"dmdcpu"),
m_mc6845(*this,"dmd6845"),
m_ram(*this,RAM_TAG),
m_rambank(*this,"dmdram"),
m_rombank(*this,"dmdrom")
{}
void decodmd_type3_device::device_start()
{
}
void decodmd_type3_device::device_reset()
{
uint8_t* ROM;
uint8_t* RAM = m_ram->pointer();
m_rom = memregion(m_gfxtag);
ROM = m_rom->base();
memset(RAM,0,0x10000);
m_rambank->configure_entry(0, &RAM[0]);
m_rambank->set_entry(0);
m_rombank->configure_entry(0, &ROM[0]);
m_rombank->set_entry(0);
}