mirror of
https://github.com/holub/mame
synced 2025-07-01 08:18:59 +03:00
modernized the TMS9927 device [Fabio Priuli]
This commit is contained in:
parent
a5695f8fda
commit
cee3efaa03
@ -8,317 +8,59 @@
|
||||
**********************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "tms9927.h"
|
||||
#include "video/tms9927.h"
|
||||
|
||||
|
||||
static const UINT8 chars_per_row_value[8] = { 20, 32, 40, 64, 72, 80, 96, 132 };
|
||||
static const UINT8 skew_bits_value[4] = { 0, 1, 2, 2 };
|
||||
|
||||
|
||||
#define HCOUNT(t) ((t)->reg[0] + 1)
|
||||
#define INTERLACED(t) (((t)->reg[1] >> 7) & 0x01)
|
||||
#define HSYNC_WIDTH(t) (((t)->reg[1] >> 4) & 0x0f)
|
||||
#define HSYNC_DELAY(t) (((t)->reg[1] >> 0) & 0x07)
|
||||
#define SCANS_PER_DATA_ROW(t) ((((t)->reg[2] >> 3) & 0x0f) + 1)
|
||||
#define CHARS_PER_DATA_ROW(t) (chars_per_row_value[((t)->reg[2] >> 0) & 0x07])
|
||||
#define SKEW_BITS(t) (skew_bits_value[((t)->reg[3] >> 6) & 0x03])
|
||||
#define DATA_ROWS_PER_FRAME(t) ((((t)->reg[3] >> 0) & 0x3f) + 1)
|
||||
#define SCAN_LINES_PER_FRAME(t) (((t)->reg[4] * 2) + 256)
|
||||
#define VERTICAL_DATA_START(t) ((t)->reg[5])
|
||||
#define LAST_DISP_DATA_ROW(t) ((t)->reg[6] & 0x3f)
|
||||
#define CURSOR_CHAR_ADDRESS(t) ((t)->reg[7])
|
||||
#define CURSOR_ROW_ADDRESS(t) ((t)->reg[8] & 0x3f)
|
||||
#define HCOUNT (m_reg[0] + 1)
|
||||
#define INTERLACED ((m_reg[1] >> 7) & 0x01)
|
||||
#define HSYNC_WIDTH ((m_reg[1] >> 4) & 0x0f)
|
||||
#define HSYNC_DELAY ((m_reg[1] >> 0) & 0x07)
|
||||
#define SCANS_PER_DATA_ROW (((m_reg[2] >> 3) & 0x0f) + 1)
|
||||
#define CHARS_PER_DATA_ROW (chars_per_row_value[(m_reg[2] >> 0) & 0x07])
|
||||
#define SKEW_BITS (skew_bits_value[(m_reg[3] >> 6) & 0x03])
|
||||
#define DATA_ROWS_PER_FRAME (((m_reg[3] >> 0) & 0x3f) + 1)
|
||||
#define SCAN_LINES_PER_FRAME ((m_reg[4] * 2) + 256)
|
||||
#define VERTICAL_DATA_START (m_reg[5])
|
||||
#define LAST_DISP_DATA_ROW (m_reg[6] & 0x3f)
|
||||
#define CURSOR_CHAR_ADDRESS (m_reg[7])
|
||||
#define CURSOR_ROW_ADDRESS (m_reg[8] & 0x3f)
|
||||
|
||||
|
||||
struct tms9927_state
|
||||
{
|
||||
/* driver-controlled state */
|
||||
const tms9927_interface *intf;
|
||||
screen_device *screen;
|
||||
const UINT8 *selfload;
|
||||
|
||||
/* live state */
|
||||
UINT32 clock;
|
||||
UINT8 reg[9];
|
||||
UINT8 start_datarow;
|
||||
UINT8 reset;
|
||||
UINT8 hpixels_per_column;
|
||||
|
||||
/* derived state; no need to save */
|
||||
UINT8 valid_config;
|
||||
UINT16 total_hpix, total_vpix;
|
||||
UINT16 visible_hpix, visible_vpix;
|
||||
};
|
||||
|
||||
|
||||
static void tms9927_state_save_postload(tms9927_state *state);
|
||||
static void recompute_parameters(tms9927_state *tms, int postload);
|
||||
|
||||
|
||||
const tms9927_interface tms9927_null_interface = { 0 };
|
||||
|
||||
|
||||
/* makes sure that the passed in device is the right type */
|
||||
INLINE tms9927_state *get_safe_token(device_t *device)
|
||||
{
|
||||
assert(device != NULL);
|
||||
assert(device->type() == TMS9927);
|
||||
return (tms9927_state *)downcast<tms9927_device *>(device)->token();
|
||||
}
|
||||
|
||||
|
||||
static void tms9927_state_save_postload(tms9927_state *state)
|
||||
{
|
||||
recompute_parameters(state, TRUE);
|
||||
}
|
||||
|
||||
|
||||
static void generic_access(device_t *device, address_space &space, offs_t offset)
|
||||
{
|
||||
tms9927_state *tms = get_safe_token(device);
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0x07: /* Processor Self Load */
|
||||
case 0x0f: /* Non-processor self-load */
|
||||
if (tms->selfload != NULL)
|
||||
{
|
||||
int cur;
|
||||
|
||||
for (cur = 0; cur < 7; cur++)
|
||||
tms9927_w(device, space, cur, tms->selfload[cur]);
|
||||
for (cur = 0; cur < 1; cur++)
|
||||
tms9927_w(device, space, cur + 0xc, tms->selfload[cur + 7]);
|
||||
}
|
||||
else
|
||||
popmessage("tms9927: self-load initiated with no PROM!");
|
||||
|
||||
/* processor self-load waits with reset enabled;
|
||||
non-processor just goes ahead */
|
||||
tms->reset = (offset == 0x07);
|
||||
break;
|
||||
|
||||
case 0x0a: /* Reset */
|
||||
if (!tms->reset)
|
||||
{
|
||||
tms->screen->update_now();
|
||||
tms->reset = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0b: /* Up scroll */
|
||||
mame_printf_debug("Up scroll\n");
|
||||
tms->screen->update_now();
|
||||
tms->start_datarow = (tms->start_datarow + 1) % DATA_ROWS_PER_FRAME(tms);
|
||||
break;
|
||||
|
||||
case 0x0e: /* Start timing chain */
|
||||
if (tms->reset)
|
||||
{
|
||||
tms->screen->update_now();
|
||||
tms->reset = FALSE;
|
||||
recompute_parameters(tms, FALSE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WRITE8_DEVICE_HANDLER( tms9927_w )
|
||||
{
|
||||
tms9927_state *tms = get_safe_token(device);
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0x00: /* HORIZONTAL CHARACTER COUNT */
|
||||
case 0x01: /* INTERLACED / HSYNC WIDTH / HSYNC DELAY */
|
||||
case 0x02: /* SCANS PER DATA ROW / CHARACTERS PER DATA ROW */
|
||||
case 0x03: /* SKEW BITS / DATA ROWS PER FRAME */
|
||||
case 0x04: /* SCAN LINES / FRAME */
|
||||
case 0x05: /* VERTICAL DATA START */
|
||||
case 0x06: /* LAST DISPLAYED DATA ROW */
|
||||
tms->reg[offset] = data;
|
||||
recompute_parameters(tms, FALSE);
|
||||
break;
|
||||
|
||||
case 0x0c: /* LOAD CURSOR CHARACTER ADDRESS */
|
||||
case 0x0d: /* LOAD CURSOR ROW ADDRESS */
|
||||
mame_printf_debug("Cursor address changed\n");
|
||||
tms->reg[offset - 0x0c + 7] = data;
|
||||
recompute_parameters(tms, FALSE);
|
||||
break;
|
||||
|
||||
default:
|
||||
generic_access(device, space, offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
READ8_DEVICE_HANDLER( tms9927_r )
|
||||
{
|
||||
tms9927_state *tms = get_safe_token(device);
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0x08: /* READ CURSOR CHARACTER ADDRESS */
|
||||
case 0x09: /* READ CURSOR ROW ADDRESS */
|
||||
return tms->reg[offset - 0x08 + 7];
|
||||
|
||||
default:
|
||||
generic_access(device, space, offset);
|
||||
break;
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
|
||||
int tms9927_screen_reset(device_t *device)
|
||||
{
|
||||
tms9927_state *tms = get_safe_token(device);
|
||||
return tms->reset;
|
||||
}
|
||||
|
||||
|
||||
int tms9927_upscroll_offset(device_t *device)
|
||||
{
|
||||
tms9927_state *tms = get_safe_token(device);
|
||||
return tms->start_datarow;
|
||||
}
|
||||
|
||||
|
||||
int tms9927_cursor_bounds(device_t *device, rectangle &bounds)
|
||||
{
|
||||
tms9927_state *tms = get_safe_token(device);
|
||||
int cursorx = CURSOR_CHAR_ADDRESS(tms);
|
||||
int cursory = CURSOR_ROW_ADDRESS(tms);
|
||||
|
||||
bounds.min_x = cursorx * tms->hpixels_per_column;
|
||||
bounds.max_x = bounds.min_x + tms->hpixels_per_column - 1;
|
||||
bounds.min_y = cursory * SCANS_PER_DATA_ROW(tms);
|
||||
bounds.max_y = bounds.min_y + SCANS_PER_DATA_ROW(tms) - 1;
|
||||
|
||||
return (cursorx < HCOUNT(tms) && cursory <= LAST_DISP_DATA_ROW(tms));
|
||||
}
|
||||
|
||||
|
||||
static void recompute_parameters(tms9927_state *tms, int postload)
|
||||
{
|
||||
UINT16 offset_hpix, offset_vpix;
|
||||
attoseconds_t refresh;
|
||||
rectangle visarea;
|
||||
|
||||
if (tms->intf == NULL || tms->reset)
|
||||
return;
|
||||
|
||||
/* compute the screen sizes */
|
||||
tms->total_hpix = HCOUNT(tms) * tms->hpixels_per_column;
|
||||
tms->total_vpix = SCAN_LINES_PER_FRAME(tms);
|
||||
|
||||
/* determine the visible area, avoid division by 0 */
|
||||
tms->visible_hpix = CHARS_PER_DATA_ROW(tms) * tms->hpixels_per_column;
|
||||
tms->visible_vpix = (LAST_DISP_DATA_ROW(tms) + 1) * SCANS_PER_DATA_ROW(tms);
|
||||
|
||||
/* determine the horizontal/vertical offsets */
|
||||
offset_hpix = HSYNC_DELAY(tms) * tms->hpixels_per_column;
|
||||
offset_vpix = VERTICAL_DATA_START(tms);
|
||||
|
||||
mame_printf_debug("TMS9937: Total = %dx%d, Visible = %dx%d, Offset=%dx%d, Skew=%d\n", tms->total_hpix, tms->total_vpix, tms->visible_hpix, tms->visible_vpix, offset_hpix, offset_vpix, SKEW_BITS(tms));
|
||||
|
||||
/* see if it all makes sense */
|
||||
tms->valid_config = TRUE;
|
||||
if (tms->visible_hpix > tms->total_hpix || tms->visible_vpix > tms->total_vpix)
|
||||
{
|
||||
tms->valid_config = FALSE;
|
||||
logerror("tms9927: invalid visible size (%dx%d) versus total size (%dx%d)\n", tms->visible_hpix, tms->visible_vpix, tms->total_hpix, tms->total_vpix);
|
||||
}
|
||||
|
||||
/* update */
|
||||
if (!tms->valid_config)
|
||||
return;
|
||||
|
||||
/* create a visible area */
|
||||
/* fix me: how do the offsets fit in here? */
|
||||
visarea.set(0, tms->visible_hpix - 1, 0, tms->visible_vpix - 1);
|
||||
|
||||
refresh = HZ_TO_ATTOSECONDS(tms->clock) * tms->total_hpix * tms->total_vpix;
|
||||
|
||||
tms->screen->configure(tms->total_hpix, tms->total_vpix, visarea, refresh);
|
||||
}
|
||||
|
||||
|
||||
/* device interface */
|
||||
static DEVICE_START( tms9927 )
|
||||
{
|
||||
tms9927_state *tms = get_safe_token(device);
|
||||
|
||||
/* validate arguments */
|
||||
assert(device != NULL);
|
||||
|
||||
tms->intf = (const tms9927_interface *)device->static_config();
|
||||
|
||||
if (tms->intf != NULL)
|
||||
{
|
||||
assert(device->clock() > 0);
|
||||
assert(tms->intf->hpixels_per_column > 0);
|
||||
|
||||
/* copy the initial parameters */
|
||||
tms->clock = device->clock();
|
||||
tms->hpixels_per_column = tms->intf->hpixels_per_column;
|
||||
|
||||
/* get the screen device */
|
||||
tms->screen = downcast<screen_device *>(device->machine().device(tms->intf->screen_tag));
|
||||
assert(tms->screen != NULL);
|
||||
|
||||
/* get the self-load PROM */
|
||||
if (tms->intf->selfload_region != NULL)
|
||||
{
|
||||
tms->selfload = device->machine().root_device().memregion(tms->intf->selfload_region)->base();
|
||||
assert(tms->selfload != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* register for state saving */
|
||||
device->machine().save().register_postload(save_prepost_delegate(FUNC(tms9927_state_save_postload), tms));
|
||||
|
||||
device->save_item(NAME(tms->clock));
|
||||
device->save_item(NAME(tms->reg));
|
||||
device->save_item(NAME(tms->start_datarow));
|
||||
device->save_item(NAME(tms->reset));
|
||||
device->save_item(NAME(tms->hpixels_per_column));
|
||||
}
|
||||
|
||||
|
||||
static DEVICE_STOP( tms9927 )
|
||||
{
|
||||
tms9927_state *tms = get_safe_token(device);
|
||||
|
||||
mame_printf_debug("TMS9937: Final params: (%d, %d, %d, %d, %d, %d, %d)\n",
|
||||
tms->clock,
|
||||
tms->total_hpix,
|
||||
0, tms->visible_hpix,
|
||||
tms->total_vpix,
|
||||
0, tms->visible_vpix);
|
||||
}
|
||||
|
||||
|
||||
static DEVICE_RESET( tms9927 )
|
||||
{
|
||||
}
|
||||
|
||||
const device_type TMS9927 = &device_creator<tms9927_device>;
|
||||
const device_type CRT5027 = &device_creator<crt5027_device>;
|
||||
const device_type CRT5037 = &device_creator<crt5037_device>;
|
||||
const device_type CRT5057 = &device_creator<crt5057_device>;
|
||||
|
||||
tms9927_device::tms9927_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, TMS9927, "TMS9927", tag, owner, clock)
|
||||
: device_t(mconfig, TMS9927, "TMS9927", tag, owner, clock)
|
||||
{
|
||||
m_token = global_alloc_clear(tms9927_state);
|
||||
}
|
||||
|
||||
tms9927_device::tms9927_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, type, name, tag, owner, clock)
|
||||
: device_t(mconfig, type, name, tag, owner, clock)
|
||||
{
|
||||
m_token = global_alloc_clear(tms9927_state);
|
||||
}
|
||||
|
||||
crt5027_device::crt5027_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: tms9927_device(mconfig, CRT5027, "CRT5027", tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
crt5037_device::crt5037_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: tms9927_device(mconfig, CRT5037, "CRT5037", tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
crt5057_device::crt5057_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: tms9927_device(mconfig, CRT5057, "CRT5057", tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_config_complete - perform any
|
||||
// operations now that the configuration is
|
||||
@ -327,6 +69,12 @@ tms9927_device::tms9927_device(const machine_config &mconfig, device_type type,
|
||||
|
||||
void tms9927_device::device_config_complete()
|
||||
{
|
||||
// inherit a copy of the static data
|
||||
const tms9927_interface *intf = reinterpret_cast<const tms9927_interface *>(static_config());
|
||||
|
||||
assert(intf != NULL);
|
||||
|
||||
*static_cast<tms9927_interface *>(this) = *intf;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -335,7 +83,29 @@ void tms9927_device::device_config_complete()
|
||||
|
||||
void tms9927_device::device_start()
|
||||
{
|
||||
DEVICE_START_NAME( tms9927 )(this);
|
||||
assert(clock() > 0);
|
||||
assert(m_hpixels_per_column > 0);
|
||||
|
||||
/* copy the initial parameters */
|
||||
m_clock = clock();
|
||||
|
||||
/* get the screen device */
|
||||
m_screen = downcast<screen_device *>(machine().device(m_screen_tag));
|
||||
assert(m_screen != NULL);
|
||||
|
||||
/* get the self-load PROM */
|
||||
if (m_selfload_region != NULL)
|
||||
{
|
||||
m_selfload = machine().root_device().memregion(m_selfload_region)->base();
|
||||
assert(m_selfload != NULL);
|
||||
}
|
||||
|
||||
/* register for state saving */
|
||||
machine().save().register_postload(save_prepost_delegate(FUNC(tms9927_device::state_postload), this));
|
||||
|
||||
save_item(NAME(m_reg));
|
||||
save_item(NAME(m_start_datarow));
|
||||
save_item(NAME(m_reset));
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -344,7 +114,6 @@ void tms9927_device::device_start()
|
||||
|
||||
void tms9927_device::device_reset()
|
||||
{
|
||||
DEVICE_RESET_NAME( tms9927 )(this);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -353,29 +122,182 @@ void tms9927_device::device_reset()
|
||||
|
||||
void tms9927_device::device_stop()
|
||||
{
|
||||
DEVICE_STOP_NAME( tms9927 )(this);
|
||||
mame_printf_debug("TMS9937: Final params: (%d, %d, %d, %d, %d, %d, %d)\n",
|
||||
m_clock,
|
||||
m_total_hpix,
|
||||
0, m_visible_hpix,
|
||||
m_total_vpix,
|
||||
0, m_visible_vpix);
|
||||
}
|
||||
|
||||
|
||||
const device_type CRT5027 = &device_creator<crt5027_device>;
|
||||
|
||||
crt5027_device::crt5027_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: tms9927_device(mconfig, CRT5027, "CRT5027", tag, owner, clock)
|
||||
|
||||
void tms9927_device::state_postload()
|
||||
{
|
||||
recompute_parameters(TRUE);
|
||||
}
|
||||
|
||||
|
||||
const device_type CRT5037 = &device_creator<crt5037_device>;
|
||||
|
||||
crt5037_device::crt5037_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: tms9927_device(mconfig, CRT5037, "CRT5037", tag, owner, clock)
|
||||
void tms9927_device::generic_access(address_space &space, offs_t offset)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0x07: /* Processor Self Load */
|
||||
case 0x0f: /* Non-processor self-load */
|
||||
if (m_selfload != NULL)
|
||||
{
|
||||
for (int cur = 0; cur < 7; cur++)
|
||||
write(space, cur, m_selfload[cur]);
|
||||
for (int cur = 0; cur < 1; cur++)
|
||||
write(space, cur + 0xc, m_selfload[cur + 7]);
|
||||
}
|
||||
else
|
||||
popmessage("tms9927: self-load initiated with no PROM!");
|
||||
|
||||
/* processor self-load waits with reset enabled;
|
||||
non-processor just goes ahead */
|
||||
m_reset = (offset == 0x07);
|
||||
break;
|
||||
|
||||
case 0x0a: /* Reset */
|
||||
if (!m_reset)
|
||||
{
|
||||
m_screen->update_now();
|
||||
m_reset = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0b: /* Up scroll */
|
||||
mame_printf_debug("Up scroll\n");
|
||||
m_screen->update_now();
|
||||
m_start_datarow = (m_start_datarow + 1) % DATA_ROWS_PER_FRAME;
|
||||
break;
|
||||
|
||||
case 0x0e: /* Start timing chain */
|
||||
if (m_reset)
|
||||
{
|
||||
m_screen->update_now();
|
||||
m_reset = FALSE;
|
||||
recompute_parameters(FALSE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const device_type CRT5057 = &device_creator<crt5057_device>;
|
||||
|
||||
crt5057_device::crt5057_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: tms9927_device(mconfig, CRT5057, "CRT5057", tag, owner, clock)
|
||||
WRITE8_MEMBER( tms9927_device::write )
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0x00: /* HORIZONTAL CHARACTER COUNT */
|
||||
case 0x01: /* INTERLACED / HSYNC WIDTH / HSYNC DELAY */
|
||||
case 0x02: /* SCANS PER DATA ROW / CHARACTERS PER DATA ROW */
|
||||
case 0x03: /* SKEW BITS / DATA ROWS PER FRAME */
|
||||
case 0x04: /* SCAN LINES / FRAME */
|
||||
case 0x05: /* VERTICAL DATA START */
|
||||
case 0x06: /* LAST DISPLAYED DATA ROW */
|
||||
m_reg[offset] = data;
|
||||
recompute_parameters(FALSE);
|
||||
break;
|
||||
|
||||
case 0x0c: /* LOAD CURSOR CHARACTER ADDRESS */
|
||||
case 0x0d: /* LOAD CURSOR ROW ADDRESS */
|
||||
mame_printf_debug("Cursor address changed\n");
|
||||
m_reg[offset - 0x0c + 7] = data;
|
||||
recompute_parameters(FALSE);
|
||||
break;
|
||||
|
||||
default:
|
||||
generic_access(space, offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
READ8_MEMBER( tms9927_device::read )
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0x08: /* READ CURSOR CHARACTER ADDRESS */
|
||||
case 0x09: /* READ CURSOR ROW ADDRESS */
|
||||
return m_reg[offset - 0x08 + 7];
|
||||
|
||||
default:
|
||||
generic_access(space, offset);
|
||||
break;
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
|
||||
int tms9927_device::screen_reset()
|
||||
{
|
||||
return m_reset;
|
||||
}
|
||||
|
||||
|
||||
int tms9927_device::upscroll_offset()
|
||||
{
|
||||
return m_start_datarow;
|
||||
}
|
||||
|
||||
|
||||
int tms9927_device::cursor_bounds(rectangle &bounds)
|
||||
{
|
||||
int cursorx = CURSOR_CHAR_ADDRESS;
|
||||
int cursory = CURSOR_ROW_ADDRESS;
|
||||
|
||||
bounds.min_x = cursorx * m_hpixels_per_column;
|
||||
bounds.max_x = bounds.min_x + m_hpixels_per_column - 1;
|
||||
bounds.min_y = cursory * SCANS_PER_DATA_ROW;
|
||||
bounds.max_y = bounds.min_y + SCANS_PER_DATA_ROW - 1;
|
||||
|
||||
return (cursorx < HCOUNT && cursory <= LAST_DISP_DATA_ROW);
|
||||
}
|
||||
|
||||
|
||||
void tms9927_device::recompute_parameters(int postload)
|
||||
{
|
||||
UINT16 offset_hpix, offset_vpix;
|
||||
attoseconds_t refresh;
|
||||
rectangle visarea;
|
||||
|
||||
if (m_reset)
|
||||
return;
|
||||
|
||||
/* compute the screen sizes */
|
||||
m_total_hpix = HCOUNT * m_hpixels_per_column;
|
||||
m_total_vpix = SCAN_LINES_PER_FRAME;
|
||||
|
||||
/* determine the visible area, avoid division by 0 */
|
||||
m_visible_hpix = CHARS_PER_DATA_ROW * m_hpixels_per_column;
|
||||
m_visible_vpix = (LAST_DISP_DATA_ROW + 1) * SCANS_PER_DATA_ROW;
|
||||
|
||||
/* determine the horizontal/vertical offsets */
|
||||
offset_hpix = HSYNC_DELAY * m_hpixels_per_column;
|
||||
offset_vpix = VERTICAL_DATA_START;
|
||||
|
||||
mame_printf_debug("TMS9937: Total = %dx%d, Visible = %dx%d, Offset=%dx%d, Skew=%d\n", m_total_hpix, m_total_vpix, m_visible_hpix, m_visible_vpix, offset_hpix, offset_vpix, SKEW_BITS);
|
||||
|
||||
/* see if it all makes sense */
|
||||
m_valid_config = TRUE;
|
||||
if (m_visible_hpix > m_total_hpix || m_visible_vpix > m_total_vpix)
|
||||
{
|
||||
m_valid_config = FALSE;
|
||||
logerror("tms9927: invalid visible size (%dx%d) versus total size (%dx%d)\n", m_visible_hpix, m_visible_vpix, m_total_hpix, m_total_vpix);
|
||||
}
|
||||
|
||||
/* update */
|
||||
if (!m_valid_config)
|
||||
return;
|
||||
|
||||
/* create a visible area */
|
||||
/* fix me: how do the offsets fit in here? */
|
||||
visarea.set(0, m_visible_hpix - 1, 0, m_visible_vpix - 1);
|
||||
|
||||
refresh = HZ_TO_ATTOSECONDS(m_clock) * m_total_hpix * m_total_vpix;
|
||||
|
||||
m_screen->configure(m_total_hpix, m_total_vpix, visarea, refresh);
|
||||
}
|
||||
|
||||
|
@ -13,24 +13,58 @@
|
||||
#include "devlegcy.h"
|
||||
|
||||
|
||||
class tms9927_device : public device_t
|
||||
/* interface */
|
||||
struct tms9927_interface
|
||||
{
|
||||
const char *m_screen_tag; /* screen we are acting on */
|
||||
int m_hpixels_per_column; /* number of pixels per video memory address */
|
||||
const char *m_selfload_region; /* name of the region with self-load data */
|
||||
};
|
||||
|
||||
|
||||
class tms9927_device : public device_t,
|
||||
public tms9927_interface
|
||||
{
|
||||
public:
|
||||
tms9927_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
tms9927_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
|
||||
~tms9927_device() { global_free(m_token); }
|
||||
~tms9927_device() {}
|
||||
|
||||
// access to legacy token
|
||||
void *token() const { assert(m_token != NULL); return m_token; }
|
||||
DECLARE_WRITE8_MEMBER(write);
|
||||
DECLARE_READ8_MEMBER(read);
|
||||
|
||||
int screen_reset();
|
||||
int upscroll_offset();
|
||||
int cursor_bounds(rectangle &bounds);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_config_complete();
|
||||
virtual void device_start();
|
||||
virtual void device_stop();
|
||||
virtual void device_reset();
|
||||
|
||||
private:
|
||||
|
||||
void state_postload();
|
||||
void recompute_parameters(int postload);
|
||||
void generic_access(address_space &space, offs_t offset);
|
||||
|
||||
// internal state
|
||||
void *m_token;
|
||||
const tms9927_interface *intf;
|
||||
screen_device *m_screen;
|
||||
const UINT8 *m_selfload;
|
||||
|
||||
/* live state */
|
||||
UINT32 m_clock;
|
||||
UINT8 m_reg[9];
|
||||
UINT8 m_start_datarow;
|
||||
UINT8 m_reset;
|
||||
|
||||
/* derived state; no need to save */
|
||||
UINT8 m_valid_config;
|
||||
UINT16 m_total_hpix, m_total_vpix;
|
||||
UINT16 m_visible_hpix, m_visible_vpix;
|
||||
};
|
||||
|
||||
extern const device_type TMS9927;
|
||||
@ -71,27 +105,4 @@ extern const device_type CRT5057;
|
||||
MCFG_DEVICE_CONFIG(_config)
|
||||
|
||||
|
||||
|
||||
/* interface */
|
||||
struct tms9927_interface
|
||||
{
|
||||
const char *screen_tag; /* screen we are acting on */
|
||||
int hpixels_per_column; /* number of pixels per video memory address */
|
||||
const char *selfload_region; /* name of the region with self-load data */
|
||||
};
|
||||
|
||||
extern const tms9927_interface tms9927_null_interface;
|
||||
|
||||
|
||||
/* basic read/write handlers */
|
||||
DECLARE_WRITE8_DEVICE_HANDLER( tms9927_w );
|
||||
DECLARE_READ8_DEVICE_HANDLER( tms9927_r );
|
||||
|
||||
/* other queries */
|
||||
int tms9927_screen_reset(device_t *device);
|
||||
int tms9927_upscroll_offset(device_t *device);
|
||||
int tms9927_cursor_bounds(device_t *device, rectangle &bounds);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -81,10 +81,14 @@ class statriv2_state : public driver_device
|
||||
public:
|
||||
statriv2_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_tms(*this, "tms"),
|
||||
m_videoram(*this, "videoram"),
|
||||
m_question_offset(*this, "question_offset"),
|
||||
m_maincpu(*this, "maincpu") { }
|
||||
m_question_offset(*this, "question_offset")
|
||||
{ }
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<tms9927_device> m_tms;
|
||||
required_shared_ptr<UINT8> m_videoram;
|
||||
tilemap_t *m_tilemap;
|
||||
required_shared_ptr<UINT8> m_question_offset;
|
||||
@ -112,7 +116,6 @@ public:
|
||||
DECLARE_VIDEO_START(vertical);
|
||||
UINT32 screen_update_statriv2(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
INTERRUPT_GEN_MEMBER(statriv2_interrupt);
|
||||
required_device<cpu_device> m_maincpu;
|
||||
};
|
||||
|
||||
|
||||
@ -197,7 +200,7 @@ WRITE8_MEMBER(statriv2_state::statriv2_videoram_w)
|
||||
|
||||
UINT32 statriv2_state::screen_update_statriv2(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
if (tms9927_screen_reset(machine().device("tms")))
|
||||
if (m_tms->screen_reset())
|
||||
bitmap.fill(get_black_pen(machine()), cliprect);
|
||||
else
|
||||
m_tilemap->draw(bitmap, cliprect, 0, 0);
|
||||
@ -311,7 +314,7 @@ static ADDRESS_MAP_START( statriv2_io_map, AS_IO, 8, statriv2_state )
|
||||
AM_RANGE(0x28, 0x2b) AM_READ(question_data_r) AM_WRITEONLY AM_SHARE("question_offset")
|
||||
AM_RANGE(0xb0, 0xb1) AM_DEVWRITE("aysnd", ay8910_device, address_data_w)
|
||||
AM_RANGE(0xb1, 0xb1) AM_DEVREAD("aysnd", ay8910_device, data_r)
|
||||
AM_RANGE(0xc0, 0xcf) AM_DEVREADWRITE_LEGACY("tms", tms9927_r, tms9927_w)
|
||||
AM_RANGE(0xc0, 0xcf) AM_DEVREADWRITE("tms", tms9927_device, read, write)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
#ifdef UNUSED_CODE
|
||||
@ -320,7 +323,7 @@ static ADDRESS_MAP_START( statusbj_io, AS_IO, 8, statriv2_state )
|
||||
AM_RANGE(0x20, 0x23) AM_DEVREADWRITE("ppi8255", i8255_device, read, write)
|
||||
AM_RANGE(0xb0, 0xb1) AM_DEVWRITE("aysnd", ay8910_device, address_data_w)
|
||||
AM_RANGE(0xb1, 0xb1) AM_DEVREAD("aysnd", ay8910_device, data_r)
|
||||
AM_RANGE(0xc0, 0xcf) AM_DEVREADWRITE_LEGACY("tms", tms9927_r, tms9927_w)
|
||||
AM_RANGE(0xc0, 0xcf) AM_DEVREADWRITE("tms", tms9927_device, read, write)
|
||||
ADDRESS_MAP_END
|
||||
#endif
|
||||
|
||||
@ -587,7 +590,8 @@ GFXDECODE_END
|
||||
static const tms9927_interface tms9927_intf =
|
||||
{
|
||||
"screen",
|
||||
8
|
||||
8,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
|
@ -26,7 +26,6 @@ Credits:
|
||||
#include "cpu/z80/z80.h"
|
||||
#include "sound/ay8910.h"
|
||||
#include "sound/samples.h"
|
||||
#include "video/tms9927.h"
|
||||
#include "includes/thief.h"
|
||||
|
||||
#define MASTER_CLOCK XTAL_20MHz
|
||||
@ -180,7 +179,7 @@ static ADDRESS_MAP_START( io_map, AS_IO, 8, thief_state )
|
||||
AM_RANGE(0x42, 0x43) AM_DEVWRITE("ay2", ay8910_device, address_data_w)
|
||||
AM_RANGE(0x43, 0x43) AM_DEVREAD("ay2", ay8910_device, data_r)
|
||||
AM_RANGE(0x50, 0x50) AM_WRITE(thief_color_plane_w)
|
||||
AM_RANGE(0x60, 0x6f) AM_DEVREADWRITE_LEGACY("tms", tms9927_r, tms9927_w)
|
||||
AM_RANGE(0x60, 0x6f) AM_DEVREADWRITE("tms", tms9927_device, read, write)
|
||||
AM_RANGE(0x70, 0x7f) AM_WRITE(thief_color_map_w)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
@ -428,7 +427,8 @@ static const samples_interface natodef_samples_interface =
|
||||
static const tms9927_interface tms9927_intf =
|
||||
{
|
||||
"screen",
|
||||
8
|
||||
8,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "sound/samples.h"
|
||||
#include "video/tms9927.h"
|
||||
|
||||
struct coprocessor_t {
|
||||
UINT8 *context_ram;
|
||||
@ -13,7 +14,8 @@ public:
|
||||
thief_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag) ,
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_samples(*this, "samples") { }
|
||||
m_samples(*this, "samples"),
|
||||
m_tms(*this, "tms") { }
|
||||
|
||||
UINT8 *m_videoram;
|
||||
UINT8 m_input_select;
|
||||
@ -44,4 +46,5 @@ public:
|
||||
void tape_set_motor( samples_device *samples, int bOn );
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<samples_device> m_samples;
|
||||
required_device<tms9927_device> m_tms;
|
||||
};
|
||||
|
@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "video/tms9927.h"
|
||||
#include "includes/thief.h"
|
||||
|
||||
|
||||
@ -105,7 +104,7 @@ UINT32 thief_state::screen_update_thief(screen_device &screen, bitmap_ind16 &bit
|
||||
int flipscreen = m_video_control&1;
|
||||
const UINT8 *source = videoram;
|
||||
|
||||
if (tms9927_screen_reset(machine().device("tms")))
|
||||
if (m_tms->screen_reset())
|
||||
{
|
||||
bitmap.fill(get_black_pen(machine()), cliprect);
|
||||
return 0;
|
||||
|
@ -466,7 +466,7 @@ READ8_MEMBER(attache_state::display_data_r)
|
||||
switch(m_current_cmd)
|
||||
{
|
||||
case DISP_CRTC:
|
||||
ret = tms9927_r(m_crtc,space,m_crtc_reg_select);
|
||||
ret = m_crtc->read(space, m_crtc_reg_select);
|
||||
break;
|
||||
case DISP_ATTR:
|
||||
ret = m_attr_ram[(m_attr_line*128)+(param & 0x7f)];
|
||||
@ -487,7 +487,7 @@ WRITE8_MEMBER(attache_state::display_data_w)
|
||||
switch(m_current_cmd)
|
||||
{
|
||||
case DISP_CRTC:
|
||||
tms9927_w(m_crtc,space,m_crtc_reg_select,data);
|
||||
m_crtc->write(space, m_crtc_reg_select, data);
|
||||
break;
|
||||
case DISP_ATTR:
|
||||
m_attr_ram[(m_attr_line*128)+(param & 0x7f)] = data;
|
||||
|
@ -174,7 +174,7 @@ static ADDRESS_MAP_START( tdv2324_sub_io, AS_IO, 8, tdv2324_state )
|
||||
//ADDRESS_MAP_GLOBAL_MASK(0xff)
|
||||
/* 20, 23, 30-36, 38, 3a, 3c, 3e, 60, 70 are written to */
|
||||
AM_RANGE(0x20, 0x23) AM_DEVREADWRITE_LEGACY(P8253_5_1_TAG, pit8253_r, pit8253_w)
|
||||
AM_RANGE(0x30, 0x3f) AM_DEVREADWRITE_LEGACY(TMS9937NL_TAG, tms9927_r, tms9927_w) // TODO: this is supposed to be a 9937, which is not quite the same as 9927
|
||||
AM_RANGE(0x30, 0x3f) AM_DEVREADWRITE(TMS9937NL_TAG, tms9927_device, read, write) // TODO: this is supposed to be a 9937, which is not quite the same as 9927
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
|
@ -54,6 +54,7 @@ public:
|
||||
m_pic(*this, P8259A_TAG),
|
||||
m_pit0(*this, P8253_5_0_TAG),
|
||||
m_pit1(*this, P8253_5_1_TAG),
|
||||
m_tms(*this, TMS9937NL_TAG),
|
||||
m_video_ram(*this, "video_ram")
|
||||
{ }
|
||||
|
||||
@ -64,6 +65,7 @@ public:
|
||||
required_device<pic8259_device> m_pic;
|
||||
required_device<pit8253_device> m_pit0;
|
||||
required_device<pit8253_device> m_pit1;
|
||||
required_device<tms9927_device> m_tms;
|
||||
|
||||
virtual void video_start();
|
||||
UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
|
Loading…
Reference in New Issue
Block a user