diff options
author | 2015-11-08 12:56:12 +0100 | |
---|---|---|
committer | 2015-11-08 12:56:12 +0100 | |
commit | 7c19aac60e12d6f5ea301bdb34d7826a01e0b06f (patch) | |
tree | f310d86aa2c6bfc19d115307dedde4eb0cd52dad /src/devices/bus/isa/mda.cpp | |
parent | a57b46ae933badd7441ce1644711dbb851e2b504 (diff) |
Rename *.c -> *.cpp in our source (nw)
Diffstat (limited to 'src/devices/bus/isa/mda.cpp')
-rw-r--r-- | src/devices/bus/isa/mda.cpp | 981 |
1 files changed, 981 insertions, 0 deletions
diff --git a/src/devices/bus/isa/mda.cpp b/src/devices/bus/isa/mda.cpp new file mode 100644 index 00000000000..1d8991cab7a --- /dev/null +++ b/src/devices/bus/isa/mda.cpp @@ -0,0 +1,981 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol, Miodrag Milanovic +/*************************************************************************** + + Monochrome Display Adapter (MDA) section + +***************************************************************************/ + +#include "emu.h" +#include "mda.h" +#include "video/mc6845.h" +#include "machine/pc_lpt.h" + +#define MDA_SCREEN_NAME "mda_screen" +#define MDA_MC6845_NAME "mc6845_mda" + +/* + Hercules video card + */ +#define HERCULES_SCREEN_NAME "hercules_screen" +#define HERCULES_MC6845_NAME "mc6845_hercules" + +#define VERBOSE_MDA 0 /* MDA (Monochrome Display Adapter) */ + +#define MDA_CLOCK 16257000 + +#define MDA_LOG(N,M,A) \ + do { \ + if(VERBOSE_MDA>=N) \ + { \ + if( M ) \ + logerror("%11.6f: %-24s",machine().time().as_double(),(char*)M ); \ + logerror A; \ + } \ + } while (0) + +static const unsigned char mda_palette[4][3] = +{ + { 0x00,0x00,0x00 }, + { 0x00,0x55,0x00 }, + { 0x00,0xaa,0x00 }, + { 0x00,0xff,0x00 } +}; + +enum +{ + MDA_TEXT_INTEN = 0, + MDA_TEXT_BLINK, + HERCULES_GFX_BLINK, + MDA_LOWRES_TEXT_INTEN, + MDA_LOWRES_TEXT_BLINK +}; + +/* F4 Character Displayer */ +static const gfx_layout pc_16_charlayout = +{ + 8, 16, /* 8 x 16 characters */ + 256, /* 256 characters */ + 1, /* 1 bits per pixel */ + { 0 }, /* no bitplanes */ + /* x offsets */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, + /* y offsets */ + { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 2048*8, 2049*8, 2050*8, 2051*8, 2052*8, 2053*8, 2054*8, 2055*8 }, + 8*8 /* every char takes 2 x 8 bytes */ +}; + +static const gfx_layout pc_8_charlayout = +{ + 8, 8, /* 8 x 8 characters */ + 512, /* 512 characters */ + 1, /* 1 bits per pixel */ + { 0 }, /* no bitplanes */ + /* x offsets */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, + /* y offsets */ + { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 }, + 8*8 /* every char takes 8 bytes */ +}; + +static GFXDECODE_START( pcmda ) + GFXDECODE_ENTRY( "gfx1", 0x0000, pc_16_charlayout, 1, 1 ) + GFXDECODE_ENTRY( "gfx1", 0x1000, pc_8_charlayout, 1, 1 ) +GFXDECODE_END + + +WRITE_LINE_MEMBER(isa8_mda_device::pc_cpu_line) +{ + m_isa->irq7_w(state); +} + + +MACHINE_CONFIG_FRAGMENT( pcvideo_mda ) + MCFG_SCREEN_ADD( MDA_SCREEN_NAME, RASTER) + MCFG_SCREEN_RAW_PARAMS(MDA_CLOCK, 882, 0, 720, 370, 0, 350 ) + MCFG_SCREEN_UPDATE_DEVICE( MDA_MC6845_NAME, mc6845_device, screen_update ) + + MCFG_PALETTE_ADD( "palette", 4 ) + + MCFG_MC6845_ADD(MDA_MC6845_NAME, MC6845, MDA_SCREEN_NAME, MDA_CLOCK/9) + MCFG_MC6845_SHOW_BORDER_AREA(false) + MCFG_MC6845_CHAR_WIDTH(9) + MCFG_MC6845_UPDATE_ROW_CB(isa8_mda_device, crtc_update_row) + MCFG_MC6845_OUT_HSYNC_CB(WRITELINE(isa8_mda_device, hsync_changed)) + MCFG_MC6845_OUT_VSYNC_CB(WRITELINE(isa8_mda_device, vsync_changed)) + + MCFG_GFXDECODE_ADD("gfxdecode", "palette", pcmda) + + MCFG_DEVICE_ADD("lpt", PC_LPT, 0) + MCFG_PC_LPT_IRQ_HANDLER(WRITELINE(isa8_mda_device, pc_cpu_line)) +MACHINE_CONFIG_END + +ROM_START( mda ) + /* IBM 1501981(CGA) and 1501985(MDA) Character rom */ + ROM_REGION(0x08100,"gfx1", 0) + ROM_LOAD("5788005.u33", 0x00000, 0x02000, CRC(0bf56d70) SHA1(c2a8b10808bf51a3c123ba3eb1e9dd608231916f)) /* "AMI 8412PI // 5788005 // (C) IBM CORP. 1981 // KOREA" */ +ROM_END + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +const device_type ISA8_MDA = &device_creator<isa8_mda_device>; + + +//------------------------------------------------- +// machine_config_additions - device-specific +// machine configurations +//------------------------------------------------- + +machine_config_constructor isa8_mda_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( pcvideo_mda ); +} + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +const rom_entry *isa8_mda_device::device_rom_region() const +{ + return ROM_NAME( mda ); +} + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// isa8_mda_device - constructor +//------------------------------------------------- + +isa8_mda_device::isa8_mda_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, ISA8_MDA, "IBM Monochrome Display and Printer Adapter", tag, owner, clock, "isa_ibm_mda", __FILE__), + device_isa8_card_interface(mconfig, *this), + m_update_row_type(-1), + m_palette(*this, "palette") +{ +} + +isa8_mda_device::isa8_mda_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) : + device_t(mconfig, type, name, tag, owner, clock, shortname, source), + device_isa8_card_interface(mconfig, *this), + m_update_row_type(-1), + m_palette(*this, "palette") +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void isa8_mda_device::device_start() +{ + if (m_palette != NULL && !m_palette->started()) + throw device_missing_dependencies(); + + set_isa_device(); + m_videoram.resize(0x1000); + m_isa->install_device(0x3b0, 0x3bf, 0, 0, read8_delegate( FUNC(isa8_mda_device::io_read), this ), write8_delegate( FUNC(isa8_mda_device::io_write), this ) ); + m_isa->install_bank(0xb0000, 0xb0fff, 0, 0x07000, "bank_mda", &m_videoram[0]); + + /* Initialise the mda palette */ + for(int i = 0; i < 4; i++) + m_palette->set_pen_color(i, rgb_t(mda_palette[i][0], mda_palette[i][1], mda_palette[i][2])); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void isa8_mda_device::device_reset() +{ + m_framecnt = 0; + m_mode_control = 0; + m_vsync = 0; + m_hsync = 0; + m_pixel = 0; + + m_chr_gen = memregion(subtag("gfx1").c_str())->base(); +} + +/*************************************************************************** + + Monochrome Display Adapter (MDA) section + +***************************************************************************/ + +/*************************************************************************** + Draw text mode with 80x25 characters (default) and intense background. + The character cell size is 9x15. Column 9 is column 8 repeated for + character codes 176 to 223. +***************************************************************************/ + +MC6845_UPDATE_ROW( isa8_mda_device::mda_text_inten_update_row ) +{ + const rgb_t *palette = m_palette->palette()->entry_list_raw(); + UINT32 *p = &bitmap.pix32(y); + UINT16 chr_base = ( ra & 0x08 ) ? 0x800 | ( ra & 0x07 ) : ra; + int i; + + if ( y == 0 ) MDA_LOG(1,"mda_text_inten_update_row",("\n")); + for ( i = 0; i < x_count; i++ ) + { + UINT16 offset = ( ( ma + i ) << 1 ) & 0x0FFF; + UINT8 chr = m_videoram[ offset ]; + UINT8 attr = m_videoram[ offset + 1 ]; + UINT8 data = m_chr_gen[ chr_base + chr * 8 ]; + UINT8 fg = ( attr & 0x08 ) ? 3 : 2; + UINT8 bg = 0; + + if ( ( attr & ~0x88 ) == 0 ) + { + data = 0x00; + } + + switch( attr ) + { + case 0x70: + bg = 2; + fg = 0; + break; + case 0x78: + bg = 2; + fg = 1; + break; + case 0xF0: + bg = 3; + fg = 0; + break; + case 0xF8: + bg = 3; + fg = 1; + break; + } + + if ( ( i == cursor_x && ( m_framecnt & 0x08 ) ) || ( attr & 0x07 ) == 0x01 ) + { + data = 0xFF; + } + + *p = palette[( data & 0x80 ) ? fg : bg]; p++; + *p = palette[( data & 0x40 ) ? fg : bg]; p++; + *p = palette[( data & 0x20 ) ? fg : bg]; p++; + *p = palette[( data & 0x10 ) ? fg : bg]; p++; + *p = palette[( data & 0x08 ) ? fg : bg]; p++; + *p = palette[( data & 0x04 ) ? fg : bg]; p++; + *p = palette[( data & 0x02 ) ? fg : bg]; p++; + *p = palette[( data & 0x01 ) ? fg : bg]; p++; + if ( ( chr & 0xE0 ) == 0xC0 ) + { + *p = palette[( data & 0x01 ) ? fg : bg]; p++; + } + else + { + *p = palette[bg]; p++; + } + } +} + + +/*************************************************************************** + Draw text mode with 80x25 characters (default) and blinking characters. + The character cell size is 9x15. Column 9 is column 8 repeated for + character codes 176 to 223. +***************************************************************************/ + +MC6845_UPDATE_ROW( isa8_mda_device::mda_text_blink_update_row ) +{ + const rgb_t *palette = m_palette->palette()->entry_list_raw(); + UINT32 *p = &bitmap.pix32(y); + UINT16 chr_base = ( ra & 0x08 ) ? 0x800 | ( ra & 0x07 ) : ra; + int i; + + if ( y == 0 ) MDA_LOG(1,"mda_text_blink_update_row",("\n")); + for ( i = 0; i < x_count; i++ ) + { + UINT16 offset = ( ( ma + i ) << 1 ) & 0x0FFF; + UINT8 chr = m_videoram[ offset ]; + UINT8 attr = m_videoram[ offset + 1 ]; + UINT8 data = m_chr_gen[ chr_base + chr * 8 ]; + UINT8 fg = ( attr & 0x08 ) ? 3 : 2; + UINT8 bg = 0; + + if ( ( attr & ~0x88 ) == 0 ) + { + data = 0x00; + } + + switch( attr ) + { + case 0x70: + case 0xF0: + bg = 2; + fg = 0; + break; + case 0x78: + case 0xF8: + bg = 2; + fg = 1; + break; + } + + if ( ( attr & 0x07 ) == 0x01 ) + { + data = 0xFF; + } + + if ( i == cursor_x ) + { + if ( m_framecnt & 0x08 ) + { + data = 0xFF; + } + } + else + { + if ( ( attr & 0x80 ) && ( m_framecnt & 0x10 ) ) + { + data = 0x00; + } + } + + *p = palette[( data & 0x80 ) ? fg : bg]; p++; + *p = palette[( data & 0x40 ) ? fg : bg]; p++; + *p = palette[( data & 0x20 ) ? fg : bg]; p++; + *p = palette[( data & 0x10 ) ? fg : bg]; p++; + *p = palette[( data & 0x08 ) ? fg : bg]; p++; + *p = palette[( data & 0x04 ) ? fg : bg]; p++; + *p = palette[( data & 0x02 ) ? fg : bg]; p++; + *p = palette[( data & 0x01 ) ? fg : bg]; p++; + if ( ( chr & 0xE0 ) == 0xC0 ) + { + *p = palette[( data & 0x01 ) ? fg : bg]; p++; + } + else + { + *p = palette[bg]; p++; + } + } +} + + +MC6845_UPDATE_ROW( isa8_mda_device::crtc_update_row ) +{ + if (m_update_row_type == -1) + return; + + switch (m_update_row_type) + { + case MDA_TEXT_INTEN: + mda_text_inten_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp); + break; + case MDA_TEXT_BLINK: + mda_text_blink_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp); + break; + } +} + + +MC6845_UPDATE_ROW( isa8_hercules_device::crtc_update_row ) +{ + if (m_update_row_type == -1) + return; + + switch (m_update_row_type) + { + case HERCULES_GFX_BLINK: + hercules_gfx_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp); + break; + default: + isa8_mda_device::crtc_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp); + break; + } +} + + +WRITE_LINE_MEMBER( isa8_mda_device::hsync_changed ) +{ + m_hsync = state ? 1 : 0; +} + + +WRITE_LINE_MEMBER( isa8_mda_device::vsync_changed ) +{ + m_vsync = state ? 0x80 : 0; + if ( state ) + { + m_framecnt++; + } +} + + +/* + * rW MDA mode control register (see #P138) + */ +WRITE8_MEMBER( isa8_mda_device::mode_control_w ) +{ + m_mode_control = data; + + switch( m_mode_control & 0x2a ) + { + case 0x08: + m_update_row_type = MDA_TEXT_INTEN; + break; + case 0x28: + m_update_row_type = MDA_TEXT_BLINK; + break; + default: + m_update_row_type = -1; + } +} + + +/* R- CRT status register (see #P139) + * (EGA/VGA) input status 1 register + * 7 HGC vertical sync in progress + * 6-4 adapter 000 hercules + * 001 hercules+ + * 101 hercules InColor + * else unknown + * 3 pixel stream (0 black, 1 white) + * 2-1 reserved + * 0 horizontal drive enable + */ +READ8_MEMBER( isa8_mda_device::status_r) +{ + // Faking pixel stream here + m_pixel++; + + return 0xF0 | (m_pixel & 0x08) | m_hsync; +} + + +/************************************************************************* + * + * MDA + * monochrome display adapter + * + *************************************************************************/ +WRITE8_MEMBER( isa8_mda_device::io_write) +{ + mc6845_device *mc6845 = subdevice<mc6845_device>(MDA_MC6845_NAME); + pc_lpt_device *lpt = subdevice<pc_lpt_device>("lpt"); + switch( offset ) + { + case 0: case 2: case 4: case 6: + mc6845->address_w( space, offset, data ); + break; + case 1: case 3: case 5: case 7: + mc6845->register_w( space, offset, data ); + break; + case 8: + mode_control_w(space, offset, data); + break; + case 12: case 13: case 14: + lpt->write(space, offset - 12, data); + break; + } +} + +READ8_MEMBER( isa8_mda_device::io_read) +{ + int data = 0xff; + mc6845_device *mc6845 = subdevice<mc6845_device>(MDA_MC6845_NAME); + pc_lpt_device *lpt = subdevice<pc_lpt_device>("lpt"); + switch( offset ) + { + case 0: case 2: case 4: case 6: + /* return last written mc6845 address value here? */ + break; + case 1: case 3: case 5: case 7: + data = mc6845->register_r( space, offset ); + break; + case 10: + data = status_r(space, offset); + break; + /* 12, 13, 14 are the LPT ports */ + case 12: case 13: case 14: + data = lpt->read(space, offset - 12); + break; + } + return data; +} + + +/*************************************************************************** + + Hercules Display Adapter section (re-uses parts from the MDA section) + +***************************************************************************/ + +/* +When the Hercules changes to graphics mode, the number of pixels per access and +clock divider should be changed. The currect mc6845 implementation does not +allow this. + +The divder/pixels per 6845 clock is 9 for text mode and 16 for graphics mode. +*/ + +static GFXDECODE_START( pcherc ) + GFXDECODE_ENTRY( "gfx1", 0x0000, pc_16_charlayout, 1, 1 ) +GFXDECODE_END + +MACHINE_CONFIG_FRAGMENT( pcvideo_hercules ) + MCFG_SCREEN_ADD( HERCULES_SCREEN_NAME, RASTER) + MCFG_SCREEN_RAW_PARAMS(MDA_CLOCK, 882, 0, 720, 370, 0, 350 ) + MCFG_SCREEN_UPDATE_DEVICE( HERCULES_MC6845_NAME, mc6845_device, screen_update ) + + MCFG_PALETTE_ADD( "palette", 4 ) + + MCFG_MC6845_ADD(HERCULES_MC6845_NAME, MC6845, HERCULES_SCREEN_NAME, MDA_CLOCK/9) + MCFG_MC6845_SHOW_BORDER_AREA(false) + MCFG_MC6845_CHAR_WIDTH(9) + MCFG_MC6845_UPDATE_ROW_CB(isa8_hercules_device, crtc_update_row) + MCFG_MC6845_OUT_HSYNC_CB(WRITELINE(isa8_mda_device, hsync_changed)) + MCFG_MC6845_OUT_VSYNC_CB(WRITELINE(isa8_mda_device, vsync_changed)) + + MCFG_GFXDECODE_ADD("gfxdecode", "palette", pcherc) + + MCFG_DEVICE_ADD("lpt", PC_LPT, 0) + MCFG_PC_LPT_IRQ_HANDLER(WRITELINE(isa8_mda_device, pc_cpu_line)) +MACHINE_CONFIG_END + +ROM_START( hercules ) + ROM_REGION(0x1000,"gfx1", 0) + ROM_LOAD("um2301.bin", 0x00000, 0x1000, CRC(0827bdac) SHA1(15f1aceeee8b31f0d860ff420643e3c7f29b5ffc)) +ROM_END + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +const device_type ISA8_HERCULES = &device_creator<isa8_hercules_device>; + +//------------------------------------------------- +// machine_config_additions - device-specific +// machine configurations +//------------------------------------------------- + +machine_config_constructor isa8_hercules_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( pcvideo_hercules ); +} + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +const rom_entry *isa8_hercules_device::device_rom_region() const +{ + return ROM_NAME( hercules ); +} + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// isa8_hercules_device - constructor +//------------------------------------------------- + +isa8_hercules_device::isa8_hercules_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + isa8_mda_device(mconfig, ISA8_HERCULES, "Hercules Graphics Card", tag, owner, clock, "isa_hercules", __FILE__) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void isa8_hercules_device::device_start() +{ + if (m_palette != NULL && !m_palette->started()) + throw device_missing_dependencies(); + + m_videoram.resize(0x10000); + set_isa_device(); + m_isa->install_device(0x3b0, 0x3bf, 0, 0, read8_delegate( FUNC(isa8_hercules_device::io_read), this ), write8_delegate( FUNC(isa8_hercules_device::io_write), this ) ); + m_isa->install_bank(0xb0000, 0xbffff, 0, 0, "bank_hercules", &m_videoram[0]); + + /* Initialise the mda palette */ + for(int i = 0; i < (sizeof(mda_palette) / 3); i++) + m_palette->set_pen_color(i, mda_palette[i][0], mda_palette[i][1], mda_palette[i][2]); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void isa8_hercules_device::device_reset() +{ + isa8_mda_device::device_reset(); + m_configuration_switch = 0; + + m_chr_gen = memregion(subtag("gfx1").c_str())->base(); +} + +/*************************************************************************** + Draw graphics with 720x348 pixels (default); so called Hercules gfx. + The memory layout is divided into 4 banks where of size 0x2000. + Every bank holds data for every n'th scanline, 8 pixels per byte, + bit 7 being the leftmost. +***************************************************************************/ + +MC6845_UPDATE_ROW( isa8_hercules_device::hercules_gfx_update_row ) +{ + const rgb_t *palette = m_palette->palette()->entry_list_raw(); + UINT32 *p = &bitmap.pix32(y); + UINT16 gfx_base = ( ( m_mode_control & 0x80 ) ? 0x8000 : 0x0000 ) | ( ( ra & 0x03 ) << 13 ); + int i; + if ( y == 0 ) MDA_LOG(1,"hercules_gfx_update_row",("\n")); + for ( i = 0; i < x_count; i++ ) + { + UINT8 data = m_videoram[ gfx_base + ( ( ma + i ) << 1 ) ]; + + *p = palette[( data & 0x80 ) ? 2 : 0]; p++; + *p = palette[( data & 0x40 ) ? 2 : 0]; p++; + *p = palette[( data & 0x20 ) ? 2 : 0]; p++; + *p = palette[( data & 0x10 ) ? 2 : 0]; p++; + *p = palette[( data & 0x08 ) ? 2 : 0]; p++; + *p = palette[( data & 0x04 ) ? 2 : 0]; p++; + *p = palette[( data & 0x02 ) ? 2 : 0]; p++; + *p = palette[( data & 0x01 ) ? 2 : 0]; p++; + + data = m_videoram[ gfx_base + ( ( ma + i ) << 1 ) + 1 ]; + + *p = palette[( data & 0x80 ) ? 2 : 0]; p++; + *p = palette[( data & 0x40 ) ? 2 : 0]; p++; + *p = palette[( data & 0x20 ) ? 2 : 0]; p++; + *p = palette[( data & 0x10 ) ? 2 : 0]; p++; + *p = palette[( data & 0x08 ) ? 2 : 0]; p++; + *p = palette[( data & 0x04 ) ? 2 : 0]; p++; + *p = palette[( data & 0x02 ) ? 2 : 0]; p++; + *p = palette[( data & 0x01 ) ? 2 : 0]; p++; + } +} + + +WRITE8_MEMBER( isa8_hercules_device::mode_control_w ) +{ + mc6845_device *mc6845 = subdevice<mc6845_device>(HERCULES_MC6845_NAME); + + m_mode_control = data; + + switch( m_mode_control & 0x2a ) + { + case 0x08: + m_update_row_type = MDA_TEXT_INTEN; + break; + case 0x28: + m_update_row_type = MDA_TEXT_BLINK; + break; + case 0x0A: /* Hercules modes */ + case 0x2A: + m_update_row_type = HERCULES_GFX_BLINK; + break; + default: + m_update_row_type = -1; + } + + mc6845->set_clock( m_mode_control & 0x02 ? MDA_CLOCK / 16 : MDA_CLOCK / 9 ); + mc6845->set_hpixels_per_column( m_mode_control & 0x02 ? 16 : 9 ); +} + + +WRITE8_MEMBER( isa8_hercules_device::io_write ) +{ + mc6845_device *mc6845 = subdevice<mc6845_device>(HERCULES_MC6845_NAME); + pc_lpt_device *lpt = subdevice<pc_lpt_device>("lpt"); + switch( offset ) + { + case 0: case 2: case 4: case 6: + mc6845->address_w( space, offset, data ); + break; + case 1: case 3: case 5: case 7: + mc6845->register_w( space, offset, data ); + break; + case 8: + mode_control_w(space, offset, data); + break; + case 12: case 13: case 14: + lpt->write(space, offset - 12, data); + break; + case 15: + m_configuration_switch = data; + break; + } +} + + +/* R- CRT status register (see #P139) + * (EGA/VGA) input status 1 register + * 7 HGC vertical sync in progress + * 6-4 adapter 000 hercules + * 001 hercules+ + * 101 hercules InColor + * else unknown + * 3 pixel stream (0 black, 1 white) + * 2-1 reserved + * 0 horizontal drive enable + */ +READ8_MEMBER( isa8_hercules_device::status_r ) +{ + // Faking pixel stream here + m_pixel++; + + return m_vsync | ( m_pixel & 0x08 ) | m_hsync; +} + + +READ8_MEMBER( isa8_hercules_device::io_read ) +{ + int data = 0xff; + mc6845_device *mc6845 = subdevice<mc6845_device>(HERCULES_MC6845_NAME); + pc_lpt_device *lpt = subdevice<pc_lpt_device>("lpt"); + switch( offset ) + { + case 0: case 2: case 4: case 6: + /* return last written mc6845 address value here? */ + break; + case 1: case 3: case 5: case 7: + data = mc6845->register_r( space, offset ); + break; + case 10: + data = status_r(space, offset); + break; + /* 12, 13, 14 are the LPT ports */ + case 12: case 13: case 14: + data = lpt->read(space, offset - 12); + break; + } + return data; +} + +// XXX +MACHINE_CONFIG_FRAGMENT( pcvideo_ec1840_0002 ) + MCFG_SCREEN_ADD( MDA_SCREEN_NAME, RASTER) + MCFG_SCREEN_RAW_PARAMS(MDA_CLOCK, 792, 0, 640, 370, 0, 350 ) + MCFG_SCREEN_UPDATE_DEVICE( MDA_MC6845_NAME, mc6845_device, screen_update ) + + MCFG_PALETTE_ADD( "palette", 4 ) + + MCFG_MC6845_ADD( MDA_MC6845_NAME, MC6845, MDA_SCREEN_NAME, MDA_CLOCK/8) + MCFG_MC6845_SHOW_BORDER_AREA(false) + MCFG_MC6845_CHAR_WIDTH(8) + MCFG_MC6845_UPDATE_ROW_CB(isa8_mda_device, crtc_update_row) + MCFG_MC6845_OUT_HSYNC_CB(WRITELINE(isa8_mda_device, hsync_changed)) + MCFG_MC6845_OUT_VSYNC_CB(WRITELINE(isa8_mda_device, vsync_changed)) +MACHINE_CONFIG_END + +const device_type ISA8_EC1840_0002 = &device_creator<isa8_ec1840_0002_device>; + + +//------------------------------------------------- +// machine_config_additions - device-specific +// machine configurations +//------------------------------------------------- + +machine_config_constructor isa8_ec1840_0002_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( pcvideo_ec1840_0002 ); +} + +//------------------------------------------------- +// isa8_ec1840_0002_device - constructor +//------------------------------------------------- + +isa8_ec1840_0002_device::isa8_ec1840_0002_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + isa8_mda_device( mconfig, ISA8_EC1840_0002, "EC 1840.0002 (MDA)", tag, owner, clock, "ec1840_0002", __FILE__) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void isa8_ec1840_0002_device::device_start() +{ + isa8_mda_device::device_start(); + + m_soft_chr_gen = auto_alloc_array(machine(), UINT8, 0x2000); + m_isa->install_bank(0xdc000, 0xddfff, 0, 0x2000, "bank_chargen", m_soft_chr_gen); +} + +void isa8_ec1840_0002_device::device_reset() +{ + isa8_mda_device::device_reset(); + + m_chr_gen = m_soft_chr_gen; +} + + +/*************************************************************************** + Draw text mode with 80x25 characters (default) and intense background. + The character cell size is 8x14. +***************************************************************************/ + +MC6845_UPDATE_ROW( isa8_ec1840_0002_device::mda_lowres_text_inten_update_row ) +{ + const rgb_t *palette = m_palette->palette()->entry_list_raw(); + UINT32 *p = &bitmap.pix32(y); + UINT16 chr_base = ra; + int i; + + if ( y == 0 ) MDA_LOG(1,"mda_lowres_text_inten_update_row",("\n")); + for ( i = 0; i < x_count; i++ ) + { + UINT16 offset = ( ( ma + i ) << 1 ) & 0x0FFF; + UINT8 chr = m_videoram[ offset ]; + UINT8 attr = m_videoram[ offset + 1 ]; + UINT8 data = m_chr_gen[ (chr_base + chr * 16) << 1 ]; + UINT8 fg = ( attr & 0x08 ) ? 3 : 2; + UINT8 bg = 0; + + if ( ( attr & ~0x88 ) == 0 ) + { + data = 0x00; + } + + switch( attr ) + { + case 0x70: + bg = 2; + fg = 0; + break; + case 0x78: + bg = 2; + fg = 1; + break; + case 0xF0: + bg = 3; + fg = 0; + break; + case 0xF8: + bg = 3; + fg = 1; + break; + } + + if ( ( i == cursor_x && ( m_framecnt & 0x08 ) ) || ( attr & 0x07 ) == 0x01 ) + { + data = 0xFF; + } + + *p = palette[( data & 0x80 ) ? fg : bg]; p++; + *p = palette[( data & 0x40 ) ? fg : bg]; p++; + *p = palette[( data & 0x20 ) ? fg : bg]; p++; + *p = palette[( data & 0x10 ) ? fg : bg]; p++; + *p = palette[( data & 0x08 ) ? fg : bg]; p++; + *p = palette[( data & 0x04 ) ? fg : bg]; p++; + *p = palette[( data & 0x02 ) ? fg : bg]; p++; + *p = palette[( data & 0x01 ) ? fg : bg]; p++; + } +} + + +/*************************************************************************** + Draw text mode with 80x25 characters (default) and blinking characters. + The character cell size is 8x14. +***************************************************************************/ + +MC6845_UPDATE_ROW( isa8_ec1840_0002_device::mda_lowres_text_blink_update_row ) +{ + const rgb_t *palette = m_palette->palette()->entry_list_raw(); + UINT32 *p = &bitmap.pix32(y); + UINT16 chr_base = ra; + int i; + + if ( y == 0 ) MDA_LOG(1,"mda_lowres_text_blink_update_row",("\n")); + for ( i = 0; i < x_count; i++ ) + { + UINT16 offset = ( ( ma + i ) << 1 ) & 0x0FFF; + UINT8 chr = m_videoram[ offset ]; + UINT8 attr = m_videoram[ offset + 1 ]; + UINT8 data = m_chr_gen[ (chr_base + chr * 16) << 1 ]; + UINT8 fg = ( attr & 0x08 ) ? 3 : 2; + UINT8 bg = 0; + + if ( ( attr & ~0x88 ) == 0 ) + { + data = 0x00; + } + + switch( attr ) + { + case 0x70: + case 0xF0: + bg = 2; + fg = 0; + break; + case 0x78: + case 0xF8: + bg = 2; + fg = 1; + break; + } + + if ( ( attr & 0x07 ) == 0x01 ) + { + data = 0xFF; + } + + if ( i == cursor_x ) + { + if ( m_framecnt & 0x08 ) + { + data = 0xFF; + } + } + else + { + if ( ( attr & 0x80 ) && ( m_framecnt & 0x10 ) ) + { + data = 0x00; + } + } + + *p = palette[( data & 0x80 ) ? fg : bg]; p++; + *p = palette[( data & 0x40 ) ? fg : bg]; p++; + *p = palette[( data & 0x20 ) ? fg : bg]; p++; + *p = palette[( data & 0x10 ) ? fg : bg]; p++; + *p = palette[( data & 0x08 ) ? fg : bg]; p++; + *p = palette[( data & 0x04 ) ? fg : bg]; p++; + *p = palette[( data & 0x02 ) ? fg : bg]; p++; + *p = palette[( data & 0x01 ) ? fg : bg]; p++; + } +} + +WRITE8_MEMBER( isa8_ec1840_0002_device::mode_control_w ) +{ + m_mode_control = data; + + switch( m_mode_control & 0x2a ) + { + case 0x08: + m_update_row_type = MDA_LOWRES_TEXT_INTEN; + break; + case 0x28: + m_update_row_type = MDA_LOWRES_TEXT_BLINK; + break; + default: + m_update_row_type = -1; + } +} + +MC6845_UPDATE_ROW( isa8_ec1840_0002_device::crtc_update_row ) +{ + if (m_update_row_type == -1) + return; + + switch (m_update_row_type) + { + case MDA_LOWRES_TEXT_INTEN: + mda_lowres_text_inten_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp); + break; + case MDA_LOWRES_TEXT_BLINK: + mda_lowres_text_blink_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp); + break; + } +} |