diff options
Diffstat (limited to 'src/devices/bus/isa/ega.c')
-rw-r--r-- | src/devices/bus/isa/ega.c | 1416 |
1 files changed, 1416 insertions, 0 deletions
diff --git a/src/devices/bus/isa/ega.c b/src/devices/bus/isa/ega.c new file mode 100644 index 00000000000..4da4ead2c6d --- /dev/null +++ b/src/devices/bus/isa/ega.c @@ -0,0 +1,1416 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol +/*************************************************************************** + + Enhanced Graphics Adapter (EGA) section + +TODO - Write documentation + +"Regular" register on an EGA graphics card: + + 3C2 - 7 6 5 4 3 2 1 0 - Misc Output Register - Write Only + | | | | | | | | + | | | | | | | +-- 3Bx/3Dx I/O port select + | | | | | | | 0 = 3Bx for CRTC I/O, 3BA for status reg 1 + | | | | | | | 1 = 3Dx for CRTC I/O, 3DA for status reg 1 + | | | | | | +---- enable ram + | | | | | | 0 = disable ram from the processor + | | | | | | 1 = enable ram to respond to addresses + | | | | | | designated by the Control Data Select + | | | | | | value in the Graphics Controllers. + | | | | | +------ clock select bit 0 + | | | | +-------- clock select bit 1 + | | | | 00 = 14MHz from Processor I/O channel + | | | | 01 = 16MHz on-bord clock + | | | | 10 = External clock from feature connector + | | | | 11 = reserved/unused + | | | +---------- disable video drivers + | | | 0 = activate internal video drivers + | | | 1 = disable internal video drivers + | | +------------ page bit for odd/even. Selects between 2 pages + | | of 64KB of memory when in odd/even mode. + | | 0 = select low page + | | 1 = select high page + | +-------------- horizontal retrace polarity + | 0 = select positive + | 1 = select negative + +---------------- vertical retrace polarity + 0 = select positive + 1 = select negative + + + 3C2 - 7 6 5 4 3 2 1 0 - Input Status Reg 0 - Read Only + | | | | | | | | + | | | | | | | +-- reserved/unused + | | | | | | +---- reserved/unused + | | | | | +------ reserved/unused + | | | | +-------- reserved/unused + | | | +---------- switch sense + | | | 0 = switch is closed + | | | 1 = allows processor to read the 4 config switches + | | | on the EGA adapter. The setting of CLKSEL determines + | | | switch to read. + | | +------------ input from FEAT0 on the feature connector + | +-------------- input from FEAT1 on the feature connector + +---------------- CRT Interrupt + 0 = vertical retrace if occurring + 1 = video is being displayed + + + Configuration switches + SW1 SW2 SW3 SW4 + OFF OFF OFF ON - EGA, Color 80x25 (5153) + - EGA (primary) + MDA, Color 80x25 + Monochrome + OFF OFF ON OFF - EGA, Monochrome (5151) + - EGA (primary) + CGA, Monochrome + Color 80x25 + OFF OFF ON ON - EGA + MDA (primary), 5154 + Enhanced Monochrome + OFF ON OFF ON - EGA + CGA (primary), Monochrome + Color 80x25 + OFF ON ON OFF - EGA, Enhanced Color - Enhanced Mode (5154) + - EGA (primary) + MDA, 5154 monitor + Enhanced Monochrome + OFF ON ON ON - EGA + MDA (primary), Color 80x25 + Monochrome + ON OFF OFF ON - EGA, Color 40x25 (5153) + - EGA (primary) + MDA, Color 40x25 + Monochrome + ON OFF ON OFF - EGA (primary) + CGA, Monochrome + Color 40x25 + ON OFF ON ON - EGA + MDA (primary), 5154 + Normal Monochrome + ON ON OFF ON - EGA + CGA (primary), Monochrome + Color 40x25 + ON ON ON OFF - EGA, Enhanced Color - Enhanced Mode (5154) + - EGA (primary) + MDA, 5154 monitor + Normal Monochrome + ON ON ON ON - EGA + MDA (primary), Color 40x25 + Monochrome + + + 3XA - 7 6 5 4 3 2 1 0 - Feature Control Register - Write Only + | | | | | | | | + | | | | | | | +-- output to FEAT0 of the feature connector + | | | | | | +---- output to FEAT1 of the feature connector + | | | | | +------ reserved/unused + | | | | +-------- reserved/unused + | | | +---------- reserved/unused + | | +------------ reserved/unused + | +-------------- reserved/unused + +---------------- reserved/unused + + 3XA - 7 6 5 4 3 2 1 0 - Input Status Reg 1 - Read Only + | | | | | | | | + | | | | | | | +-- display enable + | | | | | | | 0 = indicates the CRT raster is in a horizontal or vertical retrace + | | | | | | | 1 = otherwise + | | | | | | +---- light pen strobe + | | | | | | 0 = light pen trigger has not been set + | | | | | | 1 = light pen trigger has been set + | | | | | +------ light pen switch + | | | | | 0 = switch is closed + | | | | | 1 = switch is open + | | | | +-------- vertical blank + | | | | 0 = video information is being displayed + | | | | 1 = CRT is in vertical blank + | | | +---------- diagnostic usage, output depends on AR12 video status mux bits + | | | mux bits - output + | | | 00 - blue + | | | 01 - I blue + | | | 10 - I red + | | | 11 - unknown + | | +------------ diagnostic usage, output depends on AR12 video status mux bits + | | mux bits - output + | | 00 - red + | | 01 - green + | | 10 - I green + | | 11 - unknown + | +-------------- reserved/unused + +---------------- reserved/unused + + + +The EGA graphics card introduces a lot of new indexed registers to handle the +enhanced graphics. These new indexed registers can be divided into three +groups: +- attribute registers +- sequencer registers +- graphics controllers registers + + +Attribute Registers AR00 - AR13 + +The Attribute Registers are all accessed through I/O port 0x3C0. The first +write to I/O port 0x3C0 sets the index register. The next write to I/O port +0x3C0 actually sets the data to the indexed register. + + 3C0 - 7 6 5 4 3 2 1 0 - Attribute Access Register + | | | | | | | | + | | | | | | | +-- index bit 0 + | | | | | | +---- index bit 1 + | | | | | +------ index bit 2 + | | | | +-------- index bit 3 + | | | +---------- index bit 4 + | | +------------ palette source + | +-------------- reserved/unused + +---------------- reserved/unused + + + AR00-AR0F - 7 6 5 4 3 2 1 0 - Palette Register #00 - #0F + | | | | | | | | + | | | | | | | +-- MSB B + | | | | | | +---- MSB G + | | | | | +------ MSB R + | | | | +-------- LSB B + | | | +---------- LSB G + | | +------------ LSB R + | +-------------- reserved/unused + +---------------- reserved/unused + + + AR10 - 7 6 5 4 3 2 1 0 - Mode Control Register + | | | | | | | | + | | | | | | | +-- Text/Graphics select + | | | | | | +---- Monochrome/Color select + | | | | | +------ 9th dot setting + | | | | +-------- Blink Enable + | | | +---------- reserved/unsued + | | +------------ 0 = line compare does not affect pixel output + | | 1 = line compare does affect pixel output + | +-------------- 0 = pixel changes every dot clock + | 1 = pixel changes every other dot clock + +---------------- reserved/unused + + + AR11 - 7 6 5 4 3 2 1 0 - Overscan Color Register + | | | | | | | | + | | | | | | | +-- MSB B + | | | | | | +---- MSB G + | | | | | +------ MSB R + | | | | +-------- LSB B + | | | +---------- LSB G + | | +------------ LSB R + | +-------------- reserved/unused + +---------------- reserved/unused + + + AR12 - 7 6 5 4 3 2 1 0 - Color Plane Enable Register + | | | | | | | | + | | | | | | | +-- Enable plane 0 + | | | | | | +---- Enable plane 1 + | | | | | +------ Enable plane 2 + | | | | +-------- Enable plane 3 + | | | +---------- Video Status Mux bit 0 + | | +------------ Video Status Mux bit 1 + | +-------------- reserved/unused + +---------------- reserved/unused + + + AR13 - 7 6 5 4 3 2 1 0 - Horizontal Panning Register + | | | | | | | | + | | | | | | | +-- Pixel left shift bit 0 + | | | | | | +---- Pixel left shift bit 1 + | | | | | +------ Pixel left shift bit 2 + | | | | +-------- Pixel left shift bit 3 + | | | +---------- reserved/unused + | | +------------ reserved/unused + | +-------------- reserved/unused + +---------------- reserved/unused + + +Sequencer Registers SR00 - SR04 + +The Sequencer Registers are accessed through an index register located at I/O +port 0x3C4, and a data register located at I/O port 0x3C5. + + 3C4 - 7 6 5 4 3 2 1 0 - Sequencer Index Register - Write Only + | | | | | | | | + | | | | | | | +-- index bit 0 + | | | | | | +---- index bit 1 + | | | | | +------ index bit 2 + | | | | +-------- reserved/unused + | | | +---------- reserved/unused + | | +------------ reserved/unused + | +-------------- reserved/unused + +---------------- reserved/unused + + + 3C5 - 7 6 5 4 3 2 1 0 - Sequencer Data Register - Write Only + | | | | | | | | + | | | | | | | +-- data bit 0 + | | | | | | +---- data bit 1 + | | | | | +------ data bit 2 + | | | | +-------- data bit 3 + | | | +---------- data bit 4 + | | +------------ data bit 5 + | +-------------- data bit 6 + +---------------- data bit 7 + + + SR00 - 7 6 5 4 3 2 1 0 - Reset Control Register + | | | | | | | | + | | | | | | | +-- Must be 1 for normal operation + | | | | | | +---- Must be 1 for normal operation + | | | | | +------ reserved/unused + | | | | +-------- reserved/unused + | | | +---------- reserved/unused + | | +------------ reserved/unused + | +-------------- reserved/unused + +---------------- reserved/unused + + + SR01 - 7 6 5 4 3 2 1 0 - Clocking Mode + | | | | | | | | + | | | | | | | +-- 0 = 9 dots per char, 1 = 8 dots per char + | | | | | | +---- clock frequency, 0 = 4 out of 5 memory cycles, 1 = 2 out of 5 memory cycles + | | | | | +------ shift load + | | | | +-------- 0 = normal dot clock, 1 = master dot clock / 2 + | | | +---------- reserved/unused + | | +------------ reserved/unused + | +-------------- reserved/unused + +---------------- reserved/unused + + + SR02 - 7 6 5 4 3 2 1 0 - Map Mask + | | | | | | | | + | | | | | | | +-- 1 = enable map 0 for writing + | | | | | | +---- 1 = enable map 1 for writing + | | | | | +------ 1 = enable map 2 for writing + | | | | +-------- 1 = enable map 3 for writing + | | | +---------- reserved/unused + | | +------------ reserved/unused + | +-------------- reserved/unused + +---------------- reserved/unused + + + SR03 - 7 6 5 4 3 2 1 0 - Character Map Select + | | | | | | | | + | | | | | | | +-- character map select B bit 0 + | | | | | | +---- character map select B bit 1 + | | | | | | Selects the map used to generate alpha characters when + | | | | | | attribute bit 3 is set to 0 + | | | | | | 00 = map 0 - 1st 8KB of plane 2 bank 0 + | | | | | | 01 = map 1 - 2nd 8KB of plane 2 bank 1 + | | | | | | 10 = map 2 - 3rd 8KB of plane 2 bank 2 + | | | | | | 11 = map 3 - 4th 8KB of plane 2 bank 3 + | | | | | +------ character map select A bit 0 + | | | | +-------- character map select A bit 1 + | | | | Selects the map used to generate alpha characters when + | | | | attribute bit 3 is set to 1 + | | | | 00 = map 0 - 1st 8KB of plane 2 bank 0 + | | | | 01 = map 1 - 2nd 8KB of plane 2 bank 1 + | | | | 10 = map 2 - 3rd 8KB of plane 2 bank 2 + | | | | 11 = map 3 - 4th 8KB of plane 2 bank 3 + | | | +---------- reserved/unused + | | +------------ reserved/unused + | +-------------- reserved/unused + +---------------- reserved/unused + + + SR04 - 7 6 5 4 3 2 1 0 - Memory Mode Register + | | | | | | | | + | | | | | | | +-- 0 = graphics mode, 1 = text mode + | | | | | | +---- 0 = no memory extension, 1 = memory extension + | | | | | +------ 0 = odd/even storage, 1 = sequential storage + | | | | +-------- reserved/unused + | | | +---------- reserved/unused + | | +------------ reserved/unused + | +-------------- reserved/unused + +---------------- reserved/unused + + +Graphics Controller Registers GR00 - GR08 + +The Graphics Controller Registers are accessed through an index register +located at I/O port 0x3CE, and a data register located at I/O port 0x3CF. + + GR00 - 7 6 5 4 3 2 1 0 - Set/Reset Register + | | | | | | | | + | | | | | | | +-- set/reset for plane 0 + | | | | | | +---- set/reset for plane 1 + | | | | | +------ set/reset for plane 2 + | | | | +-------- set/reset for plane 3 + | | | +---------- reserved/unused + | | +------------ reserved/unused + | +-------------- reserved/unused + +---------------- reserved/unused + + + GR01 - 7 6 5 4 3 2 1 0 - Enable Set/Reset Register + | | | | | | | | + | | | | | | | +-- enable set/reset for plane 0 + | | | | | | +---- enable set/reset for plane 1 + | | | | | +------ enable set/reset for plane 2 + | | | | +-------- enable set/reset for plane 3 + | | | +---------- reserved/unused + | | +------------ reserved/unused + | +-------------- reserved/unused + +---------------- reserved/unused + + + GR02 - 7 6 5 4 3 2 1 0 - Color Compare Register + | | | | | | | | + | | | | | | | +-- color compare 0 + | | | | | | +---- color compare 1 + | | | | | +------ color compare 2 + | | | | +-------- color compare 3 + | | | +---------- reserved/unused + | | +------------ reserved/unused + | +-------------- reserved/unused + +---------------- reserved/unused + + + GR03 - 7 6 5 4 3 2 1 0 - Data Rotate Register + | | | | | | | | + | | | | | | | +-- number of positions to rotate bit 0 + | | | | | | +---- number of positions to rotate bit 1 + | | | | | +------ number of positions to rotate bit 2 + | | | | +-------- function select bit 0 + | | | +---------- function select bit 1 + | | | 00 = data overwrites in specified color + | | | 01 = data ANDed with latched data + | | | 10 = data ORed with latched data + | | | 11 = data XORed with latched data + | | +------------ reserved/unused + | +-------------- reserved/unused + +---------------- reserved/unused + + + GR04 - 7 6 5 4 3 2 1 0 - Read Map Select Register + | | | | | | | | + | | | | | | | +-- plane select bit 0 + | | | | | | +---- plane select bit 1 + | | | | | +------ reserved/unused + | | | | +-------- reserved/unused + | | | +---------- reserved/unused + | | +------------ reserved/unused + | +-------------- reserved/unused + +---------------- reserved/unused + + + GR05 - 7 6 5 4 3 2 1 0 - Mode Register + | | | | | | | | + | | | | | | | +-- write mode bit 0 + | | | | | | +---- write mode bit 1 + | | | | | | 00 = write 8 bits of value in set/reset register if enabled, + | | | | | | otherwise write rotated processor data + | | | | | | 01 = write with contents of processor latches + | | | | | | 10 = memory plane 0-3 filled with 8 bits of value of data bit 0-3 + | | | | | | 11 = reserved/unused + | | | | | +------ test condition + | | | | | 0 = normal operation + | | | | | 1 = put outputs in high impedance state + | | | | +-------- read mode + | | | | 0 = read from plane selected by GR04 + | | | | 1 = do color compare + | | | +---------- odd/even addressing mode + | | +------------ shift register mode + | | 0 = sequential + | | 1 = even bits from even maps, odd bits from odd maps + | +-------------- reserved/unused + +---------------- reserved/unused + + + GR06 - 7 6 5 4 3 2 1 0 - Miscellaneous Register + | | | | | | | | + | | | | | | | +-- 0 = text mode, 1 = graphics mode + | | | | | | +---- chain odd maps to even + | | | | | +------ memory map bit 0 + | | | | +-------- memory map bit 1 + | | | | 00 = 0xA0000, 128KB + | | | | 01 = 0xA0000, 64KB + | | | | 10 = 0xB0000, 32KB + | | | | 11 = 0xB8000, 32KB + | | | +---------- reserved/unused + | | +------------ reserved/unused + | +-------------- reserved/unused + +---------------- reserved/unused + + + GR07 - 7 6 5 4 3 2 1 0 - Color Plane Ignore Register + | | | | | | | | + | | | | | | | +-- ignore color plane 0 + | | | | | | +---- ignore color plane 1 + | | | | | +------ ignore color plane 2 + | | | | +-------- ignore color plane 3 + | | | +---------- reserved/unused + | | +------------ reserved/unused + | +-------------- reserved/unused + +---------------- reserved/unused + + + GR08 - 7 6 5 4 3 2 1 0 - Bit Mask Register + | | | | | | | | + | | | | | | | +-- write enable bit 0 + | | | | | | +---- write enable bit 1 + | | | | | +------ write enable bit 2 + | | | | +-------- write enable bit 3 + | | | +---------- write enable bit 4 + | | +------------ write enable bit 5 + | +-------------- write enable bit 6 + +---------------- write enable bit 7 + + +***************************************************************************/ + +#include "emu.h" +#include "ega.h" + +#define VERBOSE_EGA 1 + +#define EGA_SCREEN_NAME "ega_screen" +#define EGA_CRTC_NAME "crtc_ega_ega" + + +#define EGA_MODE_GRAPHICS 1 +#define EGA_MODE_TEXT 2 + + +/* + Prototypes +*/ + +MACHINE_CONFIG_FRAGMENT( pcvideo_ega ) + MCFG_SCREEN_ADD(EGA_SCREEN_NAME, RASTER) + MCFG_SCREEN_RAW_PARAMS(16257000,912,0,640,262,0,200) + MCFG_SCREEN_UPDATE_DEVICE(EGA_CRTC_NAME, crtc_ega_device, screen_update) + MCFG_SCREEN_PALETTE("palette") + + MCFG_PALETTE_ADD( "palette", 64 ) + + MCFG_DEVICE_ADD(EGA_CRTC_NAME, CRTC_EGA, 16257000/8) + MCFG_CRTC_EGA_SET_SCREEN(EGA_SCREEN_NAME) + MCFG_CRTC_EGA_HPIXELS_PER_COLUMN(8) + MCFG_CRTC_EGA_ROW_UPDATE_CB(isa8_ega_device, ega_update_row) + MCFG_CRTC_EGA_RES_OUT_DE_CB(WRITELINE(isa8_ega_device, de_changed)) + MCFG_CRTC_EGA_RES_OUT_HSYNC_CB(WRITELINE(isa8_ega_device, hsync_changed)) + MCFG_CRTC_EGA_RES_OUT_VSYNC_CB(WRITELINE(isa8_ega_device, vsync_changed)) + MCFG_CRTC_EGA_RES_OUT_VBLANK_CB(WRITELINE(isa8_ega_device, vblank_changed)) +MACHINE_CONFIG_END + +ROM_START( ega ) + ROM_REGION(0x4000, "user1", 0) + ROM_DEFAULT_BIOS("ega") + ROM_SYSTEM_BIOS(0, "ega", "IBM EGA BIOS") + ROMX_LOAD("6277356.u44", 0x0000, 0x4000, CRC(dc146448) SHA1(dc0794499b3e499c5777b3aa39554bbf0f2cc19b), ROM_BIOS(1)) + ROM_SYSTEM_BIOS(1, "iskr3104", "Iskra-3104 EGA BIOS") + ROMX_LOAD( "143-03.bin", 0x0001, 0x2000, CRC(d0706345) SHA1(e04bb40d944426a4ae2e3a614d3f4953d7132ede),ROM_SKIP(1)|ROM_BIOS(2)) + ROMX_LOAD( "143-02.bin", 0x0000, 0x2000, CRC(c8c18ebb) SHA1(fd6dac76d43ab8b582e70f1d5cc931d679036fb9),ROM_SKIP(1)|ROM_BIOS(2)) + ROM_REGION(0x4000, "user2", ROMREGION_ERASE00) +ROM_END + +/* +0000 - MONOC PRIMARY, EGA COLOR, 40x25 +0001 - MONOC PRIMARY, EGA COLOR, 80x25 +0010 - MONOC PRIMARY, EGA HI RES EMULATE (SAME AS 0001) +0011 - MONOC PRIMARY, EGA HI RES ENHANCED +0100 - COLOR 40 PRIMARY, EGA MONOCHROME +0101 - COLOR 80 PRIMARY, EGA MONOCHROME + +0110 - MONOC SECONDARY, EGA COLOR, 40x24 +0111 - MONOC SECONDARY, EGA COLOR, 80x25 +1000 - MONOC SECONDARY, EGA HI RES EMULATE (SAME AS 0111) +1001 - MONOC SECONDARY, EGA HI RES ENHANCED +1010 - COLOR 40 SECONDARY, EGA +1011 - COLOR 80 SECONDARY, EGA + +1100 - RESERVED +1101 - RESERVED +1110 - RESERVED +1111 - RESERVED +*/ + +INPUT_PORTS_START( ega ) + PORT_START( "config" ) + PORT_CONFNAME( 0x0f, 0x09, "dipswitches" ) + PORT_CONFSETTING( 0x00, "0000 - MDA PRIMARY, EGA COLOR, 40x25" ) /* DIAG: ?? 40 cols, RGBI */ + PORT_CONFSETTING( 0x08, "0001 - MDA PRIMARY, EGA COLOR, 80x25" ) /* DIAG: ?? 80 cols, RGBI */ + PORT_CONFSETTING( 0x04, "0010 - MDA PRIMARY, EGA HI RES EMULATE (SAME AS 0001)" ) /* DIAG: ?? 80 cols, RGBI */ + PORT_CONFSETTING( 0x0c, "0011 - MDA PRIMARY, EGA HI RES ENHANCED" ) /* DIAG: Color Display 40 cols, RrGgBb */ + PORT_CONFSETTING( 0x02, "0100 - CGA 40 PRIMARY, EGA MONOCHROME" ) /* DIAG: ??, Mono RGBI */ + PORT_CONFSETTING( 0x0a, "0101 - CGA 80 PRIMARY, EGA MONOCHROME" ) /* DIAG: ??, Mono RGBI */ + PORT_CONFSETTING( 0x06, "0110 - MDA SECONDARY, EGA COLOR, 40x25" ) /* DIAG: Color Display 40 cols, RGBI */ + PORT_CONFSETTING( 0x0e, "0111 - MDA SECONDARY, EGA COLOR, 80x25" ) /* DIAG: Color Display 80 cols, RGBI */ + PORT_CONFSETTING( 0x01, "1000 - MDA SECONDARY, EGA HI RES EMULATE (SAME AS 0111)" ) /* DIAG: Color Display 80 cols, RGBI */ + PORT_CONFSETTING( 0x09, "1001 - MDA SECONDARY, EGA HI RES ENHANCED" ) /* DIAG: Color Display 40 cols, RrGgBb */ + PORT_CONFSETTING( 0x05, "1010 - COLOR 40 SECONDARY, EGA" ) /* DIAG: Monochrome display, Mono RGBI */ + PORT_CONFSETTING( 0x0d, "1011 - COLOR 80 SECONDARY, EGA" ) /* DIAG: Monochrome display, Mono RGBI */ + PORT_CONFSETTING( 0x03, "1100 - RESERVED" ) /* ??, RGBI */ + PORT_CONFSETTING( 0x0b, "1101 - RESERVED" ) /* ??, RGBI */ + PORT_CONFSETTING( 0x07, "1110 - RESERVED" ) /* ??, RGBI */ + PORT_CONFSETTING( 0x0f, "1111 - RESERVED" ) /* ??, RGBI */ +INPUT_PORTS_END + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +const device_type ISA8_EGA = &device_creator<isa8_ega_device>; + + +//------------------------------------------------- +// machine_config_additions - device-specific +// machine configurations +//------------------------------------------------- + +machine_config_constructor isa8_ega_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( pcvideo_ega ); +} + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +const rom_entry *isa8_ega_device::device_rom_region() const +{ + return ROM_NAME( ega ); +} + +ioport_constructor isa8_ega_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( ega ); +} + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// isa8_ega_device - constructor +//------------------------------------------------- + +isa8_ega_device::isa8_ega_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, ISA8_EGA, "IBM Enhanced Graphics Adapter", tag, owner, clock, "ega", __FILE__), + device_isa8_card_interface(mconfig, *this), + m_misc_output(0), + m_palette(*this, "palette") +{ +} + +isa8_ega_device::isa8_ega_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_misc_output(0), + m_palette(*this, "palette") +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void isa8_ega_device::device_start() +{ + if (m_palette != NULL && !m_palette->started()) + throw device_missing_dependencies(); + + set_isa_device(); + + for (int i = 0; i < 64; i++ ) + { + UINT8 r = ( ( i & 0x04 ) ? 0xAA : 0x00 ) + ( ( i & 0x20 ) ? 0x55 : 0x00 ); + UINT8 g = ( ( i & 0x02 ) ? 0xAA : 0x00 ) + ( ( i & 0x10 ) ? 0x55 : 0x00 ); + UINT8 b = ( ( i & 0x01 ) ? 0xAA : 0x00 ) + ( ( i & 0x08 ) ? 0x55 : 0x00 ); + + m_palette->set_pen_color( i, r, g, b ); + } + + if(m_default_bios_tag != "iskr3104") + { + UINT8 *dst = memregion(subtag("user2").c_str())->base() + 0x0000; + UINT8 *src = memregion(subtag("user1").c_str())->base() + 0x3fff; + int i; + + /* Perform the EGA bios address line swaps */ + for( i = 0; i < 0x4000; i++ ) + { + *dst++ = *src--; + } + } + else + memcpy(memregion(subtag("user2").c_str())->base(), memregion(subtag("user1").c_str())->base(), 0x4000); + + /* Install 256KB Video ram on our EGA card */ + m_vram = machine().memory().region_alloc(subtag("vram").c_str(), 256 * 1024, 1, ENDIANNESS_LITTLE); + + m_videoram = m_vram->base(); + m_plane[0] = m_videoram + 0x00000; + memset(m_plane[0], 0, sizeof(UINT8) * 0x10000); + m_plane[1] = m_videoram + 0x10000; + memset(m_plane[1], 0, sizeof(UINT8) * 0x10000); + m_plane[2] = m_videoram + 0x20000; + memset(m_plane[2], 0, sizeof(UINT8) * 0x10000); + m_plane[3] = m_videoram + 0x30000; + memset(m_plane[3], 0, sizeof(UINT8) * 0x10000); + + m_crtc_ega = subdevice<crtc_ega_device>(EGA_CRTC_NAME); + + m_isa->install_rom(this, 0xc0000, 0xc3fff, 0, 0, "ega", "user2"); + m_isa->install_device(0x3b0, 0x3bf, 0, 0, read8_delegate(FUNC(isa8_ega_device::pc_ega8_3b0_r), this), write8_delegate(FUNC(isa8_ega_device::pc_ega8_3b0_w), this)); + m_isa->install_device(0x3c0, 0x3cf, 0, 0, read8_delegate(FUNC(isa8_ega_device::pc_ega8_3c0_r), this), write8_delegate(FUNC(isa8_ega_device::pc_ega8_3c0_w), this)); + m_isa->install_device(0x3d0, 0x3df, 0, 0, read8_delegate(FUNC(isa8_ega_device::pc_ega8_3d0_r), this), write8_delegate(FUNC(isa8_ega_device::pc_ega8_3d0_w), this)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void isa8_ega_device::device_reset() +{ + m_feature_control = 0; + + memset(&m_attribute,0,sizeof(m_attribute)); + memset(&m_sequencer,0,sizeof(m_sequencer)); + memset(&m_graphics_controller,0,sizeof(m_graphics_controller)); + + m_frame_cnt = 0; + m_hsync = 0; + m_vsync = 0; + m_vblank = 0; + m_display_enable = 0; + + install_banks(); + + m_misc_output = 0; + m_attribute.index_write = 1; + + /* Set up default palette */ + m_attribute.data[0] = 0; + m_attribute.data[1] = 1; + m_attribute.data[2] = 2; + m_attribute.data[3] = 3; + m_attribute.data[4] = 4; + m_attribute.data[5] = 5; + m_attribute.data[6] = 0x14; + m_attribute.data[7] = 7; + m_attribute.data[8] = 0x38; + m_attribute.data[9] = 0x39; + m_attribute.data[10] = 0x3A; + m_attribute.data[11] = 0x3B; + m_attribute.data[12] = 0x3C; + m_attribute.data[13] = 0x3D; + m_attribute.data[14] = 0x3E; + m_attribute.data[15] = 0x3F; + + m_video_mode = 0; +} + +void isa8_ega_device::install_banks() +{ + switch ( m_graphics_controller.data[6] & 0x0c ) + { + case 0x00: /* 0xA0000, 128KB */ + if ( m_misc_output & 0x02 ) + { + m_isa->install_memory(0xa0000, 0xbffff, 0, 0, read8_delegate(FUNC(isa8_ega_device::read), this), write8_delegate(FUNC(isa8_ega_device::write), this)); + } + else + { + m_isa->unmap_bank(0xa0000, 0xaffff,0,0); + m_isa->unmap_bank(0xb0000, 0xb7fff,0,0); + m_isa->unmap_bank(0xb8000, 0xbffff,0,0); + } + break; + case 0x04: /* 0xA0000, 64KB */ + if ( m_misc_output & 0x02 ) + { + m_isa->install_memory(0xa0000, 0xaffff, 0, 0, read8_delegate(FUNC(isa8_ega_device::read), this), write8_delegate(FUNC(isa8_ega_device::write), this)); + } + else + { + m_isa->unmap_bank(0xa0000, 0xaffff,0,0); + } + /* These unmaps may break multi graphics card support */ + m_isa->unmap_bank(0xb0000, 0xb7fff,0,0); + m_isa->unmap_bank(0xb8000, 0xbffff,0,0); + break; + case 0x08: /* 0xB0000, 32KB */ + if ( m_misc_output & 0x02 ) + { + m_isa->install_memory(0xb0000, 0xb7fff, 0, 0, read8_delegate(FUNC(isa8_ega_device::read), this), write8_delegate(FUNC(isa8_ega_device::write), this)); + } + else + { + m_isa->unmap_bank(0xb0000, 0xb7fff,0,0); + } + /* These unmaps may break multi graphics card support */ + m_isa->unmap_bank(0xa0000, 0xaffff,0,0); + m_isa->unmap_bank(0xb8000, 0xbffff,0,0); + break; + case 0x0c: /* 0xB8000, 32KB */ + if ( m_misc_output & 0x02 ) + { + m_isa->install_memory(0xb8000, 0xbffff, 0, 0, read8_delegate(FUNC(isa8_ega_device::read), this), write8_delegate(FUNC(isa8_ega_device::write), this)); + } + else + { + m_isa->unmap_bank(0xb8000, 0xbffff,0,0); + } + /* These unmaps may break multi graphics card support */ + m_isa->unmap_bank(0xa0000, 0xaffff,0,0); + m_isa->unmap_bank(0xb0000, 0xb7fff,0,0); + break; + } +} + +CRTC_EGA_ROW_UPDATE( isa8_ega_device::ega_update_row ) +{ + if (m_video_mode == EGA_MODE_GRAPHICS) + pc_ega_graphics(bitmap, cliprect, ma, ra, y, x_count, cursor_x); + else if (m_video_mode == EGA_MODE_TEXT) + pc_ega_text(bitmap, cliprect, ma, ra, y, x_count, cursor_x); +} + + +WRITE_LINE_MEMBER( isa8_ega_device::de_changed ) +{ + m_display_enable = state ? 1 : 0; +} + + +WRITE_LINE_MEMBER( isa8_ega_device::hsync_changed ) +{ + m_hsync = state ? 1 : 0; +} + + +WRITE_LINE_MEMBER( isa8_ega_device::vsync_changed ) +{ + m_vsync = state ? 1 : 0; + if ( state ) + { + m_frame_cnt++; + } +} + + +WRITE_LINE_MEMBER( isa8_ega_device::vblank_changed ) +{ + m_vblank = state ? 8 : 0; +} + + +CRTC_EGA_ROW_UPDATE( isa8_ega_device::pc_ega_graphics ) +{ + UINT16 *p = &bitmap.pix16(y); + +// logerror( "pc_ega_graphics: y = %d, x_count = %d, ma = %d, ra = %d\n", y, x_count, ma, ra ); + + if ( m_graphics_controller.data[5] & 0x10 ) + { + // Odd/Even mode (CGA compatible) + + for ( int i = 0; i < x_count; i++ ) + { + UINT16 offset = ( ( ma + i ) & 0x1fff ) | ( ( y & 1 ) << 12 ); + UINT8 data = m_plane[0][offset]; + + *p = m_attribute.data[ ( data >> 6 ) ]; p++; + *p = m_attribute.data[ ( data >> 4 ) & 0x03 ]; p++; + *p = m_attribute.data[ ( data >> 2 ) & 0x03 ]; p++; + *p = m_attribute.data[ data & 0x03 ]; p++; + + data = m_plane[1][offset]; + + *p = m_attribute.data[ ( data >> 6 ) ]; p++; + *p = m_attribute.data[ ( data >> 4 ) & 0x03 ]; p++; + *p = m_attribute.data[ ( data >> 2 ) & 0x03 ]; p++; + *p = m_attribute.data[ data & 0x03 ]; p++; + } + } + else + { + // EGA mode + + UINT8 mask = m_attribute.data[0x12] & 0x0f; + + for ( int i = 0; i < x_count; i++ ) + { + UINT16 offset = ma + i; + UINT16 data0 = m_plane[0][offset]; + UINT16 data1 = m_plane[1][offset] << 1; + UINT16 data2 = m_plane[2][offset] << 2; + UINT16 data3 = m_plane[3][offset] << 3; + + for ( int j = 7; j >= 0; j-- ) + { + UINT16 col = ( data0 & 0x01 ) | ( data1 & 0x02 ) | ( data2 & 0x04 ) | ( data3 & 0x08 ); + + col &= mask; + + p[j] = m_attribute.data[col]; + + data0 >>= 1; + data1 >>= 1; + data2 >>= 1; + data3 >>= 1; + } + p += 8; + } + } +} + + +CRTC_EGA_ROW_UPDATE( isa8_ega_device::pc_ega_text ) +{ + UINT16 *p = &bitmap.pix16(y); + int i; + +// logerror( "pc_ega_text: y = %d, x_count = %d, ma = %d, ra = %d\n", y, x_count, ma, ra ); + + for ( i = 0; i < x_count; i++ ) + { + UINT16 offset = ma + i; + UINT8 chr = m_plane[0][ offset ]; + UINT8 attr = m_plane[1][ offset ]; + UINT8 data = 0; + UINT16 fg = m_attribute.data[ attr & 0x07 ]; + UINT16 bg = m_attribute.data[ ( attr >> 4 ) & 0x07 ]; + + /* If character set A and B are equal attribute bit 3 is used as intensity */ + if ( m_charA == m_charB ) + { + /* intensity selector */ + data = m_charB[ chr * 32 + ra ]; + fg += ( attr & 0x08 ) ? 0x38 : 0x00; + } + else + { + /* character set selector */ + data = ( attr & 0x08 ) ? m_charA[ chr * 32 + ra ] : m_charB[ chr * 32 + ra ]; + } + + if ( i == cursor_x ) + { + if ( m_frame_cnt & 0x08 ) + { + data = 0xFF; + } + } + else + { + /* Check for blinking */ + if ( ( m_attribute.data[0x10] & 0x08 ) && ( attr & 0x80 ) && ( m_frame_cnt & 0x10 ) ) + { + data = 0x00; + } + } + + *p = ( data & 0x80 ) ? fg : bg; p++; + *p = ( data & 0x40 ) ? fg : bg; p++; + *p = ( data & 0x20 ) ? fg : bg; p++; + *p = ( data & 0x10 ) ? fg : bg; p++; + *p = ( data & 0x08 ) ? fg : bg; p++; + *p = ( data & 0x04 ) ? fg : bg; p++; + *p = ( data & 0x02 ) ? fg : bg; p++; + *p = ( data & 0x01 ) ? fg : bg; p++; + } +} + + +void isa8_ega_device::change_mode() +{ + int clock, pixels; + + m_video_mode = 0; + + /* Check for graphics mode */ + if ( ( m_attribute.data[0x10] & 0x01 ) && + ! ( m_sequencer.data[0x04] & 0x01 ) && + ( m_graphics_controller.data[0x06] & 0x01 ) ) + { + if ( VERBOSE_EGA ) + { + logerror("change_mode(): Switch to graphics mode\n"); + } + + m_video_mode = EGA_MODE_GRAPHICS; + } + + /* Check for text mode */ + if ( ! ( m_attribute.data[0x10] & 0x01 ) && + ( m_sequencer.data[0x04] & 0x01 ) && + ! ( m_graphics_controller.data[0x06] & 0x01 ) ) + { + if ( VERBOSE_EGA ) + { + logerror("chnage_mode(): Switching to text mode\n"); + } + + m_video_mode = EGA_MODE_TEXT; + + /* Set character maps */ + if ( m_sequencer.data[0x04] & 0x02 ) + { + m_charA = m_plane[2] + ( ( m_sequencer.data[0x03] & 0x0c ) >> 1 ) * 0x2000; + m_charB = m_plane[2] + ( m_sequencer.data[0x03] & 0x03 ) * 0x2000; + } + else + { + m_charA = m_plane[2]; + m_charB = m_plane[2]; + } + } + + /* Check for changes to the crtc input clock and number of pixels per clock */ + clock = ( ( m_misc_output & 0x0c ) ? 16257000 : XTAL_14_31818MHz ); + pixels = ( ( m_sequencer.data[0x01] & 0x01 ) ? 8 : 9 ); + + if ( m_sequencer.data[0x01] & 0x08 ) + { + clock >>= 1; + } + m_crtc_ega->set_clock( clock / pixels ); + m_crtc_ega->set_hpixels_per_column( pixels ); + + if (!m_video_mode) + logerror("unknown video mode\n"); +} + + +READ8_MEMBER( isa8_ega_device::read ) +{ + UINT8 data = 0xFF; + + if ( !space.debugger_access() && ! ( m_sequencer.data[4] & 0x04 ) ) + { + /* Fill read latches */ + m_read_latch[0] = m_plane[0][offset & 0xffff]; + m_read_latch[1] = m_plane[1][offset & 0xffff]; + m_read_latch[2] = m_plane[2][offset & 0xffff]; + m_read_latch[3] = m_plane[3][offset & 0xffff]; + } + + if ( m_graphics_controller.data[5] & 0x08 ) + { + // Read mode #1 + popmessage("ega: Read mode 1 not supported yet!"); + printf("EGA: Read mode 1 not supported yet!\n"); + } + else + { + // Read mode #0 + if ( m_sequencer.data[4] & 0x04 ) + { + // Normal addressing mode + data = m_plane[ m_graphics_controller.data[4] & 0x03 ][offset & 0xffff]; + } + else + { + // Odd/Even addressing mode + data = m_plane[offset & 1][(offset & 0xffff) >> 1]; + } + } + + return data; +} + + +UINT8 isa8_ega_device::alu_op( UINT8 data, UINT8 latch_data ) +{ + UINT8 mask = m_graphics_controller.data[8]; + + switch( m_graphics_controller.data[3] & 0x18 ) + { + case 0x00: // Unmodified + return ( data & mask ) | ( latch_data & ~mask ); + + case 0x08: // AND + return ( data | ~mask ) & latch_data; + + case 0x10: // OR + return ( data & mask ) | latch_data; + + case 0x18: // XOR + return ( data & mask ) ^ latch_data; + } + return 0; +} + + +WRITE8_MEMBER( isa8_ega_device::write ) +{ + UINT8 d[4]; + UINT8 alu[4]; + UINT8 target_mask = m_graphics_controller.data[8]; + + alu[0] =alu[1] = alu[2] = alu[3] = 0; + + switch( m_graphics_controller.data[5] & 0x03 ) + { + case 0: // Write mode 0 + // Pass through barrel shifter + data = ( ( ( data << 8 ) | data ) >> ( m_graphics_controller.data[3] & 0x07 ) ) & 0xFF; + + d[0] = d[1] = d[2] = d[3] = data; + + /* Apply Set/Reset settings */ + if ( m_graphics_controller.data[1] & 0x01 ) + { + d[0] = ( m_graphics_controller.data[0] & 0x01 ) ? 0xff : 0x00; + } + if ( m_graphics_controller.data[1] & 0x02 ) + { + d[1] = ( m_graphics_controller.data[0] & 0x02 ) ? 0xff : 0x00; + } + if ( m_graphics_controller.data[1] & 0x04 ) + { + d[2] = ( m_graphics_controller.data[0] & 0x04 ) ? 0xff : 0x00; + } + if ( m_graphics_controller.data[1] & 0x08 ) + { + d[3] = ( m_graphics_controller.data[0] & 0x08 ) ? 0xff : 0x00; + } + + // Pass through ALUs + alu[0] = alu_op( d[0], m_read_latch[0] ); + alu[1] = alu_op( d[1], m_read_latch[1] ); + alu[2] = alu_op( d[2], m_read_latch[2] ); + alu[3] = alu_op( d[3], m_read_latch[3] ); + + break; + + case 1: // Write mode 1 + alu[0] = m_read_latch[0]; + alu[1] = m_read_latch[1]; + alu[2] = m_read_latch[2]; + alu[3] = m_read_latch[3]; + target_mask = 0xff; + return; + + case 2: // Write mode 2 + d[0] = ( data & 0x01 ) ? 0xff : 0x00; + d[1] = ( data & 0x02 ) ? 0xff : 0x00; + d[2] = ( data & 0x04 ) ? 0xff : 0x00; + d[3] = ( data & 0x08 ) ? 0xff : 0x00; + + alu[0] = alu_op( d[0], m_read_latch[0] ); + alu[1] = alu_op( d[1], m_read_latch[1] ); + alu[2] = alu_op( d[2], m_read_latch[2] ); + alu[3] = alu_op( d[3], m_read_latch[3] ); + break; + + case 3: // Write mode 3 + popmessage("EGA: Write mode 3 not supported!"); + return; + } + + offset &= 0xffff; + + // + // Plane selection + // TODO: Get this logic clearer. The documentation is unclear on the exact magic combination of bits. + // + if ( m_sequencer.data[4] & 0x04 ) + { + // Sequential addressing mode + if ( m_sequencer.data[2] & 0x01 ) + { + // Plane 0 + // Bit selection + m_plane[0][offset] = ( m_plane[0][offset] & ~ target_mask ) | ( alu[0] & target_mask ); + } + if ( m_sequencer.data[2] & 0x02 ) + { + // Plane 1 + // Bit selection + m_plane[1][offset] = ( m_plane[1][offset] & ~ target_mask ) | ( alu[1] & target_mask ); + } + if ( m_sequencer.data[2] & 0x04 ) + { + // Plane 2 + // Bit selection + m_plane[2][offset] = ( m_plane[2][offset] & ~ target_mask ) | ( alu[2] & target_mask ); + } + if ( m_sequencer.data[2] & 0x08 ) + { + // Plane 3 + // Bit selection + m_plane[3][offset] = ( m_plane[3][offset] & ~ target_mask ) | ( alu[3] & target_mask ); + } + } + else + { + // Odd/Even addressing mode + if ( offset & 1 ) + { + // Odd addresses go to planes 1 and 3 + + offset >>= 1; + + if ( m_sequencer.data[2] & 0x02 ) + { + // Plane 1 + // Bit selection + m_plane[1][offset] = ( m_plane[1][offset] & ~ target_mask ) | ( alu[1] & target_mask ); + } + if ( ( m_sequencer.data[2] & 0x08 ) && ! ( m_sequencer.data[4] & 0x01 ) ) + { + // Plane 3 + // Bit selection + m_plane[3][offset] = ( m_plane[3][offset] & ~ target_mask ) | ( alu[3] & target_mask ); + } + } + else + { + // Even addresses go to planes 0 and 2 + + offset >>= 1; + + if ( m_sequencer.data[2] & 0x01 ) + { + // Plane 0 + // Bit selection + m_plane[0][offset] = ( m_plane[0][offset] & ~ target_mask ) | ( alu[0] & target_mask ); + } + if ( ( m_sequencer.data[2] & 0x04 ) && ! ( m_sequencer.data[4] & 0x01 ) ) + { + // Plane 2 + // Bit selection + m_plane[2][offset] = ( m_plane[2][offset] & ~ target_mask ) | ( alu[2] & target_mask ); + } + } + } +} + + +READ8_MEMBER( isa8_ega_device::pc_ega8_3X0_r ) +{ + int data = 0xff; + + switch ( offset ) + { + /* CRT Controller - address register */ + case 0: case 2: case 4: case 6: + /* return last written mc6845 address value here? */ + break; + + /* CRT Controller - data register */ + case 1: case 3: case 5: case 7: + data = m_crtc_ega->register_r( space, offset ); + break; + + /* Input Status Register 1 */ + case 10: + data = m_vblank | ( m_hsync | m_vsync ); // m_display_enable; + + if ( m_display_enable ) + { + /* For the moment i'm putting in some bogus data */ + static int pixel_data; + + pixel_data = ( pixel_data + 1 ) & 0x03; + data |= ( pixel_data << 4 ); + } + + /* Reset the attirubte writing flip flop to let the next write go to the index reigster */ + m_attribute.index_write = 1; + break; + } + + return data; +} + +WRITE8_MEMBER( isa8_ega_device::pc_ega8_3X0_w ) +{ + if ( VERBOSE_EGA ) + { +// logerror("pc_ega_3X0_w: offset = %02x, data = %02x\n", offset, data ); + } + + switch ( offset ) + { + /* CRT Controller - address register */ + case 0: case 2: case 4: case 6: + m_crtc_ega->address_w( space, offset, data ); + break; + + /* CRT Controller - data register */ + case 1: case 3: case 5: case 7: + m_crtc_ega->register_w( space, offset, data ); + break; + + /* Set Light Pen Flip Flop */ + case 9: + break; + + /* Feature Control */ + case 10: + m_feature_control = data; + break; + + /* Clear Light Pen Flip Flop */ + case 11: + break; + } +} + + + +READ8_MEMBER(isa8_ega_device::pc_ega8_3b0_r ) +{ + return ( m_misc_output & 0x01 ) ? 0xFF : pc_ega8_3X0_r(space, offset); +} + + +READ8_MEMBER(isa8_ega_device::pc_ega8_3d0_r ) +{ + return ( m_misc_output & 0x01 ) ? pc_ega8_3X0_r(space, offset) : 0xFF; +} + + +WRITE8_MEMBER(isa8_ega_device::pc_ega8_3b0_w ) +{ + if ( ! ( m_misc_output & 0x01 ) ) + { + pc_ega8_3X0_w( space, offset, data ); + } +} + + +WRITE8_MEMBER(isa8_ega_device::pc_ega8_3d0_w ) +{ + if ( m_misc_output & 0x01 ) + { + pc_ega8_3X0_w( space, offset, data ); + } +} + + +READ8_MEMBER(isa8_ega_device::pc_ega8_3c0_r ) +{ + int data = 0xff; + + if ( VERBOSE_EGA ) + { +// logerror("pc_ega_3c0_r: offset = %02x\n", offset ); + } + + switch ( offset ) + { + /* Attributes Controller */ + case 0: + break; + + /* Feature Read */ + case 2: + { + UINT8 dips = ioport("config")->read(); + + data = ( data & 0x0f ); + data |= ( ( m_feature_control & 0x03 ) << 5 ); + data |= ( m_vsync ? 0x00 : 0x80 ); + data |= ( ( ( dips >> ( ( ( m_misc_output & 0x0c ) >> 2 ) ) ) & 0x01 ) << 4 ); + } + break; + + /* Sequencer */ + case 4: + break; + case 5: + break; + + /* Graphics Controller */ + case 14: + break; + case 15: + break; + } + return data; +} + + +WRITE8_MEMBER(isa8_ega_device::pc_ega8_3c0_w ) +{ + static const UINT8 ar_reg_mask[0x20] = + { + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x7F, 0x3F, 0x3F, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + static const UINT8 sr_reg_mask[0x08] = + { + 0x03, 0x0F, 0x0F, 0x0F, 0x07, 0x00, 0x00, 0x00 + }; + static const UINT8 gr_reg_mask[0x10] = + { + 0x0F, 0x0F, 0x0F, 0x1F, 0x07, 0x3F, 0x0F, 0x0F, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + int index = 0; + + if ( VERBOSE_EGA ) + { +// logerror("pc_ega_3c0_w: offset = %02x, data = %02x\n", offset, data ); + } + + switch ( offset ) + { + /* Attributes Controller */ + case 0: + if ( m_attribute.index_write ) + { + m_attribute.index = data; + } + else + { + index = m_attribute.index & 0x1F; + + logerror("AR%02X = 0x%02x\n", index, data ); + + /* Clear unused bits */ + m_attribute.data[ index ] = data & ar_reg_mask[ index ]; + + switch ( index ) + { + case 0x10: /* AR10 */ + change_mode(); + break; + } + } + m_attribute.index_write ^= 0x01; + break; + + /* Misccellaneous Output */ + case 2: + m_misc_output = data; + install_banks(); + change_mode(); + break; + + /* Sequencer */ + case 4: + m_sequencer.index = data; + break; + case 5: + index = m_sequencer.index & 0x07; + + logerror("SR%02X = 0x%02x\n", index & 0x07, data ); + + /* Clear unused bits */ + m_sequencer.data[ index ] = data & sr_reg_mask[ index ]; + + switch ( index ) + { + case 0x01: /* SR01 */ + case 0x03: /* SR03 */ + case 0x04: /* SR04 */ + change_mode(); + break; + } + break; + + /* Graphics Controller */ + case 14: + m_graphics_controller.index = data; + break; + case 15: + index = m_graphics_controller.index & 0x0F; + + logerror("GR%02X = 0x%02x\n", index, data ); + + /* Clear unused bits */ + m_graphics_controller.data[ index ] = data & gr_reg_mask[ index ]; + + switch ( index ) + { + case 0x06: /* GR06 */ + change_mode(); + install_banks(); + break; + } + break; + } +} |