mirror of
https://github.com/holub/mame
synced 2025-07-04 17:38:08 +03:00
(MESS) mm1: Fixed floppy. [Curt Coder]
Added a new implementation of the Intel 8275 with accurate DMA timing. [Curt Coder]
This commit is contained in:
parent
b8d6e154db
commit
45319730ae
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1717,6 +1717,8 @@ src/emu/video/huc6272.c svneol=native#text/plain
|
||||
src/emu/video/huc6272.h svneol=native#text/plain
|
||||
src/emu/video/i8275.c svneol=native#text/plain
|
||||
src/emu/video/i8275.h svneol=native#text/plain
|
||||
src/emu/video/i8275x.c svneol=native#text/plain
|
||||
src/emu/video/i8275x.h svneol=native#text/plain
|
||||
src/emu/video/k053250.c svneol=native#text/plain
|
||||
src/emu/video/k053250.h svneol=native#text/plain
|
||||
src/emu/video/m50458.c svneol=native#text/plain
|
||||
|
@ -309,6 +309,7 @@ EMUVIDEOOBJS = \
|
||||
$(EMUVIDEO)/huc6270.o \
|
||||
$(EMUVIDEO)/huc6272.o \
|
||||
$(EMUVIDEO)/i8275.o \
|
||||
$(EMUVIDEO)/i8275x.o \
|
||||
$(EMUVIDEO)/k053250.o \
|
||||
$(EMUVIDEO)/m50458.o \
|
||||
$(EMUVIDEO)/mb90082.o \
|
||||
|
585
src/emu/video/i8275x.c
Normal file
585
src/emu/video/i8275x.c
Normal file
@ -0,0 +1,585 @@
|
||||
/**********************************************************************
|
||||
|
||||
Intel 8275 Programmable CRT Controller emulation
|
||||
|
||||
Copyright MESS Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
/*
|
||||
|
||||
TODO:
|
||||
|
||||
- double spaced rows
|
||||
|
||||
*/
|
||||
|
||||
#include "i8275x.h"
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// MACROS / CONSTANTS
|
||||
//**************************************************************************
|
||||
|
||||
const int DMA_BURST_SPACING[] = { 0, 7, 15, 23, 31, 39, 47, 55 };
|
||||
|
||||
#define DOUBLE_SPACED_ROWS \
|
||||
BIT(m_param[REG_SCN1], 7)
|
||||
|
||||
#define CHARACTERS_PER_ROW \
|
||||
((m_param[REG_SCN1] & 0x7f) + 1)
|
||||
|
||||
#define VRTC_ROW_COUNT \
|
||||
((m_param[REG_SCN2] >> 5) + 1)
|
||||
|
||||
#define CHARACTER_ROWS_PER_FRAME \
|
||||
((m_param[REG_SCN2] & 0x3f) + 1)
|
||||
|
||||
#define UNDERLINE \
|
||||
(m_param[REG_SCN3] >> 4)
|
||||
|
||||
#define SCANLINES_PER_ROW \
|
||||
((m_param[REG_SCN3] & 0x0f) + 1)
|
||||
|
||||
#define OFFSET_LINE_COUNTER \
|
||||
BIT(m_param[REG_SCN4], 7)
|
||||
|
||||
#define VISIBLE_FIELD_ATTRIBUTE \
|
||||
BIT(m_param[REG_SCN4], 6)
|
||||
|
||||
#define CURSOR_FORMAT \
|
||||
((m_param[REG_SCN4] >> 4) & 0x03)
|
||||
|
||||
#define HRTC_COUNT \
|
||||
(((m_param[REG_SCN4] & 0x0f) + 1) * 2)
|
||||
|
||||
#define DMA_BURST_COUNT \
|
||||
(1 << (m_param[REG_DMA] & 0x03))
|
||||
|
||||
#define DMA_BURST_SPACE \
|
||||
DMA_BURST_SPACING[(m_param[REG_DMA] >> 2) & 0x07]
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// somethign
|
||||
//**************************************************************************
|
||||
|
||||
// device type definition
|
||||
const device_type I8275x = &device_creator<i8275x_device>;
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// i8275x_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
i8275x_device::i8275x_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, I8275x, "I8275", tag, owner, clock),
|
||||
m_status(0),
|
||||
m_param_idx(0),
|
||||
m_param_end(0),
|
||||
m_buffer_idx(0),
|
||||
m_fifo_next(false),
|
||||
m_buffer_dma(0),
|
||||
m_lpen(0),
|
||||
m_hlgt(0),
|
||||
m_vsp(0),
|
||||
m_gpa(0),
|
||||
m_rvv(0),
|
||||
m_lten(0),
|
||||
m_scanline(0),
|
||||
m_du(false),
|
||||
m_cursor_blink(0),
|
||||
m_char_blink(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_config_complete - perform any
|
||||
// operations now that the configuration is
|
||||
// complete
|
||||
//-------------------------------------------------
|
||||
|
||||
void i8275x_device::device_config_complete()
|
||||
{
|
||||
// inherit a copy of the static data
|
||||
const i8275_interface *intf = reinterpret_cast<const i8275_interface *>(static_config());
|
||||
if (intf != NULL)
|
||||
*static_cast<i8275_interface *>(this) = *intf;
|
||||
|
||||
// or initialize to defaults if none provided
|
||||
else
|
||||
{
|
||||
memset(&m_out_drq_cb, 0, sizeof(m_out_drq_cb));
|
||||
memset(&m_out_irq_cb, 0, sizeof(m_out_irq_cb));
|
||||
memset(&m_out_hrtc_cb, 0, sizeof(m_out_hrtc_cb));
|
||||
memset(&m_out_vrtc_cb, 0, sizeof(m_out_vrtc_cb));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void i8275x_device::device_start()
|
||||
{
|
||||
// get the screen device
|
||||
m_screen = machine().device<screen_device>(m_screen_tag);
|
||||
assert(m_screen != NULL);
|
||||
m_screen->register_screen_bitmap(m_bitmap);
|
||||
|
||||
// resolve callbacks
|
||||
m_out_drq_func.resolve(m_out_drq_cb, *this);
|
||||
m_out_irq_func.resolve(m_out_irq_cb, *this);
|
||||
m_out_hrtc_func.resolve(m_out_hrtc_cb, *this);
|
||||
m_out_vrtc_func.resolve(m_out_vrtc_cb, *this);
|
||||
|
||||
// allocate timers
|
||||
m_hrtc_on_timer = timer_alloc(TIMER_HRTC_ON);
|
||||
m_drq_on_timer = timer_alloc(TIMER_DRQ_ON);
|
||||
m_drq_off_timer = timer_alloc(TIMER_DRQ_OFF);
|
||||
m_scanline_timer = timer_alloc(TIMER_SCANLINE);
|
||||
|
||||
// state saving
|
||||
save_item(NAME(m_status));
|
||||
save_item(NAME(m_param));
|
||||
save_item(NAME(m_param_idx));
|
||||
save_item(NAME(m_param_end));
|
||||
save_item(NAME(m_buffer[0]));
|
||||
save_item(NAME(m_buffer[1]));
|
||||
save_item(NAME(m_buffer_idx));
|
||||
save_item(NAME(m_fifo_idx));
|
||||
save_item(NAME(m_fifo_next));
|
||||
save_item(NAME(m_buffer_dma));
|
||||
save_item(NAME(m_lpen));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void i8275x_device::device_reset()
|
||||
{
|
||||
m_status &= ~ST_IE;
|
||||
|
||||
m_out_irq_func(CLEAR_LINE);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_timer - handle timer events
|
||||
//-------------------------------------------------
|
||||
|
||||
void i8275x_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
int y = m_screen->vpos();
|
||||
int x = m_screen->hpos();
|
||||
int rc = m_scanline / SCANLINES_PER_ROW;
|
||||
int lc = m_scanline % SCANLINES_PER_ROW;
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case TIMER_HRTC_ON:
|
||||
//logerror("I8275 '%s' y %u x %u HRTC 1\n", tag(), y, x);
|
||||
m_out_hrtc_func(1);
|
||||
break;
|
||||
|
||||
case TIMER_DRQ_ON:
|
||||
logerror("I8275 '%s' y %u x %u DRQ 1\n", tag(), y, x);
|
||||
m_out_drq_func(1);
|
||||
m_drq_off_timer->adjust(clocks_to_attotime(DMA_BURST_COUNT));
|
||||
break;
|
||||
|
||||
case TIMER_DRQ_OFF:
|
||||
if (m_buffer_idx == 0)
|
||||
{
|
||||
m_status |= ST_DU;
|
||||
m_du = true;
|
||||
logerror("I8275 '%s' y %u x %u DRQ 0\n", tag(), y, x);
|
||||
m_out_drq_func(0);
|
||||
}
|
||||
else if (m_buffer_idx == CHARACTERS_PER_ROW)
|
||||
{
|
||||
logerror("I8275 '%s' y %u x %u DRQ 0\n", tag(), y, x);
|
||||
m_out_drq_func(0);
|
||||
}
|
||||
else if (DMA_BURST_SPACE > 0)
|
||||
{
|
||||
logerror("I8275 '%s' y %u x %u DRQ 0\n", tag(), y, x);
|
||||
m_out_drq_func(0);
|
||||
m_drq_on_timer->adjust(clocks_to_attotime(DMA_BURST_SPACE));
|
||||
}
|
||||
break;
|
||||
|
||||
case TIMER_SCANLINE:
|
||||
if (!(m_status & ST_VE)) break;
|
||||
|
||||
//logerror("I8275 '%s' y %u x %u HRTC 0\n", tag(), y, x);
|
||||
m_out_hrtc_func(0);
|
||||
|
||||
if (m_scanline == 0)
|
||||
{
|
||||
//logerror("I8275 '%s' y %u x %u VRTC 0\n", tag(), y, x);
|
||||
m_out_vrtc_func(0);
|
||||
}
|
||||
else if (m_scanline == m_irq_scanline)
|
||||
{
|
||||
if (m_status & ST_IE)
|
||||
{
|
||||
//logerror("I8275 '%s' y %u x %u IRQ 1\n", tag(), y, x);
|
||||
m_status |= ST_IR;
|
||||
m_out_irq_func(ASSERT_LINE);
|
||||
}
|
||||
}
|
||||
else if (m_scanline == m_vrtc_scanline)
|
||||
{
|
||||
//logerror("I8275 '%s' y %u x %u VRTC 1\n", tag(), y, x);
|
||||
m_out_vrtc_func(1);
|
||||
|
||||
// reset field attributes
|
||||
m_hlgt = 0;
|
||||
m_vsp = 0;
|
||||
m_gpa = 0;
|
||||
m_rvv = 0,
|
||||
m_lten = 0;
|
||||
|
||||
m_du = false;
|
||||
|
||||
m_cursor_blink++;
|
||||
m_cursor_blink &= 0x1f;
|
||||
|
||||
m_char_blink++;
|
||||
m_char_blink &= 0x3f;
|
||||
}
|
||||
|
||||
if (lc == 0)
|
||||
{
|
||||
// swap line buffers
|
||||
m_buffer_dma = !m_buffer_dma;
|
||||
m_buffer_idx = 0;
|
||||
m_fifo_idx = 0;
|
||||
|
||||
if (!m_du && ((m_scanline < m_vrtc_scanline - SCANLINES_PER_ROW) || (m_scanline == m_vrtc_drq_scanline)))
|
||||
{
|
||||
// start DMA burst
|
||||
m_drq_on_timer->adjust(clocks_to_attotime(DMA_BURST_SPACE));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_scanline < m_vrtc_scanline)
|
||||
{
|
||||
for (int sx = 0; sx < CHARACTERS_PER_ROW; sx++)
|
||||
{
|
||||
int m_lineattr = 0;
|
||||
int lten = 0;
|
||||
int vsp = 0;
|
||||
|
||||
UINT8 data = m_buffer[!m_buffer_dma][sx];
|
||||
|
||||
if (data & 0x80)
|
||||
{
|
||||
if ((data & 0xc0) == 0x80)
|
||||
{
|
||||
// field attribute code
|
||||
m_hlgt = (data & FAC_H) ? 1 : 0;
|
||||
m_vsp = (data & FAC_B) ? 1 : 0;
|
||||
m_gpa = (data & FAC_GG) >> 2;
|
||||
m_rvv = (data & FAC_R) ? 1 : 0;
|
||||
m_lten = (data & FAC_U) ? 1 : 0;
|
||||
|
||||
if (!VISIBLE_FIELD_ATTRIBUTE)
|
||||
{
|
||||
int fifo_idx = 0;
|
||||
|
||||
data = m_fifo[!m_buffer_dma][fifo_idx];
|
||||
|
||||
fifo_idx++;
|
||||
fifo_idx &= 0xf;
|
||||
}
|
||||
else
|
||||
{
|
||||
vsp = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// character attribute code
|
||||
}
|
||||
}
|
||||
|
||||
if (!vsp && m_vsp)
|
||||
{
|
||||
vsp = (m_char_blink < 32) ? 1 : 0;
|
||||
}
|
||||
|
||||
if ((rc == m_param[REG_CUR_ROW]) && (sx == m_param[REG_CUR_COL]))
|
||||
{
|
||||
int vis = 1;
|
||||
|
||||
if (!(CURSOR_FORMAT & 0x02))
|
||||
{
|
||||
vis = (m_cursor_blink < 16) ? 1 : 0;
|
||||
}
|
||||
|
||||
if (CURSOR_FORMAT & 0x01)
|
||||
{
|
||||
lten = (lc == UNDERLINE) ? vis : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
lten = vis;
|
||||
}
|
||||
}
|
||||
|
||||
if (OFFSET_LINE_COUNTER)
|
||||
{
|
||||
lc = (lc - 1) & 0x0f;
|
||||
}
|
||||
|
||||
m_display_pixels_func(this, m_bitmap,
|
||||
sx * m_hpixels_per_column, // x position on screen of starting point
|
||||
m_scanline, // y position on screen
|
||||
lc, // current line of char
|
||||
(data & 0x7f), // char code to be displayed
|
||||
m_lineattr, // line attribute code
|
||||
lten | m_lten, // light enable signal
|
||||
m_rvv, // reverse video signal
|
||||
vsp, // video suppression
|
||||
m_gpa, // general purpose attribute code
|
||||
m_hlgt // highlight
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
m_scanline++;
|
||||
m_scanline %= ((CHARACTER_ROWS_PER_FRAME + VRTC_ROW_COUNT) * SCANLINES_PER_ROW);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// read -
|
||||
//-------------------------------------------------
|
||||
|
||||
READ8_MEMBER( i8275x_device::read )
|
||||
{
|
||||
UINT8 data = 0;
|
||||
|
||||
if (offset & 0x01)
|
||||
{
|
||||
data = m_status;
|
||||
|
||||
if (m_status & ST_IR)
|
||||
{
|
||||
//logerror("I8275 '%s' IRQ 0\n", tag());
|
||||
m_out_irq_func(CLEAR_LINE);
|
||||
}
|
||||
|
||||
m_status &= ~(ST_IR | ST_LP | ST_IC | ST_DU | ST_FO);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = m_param[m_param_idx];
|
||||
m_param_idx++;
|
||||
|
||||
if (m_param_idx > m_param_end)
|
||||
{
|
||||
m_status |= ST_IC;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// write -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE8_MEMBER( i8275x_device::write )
|
||||
{
|
||||
if (offset & 0x01)
|
||||
{
|
||||
logerror("I8275 '%s' Command %02x\n", tag(), data);
|
||||
|
||||
switch (data >> 5)
|
||||
{
|
||||
case CMD_RESET:
|
||||
logerror("I8275 '%s' Reset\n", tag());
|
||||
|
||||
m_status &= ~ST_IE;
|
||||
logerror("I8275 '%s' IRQ 0\n", tag());
|
||||
m_out_irq_func(CLEAR_LINE);
|
||||
|
||||
m_param_idx = REG_SCN1;
|
||||
m_param_end = REG_SCN4;
|
||||
break;
|
||||
|
||||
case CMD_START_DISPLAY:
|
||||
{
|
||||
m_param[REG_DMA] = data;
|
||||
logerror("I8275 '%s' Start Display %u %u\n", tag(), DMA_BURST_COUNT, DMA_BURST_SPACE);
|
||||
m_status |= (ST_IE | ST_VE);
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_STOP_DISPLAY:
|
||||
logerror("I8275 '%s' Stop Display\n", tag());
|
||||
m_status &= ~ST_VE;
|
||||
break;
|
||||
|
||||
case CMD_READ_LIGHT_PEN:
|
||||
logerror("I8275 '%s' Read Light Pen\n", tag());
|
||||
m_param_idx = REG_LPEN_COL;
|
||||
m_param_end = REG_LPEN_ROW;
|
||||
break;
|
||||
|
||||
case CMD_LOAD_CURSOR:
|
||||
logerror("I8275 '%s' Load Cursor\n", tag());
|
||||
m_param_idx = REG_CUR_COL;
|
||||
m_param_end = REG_CUR_ROW;
|
||||
break;
|
||||
|
||||
case CMD_ENABLE_INTERRUPT:
|
||||
logerror("I8275 '%s' Enable Interrupt\n", tag());
|
||||
m_status |= ST_IE;
|
||||
break;
|
||||
|
||||
case CMD_DISABLE_INTERRUPT:
|
||||
logerror("I8275 '%s' Disable Interrupt\n", tag());
|
||||
m_status &= ~ST_IE;
|
||||
break;
|
||||
|
||||
case CMD_PRESET_COUNTERS:
|
||||
logerror("I8275 '%s' Preset Counters\n", tag());
|
||||
m_scanline = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("I8275 '%s' Parameter %02x\n", tag(), data);
|
||||
|
||||
m_param[m_param_idx] = data;
|
||||
|
||||
if (m_param_idx == REG_SCN4)
|
||||
{
|
||||
recompute_parameters();
|
||||
}
|
||||
|
||||
m_param_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// dack_w -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE8_MEMBER( i8275x_device::dack_w )
|
||||
{
|
||||
logerror("DACK write %02x %u\n", data, m_buffer_idx);
|
||||
|
||||
if (m_fifo_next)
|
||||
{
|
||||
if (m_fifo_idx == 16)
|
||||
{
|
||||
m_fifo_idx = 0;
|
||||
m_status |= ST_FO;
|
||||
}
|
||||
|
||||
m_fifo[m_buffer_dma][m_fifo_idx++] = data;
|
||||
|
||||
m_fifo_next = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_buffer[m_buffer_dma][m_buffer_idx++] = data;
|
||||
|
||||
if (!VISIBLE_FIELD_ATTRIBUTE && ((data & 0xc0) == 0x80))
|
||||
{
|
||||
m_fifo_next = true;
|
||||
}
|
||||
|
||||
if (m_buffer_idx == CHARACTERS_PER_ROW)
|
||||
{
|
||||
m_drq_off_timer->adjust(attotime::zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// lpen_w -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER( i8275x_device::lpen_w )
|
||||
{
|
||||
if (!m_lpen && state)
|
||||
{
|
||||
m_param[REG_LPEN_COL] = m_screen->hpos() / m_hpixels_per_column;
|
||||
m_param[REG_LPEN_ROW] = m_screen->vpos() / SCANLINES_PER_ROW;
|
||||
|
||||
m_status |= ST_LP;
|
||||
}
|
||||
|
||||
m_lpen = state;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// screen_update -
|
||||
//-------------------------------------------------
|
||||
|
||||
UINT32 i8275x_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
if (!(m_status & ST_VE))
|
||||
{
|
||||
m_bitmap.fill(RGB_BLACK);
|
||||
}
|
||||
|
||||
copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// recompute_parameters -
|
||||
//-------------------------------------------------
|
||||
|
||||
void i8275x_device::recompute_parameters()
|
||||
{
|
||||
int y = m_screen->vpos();
|
||||
|
||||
int horiz_pix_total = (CHARACTERS_PER_ROW + HRTC_COUNT) * m_hpixels_per_column;
|
||||
int vert_pix_total = (CHARACTER_ROWS_PER_FRAME + VRTC_ROW_COUNT) * SCANLINES_PER_ROW;
|
||||
attoseconds_t refresh = m_screen->frame_period().attoseconds;
|
||||
int max_visible_x = (CHARACTERS_PER_ROW * m_hpixels_per_column) - 1;
|
||||
int max_visible_y = (CHARACTER_ROWS_PER_FRAME * SCANLINES_PER_ROW) - 1;
|
||||
|
||||
logerror("width %u height %u max_x %u max_y %u refresh %f\n", horiz_pix_total, vert_pix_total, max_visible_x, max_visible_y, 1 / ATTOSECONDS_TO_DOUBLE(refresh));
|
||||
|
||||
rectangle visarea;
|
||||
visarea.set(0, max_visible_x, 0, max_visible_y);
|
||||
m_screen->configure(horiz_pix_total, vert_pix_total, visarea, refresh);
|
||||
|
||||
int hrtc_on_pos = CHARACTERS_PER_ROW * m_hpixels_per_column;
|
||||
m_hrtc_on_timer->adjust(m_screen->time_until_pos(y, hrtc_on_pos), 0, m_screen->scan_period());
|
||||
|
||||
m_irq_scanline = (CHARACTER_ROWS_PER_FRAME - 1) * SCANLINES_PER_ROW;
|
||||
m_vrtc_scanline = CHARACTER_ROWS_PER_FRAME * SCANLINES_PER_ROW;
|
||||
m_vrtc_drq_scanline = vert_pix_total - SCANLINES_PER_ROW;
|
||||
|
||||
m_scanline_timer->adjust(m_screen->time_until_pos(0, 0), 0, m_screen->scan_period());
|
||||
}
|
225
src/emu/video/i8275x.h
Normal file
225
src/emu/video/i8275x.h
Normal file
@ -0,0 +1,225 @@
|
||||
/**********************************************************************
|
||||
|
||||
Intel 8275 Programmable CRT Controller emulation
|
||||
|
||||
Copyright MESS Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
**********************************************************************
|
||||
_____ _____
|
||||
LC3 1 |* \_/ | 40 Vcc
|
||||
LC2 2 | | 39 LA0
|
||||
LC1 3 | | 38 LA1
|
||||
LC0 4 | | 37 LTEN
|
||||
DRQ 5 | | 36 RVV
|
||||
_DACK 6 | | 35 VSP
|
||||
HRTC 7 | | 34 GPA1
|
||||
VRTC 8 | | 33 GPA0
|
||||
_RD 9 | | 32 HLGT
|
||||
_WR 10 | 8275 | 31 IRQ
|
||||
LPEN 11 | | 30 CCLK
|
||||
DB0 12 | | 29 CC6
|
||||
DB1 13 | | 28 CC5
|
||||
DB2 14 | | 27 CC4
|
||||
DB3 15 | | 26 CC3
|
||||
DB4 16 | | 25 CC2
|
||||
DB5 17 | | 24 CC1
|
||||
DB6 18 | | 23 CC0
|
||||
DB7 19 | | 22 _CS
|
||||
GND 20 |_____________| 21 A0
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __I8275x__
|
||||
#define __I8275x__
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// INTERFACE CONFIGURATION MACROS
|
||||
//**************************************************************************
|
||||
|
||||
#define MCFG_I8275_ADD(_tag, _clock, _config) \
|
||||
MCFG_DEVICE_ADD(_tag, I8275x, _clock) \
|
||||
MCFG_DEVICE_CONFIG(_config)
|
||||
|
||||
|
||||
#define I8275_INTERFACE(name) \
|
||||
const i8275_interface (name) =
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
class i8275x_device;
|
||||
|
||||
|
||||
// ======================> i8275_display_pixels_func
|
||||
|
||||
typedef void (*i8275_display_pixels_func)(i8275x_device *device, bitmap_rgb32 &bitmap, int x, int y, UINT8 linecount, UINT8 charcode, UINT8 lineattr, UINT8 lten, UINT8 rvv, UINT8 vsp, UINT8 gpa, UINT8 hlgt);
|
||||
#define I8275_DISPLAY_PIXELS(name) void name(i8275x_device *device, bitmap_rgb32 &bitmap, int x, int y, UINT8 linecount, UINT8 charcode, UINT8 lineattr, UINT8 lten, UINT8 rvv, UINT8 vsp, UINT8 gpa, UINT8 hlgt)
|
||||
|
||||
|
||||
// ======================> i8275_interface
|
||||
|
||||
struct i8275_interface
|
||||
{
|
||||
const char *m_screen_tag;
|
||||
int m_hpixels_per_column;
|
||||
int m_dummy;
|
||||
|
||||
devcb_write_line m_out_drq_cb;
|
||||
devcb_write_line m_out_irq_cb;
|
||||
|
||||
devcb_write_line m_out_hrtc_cb;
|
||||
devcb_write_line m_out_vrtc_cb;
|
||||
|
||||
i8275_display_pixels_func m_display_pixels_func;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// ======================> i8275x_device
|
||||
|
||||
class i8275x_device : public device_t,
|
||||
public i8275_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
i8275x_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
DECLARE_READ8_MEMBER( read );
|
||||
DECLARE_WRITE8_MEMBER( write );
|
||||
|
||||
DECLARE_WRITE8_MEMBER( dack_w );
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER( lpen_w );
|
||||
|
||||
UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_config_complete();
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||
|
||||
void recompute_parameters();
|
||||
|
||||
enum
|
||||
{
|
||||
TIMER_HRTC_ON,
|
||||
TIMER_DRQ_ON,
|
||||
TIMER_DRQ_OFF,
|
||||
TIMER_SCANLINE
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ST_IE = 0x40,
|
||||
ST_IR = 0x20,
|
||||
ST_LP = 0x10,
|
||||
ST_IC = 0x08,
|
||||
ST_VE = 0x04,
|
||||
ST_DU = 0x02,
|
||||
ST_FO = 0x01
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CMD_RESET = 0,
|
||||
CMD_START_DISPLAY,
|
||||
CMD_STOP_DISPLAY,
|
||||
CMD_READ_LIGHT_PEN,
|
||||
CMD_LOAD_CURSOR,
|
||||
CMD_ENABLE_INTERRUPT,
|
||||
CMD_DISABLE_INTERRUPT,
|
||||
CMD_PRESET_COUNTERS
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
REG_SCN1 = 0,
|
||||
REG_SCN2,
|
||||
REG_SCN3,
|
||||
REG_SCN4,
|
||||
REG_CUR_COL,
|
||||
REG_CUR_ROW,
|
||||
REG_LPEN_COL,
|
||||
REG_LPEN_ROW,
|
||||
REG_DMA
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CA_H = 0x01,
|
||||
CA_B = 0x02,
|
||||
CA_CCCC = 0x3c
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FAC_H = 0x01,
|
||||
FAC_B = 0x02,
|
||||
FAC_GG = 0x0c,
|
||||
FAC_R = 0x10,
|
||||
FAC_U = 0x20
|
||||
};
|
||||
|
||||
devcb_resolved_write_line m_out_drq_func;
|
||||
devcb_resolved_write_line m_out_irq_func;
|
||||
devcb_resolved_write_line m_out_hrtc_func;
|
||||
devcb_resolved_write_line m_out_vrtc_func;
|
||||
|
||||
screen_device *m_screen;
|
||||
bitmap_rgb32 m_bitmap;
|
||||
|
||||
UINT8 m_status;
|
||||
UINT8 m_param[REG_DMA + 1];
|
||||
int m_param_idx;
|
||||
int m_param_end;
|
||||
|
||||
UINT8 m_buffer[2][80];
|
||||
UINT8 m_fifo[2][16];
|
||||
int m_buffer_idx;
|
||||
int m_fifo_idx;
|
||||
bool m_fifo_next;
|
||||
int m_buffer_dma;
|
||||
|
||||
int m_lpen;
|
||||
|
||||
int m_hlgt;
|
||||
int m_vsp;
|
||||
int m_gpa;
|
||||
int m_rvv;
|
||||
int m_lten;
|
||||
|
||||
int m_scanline;
|
||||
int m_irq_scanline;
|
||||
int m_vrtc_scanline;
|
||||
int m_vrtc_drq_scanline;
|
||||
bool m_du;
|
||||
|
||||
int m_cursor_blink;
|
||||
int m_char_blink;
|
||||
|
||||
// timers
|
||||
emu_timer *m_hrtc_on_timer;
|
||||
emu_timer *m_drq_on_timer;
|
||||
emu_timer *m_drq_off_timer;
|
||||
emu_timer *m_scanline_timer;
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
extern const device_type I8275x;
|
||||
|
||||
|
||||
|
||||
#endif
|
@ -41,8 +41,6 @@
|
||||
|
||||
TODO:
|
||||
|
||||
- fix i8275 DMA timing (full screen is transferred in 1 burst, which kills floppy sector DMA)
|
||||
- add HRTC/VRTC output to i8275
|
||||
- NEC uPD7220 GDC
|
||||
- accurate video timing
|
||||
- floppy DRQ during RECALL = 0
|
||||
@ -59,7 +57,7 @@
|
||||
// MACROS / CONSTANTS
|
||||
//**************************************************************************
|
||||
|
||||
#define LOG 1
|
||||
#define LOG 0
|
||||
|
||||
#define MMU_IOEN 0x01
|
||||
#define MMU_RAMEN 0x02
|
||||
@ -540,7 +538,7 @@ static I8237_INTERFACE( dmac_intf )
|
||||
DEVCB_DRIVER_MEMBER(mm1_state, read),
|
||||
DEVCB_DRIVER_MEMBER(mm1_state, write),
|
||||
{ DEVCB_NULL, DEVCB_NULL, DEVCB_DRIVER_MEMBER(mm1_state, mpsc_dack_r), DEVCB_DEVICE_MEMBER(UPD765_TAG, upd765_family_device, mdma_r) },
|
||||
{ DEVCB_DEVICE_MEMBER(I8275_TAG, i8275_device, dack_w), DEVCB_DRIVER_MEMBER(mm1_state, mpsc_dack_w), DEVCB_NULL, DEVCB_DEVICE_MEMBER(UPD765_TAG, upd765_family_device, mdma_w) },
|
||||
{ DEVCB_DEVICE_MEMBER(I8275_TAG, i8275x_device, dack_w), DEVCB_DRIVER_MEMBER(mm1_state, mpsc_dack_w), DEVCB_NULL, DEVCB_DEVICE_MEMBER(UPD765_TAG, upd765_family_device, mdma_w) },
|
||||
{ DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_DRIVER_LINE_MEMBER(mm1_state, dack3_w) }
|
||||
};
|
||||
|
||||
@ -841,5 +839,5 @@ ROM_END
|
||||
//**************************************************************************
|
||||
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS
|
||||
COMP( 1981, mm1m6, 0, 0, mm1m6, mm1, driver_device, 0, "Nokia Data", "MikroMikko 1 M6", GAME_NOT_WORKING | GAME_SUPPORTS_SAVE )
|
||||
COMP( 1981, mm1m7, mm1m6, 0, mm1m7, mm1, driver_device, 0, "Nokia Data", "MikroMikko 1 M7", GAME_NOT_WORKING | GAME_SUPPORTS_SAVE )
|
||||
COMP( 1981, mm1m6, 0, 0, mm1m6, mm1, driver_device, 0, "Nokia Data", "MikroMikko 1 M6", GAME_SUPPORTS_SAVE )
|
||||
COMP( 1981, mm1m7, mm1m6, 0, mm1m7, mm1, driver_device, 0, "Nokia Data", "MikroMikko 1 M7", GAME_SUPPORTS_SAVE )
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "machine/upd7201.h"
|
||||
#include "machine/upd765.h"
|
||||
#include "sound/speaker.h"
|
||||
#include "video/i8275.h"
|
||||
#include "video/i8275x.h"
|
||||
#include "video/upd7220.h"
|
||||
|
||||
#define SCREEN_TAG "screen"
|
||||
@ -55,7 +55,7 @@ public:
|
||||
required_device<i8212_device> m_iop;
|
||||
required_device<am9517a_device> m_dmac;
|
||||
required_device<pit8253_device> m_pit;
|
||||
required_device<i8275_device> m_crtc;
|
||||
required_device<i8275x_device> m_crtc;
|
||||
required_device<upd765a_device> m_fdc;
|
||||
required_device<upd7201_device> m_mpsc;
|
||||
required_device<upd7220_device> m_hgdc;
|
||||
|
@ -150,6 +150,6 @@ MACHINE_CONFIG_FRAGMENT( mm1m6_video )
|
||||
|
||||
MCFG_GFXDECODE(mm1)
|
||||
|
||||
MCFG_I8275_ADD(I8275_TAG, crtc_intf) // XTAL_18_720MHz/8
|
||||
MCFG_I8275_ADD(I8275_TAG, XTAL_18_720MHz/8, crtc_intf)
|
||||
MCFG_UPD7220_ADD(UPD7220_TAG, XTAL_18_720MHz/8, hgdc_intf, mm1_upd7220_map)
|
||||
MACHINE_CONFIG_END
|
||||
|
Loading…
Reference in New Issue
Block a user