saa5240.cpp: Preliminary SAA5240/43 Computer Controlled Teletext emulation.

This commit is contained in:
Nigel Barnes 2020-12-24 18:01:26 +00:00
parent 359bd05152
commit 8aacde2c3f
4 changed files with 981 additions and 0 deletions

View File

@ -853,6 +853,18 @@ if (VIDEOS["SAA5050"]~=null) then
} }
end end
--------------------------------------------------
--
--@src/devices/video/saa5240.h,VIDEOS["SAA5240"] = true
--------------------------------------------------
if (VIDEOS["SAA5240"]~=null) then
files {
MAME_DIR .. "src/devices/video/saa5240.cpp",
MAME_DIR .. "src/devices/video/saa5240.h",
}
end
-------------------------------------------------- --------------------------------------------------
-- --
--@src/devices/video/pwm.h,VIDEOS["PWM_DISPLAY"] = true --@src/devices/video/pwm.h,VIDEOS["PWM_DISPLAY"] = true

View File

@ -390,6 +390,7 @@ VIDEOS["PSX"] = true
VIDEOS["RAMDAC"] = true VIDEOS["RAMDAC"] = true
VIDEOS["S2636"] = true VIDEOS["S2636"] = true
VIDEOS["SAA5050"] = true VIDEOS["SAA5050"] = true
VIDEOS["SAA5240"] = true
VIDEOS["PWM_DISPLAY"] = true VIDEOS["PWM_DISPLAY"] = true
VIDEOS["SDA5708"] = true VIDEOS["SDA5708"] = true
VIDEOS["SED1200"] = true VIDEOS["SED1200"] = true

View File

@ -0,0 +1,741 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/*********************************************************************
Philips SAA5240 European Controlled Teletext Circuit
*********************************************************************/
#include "emu.h"
#include "saa5240.h"
#define LOG_DATA (1 << 1)
#define LOG_LINE (1 << 2)
#define VERBOSE (LOG_DATA)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(SAA5240A, saa5240a_device, "saa5240a", "SAA5240A EURO CCT")
DEFINE_DEVICE_TYPE(SAA5240B, saa5240b_device, "saa5240b", "SAA5240B EURO CCT")
DEFINE_DEVICE_TYPE(SAA5243E, saa5243e_device, "saa5243e", "SAA5243E EURO CCT")
//DEFINE_DEVICE_TYPE(SAA5243H, saa5243h_device, "saa5243h", "SAA5243H EURO CCT")
//-------------------------------------------------
// default address map
//-------------------------------------------------
void saa5240_device::saa5240_vram(address_map &map)
{
if (!has_configured_map(0))
map(0x0000, 0x1fff).ram();
}
//-------------------------------------------------
// memory_space_config - return a description of
// any address spaces owned by this device
//-------------------------------------------------
device_memory_interface::space_config_vector saa5240_device::memory_space_config() const
{
return space_config_vector {
std::make_pair(0, &m_space_config)
};
}
//-------------------------------------------------
// ROM( saa5240 )
//-------------------------------------------------
ROM_START( saa5240a )
ROM_REGION16_BE( 0xc80, "chargen", ROMREGION_ERASE00 )
ROM_LOAD("saa5240a", 0x0280, 0x0a00, BAD_DUMP CRC(e205d1fc) SHA1(cb6872260c91f0665f8c7d691c9becc327e0ecc3)) // hand made from datasheet
ROM_END
ROM_START( saa5240b )
ROM_REGION16_BE( 0xc80, "chargen", ROMREGION_ERASE00 )
ROM_LOAD("saa5240b", 0x0280, 0x0a00, BAD_DUMP CRC(7b196f2c) SHA1(61d4460ed0956ff470cc1362ea6bb1f9abe4bc03)) // hand made from datasheet
ROM_END
ROM_START( saa5243e )
ROM_REGION16_BE( 0x1180, "chargen", ROMREGION_ERASE00 )
ROM_LOAD("saa5243e", 0x0280, 0x0f00, BAD_DUMP CRC(a74402e7) SHA1(48123c9bb0377e417a147f5a68088c1ed7bee12d)) // hand made from datasheet
ROM_END
//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
const tiny_rom_entry *saa5240a_device::device_rom_region() const
{
return ROM_NAME( saa5240a );
}
const tiny_rom_entry *saa5240b_device::device_rom_region() const
{
return ROM_NAME( saa5240b );
}
const tiny_rom_entry *saa5243e_device::device_rom_region() const
{
return ROM_NAME( saa5243e );
}
#define ALPHANUMERIC 0x01
#define CONTIGUOUS 0x02
#define SEPARATED 0x03
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// saa5240_device - constructor
//-------------------------------------------------
saa5240_device::saa5240_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, device_memory_interface(mconfig, *this)
, m_char_rom(*this, "chargen")
, m_space_config("videoram", ENDIANNESS_LITTLE, 8, 13, 0, address_map_constructor(FUNC(saa5240a_device::saa5240_vram), this))
, m_slave_address(SAA5240_SLAVE_ADDRESS)
, m_i2c_scl(0)
, m_i2c_sdaw(0)
, m_i2c_sdar(1)
, m_i2c_state(STATE_IDLE)
, m_i2c_bits(0)
, m_i2c_shift(0)
, m_i2c_devsel(0)
, m_i2c_address(0)
{
}
saa5240a_device::saa5240a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
saa5240_device(mconfig, SAA5240A, tag, owner, clock)
{
}
saa5240b_device::saa5240b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
saa5240_device(mconfig, SAA5240B, tag, owner, clock)
{
}
saa5243e_device::saa5243e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
saa5240_device(mconfig, SAA5243E, tag, owner, clock)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void saa5240_device::device_start()
{
m_videoram = &space(0);
// state saving
save_item(NAME(m_i2c_scl));
save_item(NAME(m_i2c_sdaw));
save_item(NAME(m_i2c_sdar));
save_item(NAME(m_i2c_state));
save_item(NAME(m_i2c_bits));
save_item(NAME(m_i2c_shift));
save_item(NAME(m_i2c_devsel));
save_item(NAME(m_i2c_address));
save_item(NAME(m_register));
save_item(NAME(m_slave_address));
}
void saa5240_device::device_reset()
{
// memmory is cleared to 'space' on power-up
for (int i = 0; i < 0x1fff; i++)
m_videoram->write_byte(i, 0x20);
// row 0 column 7 chapter 0 is alpha white
m_videoram->write_byte(7, 0x07);
// reset registers
std::fill(std::begin(m_register), std::end(m_register), 0x00);
m_register[5] = 0x03;
m_register[6] = 0x03;
}
//**************************************************************************
// READ/WRITE HANDLERS
//**************************************************************************
WRITE_LINE_MEMBER(saa5240_device::write_scl)
{
if (m_i2c_scl != state)
{
m_i2c_scl = state;
LOGMASKED(LOG_LINE, "set_scl_line %d\n", m_i2c_scl);
switch (m_i2c_state)
{
case STATE_DEVSEL:
case STATE_ADDRESS:
case STATE_DATAIN:
if (m_i2c_bits < 8)
{
if (m_i2c_scl)
{
m_i2c_shift = ((m_i2c_shift << 1) | m_i2c_sdaw) & 0xff;
m_i2c_bits++;
}
}
else
{
if (m_i2c_scl)
{
switch (m_i2c_state)
{
case STATE_DEVSEL:
m_i2c_devsel = m_i2c_shift;
if ((m_i2c_devsel & 0xfe) != m_slave_address)
{
LOGMASKED(LOG_DATA, "devsel %02x: not this device\n", m_i2c_devsel);
m_i2c_state = STATE_IDLE;
}
else if ((m_i2c_devsel & 1) == 0)
{
LOGMASKED(LOG_DATA, "devsel %02x: write\n", m_i2c_devsel);
m_i2c_state = STATE_ADDRESS;
}
else
{
LOGMASKED(LOG_DATA, "devsel %02x: read\n", m_i2c_devsel);
m_i2c_state = STATE_DATAOUT;
}
break;
case STATE_ADDRESS:
m_i2c_address = m_i2c_shift;
LOGMASKED(LOG_DATA, "address %02x\n", m_i2c_shift);
m_i2c_state = STATE_DATAIN;
break;
case STATE_DATAIN:
m_register[m_i2c_address] = m_i2c_shift;
LOGMASKED(LOG_DATA, "data[ %02x ] <- %02x\n", m_i2c_address, m_i2c_shift);
switch (m_i2c_address)
{
case 1: case 2: case 3: case 4: case 5: case 6:
// auto-increment register
m_i2c_address++;
break;
case 8:
// active chapter - clear memory
//if (BIT(m_register[8], 3))
//{
// for (int i = 0; i < 0x3ff; i++)
// m_videoram->write_byte((m_register[8] & 0x07) * 0x400 + i, 0x20);
//}
[[fallthrough]];
case 9: case 10:
update_active_data();
// auto-increment register
m_i2c_address++;
break;
case 11:
// active data
offs_t offset = (m_register[8] & 0x07) * 0x400 + (m_register[9] & 0x1f) * 40 + (m_register[10] & 0x3f);
m_videoram->write_byte(offset, m_i2c_shift);
increment_active_data();
break;
}
break;
}
m_i2c_bits++;
}
else
{
if (m_i2c_bits == 8)
{
m_i2c_sdar = 0;
}
else
{
m_i2c_bits = 0;
m_i2c_sdar = 1;
}
}
}
break;
case STATE_DATAOUT:
if (m_i2c_bits < 8)
{
if (m_i2c_scl)
{
if (m_i2c_bits == 0)
{
m_i2c_shift = m_register[m_i2c_address];
LOGMASKED(LOG_DATA, "data[ %02x ] -> %02x\n", m_i2c_address, m_i2c_shift);
if (m_i2c_address == 11)
increment_active_data();
// FIXME: is this conditional?
if (BIT(m_register[1], 6))
{
// 7 bits with parity checking
m_i2c_shift &= 0x7f;
m_i2c_shift = (m_i2c_shift << 1) | calc_parity(m_i2c_shift);
}
}
m_i2c_sdar = (m_i2c_shift >> 7) & 1;
m_i2c_shift = (m_i2c_shift << 1) & 0xff;
m_i2c_bits++;
}
}
else
{
if (m_i2c_scl)
{
if (m_i2c_sdaw)
{
LOGMASKED(LOG_DATA, "nack\n");
m_i2c_state = STATE_IDLE;
}
m_i2c_bits++;
}
else
{
if (m_i2c_bits == 8)
{
m_i2c_sdar = 1;
}
else
{
m_i2c_bits = 0;
}
}
}
break;
}
}
}
WRITE_LINE_MEMBER(saa5240_device::write_sda)
{
state &= 1;
if (m_i2c_sdaw != state)
{
LOGMASKED(LOG_LINE, "set sda %d\n", state);
m_i2c_sdaw = state;
if (m_i2c_scl)
{
if (m_i2c_sdaw)
{
LOGMASKED(LOG_DATA, "stop\n");
m_i2c_state = STATE_IDLE;
}
else
{
LOGMASKED(LOG_DATA, "start\n");
m_i2c_state = STATE_DEVSEL;
m_i2c_bits = 0;
}
m_i2c_sdar = 1;
}
}
}
READ_LINE_MEMBER(saa5240_device::read_sda)
{
int res = m_i2c_sdar & 1;
LOGMASKED(LOG_LINE, "read sda %d\n", res);
return res;
}
void saa5240_device::increment_active_data()
{
// auto-increment column
m_register[10]++;
if (m_register[10] >= 40)
{
m_register[10] = 0;
m_register[9]++;
}
update_active_data();
}
void saa5240_device::update_active_data()
{
offs_t offset = (m_register[8] & 0x07) * 0x400 + (m_register[9] & 0x1f) * 40 + (m_register[10] & 0x3f);
m_register[11] = m_videoram->read_byte(offset);
}
//-------------------------------------------------
// calculate the byte parity
//-------------------------------------------------
int saa5240_device::calc_parity(uint8_t data)
{
uint8_t count = 0;
while(data != 0)
{
count++;
data &= (data-1);
}
return (count ^ 1) & 1;
}
//-------------------------------------------------
// process_control_character
//-------------------------------------------------
void saa5240_device::process_control_character(uint8_t data)
{
m_hold_clear = false;
m_hold_off = false;
switch (data)
{
case ALPHA_RED:
case ALPHA_GREEN:
case ALPHA_YELLOW:
case ALPHA_BLUE:
case ALPHA_MAGENTA:
case ALPHA_CYAN:
case ALPHA_WHITE:
m_graphics = false;
m_hold_clear = true;
m_fg = data & 0x07;
set_next_chartype();
break;
case FLASH:
m_flash = true;
break;
case STEADY:
m_flash = false;
break;
case END_BOX:
case START_BOX:
// TODO
break;
case NORMAL_HEIGHT:
case DOUBLE_HEIGHT:
m_double_height = !!(data & 1);
if (m_double_height) m_double_height_prev_row = true;
break;
case GRAPHICS_RED:
case GRAPHICS_GREEN:
case GRAPHICS_YELLOW:
case GRAPHICS_BLUE:
case GRAPHICS_MAGENTA:
case GRAPHICS_CYAN:
case GRAPHICS_WHITE:
m_graphics = true;
m_fg = data & 0x07;
set_next_chartype();
break;
case CONCEAL_DISPLAY:
m_fg = m_prev_col = m_bg;
break;
case CONTIGUOUS_GFX:
m_separated = false;
set_next_chartype();
break;
case SEPARATED_GFX:
m_separated = true;
set_next_chartype();
break;
case BLACK_BACKGROUND:
m_bg = 0;
break;
case NEW_BACKGROUND:
m_bg = m_fg;
break;
case HOLD_GRAPHICS:
m_hold_char = true;
break;
case RELEASE_GRAPHICS:
m_hold_off = true;
break;
}
}
void saa5240_device::set_next_chartype()
{
if (m_graphics)
{
if (m_separated)
m_next_chartype = SEPARATED;
else
m_next_chartype = CONTIGUOUS;
}
else
{
m_next_chartype = ALPHANUMERIC;
}
};
//-------------------------------------------------
// get_gfx_data - graphics generator
//-------------------------------------------------
uint16_t saa5240_device::get_gfx_data(uint8_t data, offs_t row, bool separated)
{
uint16_t c = 0;
switch (row >> 1)
{
case 0: case 1:
c += (data & 0x01) ? 0xfc0 : 0; // bit 1 top left
c += (data & 0x02) ? 0x03f : 0; // bit 2 top right
if (separated) c &= 0x3cf;
break;
case 2:
if (separated) break;
c += (data & 0x01) ? 0xfc0 : 0; // bit 1 top left
c += (data & 0x02) ? 0x03f : 0; // bit 2 top right
break;
case 3: case 4: case 5:
c += (data & 0x04) ? 0xfc0 : 0; // bit 3 middle left
c += (data & 0x08) ? 0x03f : 0; // bit 4 middle right
if (separated) c &= 0x3cf;
break;
case 6:
if (separated) break;
c += (data & 0x04) ? 0xfc0 : 0; // bit 3 middle left
c += (data & 0x08) ? 0x03f : 0; // bit 4 middle right
break;
case 7: case 8:
c += (data & 0x10) ? 0xfc0 : 0; // bit 5 bottom left
c += (data & 0x40) ? 0x03f : 0; // bit 7 bottom right
if (separated) c &= 0x3cf;
break;
case 9:
if (separated) break;
c += (data & 0x10) ? 0xfc0 : 0; // bit 5 bottom left
c += (data & 0x40) ? 0x03f : 0; // bit 7 bottom right
break;
}
return c;
}
//-------------------------------------------------
// get_rom_data - read rom
//-------------------------------------------------
uint16_t saa5240_device::get_rom_data(uint8_t data, offs_t row)
{
uint16_t c;
if (row < 0 || row >= 10)
{
c = 0;
}
else
{
c = m_char_rom[(data * 10) + row];
}
return c;
}
//-------------------------------------------------
// get_character_data
//-------------------------------------------------
void saa5240_device::get_character_data(uint8_t data)
{
m_double_height_old = m_double_height;
m_prev_col = m_fg;
m_curr_chartype = m_next_chartype;
if (data < 0x20)
{
process_control_character(data);
if (m_hold_char && m_double_height == m_double_height_old)
{
data = m_held_char;
if (data >= 0x40 && data < 0x60) data = 0x20;
m_curr_chartype = m_held_chartype;
}
else
{
data = 0x20;
}
}
else if (m_graphics)
{
m_held_char = data;
m_held_chartype = m_curr_chartype;
}
offs_t ra = m_ra;
if (m_double_height_old)
{
ra >>= 1;
if (m_double_height_bottom_row) ra += 10;
}
if (m_flash && (m_frame_count > 38)) data = 0x20;
if (m_double_height_bottom_row && !m_double_height) data = 0x20;
if (m_hold_off)
{
m_hold_char = false;
m_held_char = 32;
}
if (m_hold_clear)
{
m_held_char = 32;
}
if (m_curr_chartype == ALPHANUMERIC || !BIT(data,5))
m_char_data = get_rom_data(data, ra);
else
m_char_data = get_gfx_data(data, ra, (m_curr_chartype == SEPARATED));
}
//-------------------------------------------------
// vcs_w - video composite sync
//-------------------------------------------------
WRITE_LINE_MEMBER(saa5240_device::vcs_w)
{
if (state)
{
m_ra++;
m_ra %= 10;
if (!m_ra)
{
if (m_double_height_bottom_row)
m_double_height_bottom_row = false;
else
m_double_height_bottom_row = m_double_height_prev_row;
}
m_fg = 7;
m_bg = 0;
m_graphics = false;
m_separated = false;
m_flash = false;
m_boxed = false;
m_hold_char = false;
m_held_char = 0x20;
m_next_chartype = ALPHANUMERIC;
m_held_chartype = ALPHANUMERIC;
m_double_height = false;
m_double_height_prev_row = false;
m_bit = 11;
}
}
//-------------------------------------------------
// f6_w - character display clock
//-------------------------------------------------
WRITE_LINE_MEMBER(saa5240_device::f6_w)
{
if (state)
{
m_color = BIT(m_char_data, m_bit) ? m_prev_col : m_bg;
m_bit--;
if (m_bit < 0)
{
m_bit = 11;
}
}
}
//-------------------------------------------------
// get_rgb - get output color
//-------------------------------------------------
int saa5240_device::get_rgb()
{
return m_color;
}
//-------------------------------------------------
// screen_update
//-------------------------------------------------
uint32_t saa5240_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
for (int y = 0; y < 25 * 10; y++)
{
int sy = y / 10;
int x = 0;
vcs_w(1);
vcs_w(0);
for (int sx = 0; sx < 40; sx++)
{
uint8_t code = m_videoram->read_byte((sy * 40) + sx) & 0x7f;
get_character_data(code);
for (int bit = 0; bit < 12; bit++)
{
f6_w(1);
f6_w(0);
int color = get_rgb();
if (BIT(code, 7)) color ^= 0x07;
int r = BIT(color, 0) * 0xff;
int g = BIT(color, 1) * 0xff;
int b = BIT(color, 2) * 0xff;
bitmap.pix(y, x++) = rgb_t(r, g, b);
}
}
}
return 0;
}

227
src/devices/video/saa5240.h Normal file
View File

@ -0,0 +1,227 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/*********************************************************************
Philips SAA5240 European Controlled Teletext Circuit
**********************************************************************
Pinning: ____ ____
| \/ |
Vdd 1 | | 40 A10
A11 2 | | 39 A9
A12 3 | | 38 A8
nOE 4 | | 37 A7
nWE 5 | | 36 A6
TTD 6 | | 35 A5
TTC 7 | | 34 A4
HDK 8 | | 33 A3
F6 9 | | 32 A2
VCS 10 | SAA5240 | 31 A1
SAND 11 | | 30 A0
nTCS/nSCS 12 | | 29 D7
R 13 | | 28 D6
G 14 | | 27 D5
B 15 | | 26 D4
nCOR 16 | | 25 D3
BLAN 17 | | 24 D2
Y 18 | | 23 D1
SCL 19 | | 22 D0
SDA 20 | | 21 Vss
|__________|
*********************************************************************/
#ifndef MAME_VIDEO_SAA5240_H
#define MAME_VIDEO_SAA5240_H
#pragma once
//**************************************************************************
// CONSTANTS
//**************************************************************************
#define SAA5240_SLAVE_ADDRESS ( 0x22 )
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> saa5240_device
class saa5240_device :
public device_t,
public device_memory_interface
{
public:
// construction/destruction
saa5240_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_WRITE_LINE_MEMBER(write_scl);
DECLARE_WRITE_LINE_MEMBER(write_sda);
DECLARE_READ_LINE_MEMBER(read_sda);
DECLARE_WRITE_LINE_MEMBER(vcs_w);
DECLARE_WRITE_LINE_MEMBER(f6_w);
int get_rgb();
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
protected:
saa5240_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
// optional information overrides
virtual space_config_vector memory_space_config() const override;
private:
required_region_ptr<uint16_t> m_char_rom;
const address_space_config m_space_config;
address_space *m_videoram;
// internal state
uint8_t m_register[12];
int m_slave_address;
int m_i2c_scl;
int m_i2c_sdaw;
int m_i2c_sdar;
int m_i2c_state;
int m_i2c_bits;
int m_i2c_shift;
int m_i2c_devsel;
int m_i2c_address;
void increment_active_data();
void update_active_data();
enum { STATE_IDLE, STATE_DEVSEL, STATE_ADDRESS, STATE_DATAIN, STATE_DATAOUT };
void saa5240_vram(address_map &map);
enum
{
NUL = 0,
ALPHA_RED,
ALPHA_GREEN,
ALPHA_YELLOW,
ALPHA_BLUE,
ALPHA_MAGENTA,
ALPHA_CYAN,
ALPHA_WHITE,
FLASH,
STEADY,
END_BOX,
START_BOX,
NORMAL_HEIGHT,
DOUBLE_HEIGHT,
S0,
S1,
DLE,
GRAPHICS_RED,
GRAPHICS_GREEN,
GRAPHICS_YELLOW,
GRAPHICS_BLUE,
GRAPHICS_MAGENTA,
GRAPHICS_CYAN,
GRAPHICS_WHITE,
CONCEAL_DISPLAY,
CONTIGUOUS_GFX,
SEPARATED_GFX,
ESC,
BLACK_BACKGROUND,
NEW_BACKGROUND,
HOLD_GRAPHICS,
RELEASE_GRAPHICS
};
void process_control_character(uint8_t data);
void set_next_chartype();
uint16_t get_gfx_data(uint8_t data, offs_t row, bool separated);
uint16_t get_rom_data(uint8_t data, offs_t row);
void get_character_data(uint8_t data);
uint8_t m_held_char;
uint8_t m_next_chartype;
uint8_t m_curr_chartype;
uint8_t m_held_chartype;
uint16_t m_char_data;
int m_bit;
rgb_t m_color;
int m_crs;
int m_ra;
int m_bg;
int m_fg;
int m_prev_col;
bool m_graphics;
bool m_separated;
bool m_flash;
bool m_boxed;
bool m_double_height;
bool m_double_height_old;
bool m_double_height_bottom_row;
bool m_double_height_prev_row;
bool m_hold_char;
bool m_hold_clear;
bool m_hold_off;
int m_frame_count;
// internal helpers
int calc_parity(uint8_t data);
};
// ======================> saa5240a_device
class saa5240a_device : public saa5240_device
{
public:
// construction/destruction
saa5240a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// optional information overrides
virtual const tiny_rom_entry *device_rom_region() const override;
};
// ======================> saa5240b_device
class saa5240b_device : public saa5240_device
{
public:
// construction/destruction
saa5240b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// optional information overrides
virtual const tiny_rom_entry *device_rom_region() const override;
};
// ======================> saa5243e_device
class saa5243e_device : public saa5240_device
{
public:
// construction/destruction
saa5243e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// optional information overrides
virtual const tiny_rom_entry *device_rom_region() const override;
};
// device type definition
DECLARE_DEVICE_TYPE(SAA5240A, saa5240a_device) // English, German, Swedish
DECLARE_DEVICE_TYPE(SAA5240B, saa5240b_device) // Italian, German, French
DECLARE_DEVICE_TYPE(SAA5243E, saa5243e_device) // West European
//DECLARE_DEVICE_TYPE(SAA5243H, saa5243h_device) // East European
#endif // MAME_VIDEO_SAA5240_H