diff options
Diffstat (limited to 'src/devices/video/pc_vga.cpp')
-rw-r--r-- | src/devices/video/pc_vga.cpp | 6510 |
1 files changed, 1411 insertions, 5099 deletions
diff --git a/src/devices/video/pc_vga.cpp b/src/devices/video/pc_vga.cpp index 7e15f1efe5e..34ae2bf4881 100644 --- a/src/devices/video/pc_vga.cpp +++ b/src/devices/video/pc_vga.cpp @@ -1,31 +1,26 @@ // license:BSD-3-Clause // copyright-holders:Nathan Woods, Peter Trauner, Angelo Salese -/*************************************************************************** +/************************************************************************************************** Video Graphics Adapter (VGA) section Nathan Woods npwoods@mess.org Peter Trauner PeT mess@utanet.at - This code takes care of installing the various VGA memory and port - handlers - - The VGA standard is compatible with MDA, CGA, Hercules, EGA - (mda, cga, hercules not real register compatible) - several vga cards drive also mda, cga, ega monitors - some vga cards have register compatible mda, cga, hercules modes - ega/vga 64k (early ega 16k) words of 32 bit memory TODO: - - modernize - - fix video update, still need to get that choosevideomode() out of it. - - rewrite video drawing functions (they are horrible) - - add per-gfx card VESA functions; - - (and many more ...) - - per-game issues: + - modernize (in progress); + - Make RAMDAC a subclassable entity; + \- Clients needs to be able to swap that to SVGA extensions of the original 6bpp; + - Attribute from graphics to text mode in DOS doesn't restore properly, particularly if you + have a custom background color defined (verify); + - Improve debugging; + - Make a VGA bus slot option, already needed by 3dfx Voodoo and other similar cards; + - Verify how CAD ISA cards needs to r/w the VRAM space (uPD7220, HD63484, others); + + per-game issues (very outdated, to be moved to SW list/to device files if necessary): - The Incredible Machine: fix partial updates - MAME 0.01: fix 92 Hz refresh rate bug (uses VESA register?). - Virtual Pool: ET4k unrecognized; @@ -33,26 +28,47 @@ - Jazz Jackrabbit: status bar is very jerky, but main screen scrolling is fine? - Catacombs: weird resolution (untested) - ROM declarations: + Notes: + - The VGA standard is compatible with MDA, CGA, Hercules, EGA + (MDA, EGA, Hercules not real register compatible) + - several vga cards drive also MDA, CGA, EGA monitors, some vga cards have register compatible + MDA, CGA, Hercules modes; + - SVGA is not a real interface but more like an overlay of the VGA standard that individual + manufacturers put together and which eventually became the VESA consortium. + It has incidentally a couple points in common across families but it's otherwise mostly a + commercial naming rather than a real physical change over the bus slot. + In the end we may not even need this extra device but rather move "SVGA mode" + responsibility to RAMDACs. + + References: + - http://www.osdever.net/FreeVGA/vga/vga.htm + + ROM declarations (move to pc_vga_oak): (oti 037 chip) - ROM_LOAD("oakvga.bin", 0xc0000, 0x8000, 0x318c5f43) - (tseng labs famous et4000 isa vga card (oem)) - ROM_LOAD("et4000b.bin", 0xc0000, 0x8000, 0xa903540d) - (tseng labs famous et4000 isa vga card) - ROM_LOAD("et4000.bin", 0xc0000, 0x8000, 0xf01e4be0) + ROM_LOAD("oakvga.bin", 0xc0000, 0x8000, CRC(318c5f43) SHA1(2aeb6cf737fd87dfd08c9f5b5bc421fcdbab4ce9) ) -***************************************************************************/ +***************************************************************************************************/ #include "emu.h" #include "pc_vga.h" -#include "bus/isa/trident.h" -#include "machine/eepromser.h" - -#include "debugger.h" #include "screen.h" +#define LOG_WARN (1U << 1) +#define LOG_REGS (1U << 2) // deprecated +#define LOG_DSW (1U << 3) // Input sense at $3c2 +#define LOG_CRTC (1U << 4) // CRTC setups with monitor geometry + +#define VERBOSE (LOG_GENERAL | LOG_WARN) +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" + +#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__) +#define LOGREGS(...) LOGMASKED(LOG_REGS, __VA_ARGS__) +#define LOGDSW(...) LOGMASKED(LOG_DSW, __VA_ARGS__) +#define LOGCRTC(...) LOGMASKED(LOG_CRTC, __VA_ARGS__) + /*************************************************************************** @@ -60,36 +76,18 @@ ***************************************************************************/ -enum -{ - IBM8514_IDLE = 0, - IBM8514_DRAWING_RECT, - IBM8514_DRAWING_LINE, - IBM8514_DRAWING_BITBLT, - IBM8514_DRAWING_PATTERN, - IBM8514_DRAWING_SSV_1, - IBM8514_DRAWING_SSV_2, - MACH8_DRAWING_SCAN -}; - -#define CRTC_PORT_ADDR ((vga.miscellaneous_output&1)?0x3d0:0x3b0) - //#define TEXT_LINES (LINES_HELPER) -#define LINES (vga.crtc.vert_disp_end+1) +#define LINES ((vga.crtc.vert_disp_end + 1) * (get_interlace_mode() + 1)) #define TEXT_LINES (vga.crtc.vert_disp_end+1) #define GRAPHIC_MODE (vga.gc.alpha_dis) /* else text mode */ #define EGA_COLUMNS (vga.crtc.horz_disp_end+1) -#define EGA_START_ADDRESS (vga.crtc.start_addr) #define EGA_LINE_LENGTH (vga.crtc.offset<<1) #define VGA_COLUMNS (vga.crtc.horz_disp_end+1) -#define VGA_START_ADDRESS (vga.crtc.start_addr) #define VGA_LINE_LENGTH (vga.crtc.offset<<3) -#define IBM8514_LINE_LENGTH (m_vga->offset()) - #define VGA_CH_WIDTH ((vga.sequencer.data[1]&1)?8:9) #define TEXT_COLUMNS (vga.crtc.horz_disp_end+1) @@ -101,40 +99,31 @@ enum // Special values for SVGA Trident - Mode Vesa 110h #define TLINES (LINES) #define TGA_COLUMNS (EGA_COLUMNS) -#define TGA_START_ADDRESS (vga.crtc.start_addr<<2) #define TGA_LINE_LENGTH (vga.crtc.offset<<3) /*************************************************************************** - Static declarations - -***************************************************************************/ - -#define LOG_ACCESSES 0 -#define LOG_REGISTERS 0 - -#define LOG_8514 1 - -/*************************************************************************** - Generic VGA ***************************************************************************/ // device type definition -DEFINE_DEVICE_TYPE(VGA, vga_device, "vga", "VGA") -DEFINE_DEVICE_TYPE(TSENG_VGA, tseng_vga_device, "tseng_vga", "Tseng Labs VGA") -DEFINE_DEVICE_TYPE(S3_VGA, s3_vga_device, "s3_vga", "S3 Graphics VGA") -DEFINE_DEVICE_TYPE(GAMTOR_VGA, gamtor_vga_device, "gamtor_vga", "GAMTOR VGA") -DEFINE_DEVICE_TYPE(ATI_VGA, ati_vga_device, "ati_vga", "ATi VGA") -DEFINE_DEVICE_TYPE(IBM8514A, ibm8514a_device, "ibm8514a", "IBM 8514/A Video") -DEFINE_DEVICE_TYPE(MACH8, mach8_device, "mach8", "Mach8") +DEFINE_DEVICE_TYPE(VGA, vga_device, "vga", "VGA") vga_device::vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, type, tag, owner, clock) , device_video_interface(mconfig, *this) , device_palette_interface(mconfig, *this) + , device_memory_interface(mconfig, *this) + , vga(*this) + , m_input_sense(*this, "VGA_SENSE") + , m_vsync_cb(*this) { + m_main_if_space_config = address_space_config("io_regs", ENDIANNESS_LITTLE, 8, 4, 0, address_map_constructor(FUNC(vga_device::io_3bx_3dx_map), this)); + m_crtc_space_config = address_space_config("crtc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(vga_device::crtc_map), this)); + m_gc_space_config = address_space_config("gc_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(vga_device::gc_map), this)); + m_seq_space_config = address_space_config("sequencer_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(vga_device::sequencer_map), this)); + m_atc_space_config = address_space_config("attribute_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(vga_device::attribute_map), this)); } vga_device::vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) @@ -142,67 +131,9 @@ vga_device::vga_device(const machine_config &mconfig, const char *tag, device_t { } -svga_device::svga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : vga_device(mconfig, type, tag, owner, clock) -{ -} - -tseng_vga_device::tseng_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : svga_device(mconfig, TSENG_VGA, tag, owner, clock) -{ -} - -s3_vga_device::s3_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : s3_vga_device(mconfig, S3_VGA, tag, owner, clock) -{ -} - -s3_vga_device::s3_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : ati_vga_device(mconfig, type, tag, owner, clock) -{ -} - -gamtor_vga_device::gamtor_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : svga_device(mconfig, GAMTOR_VGA, tag, owner, clock) -{ -} - -ati_vga_device::ati_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : ati_vga_device(mconfig, ATI_VGA, tag, owner, clock) -{ -} - -ati_vga_device::ati_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : svga_device(mconfig, type, tag, owner, clock) -{ -} - -ibm8514a_device::ibm8514a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : ibm8514a_device(mconfig, IBM8514A, tag, owner, clock) -{ -} - -ibm8514a_device::ibm8514a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, type, tag, owner, clock) - , m_vga(*this, finder_base::DUMMY_TAG) -{ -} - -mach8_device::mach8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : ibm8514a_device(mconfig, type, tag, owner, clock) -{ -} - -mach8_device::mach8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : mach8_device(mconfig, MACH8, tag, owner, clock) -{ -} - // zero everything, keep vtbls void vga_device::zero() { - memset(&vga.svga_intf, 0, sizeof(vga.svga_intf)); - vga.memory.resize(0); memset(vga.pens, 0, sizeof(vga.pens)); vga.miscellaneous_output = 0; vga.feature_control = 0; @@ -214,52 +145,31 @@ void vga_device::zero() memset(&vga.oak, 0, sizeof(vga.oak)); } -void svga_device::zero() -{ - vga_device::zero(); - memset(&svga, 0, sizeof(svga)); -} - -/* VBLANK callback, start address definitely updates AT vblank, not before. */ -TIMER_CALLBACK_MEMBER(vga_device::vblank_timer_cb) -{ - vga.crtc.start_addr = vga.crtc.start_addr_latch; - vga.attribute.pel_shift = vga.attribute.pel_shift_latch; - m_vblank_timer->adjust( screen().time_until_pos(vga.crtc.vert_blank_start + vga.crtc.vert_blank_end) ); -} - -TIMER_CALLBACK_MEMBER(s3_vga_device::vblank_timer_cb) +device_memory_interface::space_config_vector vga_device::memory_space_config() const { - // not sure if this is correct, but XF86_S3 seems to expect the viewport scrolling to be faster - if(s3.memory_config & 0x08) - vga.crtc.start_addr = vga.crtc.start_addr_latch << 2; - else - vga.crtc.start_addr = vga.crtc.start_addr_latch; - vga.attribute.pel_shift = vga.attribute.pel_shift_latch; - m_vblank_timer->adjust( screen().time_until_pos(vga.crtc.vert_blank_start + vga.crtc.vert_blank_end) ); + return space_config_vector { + std::make_pair(MAIN_IF_REG, &m_main_if_space_config), + std::make_pair(CRTC_REG, &m_crtc_space_config), + std::make_pair(GC_REG, &m_gc_space_config), + std::make_pair(SEQ_REG, &m_seq_space_config), + std::make_pair(ATC_REG, &m_atc_space_config) + }; } void vga_device::device_start() { zero(); - int i; - for (i = 0; i < 0x100; i++) + for (int i = 0; i < 0x100; i++) set_pen_color(i, 0, 0, 0); // Avoid an infinite loop when displaying. 0 is not possible anyway. vga.crtc.maximum_scan_line = 1; - // copy over interfaces - vga.read_dipswitch = read8_delegate(); //read_dipswitch; - vga.svga_intf.seq_regcount = 0x05; - vga.svga_intf.crtc_regcount = 0x19; - vga.svga_intf.vram_size = 0x100000; - - vga.memory.resize(vga.svga_intf.vram_size); + vga.memory = std::make_unique<uint8_t []>(vga.svga_intf.vram_size); memset(&vga.memory[0], 0, vga.svga_intf.vram_size); - save_item(NAME(vga.memory)); + save_pointer(NAME(vga.memory), vga.svga_intf.vram_size); save_item(NAME(vga.pens)); save_item(NAME(vga.miscellaneous_output)); @@ -314,6 +224,7 @@ void vga_device::device_start() save_item(NAME(vga.crtc.map13)); save_item(NAME(vga.crtc.irq_clear)); save_item(NAME(vga.crtc.irq_disable)); + save_item(NAME(vga.crtc.irq_latch)); save_item(NAME(vga.crtc.no_wrap)); save_item(NAME(vga.gc.index)); @@ -349,81 +260,979 @@ void vga_device::device_start() save_item(NAME(vga.dac.state)); save_item(NAME(vga.dac.color)); save_item(NAME(vga.dac.dirty)); + save_item(NAME(vga.dac.loading)); - m_vblank_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(vga_device::vblank_timer_cb),this)); + m_vblank_timer = timer_alloc(FUNC(vga_device::vblank_timer_cb), this); } -void svga_device::device_start() +void vga_device::device_reset() { - vga_device::device_start(); - memset(&svga, 0, sizeof(svga)); + /* clear out the VGA structure */ + memset(vga.pens, 0, sizeof(vga.pens)); + vga.miscellaneous_output = 0; + m_ioas = false; + vga.feature_control = 0; + vga.sequencer.index = 0; + memset(vga.sequencer.data, 0, sizeof(vga.sequencer.data)); + vga.crtc.index = 0; + memset(vga.crtc.data, 0, sizeof(vga.crtc.data)); + vga.gc.index = 0; + memset(vga.gc.latch, 0, sizeof(vga.gc.latch)); + memset(&vga.attribute, 0, sizeof(vga.attribute)); + memset(&vga.dac, 0, sizeof(vga.dac)); + memset(&vga.cursor, 0, sizeof(vga.cursor)); + memset(&vga.oak, 0, sizeof(vga.oak)); - save_item(NAME(svga.bank_r)); - save_item(NAME(svga.bank_w)); - save_item(NAME(svga.rgb8_en)); - save_item(NAME(svga.rgb15_en)); - save_item(NAME(svga.rgb16_en)); - save_item(NAME(svga.rgb24_en)); - save_item(NAME(svga.rgb32_en)); - save_item(NAME(svga.id)); + vga.gc.memory_map_sel = 0x3; /* prevent xtbios excepting vga ram as system ram */ +/* amstrad pc1640 bios relies on the position of + the video memory area, + so I introduced the reset to switch to b8000 area */ + vga.sequencer.data[4] = 0; + + /* TODO: real defaults */ + vga.crtc.line_compare = 0x3ff; + /* skeleton/indiana.cpp boot PROM doesn't set this and assumes it's 0xff */ + vga.dac.mask = 0xff; +} + +/************************************** + * + * Main I/O space + * + *************************************/ + +// A bare minimum VGA installs 3 main I/O areas, a fixed one at $3c0 and a moveable one at $3b0-$3bb +// (for MDA compatibility) and $3d0-$3df. $3bc-$3bf is canonically assigned to LPT3 in an IBM machine. +void vga_device::io_map(address_map &map) +{ + map.unmap_value_high(); +// map(0x00, 0x0b).view(m_ioas_3bx_view); +// m_ioas_3bx_view[0](0x00, 0x0b).m(FUNC(vga_device::io_3bx_3dx_map)); +// m_ioas_3bx_view[1](0x00, 0x0b).unmaprw(); + map(0x00, 0x0b).lrw8( + NAME([this] (offs_t offset) { + if (m_ioas == false) + return space(MAIN_IF_REG).read_byte(offset); + return (u8)space().unmap(); + }), + NAME([this] (offs_t offset, u8 data) { + if (m_ioas == false) + { + space(MAIN_IF_REG).write_byte(offset, data); + } + }) + ); + + map(0x10, 0x1f).m(FUNC(vga_device::io_3cx_map)); + +// map(0x20, 0x2f).view(m_ioas_3dx_view); +// m_ioas_3dx_view[0](0x20, 0x2f).unmaprw(); +// m_ioas_3dx_view[1](0x20, 0x2f).m(FUNC(vga_device::io_3bx_3dx_map)); + map(0x20, 0x2f).lrw8( + NAME([this] (offs_t offset) { + if (m_ioas == true) + return space(MAIN_IF_REG).read_byte(offset); + return (u8)space().unmap(); + }), + NAME([this] (offs_t offset, u8 data) { + if (m_ioas == true) + { + space(MAIN_IF_REG).write_byte(offset, data); + } + }) + ); +} + +void vga_device::io_3bx_3dx_map(address_map &map) +{ + map(0x04, 0x04).rw(FUNC(vga_device::crtc_address_r), FUNC(vga_device::crtc_address_w)); + map(0x05, 0x05).rw(FUNC(vga_device::crtc_data_r), FUNC(vga_device::crtc_data_w)); + map(0x0a, 0x0a).rw(FUNC(vga_device::input_status_1_r), FUNC(vga_device::feature_control_w)); + // TODO: move these to indicated subclasses + map(0x08, 0x08).lr8( + NAME([this] (offs_t offset) { + LOG("VGA: 0x3d8 read %s\n", machine().describe_context()); + // TODO: PC-200 reads back CGA register here, everything else returns open bus OR CGA emulation of register 0x3d8 + return 0; + }) + ); + map(0x0f, 0x0f).lr8( + NAME([this] (offs_t offset) { + LOG("VGA: 0x3df \"oak test\" read %s\n", machine().describe_context()); + /* oak test */ + //return 0; + /* pega bios on/off */ + return 0x80; + }) + ); +} + +void vga_device::io_3cx_map(address_map &map) +{ + map(0x00, 0x00).rw(FUNC(vga_device::atc_address_r), FUNC(vga_device::atc_address_data_w)); + map(0x01, 0x01).r(FUNC(vga_device::atc_data_r)); + map(0x02, 0x02).rw(FUNC(vga_device::input_status_0_r), FUNC(vga_device::miscellaneous_output_w)); +// map(0x03, 0x03).w(FUNC(vga_device::wakeup_w)); + map(0x04, 0x04).rw(FUNC(vga_device::sequencer_address_r), FUNC(vga_device::sequencer_address_w)); + map(0x05, 0x05).rw(FUNC(vga_device::sequencer_data_r), FUNC(vga_device::sequencer_data_w)); + map(0x06, 0x06).rw(FUNC(vga_device::ramdac_mask_r), FUNC(vga_device::ramdac_mask_w)); + map(0x07, 0x07).rw(FUNC(vga_device::ramdac_state_r), FUNC(vga_device::ramdac_read_index_w)); + map(0x08, 0x08).rw(FUNC(vga_device::ramdac_write_index_r), FUNC(vga_device::ramdac_write_index_w)); + map(0x09, 0x09).rw(FUNC(vga_device::ramdac_data_r), FUNC(vga_device::ramdac_data_w)); + map(0x0a, 0x0a).r(FUNC(vga_device::feature_control_r)); + map(0x0c, 0x0c).r(FUNC(vga_device::miscellaneous_output_r)); + map(0x0e, 0x0e).rw(FUNC(vga_device::gc_address_r), FUNC(vga_device::gc_address_w)); + map(0x0f, 0x0f).rw(FUNC(vga_device::gc_data_r), FUNC(vga_device::gc_data_w)); + // TODO: doesn't belong here + map(0x03, 0x03).lrw8( + NAME([this] (offs_t offset) { + return vga.oak.reg; + }), + NAME([this] (offs_t offset, u8 data) { + vga.oak.reg = data; + }) + ); +} + +/************************************** + * + * 3bx/3dx implementation + * + *************************************/ + +u8 vga_device::crtc_address_r(offs_t offset) +{ + return vga.crtc.index; +} + +void vga_device::crtc_address_w(offs_t offset, u8 data) +{ + vga.crtc.index = data; +} + +u8 vga_device::crtc_data_r(offs_t offset) +{ + return space(CRTC_REG).read_byte(vga.crtc.index); +} + +void vga_device::crtc_data_w(offs_t offset, u8 data) +{ + vga.crtc.data[vga.crtc.index] = data; + space(CRTC_REG).write_byte(vga.crtc.index, data); +} + +u8 vga_device::input_status_1_r(offs_t offset) +{ + u8 res = 0; + u8 hsync, vsync; + vga.attribute.state = 0; + + hsync = screen().hblank() & 1; + vsync = vga_vblank(); //screen().vblank() & 1; + + res |= (hsync | vsync) & 1; // DD - display disable register + res |= (vsync & 1) << 3; // VRetrace register + + /* ega diagnostic readback enough for oak bios */ + // TODO: move to OAK + switch (vga.attribute.data[0x12]&0x30) { + case 0: + if (vga.attribute.data[0x11]&1) + res |= 0x10; + if (vga.attribute.data[0x11]&4) + res |= 0x20; + break; + case 0x10: + res |= (vga.attribute.data[0x11]&0x30); + break; + case 0x20: + if (vga.attribute.data[0x11]&2) + res |= 0x10; + if (vga.attribute.data[0x11]&8) + res |= 0x20; + break; + case 0x30: + res |= (vga.attribute.data[0x11]&0xc0)>>2; + break; + } + + return res; +} + +void vga_device::feature_control_w(offs_t offset, u8 data) +{ + vga.feature_control = data; +} + +/************************************** + * + * 3cx implementation + * + *************************************/ + +u8 vga_device::atc_address_r(offs_t offset) +{ + return vga.attribute.index; } -void ati_vga_device::device_start() +u8 vga_device::atc_data_r(offs_t offset) { - svga_device::device_start(); - memset(&ati, 0, sizeof(ati)); - save_pointer(ati.ext_reg,"ATi Extended Registers",64); - m_8514 = subdevice<mach8_device>("8514a"); - ati.vga_chip_id = 0x06; // 28800-6 + return space(ATC_REG).read_byte(vga.attribute.index); } -void s3_vga_device::device_start() +void vga_device::atc_address_data_w(offs_t offset, u8 data) { - svga_device::device_start(); - memset(&s3, 0, sizeof(s3)); - int x; - // Initialise hardware graphics cursor colours, Windows 95 doesn't touch the registers for some reason - for(x=0;x<4;x++) + if (vga.attribute.state == 0) { - s3.cursor_fg[x] = 0xff; - s3.cursor_bg[x] = 0x00; + vga.attribute.index = data; } - m_8514 = subdevice<ibm8514a_device>("8514a"); - // set device ID - s3.id_high = 0x88; // CR2D - s3.id_low = 0x11; // CR2E - s3.revision = 0x00; // CR2F - s3.id_cr30 = 0xe1; // CR30 + else + { + space(ATC_REG).write_byte(vga.attribute.index, data); + } + + vga.attribute.state = !vga.attribute.state; +} + +u8 vga_device::input_status_0_r(offs_t offset) +{ + u8 res = 0x60; // is VGA + const u8 sense_bit = (3 - (vga.miscellaneous_output >> 2)) & 3; + LOGDSW("Reading sense bit %d\n", sense_bit); + if(BIT(m_input_sense->read(), sense_bit)) + res |= 0x10; + res |= vga.crtc.irq_latch << 7; + return res; +} + +void vga_device::miscellaneous_output_w(offs_t offset, u8 data) +{ + vga.miscellaneous_output = data; + recompute_params(); + m_ioas = bool(BIT(data, 0)); +} + +u8 vga_device::sequencer_address_r(offs_t offset) +{ + return vga.sequencer.index; +} + +u8 vga_device::sequencer_data_r(offs_t offset) +{ + return space(SEQ_REG).read_byte(vga.sequencer.index); +} + +void vga_device::sequencer_address_w(offs_t offset, u8 data) +{ + vga.sequencer.index = data; +} + +void vga_device::sequencer_data_w(offs_t offset, u8 data) +{ + // TODO: temporary cheat for read-back + vga.sequencer.data[vga.sequencer.index] = data; + space(SEQ_REG).write_byte(vga.sequencer.index, data); + recompute_params(); +} + +u8 vga_device::ramdac_mask_r(offs_t offset) +{ + return vga.dac.mask; +} + +u8 vga_device::ramdac_state_r(offs_t offset) +{ + return (vga.dac.read) ? 3 : 0; +} + +u8 vga_device::ramdac_write_index_r(offs_t offset) +{ + return vga.dac.write_index; +} + +u8 vga_device::ramdac_data_r(offs_t offset) +{ + u8 res = space().unmap(); + if (vga.dac.read) + { + switch (vga.dac.state++) + { + case 0: + res = vga.dac.color[3*vga.dac.read_index]; + break; + case 1: + res = vga.dac.color[3*vga.dac.read_index + 1]; + break; + case 2: + res = vga.dac.color[3*vga.dac.read_index + 2]; + break; + } + + if (vga.dac.state == 3) + { + vga.dac.state = 0; + vga.dac.read_index++; + } + } + return res; +} + +u8 vga_device::feature_control_r(offs_t offset) +{ + return vga.feature_control; +} + +u8 vga_device::miscellaneous_output_r(offs_t offset) +{ + return vga.miscellaneous_output; +} + +u8 vga_device::gc_address_r(offs_t offset) +{ + return vga.gc.index; +} + +u8 vga_device::gc_data_r(offs_t offset) +{ + return space(GC_REG).read_byte(vga.gc.index); +} + + +void vga_device::ramdac_mask_w(offs_t offset, u8 data) +{ + vga.dac.mask = data; + vga.dac.dirty = 1; +} + +void vga_device::ramdac_read_index_w(offs_t offset, u8 data) +{ + vga.dac.read_index = data; + vga.dac.state = 0; + vga.dac.read = 1; +} + +void vga_device::ramdac_write_index_w(offs_t offset, u8 data) +{ + vga.dac.write_index = data; + vga.dac.state = 0; + vga.dac.read = 0; } -void tseng_vga_device::device_start() +void vga_device::ramdac_data_w(offs_t offset, u8 data) { - svga_device::device_start(); - memset(&et4k, 0, sizeof(et4k)); - - save_item(NAME(et4k.reg_3d8)); - save_item(NAME(et4k.dac_ctrl)); - save_item(NAME(et4k.dac_state)); - save_item(NAME(et4k.horz_overflow)); - save_item(NAME(et4k.aux_ctrl)); - save_item(NAME(et4k.ext_reg_ena)); - save_item(NAME(et4k.misc1)); - save_item(NAME(et4k.misc2)); + if (!vga.dac.read) + { + vga.dac.loading[vga.dac.state] = data; + vga.dac.state++; + + if (vga.dac.state==3) + { + vga.dac.color[3*vga.dac.write_index] = vga.dac.loading[0]; + vga.dac.color[3*vga.dac.write_index+1] = vga.dac.loading[1]; + vga.dac.color[3*vga.dac.write_index+2] = vga.dac.loading[2]; + vga.dac.dirty = 1; + vga.dac.state = 0; + vga.dac.write_index++; + } + } } -void ibm8514a_device::device_start() +void vga_device::gc_address_w(offs_t offset, u8 data) { - memset(&ibm8514, 0, sizeof(ibm8514)); - ibm8514.read_mask = 0x00000000; - ibm8514.write_mask = 0xffffffff; + vga.gc.index=data; } -void mach8_device::device_start() +void vga_device::gc_data_w(offs_t offset, u8 data) { - ibm8514a_device::device_start(); - memset(&mach8, 0, sizeof(mach8)); + space(GC_REG).write_byte(vga.gc.index, data); } + +/************************************** + * + * CRTC + * + *************************************/ + +void vga_device::crtc_map(address_map &map) +{ + map(0x00, 0x00).lrw8( + NAME([this](offs_t offset) { + return vga.crtc.horz_total & 0xff; + }), + NAME([this](offs_t offset, u8 data) { + // doom (DOS) tries to write to protected regs + LOGCRTC("CR00 H total %02x %s", data, vga.crtc.protect_enable ? "P?\n" : "-> "); + if(vga.crtc.protect_enable) + return; + vga.crtc.horz_total = (vga.crtc.horz_total & ~0xff) | (data & 0xff); + LOGCRTC("%04d\n", vga.crtc.horz_total); + recompute_params(); + }) + ); + map(0x01, 0x01).lrw8( + NAME([this](offs_t offset) { + return vga.crtc.horz_disp_end & 0xff; + }), + NAME([this](offs_t offset, u8 data) { + LOGCRTC("CR01 H display end %02x %s", data, vga.crtc.protect_enable ? "P?\n" : "-> "); + if(vga.crtc.protect_enable) + return; + vga.crtc.horz_disp_end = (vga.crtc.horz_disp_end & ~0xff) | (data & 0xff); + LOGCRTC("%04d\n", vga.crtc.horz_disp_end); + recompute_params(); + }) + ); + map(0x02, 0x02).lrw8( + NAME([this](offs_t offset) { + return vga.crtc.horz_blank_start & 0xff; + }), + NAME([this](offs_t offset, u8 data) { + LOGCRTC("CR02 H start blank %02x %s", data, vga.crtc.protect_enable ? "P?\n" : "-> "); + if(vga.crtc.protect_enable) + return; + vga.crtc.horz_blank_start = (vga.crtc.horz_blank_start & ~0xff) | (data & 0xff); + LOGCRTC("%04d\n", vga.crtc.horz_blank_start); + }) + ); + map(0x03, 0x03).lrw8( + NAME([this](offs_t offset) { + u8 res = vga.crtc.horz_blank_end & 0x1f; + res |= (vga.crtc.disp_enable_skew & 3) << 5; + res |= (vga.crtc.evra & 1) << 7; + return res; + }), + NAME([this](offs_t offset, u8 data) { + LOGCRTC("CR03 H blank end %02x %s", data, vga.crtc.protect_enable ? "P?\n" : "-> "); + if(vga.crtc.protect_enable) + return; + vga.crtc.horz_blank_end &= ~0x1f; + vga.crtc.horz_blank_end |= data & 0x1f; + vga.crtc.disp_enable_skew = (data & 0x60) >> 5; + vga.crtc.evra = BIT(data, 7); + LOGCRTC("%04d evra %d display enable skew %01x\n", vga.crtc.horz_blank_end, vga.crtc.evra, vga.crtc.disp_enable_skew); + }) + ); + map(0x04, 0x04).lrw8( + NAME([this](offs_t offset) { + return vga.crtc.horz_retrace_start & 0xff; + }), + NAME([this](offs_t offset, u8 data) { + LOGCRTC("CR04 H retrace start %02x %s", data, vga.crtc.protect_enable ? "P?\n" : "-> "); + if(vga.crtc.protect_enable) + return; + vga.crtc.horz_retrace_start = (vga.crtc.horz_retrace_start & ~0xff) | (data & 0xff); + LOGCRTC("%04d\n", vga.crtc.horz_retrace_start); + }) + ); + map(0x05, 0x05).lrw8( + NAME([this](offs_t offset) { + u8 res = (vga.crtc.horz_blank_end & 0x20) << 2; + res |= (vga.crtc.horz_retrace_skew & 3) << 5; + res |= (vga.crtc.horz_retrace_end & 0x1f); + return res; + }), + NAME([this](offs_t offset, u8 data) { + LOGCRTC("CR05 H blank end %02x %s", data, vga.crtc.protect_enable ? "P?\n" : "-> "); + if(vga.crtc.protect_enable) + return; + vga.crtc.horz_blank_end &= ~0x20; + vga.crtc.horz_blank_end |= ((data & 0x80) >> 2); + vga.crtc.horz_retrace_skew = ((data & 0x60) >> 5); + vga.crtc.horz_retrace_end = (vga.crtc.horz_retrace_end & ~0x1f) | (data & 0x1f); + LOGCRTC("%04d retrace skew %01d retrace end %02d\n" + , vga.crtc.horz_blank_end + , vga.crtc.horz_retrace_skew + , vga.crtc.horz_retrace_end + ); + }) + ); + map(0x06, 0x06).lrw8( + NAME([this](offs_t offset) { + return vga.crtc.vert_total & 0xff; + }), + NAME([this](offs_t offset, u8 data) { + LOGCRTC("CR06 V total %02x %s", data, vga.crtc.protect_enable ? "P?\n" : "-> "); + if(vga.crtc.protect_enable) + return; + vga.crtc.vert_total &= ~0xff; + vga.crtc.vert_total |= data & 0xff; + LOGCRTC("%04d\n", vga.crtc.vert_total); + recompute_params(); + }) + ); + // Overflow Register + map(0x07, 0x07).lrw8( + NAME([this](offs_t offset) { + u8 res = (vga.crtc.line_compare & 0x100) >> 4; + res |= (vga.crtc.vert_retrace_start & 0x200) >> 2; + res |= (vga.crtc.vert_disp_end & 0x200) >> 3; + res |= (vga.crtc.vert_total & 0x200) >> 4; + res |= (vga.crtc.vert_blank_start & 0x100) >> 5; + res |= (vga.crtc.vert_retrace_start & 0x100) >> 6; + res |= (vga.crtc.vert_disp_end & 0x100) >> 7; + res |= (vga.crtc.vert_total & 0x100) >> 8; + return res; + }), + NAME([this](offs_t offset, u8 data) { + vga.crtc.line_compare &= ~0x100; + vga.crtc.line_compare |= ((data & 0x10) << (8-4)); + LOGCRTC("CR07 Overflow %02x -> line compare %04d %s", data, vga.crtc.line_compare, vga.crtc.protect_enable ? "P?\n" : ""); + if(vga.crtc.protect_enable) + return; + vga.crtc.vert_total &= ~0x300; + vga.crtc.vert_retrace_start &= ~0x300; + vga.crtc.vert_disp_end &= ~0x300; + vga.crtc.vert_blank_start &= ~0x100; + vga.crtc.vert_retrace_start |= ((data & 0x80) << (9-7)); + vga.crtc.vert_disp_end |= ((data & 0x40) << (9-6)); + vga.crtc.vert_total |= ((data & 0x20) << (9-5)); + vga.crtc.vert_blank_start |= ((data & 0x08) << (8-3)); + vga.crtc.vert_retrace_start |= ((data & 0x04) << (8-2)); + vga.crtc.vert_disp_end |= ((data & 0x02) << (8-1)); + vga.crtc.vert_total |= ((data & 0x01) << (8-0)); + LOGCRTC("V total %04d V retrace start %04d V display end %04d V blank start %04d\n" + , vga.crtc.vert_total + , vga.crtc.vert_retrace_start + , vga.crtc.vert_disp_end + , vga.crtc.vert_blank_start + ); + recompute_params(); + }) + ); + // Preset Row Scan Register + map(0x08, 0x08).lrw8( + NAME([this](offs_t offset) { + u8 res = (vga.crtc.byte_panning & 3) << 5; + res |= (vga.crtc.preset_row_scan & 0x1f); + return res; + }), + NAME([this](offs_t offset, u8 data) { + vga.crtc.byte_panning = (data & 0x60) >> 5; + vga.crtc.preset_row_scan = (data & 0x1f); + LOGCRTC("CR08 Preset Row Scan %02x -> %02d byte panning %d\n" + , data + , vga.crtc.preset_row_scan + , vga.crtc.byte_panning + ); + }) + ); + // Maximum Scan Line Register + map(0x09, 0x09).lrw8( + NAME([this](offs_t offset) { + u8 res = (vga.crtc.maximum_scan_line - 1) & 0x1f; + res |= (vga.crtc.scan_doubling & 1) << 7; + res |= (vga.crtc.line_compare & 0x200) >> 3; + res |= (vga.crtc.vert_blank_start & 0x200) >> 4; + return res; + }), + NAME([this](offs_t offset, u8 data) { + vga.crtc.line_compare &= ~0x200; + vga.crtc.vert_blank_start &= ~0x200; + vga.crtc.scan_doubling = ((data & 0x80) >> 7); + vga.crtc.line_compare |= ((data & 0x40) << (9-6)); + vga.crtc.vert_blank_start |= ((data & 0x20) << (9-5)); + vga.crtc.maximum_scan_line = (data & 0x1f) + 1; + LOGCRTC("CR09 Maximum Scan Line %02x -> %02d V blank start %04d line compare %04d scan doubling %d\n" + , data + , vga.crtc.maximum_scan_line + , vga.crtc.vert_blank_start + , vga.crtc.line_compare + , vga.crtc.scan_doubling + ); + }) + ); + map(0x0a, 0x0a).lrw8( + NAME([this](offs_t offset) { + u8 res = (vga.crtc.cursor_scan_start & 0x1f); + res |= ((vga.crtc.cursor_enable & 1) ^ 1) << 5; + return res; + }), + NAME([this](offs_t offset, u8 data) { + vga.crtc.cursor_enable = ((data & 0x20) ^ 0x20) >> 5; + vga.crtc.cursor_scan_start = data & 0x1f; + }) + ); + map(0x0b, 0x0b).lrw8( + NAME([this](offs_t offset) { + u8 res = (vga.crtc.cursor_skew & 3) << 5; + res |= (vga.crtc.cursor_scan_end & 0x1f); + return res; + }), + NAME([this](offs_t offset, u8 data) { + vga.crtc.cursor_skew = (data & 0x60) >> 5; + vga.crtc.cursor_scan_end = data & 0x1f; + }) + ); + map(0x0c, 0x0d).lrw8( + NAME([this](offs_t offset) { + return (vga.crtc.start_addr_latch >> ((offset & 1) ^ 1) * 8) & 0xff; + }), + NAME([this](offs_t offset, u8 data) { + vga.crtc.start_addr_latch &= ~(0xff << (((offset & 1) ^ 1) * 8)); + vga.crtc.start_addr_latch |= (data << (((offset & 1) ^ 1) * 8)); + }) + ); + map(0x0e, 0x0f).lrw8( + NAME([this](offs_t offset) { + return (vga.crtc.cursor_addr >> ((offset & 1) ^ 1)*8) & 0xff; + }), + NAME([this](offs_t offset, u8 data) { + vga.crtc.cursor_addr &= ~(0xff << (((offset & 1) ^ 1) * 8)); + vga.crtc.cursor_addr |= (data << (((offset & 1) ^ 1) * 8)); + }) + ); + map(0x10, 0x10).lrw8( + NAME([this](offs_t offset) { + return vga.crtc.vert_retrace_start & 0xff; + }), + NAME([this](offs_t offset, u8 data) { + vga.crtc.vert_retrace_start &= ~0xff; + vga.crtc.vert_retrace_start |= data & 0xff; + LOGCRTC("CR10 V retrace start %02x -> %04d\n", data, vga.crtc.vert_retrace_start); + }) + ); + map(0x11, 0x11).lrw8( + NAME([this](offs_t offset) { + u8 res = (vga.crtc.protect_enable & 1) << 7; + res |= (vga.crtc.bandwidth & 1) << 6; + res |= (vga.crtc.vert_retrace_end & 0xf); + res |= (vga.crtc.irq_clear & 1) << 4; + res |= (vga.crtc.irq_disable & 1) << 5; + return res; + }), + NAME([this](offs_t offset, u8 data) { + vga.crtc.protect_enable = BIT(data, 7); + vga.crtc.bandwidth = BIT(data, 6); + // IRQ: Original VGA only supports this for PS/2, but clone cards may supports this on ISA too + // see https://scalibq.wordpress.com/2022/12/06/the-myth-of-the-vertical-retrace-interrupt/ + vga.crtc.irq_disable = BIT(data, 5); + vga.crtc.irq_clear = BIT(data, 4); + vga.crtc.vert_retrace_end = (vga.crtc.vert_retrace_end & ~0xf) | (data & 0x0f); + + if (vga.crtc.irq_clear == 0) + { + vga.crtc.irq_latch = 0; + m_vsync_cb(0); + } + + LOGCRTC("CR11 V retrace end %02x -> %02d protect enable %d bandwidth %d irq %02x\n" + , data + , vga.crtc.vert_retrace_end + , vga.crtc.protect_enable + , vga.crtc.bandwidth + , data & 0x30 + ); + }) + ); + map(0x12, 0x12).lrw8( + NAME([this](offs_t offset) { + return vga.crtc.vert_disp_end & 0xff; + }), + NAME([this](offs_t offset, u8 data) { + vga.crtc.vert_disp_end &= ~0xff; + vga.crtc.vert_disp_end |= data & 0xff; + LOGCRTC("CR12 V display end %02x -> %04d\n", data, vga.crtc.vert_disp_end); + recompute_params(); + }) + ); + map(0x13, 0x13).lrw8( + NAME([this](offs_t offset) { + return vga.crtc.offset & 0xff; + }), + NAME([this](offs_t offset, u8 data) { + vga.crtc.offset &= ~0xff; + vga.crtc.offset |= data & 0xff; + }) + ); + map(0x14, 0x14).lrw8( + NAME([this](offs_t offset) { + u8 res = (vga.crtc.dw & 1) << 6; + res |= (vga.crtc.div4 & 1) << 5; + res |= (vga.crtc.underline_loc & 0x1f); + return res; + }), + NAME([this](offs_t offset, u8 data) { + vga.crtc.dw = (data & 0x40) >> 6; + vga.crtc.div4 = (data & 0x20) >> 5; + vga.crtc.underline_loc = (data & 0x1f); + }) + ); + map(0x15, 0x15).lrw8( + NAME([this](offs_t offset) { + return vga.crtc.vert_blank_start & 0xff; + }), + NAME([this](offs_t offset, u8 data) { + vga.crtc.vert_blank_start &= ~0xff; + vga.crtc.vert_blank_start |= data & 0xff; + LOGCRTC("CR15 V blank start %02x -> %04d\n", data, vga.crtc.vert_blank_start); + }) + ); + map(0x16, 0x16).lrw8( + NAME([this](offs_t offset) { + return vga.crtc.vert_blank_end & 0x7f; + }), + NAME([this](offs_t offset, u8 data) { + vga.crtc.vert_blank_end = (vga.crtc.vert_blank_end & ~0x7f) | (data & 0x7f); + LOGCRTC("CR16 V blank end %02x -> %04d\n", data, vga.crtc.vert_blank_end); + }) + ); + map(0x17, 0x17).lrw8( + NAME([this](offs_t offset) { + u8 res = (vga.crtc.sync_en & 1) << 7; + res |= (vga.crtc.word_mode & 1) << 6; + res |= (vga.crtc.aw & 1) << 5; + res |= (vga.crtc.div2 & 1) << 3; + res |= (vga.crtc.sldiv & 1) << 2; + res |= (vga.crtc.map14 & 1) << 1; + res |= (vga.crtc.map13 & 1) << 0; + return res; + }), + NAME([this](offs_t offset, u8 data) { + vga.crtc.sync_en = BIT(data, 7); + vga.crtc.word_mode = BIT(data, 6); + vga.crtc.aw = BIT(data, 5); + vga.crtc.div2 = BIT(data, 3); + vga.crtc.sldiv = BIT(data, 2); + vga.crtc.map14 = BIT(data, 1); + vga.crtc.map13 = BIT(data, 0); + LOGCRTC("CR17 Mode control %02x -> Sync Enable %d Word/Byte %d Address Wrap select %d\n" + , data + , vga.crtc.sync_en + , vga.crtc.word_mode + , vga.crtc.aw + ); + LOGCRTC("\tDIV2 %d Scan Line Divide %d MAP14 %d MAP13 %d\n" + , vga.crtc.div2 + , vga.crtc.sldiv + , vga.crtc.map14 + , vga.crtc.map13 + ); + }) + ); + map(0x18, 0x18).lrw8( + NAME([this](offs_t offset) { + return vga.crtc.line_compare & 0xff; + }), + NAME([this](offs_t offset, u8 data) { + vga.crtc.line_compare &= ~0xff; + vga.crtc.line_compare |= data & 0xff; + LOGCRTC("CR18 Line Compare %02x -> %04d\n", data, vga.crtc.line_compare); + }) + ); + // TODO: (undocumented) CR22 Memory Data Latch Register (read only) + // map(0x22, 0x22).lr8( + // (undocumented) CR24 Attribute Controller Toggle Register (read only) + // 0--- ---- index + // 1--- ---- data + map(0x24, 0x24).lr8( + NAME([this](offs_t offset) { + if (!machine().side_effects_disabled()) + LOG("CR24 read undocumented Attribute reg\n"); + return vga.attribute.state << 7; + }) + ); +} + +/************************************** + * + * GC + * + *************************************/ + +void vga_device::gc_map(address_map &map) +{ + map.unmap_value_high(); + map(0x00, 0x00).lrw8( + NAME([this](offs_t offset) { + return vga.gc.set_reset & 0xf; + }), + NAME([this](offs_t offset, u8 data) { + vga.gc.set_reset = data & 0xf; + }) + ); + map(0x01, 0x01).lrw8( + NAME([this](offs_t offset) { + return vga.gc.enable_set_reset & 0xf; + }), + NAME([this](offs_t offset, u8 data) { + vga.gc.enable_set_reset = data & 0xf; + }) + ); + map(0x02, 0x02).lrw8( + NAME([this](offs_t offset) { + return vga.gc.color_compare & 0xf; + }), + NAME([this](offs_t offset, u8 data) { + vga.gc.color_compare = data & 0xf; + }) + ); + map(0x03, 0x03).lrw8( + NAME([this](offs_t offset) { + return ((vga.gc.logical_op & 3) << 3) | (vga.gc.rotate_count & 7); + }), + NAME([this](offs_t offset, u8 data) { + vga.gc.logical_op = (data & 0x18) >> 3; + vga.gc.rotate_count = data & 7; + }) + ); + map(0x04, 0x04).lrw8( + NAME([this](offs_t offset) { + return vga.gc.read_map_sel & 3; + }), + NAME([this](offs_t offset, u8 data) { + vga.gc.read_map_sel = data & 3; + }) + ); + map(0x05, 0x05).lrw8( + NAME([this](offs_t offset) { + u8 res = (vga.gc.shift256 & 1) << 6; + res |= (vga.gc.shift_reg & 1) << 5; + res |= (vga.gc.host_oe & 1) << 4; + res |= (vga.gc.read_mode & 1) << 3; + res |= (vga.gc.write_mode & 3); + return res; + }), + NAME([this](offs_t offset, u8 data) { + vga.gc.shift256 = BIT(data, 6); + vga.gc.shift_reg = BIT(data, 5); + vga.gc.host_oe = BIT(data, 4); + vga.gc.read_mode = BIT(data, 3); + vga.gc.write_mode = data & 3; + //if(data & 0x10 && vga.gc.alpha_dis) + // popmessage("Host O/E enabled, contact MAMEdev"); + }) + ); + map(0x06, 0x06).lrw8( + NAME([this](offs_t offset) { + u8 res = (vga.gc.memory_map_sel & 3) << 2; + res |= (vga.gc.chain_oe & 1) << 1; + res |= (vga.gc.alpha_dis & 1); + return res; + }), + NAME([this](offs_t offset, u8 data) { + vga.gc.memory_map_sel = (data & 0xc) >> 2; + vga.gc.chain_oe = BIT(data, 1); + vga.gc.alpha_dis = BIT(data, 0); + //if(data & 2 && vga.gc.alpha_dis) + // popmessage("Chain O/E enabled, contact MAMEdev"); + }) + ); + map(0x07, 0x07).lrw8( + NAME([this](offs_t offset) { + return vga.gc.color_dont_care & 0xf; + }), + NAME([this](offs_t offset, u8 data) { + vga.gc.color_dont_care = data & 0xf; + }) + ); + map(0x08, 0x08).lrw8( + NAME([this](offs_t offset) { + return vga.gc.bit_mask & 0xff; + }), + NAME([this](offs_t offset, u8 data) { + vga.gc.bit_mask = data & 0xff; + }) + ); +} + +/************************************** + * + * Sequencer + * + *************************************/ + +void vga_device::sequencer_map(address_map &map) +{ + // TODO: legacy fallback trick + map(0x00, 0xff).lr8( + NAME([this] (offs_t offset) { + const u8 res = vga.sequencer.data[offset]; + if (!machine().side_effects_disabled()) + LOGREGS("Reading unmapped sequencer read register [%02x] -> %02x (SVGA?)\n", offset, res); + return res; + }) + ); +// map(0x00, 0x00) Reset Register +// map(0x01, 0x01) Clocking Mode Register + map(0x02, 0x02).lw8( + NAME([this] (offs_t offset, u8 data) { + vga.sequencer.map_mask = data & 0xf; + }) + ); + map(0x03, 0x03).lw8( + NAME([this] (offs_t offset, u8 data) { + /* --2- 84-- character select A + ---2 --84 character select B */ + vga.sequencer.char_sel.A = (((data & 0xc) >> 2)<<1) | ((data & 0x20) >> 5); + vga.sequencer.char_sel.B = (((data & 0x3) >> 0)<<1) | ((data & 0x10) >> 4); + if(data) + popmessage("Char SEL checker (%02x %02x)\n",vga.sequencer.char_sel.A,vga.sequencer.char_sel.B); + }) + ); + // Sequencer Memory Mode Register +// map(0x04, 0x04) + // (undocumented) Sequencer Horizontal Character Counter Reset + // Any write strobe to this register will lock the character generator until another write to other regs happens. +// map(0x07, 0x07) +} + +/************************************** + * + * Attribute (ATC) + * + *************************************/ + +/* + * xx-- ---- <reserved> + * --x- ---- Palette RAM address source (0) CPU access (1) ATC access + * \- NB: leaving to '0' will disable video output from the ATC, + * and cause overscan drawing in canvas instead. + * ---x xxxx index register + * + */ +void vga_device::attribute_map(address_map &map) +{ + map.global_mask(0x3f); + map.unmap_value_high(); + map(0x00, 0x0f).lrw8( + NAME([this] (offs_t offset) { return vga.attribute.data[ offset & 0x1f]; }), + NAME([this] (offs_t offset, u8 data) { vga.attribute.data[offset & 0x1f] = data & 0x3f; }) + ); + map(0x20, 0x2f).noprw(); + // Mode Control + map(0x10, 0x10).mirror(0x20).lrw8( + NAME([this] (offs_t offset) { return vga.attribute.data[ 0x10 ]; }), + NAME([this] (offs_t offset, u8 data) { vga.attribute.data[ 0x10 ] = data & 0x3f; }) + ); + // Overscan Color + map(0x11, 0x11).mirror(0x20).lrw8( + NAME([this] (offs_t offset) { return vga.attribute.data[ 0x11 ]; }), + NAME([this] (offs_t offset, u8 data) { vga.attribute.data[ 0x11 ] = data & 0x3f; }) + ); + // Color Plane Enable + map(0x12, 0x12).mirror(0x20).lrw8( + NAME([this] (offs_t offset) { return vga.attribute.data[ 0x12 ]; }), + NAME([this] (offs_t offset, u8 data) { vga.attribute.data[ 0x12 ] = data & 0x3f; }) + ); + // Horizontal PEL shift + map(0x13, 0x13).mirror(0x20).lrw8( + NAME([this] (offs_t offset) { return vga.attribute.data[ 0x13 ]; }), + NAME([this] (offs_t offset, u8 data) { vga.attribute.pel_shift_latch = vga.attribute.data[ 0x13 ] = data & 0xf; }) + ); + // Color Select + map(0x14, 0x14).mirror(0x20).lrw8( + NAME([this] (offs_t offset) { return vga.attribute.data[ 0x14 ]; }), + NAME([this] (offs_t offset, u8 data) { vga.attribute.pel_shift_latch = vga.attribute.data[ 0x14 ] = data & 0xf; }) + ); +} + +/************************************** + * + * Drawing routines + * + *************************************/ + uint16_t vga_device::offset() { // popmessage("Offset: %04x %s %s **",vga.crtc.offset,vga.crtc.dw?"DW":"--",vga.crtc.word_mode?"BYTE":"WORD"); @@ -446,44 +1255,66 @@ uint32_t vga_device::start_addr() return vga.crtc.start_addr << 1; } +uint8_t vga_device::vga_latch_write(int offs, uint8_t data) +{ + uint8_t res = 0; + + switch (vga.gc.write_mode & 3) { + case 0: + data = rotate_right(data); + if(vga.gc.enable_set_reset & 1<<offs) + res = vga_logical_op((vga.gc.set_reset & 1<<offs) ? vga.gc.bit_mask : 0, offs,vga.gc.bit_mask); + else + res = vga_logical_op(data, offs, vga.gc.bit_mask); + break; + case 1: + res = vga.gc.latch[offs]; + break; + case 2: + res = vga_logical_op((data & 1<<offs) ? 0xff : 0x00,offs,vga.gc.bit_mask); + break; + case 3: + data = rotate_right(data); + res = vga_logical_op((vga.gc.set_reset & 1<<offs) ? 0xff : 0x00,offs,data&vga.gc.bit_mask); + break; + } + + return res; +} + void vga_device::vga_vh_text(bitmap_rgb32 &bitmap, const rectangle &cliprect) { - uint8_t ch, attr; - uint8_t bits; - uint32_t font_base; - uint32_t *bitmapline; int width=VGA_CH_WIDTH, height = (vga.crtc.maximum_scan_line) * (vga.crtc.scan_doubling + 1); - int pos, line, column, mask, w, h, addr; - uint8_t blink_en,fore_col,back_col; - pen_t pen; if(vga.crtc.cursor_enable) vga.cursor.visible = screen().frame_number() & 0x10; else vga.cursor.visible = 0; - for (addr = vga.crtc.start_addr, line = -vga.crtc.preset_row_scan; line < TEXT_LINES; + for (int addr = vga.crtc.start_addr, line = -vga.crtc.preset_row_scan; line < TEXT_LINES; line += height, addr += (offset()>>1)) { - for (pos = addr, column=0; column<TEXT_COLUMNS; column++, pos++) + for (int pos = addr, column=0; column<TEXT_COLUMNS; column++, pos++) { - ch = vga.memory[(pos<<1) + 0]; - attr = vga.memory[(pos<<1) + 1]; - font_base = 0x20000+(ch<<5); + uint8_t ch = vga.memory[(pos<<1) + 0]; + uint8_t attr = vga.memory[(pos<<1) + 1]; + uint32_t font_base = 0x20000+(ch<<5); font_base += ((attr & 8) ? vga.sequencer.char_sel.A : vga.sequencer.char_sel.B)*0x2000; - blink_en = (vga.attribute.data[0x10]&8&&screen().frame_number() & 0x20) ? attr & 0x80 : 0; + uint8_t blink_en = (vga.attribute.data[0x10]&8&&screen().frame_number() & 0x20) ? attr & 0x80 : 0; - fore_col = attr & 0xf; - back_col = (attr & 0x70) >> 4; + uint8_t fore_col = attr & 0xf; + uint8_t back_col = (attr & 0x70) >> 4; back_col |= (vga.attribute.data[0x10]&8) ? 0 : ((attr & 0x80) >> 4); - for (h = std::max(-line, 0); (h < height) && (line+h < std::min(TEXT_LINES, bitmap.height())); h++) + for (int h = std::max(-line, 0); (h < height) && (line+h < std::min(TEXT_LINES, bitmap.height())); h++) { - bitmapline = &bitmap.pix32(line+h); - bits = vga.memory[font_base+(h>>(vga.crtc.scan_doubling))]; + uint32_t *const bitmapline = &bitmap.pix(line+h); + uint8_t bits = vga.memory[font_base+(h>>(vga.crtc.scan_doubling))]; + int mask, w; for (mask=0x80, w=0; (w<width)&&(w<8); w++, mask>>=1) { + pen_t pen; if (bits&mask) pen = vga.pens[blink_en ? back_col : fore_col]; else @@ -497,6 +1328,7 @@ void vga_device::vga_vh_text(bitmap_rgb32 &bitmap, const rectangle &cliprect) if (w<width) { /* 9 column */ + pen_t pen; if (TEXT_COPY_9COLUMN(ch)&&(bits&1)) pen = vga.pens[blink_en ? back_col : fore_col]; else @@ -509,7 +1341,7 @@ void vga_device::vga_vh_text(bitmap_rgb32 &bitmap, const rectangle &cliprect) } if (vga.cursor.visible&&(pos==vga.crtc.cursor_addr)) { - for (h=vga.crtc.cursor_scan_start; + for (int h=vga.crtc.cursor_scan_start; (h<=vga.crtc.cursor_scan_end)&&(h<height)&&(line+h<TEXT_LINES); h++) { @@ -524,34 +1356,32 @@ void vga_device::vga_vh_text(bitmap_rgb32 &bitmap, const rectangle &cliprect) void vga_device::vga_vh_ega(bitmap_rgb32 &bitmap, const rectangle &cliprect) { - int pos, line, column, c, addr, i, yi; int height = vga.crtc.maximum_scan_line * (vga.crtc.scan_doubling + 1); - uint32_t *bitmapline; - pen_t pen; int pel_shift = (vga.attribute.pel_shift & 7); -// popmessage("%08x %02x",EGA_START_ADDRESS,pel_shift); - - /**/ - for (addr=EGA_START_ADDRESS, pos=0, line=0; line<LINES; - line += height, addr += offset()) + for (int addr = vga.crtc.start_addr, line = 0; line < LINES; line += height, addr += offset()) { - for(yi=0;yi<height;yi++) + for (int yi=0;yi<height;yi++) { - bitmapline = &bitmap.pix32(line + yi); + uint32_t *const bitmapline = &bitmap.pix(line + yi); + // ibm_5150:batmanmv uses this on gameplay for both EGA and "VGA" modes + // NB: EGA mode in that game sets 663, should be 303 like the other mode + // causing no status bar to appear. This is a known btanb in how VGA + // handles EGA mode, cfr. https://www.os2museum.com/wp/fantasyland-on-vga/ + if((line + yi) == (vga.crtc.line_compare & 0x3ff)) + addr = 0; - for (pos=addr, c=0, column=0; column<EGA_COLUMNS+1; column++, c+=8, pos=(pos+1)&0xffff) + for (int pos=addr, c=0, column=0; column<EGA_COLUMNS+1; column++, c+=8, pos=(pos+1)&0xffff) { - int data[4]; - - data[0]=vga.memory[(pos & 0xffff)]; - data[1]=vga.memory[(pos & 0xffff)+0x10000]<<1; - data[2]=vga.memory[(pos & 0xffff)+0x20000]<<2; - data[3]=vga.memory[(pos & 0xffff)+0x30000]<<3; + int data[4] = { + vga.memory[(pos & 0xffff)], + vga.memory[(pos & 0xffff)+0x10000]<<1, + vga.memory[(pos & 0xffff)+0x20000]<<2, + vga.memory[(pos & 0xffff)+0x30000]<<3 }; - for (i = 7; i >= 0; i--) + for (int i = 7; i >= 0; i--) { - pen = vga.pens[(data[0]&1) | (data[1]&2) | (data[2]&4) | (data[3]&8)]; + pen_t pen = vga.pens[(data[0]&1) | (data[1]&2) | (data[2]&4) | (data[3]&8)]; data[0]>>=1; data[1]>>=1; @@ -567,29 +1397,25 @@ void vga_device::vga_vh_ega(bitmap_rgb32 &bitmap, const rectangle &cliprect) } } -/* TODO: I'm guessing that in 256 colors mode every pixel actually outputs two pixels. Is it right? */ +// In mode 13h (256 colors) every pixel actually double height/width +// i.e. a 320x200 is really 640x400 void vga_device::vga_vh_vga(bitmap_rgb32 &bitmap, const rectangle &cliprect) { - int pos, line, column, c, addr, curr_addr; - uint32_t *bitmapline; - uint16_t mask_comp; int height = vga.crtc.maximum_scan_line * (vga.crtc.scan_doubling + 1); - int yi; - int xi; int pel_shift = (vga.attribute.pel_shift & 6); int addrmask = vga.crtc.no_wrap ? -1 : 0xffff; /* line compare is screen sensitive */ - mask_comp = 0x3ff; //| (LINES & 0x300); + uint16_t mask_comp = 0x3ff; //| (LINES & 0x300); // popmessage("%02x %02x",vga.attribute.pel_shift,vga.sequencer.data[4] & 0x08); - curr_addr = 0; + int curr_addr = 0; if(!(vga.sequencer.data[4] & 0x08)) { - for (addr = start_addr(), line=0; line<LINES; line+=height, addr+=offset(), curr_addr+=offset()) + for (int addr = start_addr(), line=0; line<LINES; line+=height, addr+=offset(), curr_addr+=offset()) { - for(yi = 0;yi < height; yi++) + for(int yi = 0;yi < height; yi++) { if((line + yi) < (vga.crtc.line_compare & mask_comp)) curr_addr = addr; @@ -598,15 +1424,15 @@ void vga_device::vga_vh_vga(bitmap_rgb32 &bitmap, const rectangle &cliprect) curr_addr = 0; pel_shift = 0; } - bitmapline = &bitmap.pix32(line + yi); - for (pos=curr_addr, c=0, column=0; column<VGA_COLUMNS+1; column++, c+=8, pos++) + uint32_t *const bitmapline = &bitmap.pix(line + yi); + for (int pos=curr_addr, c=0, column=0; column<VGA_COLUMNS+1; column++, c+=8, pos++) { if(pos > 0x80000/4) return; - for(xi=0;xi<8;xi++) + for(int xi=0;xi<8;xi++) { - if(!screen().visible_area().contains(c+xi-(pel_shift), line + yi)) + if (!screen().visible_area().contains(c+xi-(pel_shift), line + yi)) continue; bitmapline[c+xi-(pel_shift)] = pen(vga.memory[(pos & addrmask)+((xi >> 1)*0x10000)]); } @@ -616,22 +1442,22 @@ void vga_device::vga_vh_vga(bitmap_rgb32 &bitmap, const rectangle &cliprect) } else { - for (addr = start_addr(), line=0; line<LINES; line+=height, addr+=offset(), curr_addr+=offset()) + for (int addr = start_addr(), line=0; line<LINES; line+=height, addr+=offset(), curr_addr+=offset()) { - for(yi = 0;yi < height; yi++) + for(int yi = 0;yi < height; yi++) { if((line + yi) < (vga.crtc.line_compare & mask_comp)) curr_addr = addr; if((line + yi) == (vga.crtc.line_compare & mask_comp)) curr_addr = 0; - bitmapline = &bitmap.pix32(line + yi); + uint32_t *const bitmapline = &bitmap.pix(line + yi); //addr %= 0x80000; - for (pos=curr_addr, c=0, column=0; column<VGA_COLUMNS+1; column++, c+=0x10, pos+=0x8) + for (int pos=curr_addr, c=0, column=0; column<VGA_COLUMNS+1; column++, c+=0x10, pos+=0x8) { if(pos + 0x08 > 0x80000) return; - for(xi=0;xi<0x10;xi++) + for (int xi=0;xi<0x10;xi++) { if(!screen().visible_area().contains(c+xi-(pel_shift), line + yi)) continue; @@ -645,28 +1471,23 @@ void vga_device::vga_vh_vga(bitmap_rgb32 &bitmap, const rectangle &cliprect) void vga_device::vga_vh_cga(bitmap_rgb32 &bitmap, const rectangle &cliprect) { - uint32_t *bitmapline; int height = (vga.crtc.scan_doubling + 1); - int x,xi,y,yi; - uint32_t addr; - pen_t pen; - int width; - width = (vga.crtc.horz_disp_end + 1) * 8; + int width = (vga.crtc.horz_disp_end + 1) * 8; - for(y=0;y<LINES;y++) + for(int y=0;y<LINES;y++) { - addr = ((y & 1) * 0x2000) + (((y & ~1) >> 1) * width/4); + uint32_t addr = ((y & 1) * 0x2000) + (((y & ~1) >> 1) * width/4); - for(x=0;x<width;x+=4) + for(int x=0;x<width;x+=4) { - for(yi=0;yi<height;yi++) + for(int yi=0;yi<height;yi++) { - bitmapline = &bitmap.pix32(y * height + yi); + uint32_t *const bitmapline = &bitmap.pix(y * height + yi); - for(xi=0;xi<4;xi++) + for(int xi=0;xi<4;xi++) { - pen = vga.pens[(vga.memory[addr] >> (6-xi*2)) & 3]; + pen_t pen = vga.pens[(vga.memory[addr] >> (6-xi*2)) & 3]; if(!screen().visible_area().contains(x+xi, y * height + yi)) continue; bitmapline[x+xi] = pen; @@ -680,28 +1501,23 @@ void vga_device::vga_vh_cga(bitmap_rgb32 &bitmap, const rectangle &cliprect) void vga_device::vga_vh_mono(bitmap_rgb32 &bitmap, const rectangle &cliprect) { - uint32_t *bitmapline; int height = (vga.crtc.scan_doubling + 1); - int x,xi,y,yi; - uint32_t addr; - pen_t pen; - int width; - width = (vga.crtc.horz_disp_end + 1) * 8; + int width = (vga.crtc.horz_disp_end + 1) * 8; - for(y=0;y<LINES;y++) + for(int y=0;y<LINES;y++) { - addr = ((y & 1) * 0x2000) + (((y & ~1) >> 1) * width/8); + uint32_t addr = ((y & 1) * 0x2000) + (((y & ~1) >> 1) * width/8); - for(x=0;x<width;x+=8) + for(int x=0;x<width;x+=8) { - for(yi=0;yi<height;yi++) + for(int yi=0;yi<height;yi++) { - bitmapline = &bitmap.pix32(y * height + yi); + uint32_t *const bitmapline = &bitmap.pix(y * height + yi); - for(xi=0;xi<8;xi++) + for(int xi=0;xi<8;xi++) { - pen = vga.pens[(vga.memory[addr] >> (7-xi)) & 1]; + pen_t pen = vga.pens[(vga.memory[addr] >> (7-xi)) & 1]; if(!screen().visible_area().contains(x+xi, y * height + yi)) continue; bitmapline[x+xi] = pen; @@ -713,247 +1529,33 @@ void vga_device::vga_vh_mono(bitmap_rgb32 &bitmap, const rectangle &cliprect) } } -void svga_device::svga_vh_rgb8(bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - int pos, line, column, c, addr, curr_addr; - uint32_t *bitmapline; - uint16_t mask_comp; - int height = vga.crtc.maximum_scan_line * (vga.crtc.scan_doubling + 1); - int yi; - int xi; - uint8_t start_shift; -// uint16_t line_length; - - /* line compare is screen sensitive */ - mask_comp = 0x3ff; - curr_addr = 0; -// if(vga.crtc.dw) -// line_length = vga.crtc.offset << 3; // doubleword mode -// else -// { -// line_length = vga.crtc.offset << 4; -// } - - start_shift = (!(vga.sequencer.data[4] & 0x08)) ? 2 : 0; - { - for (addr = VGA_START_ADDRESS << start_shift, line=0; line<LINES; line+=height, addr+=offset(), curr_addr+=offset()) - { - for(yi = 0;yi < height; yi++) - { - if((line + yi) < (vga.crtc.line_compare & mask_comp)) - curr_addr = addr; - if((line + yi) == (vga.crtc.line_compare & mask_comp)) - curr_addr = 0; - bitmapline = &bitmap.pix32(line + yi); - addr %= vga.svga_intf.vram_size; - for (pos=curr_addr, c=0, column=0; column<VGA_COLUMNS; column++, c+=8, pos+=0x8) - { - if(pos + 0x08 >= vga.svga_intf.vram_size) - return; - - for(xi=0;xi<8;xi++) - { - if(!screen().visible_area().contains(c+xi, line + yi)) - continue; - bitmapline[c+xi] = pen(vga.memory[(pos+(xi))]); - } - } - } - } - } -} - -void svga_device::svga_vh_rgb15(bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - #define MV(x) (vga.memory[x]+(vga.memory[x+1]<<8)) - #define IV 0xff000000 - int height = vga.crtc.maximum_scan_line * (vga.crtc.scan_doubling + 1); - int xi; - int yi; - int xm; - int pos, line, column, c, addr, curr_addr; - - uint32_t *bitmapline; -// uint16_t mask_comp; - - /* line compare is screen sensitive */ -// mask_comp = 0xff | (TLINES & 0x300); - curr_addr = 0; - yi=0; - for (addr = TGA_START_ADDRESS, line=0; line<TLINES; line+=height, addr+=offset(), curr_addr+=offset()) - { - bitmapline = &bitmap.pix32(line); - addr %= vga.svga_intf.vram_size; - for (pos=addr, c=0, column=0; column<TGA_COLUMNS; column++, c+=8, pos+=0x10) - { - if(pos + 0x10 >= vga.svga_intf.vram_size) - return; - for(xi=0,xm=0;xi<8;xi++,xm+=2) - { - int r,g,b; - - if(!screen().visible_area().contains(c+xi, line + yi)) - continue; - - r = (MV(pos+xm)&0x7c00)>>10; - g = (MV(pos+xm)&0x03e0)>>5; - b = (MV(pos+xm)&0x001f)>>0; - r = (r << 3) | (r & 0x7); - g = (g << 3) | (g & 0x7); - b = (b << 3) | (b & 0x7); - bitmapline[c+xi] = IV|(r<<16)|(g<<8)|(b<<0); - } - } - } -} - -void svga_device::svga_vh_rgb16(bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - #define MV(x) (vga.memory[x]+(vga.memory[x+1]<<8)) - #define IV 0xff000000 - int height = vga.crtc.maximum_scan_line * (vga.crtc.scan_doubling + 1); - int xi; - int yi; - int xm; - int pos, line, column, c, addr, curr_addr; - - uint32_t *bitmapline; -// uint16_t mask_comp; - - /* line compare is screen sensitive */ -// mask_comp = 0xff | (TLINES & 0x300); - curr_addr = 0; - yi=0; - for (addr = TGA_START_ADDRESS, line=0; line<TLINES; line+=height, addr+=offset(), curr_addr+=offset()) - { - bitmapline = &bitmap.pix32(line); - addr %= vga.svga_intf.vram_size; - for (pos=addr, c=0, column=0; column<TGA_COLUMNS; column++, c+=8, pos+=0x10) - { - if(pos + 0x10 >= vga.svga_intf.vram_size) - return; - for(xi=0,xm=0;xi<8;xi++,xm+=2) - { - int r,g,b; - - if(!screen().visible_area().contains(c+xi, line + yi)) - continue; - - r = (MV(pos+xm)&0xf800)>>11; - g = (MV(pos+xm)&0x07e0)>>5; - b = (MV(pos+xm)&0x001f)>>0; - r = (r << 3) | (r & 0x7); - g = (g << 2) | (g & 0x3); - b = (b << 3) | (b & 0x7); - bitmapline[c+xi] = IV|(r<<16)|(g<<8)|(b<<0); - } - } - } -} - -void svga_device::svga_vh_rgb24(bitmap_rgb32 &bitmap, const rectangle &cliprect) +void vga_device::palette_update() { - #define MD(x) (vga.memory[x]+(vga.memory[x+1]<<8)+(vga.memory[x+2]<<16)) - #define ID 0xff000000 - int height = vga.crtc.maximum_scan_line * (vga.crtc.scan_doubling + 1); - int xi; - int yi; - int xm; - int pos, line, column, c, addr, curr_addr; - uint32_t *bitmapline; - -// uint16_t mask_comp; - - /* line compare is screen sensitive */ -// mask_comp = 0xff | (TLINES & 0x300); - curr_addr = 0; - yi=0; - for (addr = TGA_START_ADDRESS<<1, line=0; line<TLINES; line+=height, addr+=offset(), curr_addr+=offset()) + for (int i = 0; i < 256; i++) { - bitmapline = &bitmap.pix32(line); - addr %= vga.svga_intf.vram_size; - for (pos=addr, c=0, column=0; column<TGA_COLUMNS; column++, c+=8, pos+=24) - { - if(pos + 24 >= vga.svga_intf.vram_size) - return; - for(xi=0,xm=0;xi<8;xi++,xm+=3) - { - int r,g,b; - - if(!screen().visible_area().contains(c+xi, line + yi)) - continue; - - r = (MD(pos+xm)&0xff0000)>>16; - g = (MD(pos+xm)&0x00ff00)>>8; - b = (MD(pos+xm)&0x0000ff)>>0; - bitmapline[c+xi] = IV|(r<<16)|(g<<8)|(b<<0); - } - } + set_pen_color( + i, + pal6bit(vga.dac.color[3*(i & vga.dac.mask) + 0] & 0x3f), + pal6bit(vga.dac.color[3*(i & vga.dac.mask) + 1] & 0x3f), + pal6bit(vga.dac.color[3*(i & vga.dac.mask) + 2] & 0x3f) + ); } } -void svga_device::svga_vh_rgb32(bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - #define MD(x) (vga.memory[x]+(vga.memory[x+1]<<8)+(vga.memory[x+2]<<16)) - #define ID 0xff000000 - int height = vga.crtc.maximum_scan_line * (vga.crtc.scan_doubling + 1); - int xi; - int yi; - int xm; - int pos, line, column, c, addr, curr_addr; - uint32_t *bitmapline; - -// uint16_t mask_comp; - - /* line compare is screen sensitive */ -// mask_comp = 0xff | (TLINES & 0x300); - curr_addr = 0; - yi=0; - for (addr = TGA_START_ADDRESS, line=0; line<TLINES; line+=height, addr+=(offset()), curr_addr+=(offset())) - { - bitmapline = &bitmap.pix32(line); - addr %= vga.svga_intf.vram_size; - for (pos=addr, c=0, column=0; column<TGA_COLUMNS; column++, c+=8, pos+=0x20) - { - if(pos + 0x20 >= vga.svga_intf.vram_size) - return; - for(xi=0,xm=0;xi<8;xi++,xm+=4) - { - int r,g,b; - - if(!screen().visible_area().contains(c+xi, line + yi)) - continue; - - r = (MD(pos+xm)&0xff0000)>>16; - g = (MD(pos+xm)&0x00ff00)>>8; - b = (MD(pos+xm)&0x0000ff)>>0; - bitmapline[c+xi] = IV|(r<<16)|(g<<8)|(b<<0); - } - } - } -} uint8_t vga_device::pc_vga_choosevideomode() { - int i; - if (vga.crtc.sync_en) { if (vga.dac.dirty) { - for (i=0; i<256;i++) - { - /* TODO: color shifters? */ - set_pen_color(i, (vga.dac.color[3*(i & vga.dac.mask)] & 0x3f) << 2, - (vga.dac.color[3*(i & vga.dac.mask) + 1] & 0x3f) << 2, - (vga.dac.color[3*(i & vga.dac.mask) + 2] & 0x3f) << 2); - } + palette_update(); vga.dac.dirty = 0; } if (vga.attribute.data[0x10] & 0x80) { - for (i=0; i<16;i++) + for (int i=0; i<16;i++) { vga.pens[i] = pen((vga.attribute.data[i]&0x0f) |((vga.attribute.data[0x14]&0xf)<<4)); @@ -961,7 +1563,7 @@ uint8_t vga_device::pc_vga_choosevideomode() } else { - for (i=0; i<16;i++) + for (int i=0; i<16;i++) { vga.pens[i] = pen((vga.attribute.data[i]&0x3f) |((vga.attribute.data[0x14]&0xc)<<4)); @@ -993,123 +1595,9 @@ uint8_t vga_device::pc_vga_choosevideomode() return SCREEN_OFF; } - -uint8_t svga_device::pc_vga_choosevideomode() -{ - int i; - - if (vga.crtc.sync_en) - { - if (vga.dac.dirty) - { - for (i=0; i<256;i++) - { - /* TODO: color shifters? */ - set_pen_color(i, (vga.dac.color[3*(i & vga.dac.mask)] & 0x3f) << 2, - (vga.dac.color[3*(i & vga.dac.mask) + 1] & 0x3f) << 2, - (vga.dac.color[3*(i & vga.dac.mask) + 2] & 0x3f) << 2); - } - vga.dac.dirty = 0; - } - - if (vga.attribute.data[0x10] & 0x80) - { - for (i=0; i<16;i++) - { - vga.pens[i] = pen((vga.attribute.data[i]&0x0f) - |((vga.attribute.data[0x14]&0xf)<<4)); - } - } - else - { - for (i=0; i<16;i++) - { - vga.pens[i] = pen((vga.attribute.data[i]&0x3f) - |((vga.attribute.data[0x14]&0xc)<<4)); - } - } - - if (svga.rgb32_en) - { - return RGB32_MODE; - } - else if (svga.rgb24_en) - { - return RGB24_MODE; - } - else if (svga.rgb16_en) - { - return RGB16_MODE; - } - else if (svga.rgb15_en) - { - return RGB15_MODE; - } - else if (svga.rgb8_en) - { - return RGB8_MODE; - } - else if (!GRAPHIC_MODE) - { - return TEXT_MODE; - } - else if (vga.gc.shift256) - { - return VGA_MODE; - } - else if (vga.gc.shift_reg) - { - return CGA_MODE; - } - else if (vga.gc.memory_map_sel == 0x03) - { - return MONO_MODE; - } - else - { - return EGA_MODE; - } - } - - return SCREEN_OFF; -} - -uint8_t svga_device::get_video_depth() -{ - switch(pc_vga_choosevideomode()) - { - case VGA_MODE: - case RGB8_MODE: - return 8; - case RGB15_MODE: - case RGB16_MODE: - return 16; - case RGB24_MODE: - case RGB32_MODE: - return 32; - } - return 0; -} - uint32_t vga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { uint8_t cur_mode = pc_vga_choosevideomode(); - switch(cur_mode) - { - case SCREEN_OFF: bitmap.fill (black_pen(), cliprect);break; - case TEXT_MODE: vga_vh_text (bitmap, cliprect); break; - case VGA_MODE: vga_vh_vga (bitmap, cliprect); break; - case EGA_MODE: vga_vh_ega (bitmap, cliprect); break; - case CGA_MODE: vga_vh_cga (bitmap, cliprect); break; - case MONO_MODE: vga_vh_mono (bitmap, cliprect); break; - } - - return 0; -} - -uint32_t svga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - uint8_t cur_mode = pc_vga_choosevideomode(); switch(cur_mode) { @@ -1119,278 +1607,20 @@ uint32_t svga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, case EGA_MODE: vga_vh_ega (bitmap, cliprect); break; case CGA_MODE: vga_vh_cga (bitmap, cliprect); break; case MONO_MODE: vga_vh_mono (bitmap, cliprect); break; - case RGB8_MODE: svga_vh_rgb8 (bitmap, cliprect); break; - case RGB15_MODE: svga_vh_rgb15(bitmap, cliprect); break; - case RGB16_MODE: svga_vh_rgb16(bitmap, cliprect); break; - case RGB24_MODE: svga_vh_rgb24(bitmap, cliprect); break; - case RGB32_MODE: svga_vh_rgb32(bitmap, cliprect); break; } return 0; } -uint32_t s3_vga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - uint8_t cur_mode; - - svga_device::screen_update(screen, bitmap, cliprect); - - cur_mode = pc_vga_choosevideomode(); - - // draw hardware graphics cursor - // TODO: support 16 bit and greater video modes - if(s3.cursor_mode & 0x01) // if cursor is enabled - { - uint32_t src; - uint32_t* dst; - uint8_t val; - int x,y; - uint16_t cx = s3.cursor_x & 0x07ff; - uint16_t cy = s3.cursor_y & 0x07ff; - uint32_t bg_col; - uint32_t fg_col; - - if(cur_mode == SCREEN_OFF || cur_mode == TEXT_MODE || cur_mode == MONO_MODE || cur_mode == CGA_MODE || cur_mode == EGA_MODE) - return 0; // cursor only works in VGA or SVGA modes - - src = s3.cursor_start_addr * 1024; // start address is in units of 1024 bytes - - if(cur_mode == RGB16_MODE) - { - int r,g,b; - uint16_t datax; - - datax = s3.cursor_bg[0]|s3.cursor_bg[1]<<8; - r = (datax&0xf800)>>11; - g = (datax&0x07e0)>>5; - b = (datax&0x001f)>>0; - r = (r << 3) | (r & 0x7); - g = (g << 2) | (g & 0x3); - b = (b << 3) | (b & 0x7); - bg_col = (0xff<<24)|(r<<16)|(g<<8)|(b<<0); - - datax = s3.cursor_fg[0]|s3.cursor_fg[1]<<8; - r = (datax&0xf800)>>11; - g = (datax&0x07e0)>>5; - b = (datax&0x001f)>>0; - r = (r << 3) | (r & 0x7); - g = (g << 2) | (g & 0x3); - b = (b << 3) | (b & 0x7); - fg_col = (0xff<<24)|(r<<16)|(g<<8)|(b<<0); - } - else /* TODO: other modes */ - { - bg_col = pen(s3.cursor_bg[0]); - fg_col = pen(s3.cursor_fg[0]); - } - - //popmessage("%08x %08x",(s3.cursor_bg[0])|(s3.cursor_bg[1]<<8)|(s3.cursor_bg[2]<<16)|(s3.cursor_bg[3]<<24) - // ,(s3.cursor_fg[0])|(s3.cursor_fg[1]<<8)|(s3.cursor_fg[2]<<16)|(s3.cursor_fg[3]<<24)); -// for(x=0;x<64;x++) -// printf("%08x: %02x %02x %02x %02x\n",src+x*4,vga.memory[src+x*4],vga.memory[src+x*4+1],vga.memory[src+x*4+2],vga.memory[src+x*4+3]); - for(y=0;y<64;y++) - { - if(cy + y < cliprect.max_y && cx < cliprect.max_x) - { - dst = &bitmap.pix32(cy + y, cx); - for(x=0;x<64;x++) - { - uint16_t bita = (vga.memory[(src+1) % vga.svga_intf.vram_size] | ((vga.memory[(src+0) % vga.svga_intf.vram_size]) << 8)) >> (15-(x % 16)); - uint16_t bitb = (vga.memory[(src+3) % vga.svga_intf.vram_size] | ((vga.memory[(src+2) % vga.svga_intf.vram_size]) << 8)) >> (15-(x % 16)); - val = ((bita & 0x01) << 1) | (bitb & 0x01); - if(s3.extended_dac_ctrl & 0x10) - { // X11 mode - switch(val) - { - case 0x00: - // no change - break; - case 0x01: - // no change - break; - case 0x02: - dst[x] = bg_col; - break; - case 0x03: - dst[x] = fg_col; - break; - } - } - else - { // Windows mode - switch(val) - { - case 0x00: - dst[x] = bg_col; - break; - case 0x01: - dst[x] = fg_col; - break; - case 0x02: // screen data - // no change - break; - case 0x03: // inverted screen data - dst[x] = ~(dst[x]); - break; - } - } - if(x % 16 == 15) - src+=4; - } - } - } - } - return 0; -} - - -/***************************************************************************/ - -inline uint8_t vga_device::vga_latch_write(int offs, uint8_t data) -{ - uint8_t res = 0; - - switch (vga.gc.write_mode & 3) { - case 0: - data = rotate_right(data); - if(vga.gc.enable_set_reset & 1<<offs) - res = vga_logical_op((vga.gc.set_reset & 1<<offs) ? vga.gc.bit_mask : 0, offs,vga.gc.bit_mask); - else - res = vga_logical_op(data, offs, vga.gc.bit_mask); - break; - case 1: - res = vga.gc.latch[offs]; - break; - case 2: - res = vga_logical_op((data & 1<<offs) ? 0xff : 0x00,offs,vga.gc.bit_mask); - break; - case 3: - data = rotate_right(data); - res = vga_logical_op((vga.gc.set_reset & 1<<offs) ? 0xff : 0x00,offs,data&vga.gc.bit_mask); - break; - } - - return res; -} - -uint8_t vga_device::crtc_reg_read(uint8_t index) -{ - uint8_t res; - - res = 0xff; - - switch(index) - { - case 0x00: - res = vga.crtc.horz_total & 0xff; - break; - case 0x01: - res = vga.crtc.horz_disp_end & 0xff; - break; - case 0x02: - res = vga.crtc.horz_blank_start & 0xff; - break; - case 0x03: - res = vga.crtc.horz_blank_end & 0x1f; - res |= (vga.crtc.disp_enable_skew & 3) << 5; - res |= (vga.crtc.evra & 1) << 7; - break; - case 0x04: - res = vga.crtc.horz_retrace_start & 0xff; - break; - case 0x05: - res = (vga.crtc.horz_blank_end & 0x20) << 2; - res |= (vga.crtc.horz_retrace_skew & 3) << 5; - res |= (vga.crtc.horz_retrace_end & 0x1f); - break; - case 0x06: - res = vga.crtc.vert_total & 0xff; - break; - case 0x07: // Overflow Register - res = (vga.crtc.line_compare & 0x100) >> 4; - res |= (vga.crtc.vert_retrace_start & 0x200) >> 2; - res |= (vga.crtc.vert_disp_end & 0x200) >> 3; - res |= (vga.crtc.vert_total & 0x200) >> 4; - res |= (vga.crtc.vert_blank_start & 0x100) >> 5; - res |= (vga.crtc.vert_retrace_start & 0x100) >> 6; - res |= (vga.crtc.vert_disp_end & 0x100) >> 7; - res |= (vga.crtc.vert_total & 0x100) >> 8; - break; - case 0x08: // Preset Row Scan Register - res = (vga.crtc.byte_panning & 3) << 5; - res |= (vga.crtc.preset_row_scan & 0x1f); - break; - case 0x09: // Maximum Scan Line Register - res = (vga.crtc.maximum_scan_line - 1) & 0x1f; - res |= (vga.crtc.scan_doubling & 1) << 7; - res |= (vga.crtc.line_compare & 0x200) >> 3; - res |= (vga.crtc.vert_blank_start & 0x200) >> 4; - break; - case 0x0a: - res = (vga.crtc.cursor_scan_start & 0x1f); - res |= ((vga.crtc.cursor_enable & 1) ^ 1) << 5; - break; - case 0x0b: - res = (vga.crtc.cursor_skew & 3) << 5; - res |= (vga.crtc.cursor_scan_end & 0x1f); - break; - case 0x0c: - case 0x0d: - res = (vga.crtc.start_addr_latch >> ((index & 1) ^ 1)*8) & 0xff; - break; - case 0x0e: - case 0x0f: - res = (vga.crtc.cursor_addr >> ((index & 1) ^ 1)*8) & 0xff; - break; - case 0x10: - res = vga.crtc.vert_retrace_start & 0xff; - break; - case 0x11: - res = (vga.crtc.protect_enable & 1) << 7; - res |= (vga.crtc.bandwidth & 1) << 6; - res |= (vga.crtc.vert_retrace_end & 0xf); - res |= (vga.crtc.irq_clear & 1) << 4; - res |= (vga.crtc.irq_disable & 1) << 5; - break; - case 0x12: - res = vga.crtc.vert_disp_end & 0xff; - break; - case 0x13: - res = vga.crtc.offset & 0xff; - break; - case 0x14: - res = (vga.crtc.dw & 1) << 6; - res |= (vga.crtc.div4 & 1) << 5; - res |= (vga.crtc.underline_loc & 0x1f); - break; - case 0x15: - res = vga.crtc.vert_blank_start & 0xff; - break; - case 0x16: - res = vga.crtc.vert_blank_end & 0x7f; - break; - case 0x17: - res = (vga.crtc.sync_en & 1) << 7; - res |= (vga.crtc.word_mode & 1) << 6; - res |= (vga.crtc.aw & 1) << 5; - res |= (vga.crtc.div2 & 1) << 3; - res |= (vga.crtc.sldiv & 1) << 2; - res |= (vga.crtc.map14 & 1) << 1; - res |= (vga.crtc.map13 & 1) << 0; - break; - case 0x18: - res = vga.crtc.line_compare & 0xff; - break; - default: - printf("Unhandled CRTC reg r %02x\n",index); - break; - } - return res; -} +/************************************** + * + * CRTC setups + * + *************************************/ void vga_device::recompute_params_clock(int divisor, int xtal) { - int vblank_period,hblank_period; + int vblank_period, hblank_period; attoseconds_t refresh; uint8_t hclock_m = (!GRAPHIC_MODE) ? VGA_CH_WIDTH : 8; int pixel_clock; @@ -1399,197 +1629,31 @@ void vga_device::recompute_params_clock(int divisor, int xtal) if(!vga.crtc.horz_disp_end || !vga.crtc.vert_disp_end || !vga.crtc.horz_total || !vga.crtc.vert_total) return; - rectangle visarea(0, ((vga.crtc.horz_disp_end + 1) * ((float)(hclock_m)/divisor))-1, 0, vga.crtc.vert_disp_end); + const u8 is_interlace_mode = get_interlace_mode() + 1; + const int display_lines = vga.crtc.vert_disp_end * is_interlace_mode; + + rectangle visarea(0, ((vga.crtc.horz_disp_end + 1) * ((float)(hclock_m)/divisor))-1, 0, display_lines); - vblank_period = (vga.crtc.vert_total + 2); + vblank_period = (vga.crtc.vert_total + 2) * is_interlace_mode; hblank_period = ((vga.crtc.horz_total + 5) * ((float)(hclock_m)/divisor)); - /* TODO: 10b and 11b settings aren't known */ + // TODO: improve/complete clocking modes pixel_clock = xtal / (((vga.sequencer.data[1]&8) >> 3) + 1); refresh = HZ_TO_ATTOSECONDS(pixel_clock) * (hblank_period) * vblank_period; screen().configure((hblank_period), (vblank_period), visarea, refresh ); - //popmessage("%d %d\n",vga.crtc.horz_total * 8,vga.crtc.vert_total); m_vblank_timer->adjust( screen().time_until_pos(vga.crtc.vert_blank_start + vga.crtc.vert_blank_end) ); } +// TODO: rename me void vga_device::recompute_params() { if(vga.miscellaneous_output & 8) - logerror("Warning: VGA external clock latch selected\n"); + LOGWARN("Warning: VGA external clock latch selected\n"); else recompute_params_clock(1, ((vga.miscellaneous_output & 0xc) ? XTAL(28'636'363) : XTAL(25'174'800)).value()); } -void vga_device::crtc_reg_write(uint8_t index, uint8_t data) -{ - /* Doom does this */ -// if(vga.crtc.protect_enable && index <= 0x07) -// printf("write to protected address %02x\n",index); - switch(index) - { - case 0x00: - if(vga.crtc.protect_enable) - break; - vga.crtc.horz_total = (vga.crtc.horz_total & ~0xff) | (data & 0xff); - recompute_params(); - break; - case 0x01: - if(vga.crtc.protect_enable) - break; - vga.crtc.horz_disp_end = (data & 0xff); - recompute_params(); - break; - case 0x02: - if(vga.crtc.protect_enable) - break; - vga.crtc.horz_blank_start = (data & 0xff); - break; - case 0x03: - if(vga.crtc.protect_enable) - break; - vga.crtc.horz_blank_end &= ~0x1f; - vga.crtc.horz_blank_end |= data & 0x1f; - vga.crtc.disp_enable_skew = (data & 0x60) >> 5; - vga.crtc.evra = (data & 0x80) >> 7; - break; - case 0x04: - if(vga.crtc.protect_enable) - break; - vga.crtc.horz_retrace_start = data & 0xff; - break; - case 0x05: - if(vga.crtc.protect_enable) - break; - vga.crtc.horz_blank_end &= ~0x20; - vga.crtc.horz_blank_end |= ((data & 0x80) >> 2); - vga.crtc.horz_retrace_skew = ((data & 0x60) >> 5); - vga.crtc.horz_retrace_end = data & 0x1f; - break; - case 0x06: - if(vga.crtc.protect_enable) - break; - vga.crtc.vert_total &= ~0xff; - vga.crtc.vert_total |= data & 0xff; - recompute_params(); - break; - case 0x07: // Overflow Register - vga.crtc.line_compare &= ~0x100; - vga.crtc.line_compare |= ((data & 0x10) << (8-4)); - if(vga.crtc.protect_enable) - break; - vga.crtc.vert_total &= ~0x300; - vga.crtc.vert_retrace_start &= ~0x300; - vga.crtc.vert_disp_end &= ~0x300; - vga.crtc.vert_blank_start &= ~0x100; - vga.crtc.vert_retrace_start |= ((data & 0x80) << (9-7)); - vga.crtc.vert_disp_end |= ((data & 0x40) << (9-6)); - vga.crtc.vert_total |= ((data & 0x20) << (9-5)); - vga.crtc.vert_blank_start |= ((data & 0x08) << (8-3)); - vga.crtc.vert_retrace_start |= ((data & 0x04) << (8-2)); - vga.crtc.vert_disp_end |= ((data & 0x02) << (8-1)); - vga.crtc.vert_total |= ((data & 0x01) << (8-0)); - recompute_params(); - break; - case 0x08: // Preset Row Scan Register - vga.crtc.byte_panning = (data & 0x60) >> 5; - vga.crtc.preset_row_scan = (data & 0x1f); - break; - case 0x09: // Maximum Scan Line Register - vga.crtc.line_compare &= ~0x200; - vga.crtc.vert_blank_start &= ~0x200; - vga.crtc.scan_doubling = ((data & 0x80) >> 7); - vga.crtc.line_compare |= ((data & 0x40) << (9-6)); - vga.crtc.vert_blank_start |= ((data & 0x20) << (9-5)); - vga.crtc.maximum_scan_line = (data & 0x1f) + 1; - break; - case 0x0a: - vga.crtc.cursor_enable = ((data & 0x20) ^ 0x20) >> 5; - vga.crtc.cursor_scan_start = data & 0x1f; - break; - case 0x0b: - vga.crtc.cursor_skew = (data & 0x60) >> 5; - vga.crtc.cursor_scan_end = data & 0x1f; - break; - case 0x0c: - case 0x0d: - vga.crtc.start_addr_latch &= ~(0xff << (((index & 1)^1) * 8)); - vga.crtc.start_addr_latch |= (data << (((index & 1)^1) * 8)); - break; - case 0x0e: - case 0x0f: - vga.crtc.cursor_addr &= ~(0xff << (((index & 1)^1) * 8)); - vga.crtc.cursor_addr |= (data << (((index & 1)^1) * 8)); - break; - case 0x10: - vga.crtc.vert_retrace_start &= ~0xff; - vga.crtc.vert_retrace_start |= data & 0xff; - break; - case 0x11: - vga.crtc.protect_enable = (data & 0x80) >> 7; - vga.crtc.bandwidth = (data & 0x40) >> 6; - vga.crtc.vert_retrace_end = data & 0x0f; - vga.crtc.irq_clear = (data & 0x10) >> 4; - vga.crtc.irq_disable = (data & 0x20) >> 5; - break; - case 0x12: - vga.crtc.vert_disp_end &= ~0xff; - vga.crtc.vert_disp_end |= data & 0xff; - recompute_params(); - break; - case 0x13: - vga.crtc.offset &= ~0xff; - vga.crtc.offset |= data & 0xff; - break; - case 0x14: - vga.crtc.dw = (data & 0x40) >> 6; - vga.crtc.div4 = (data & 0x20) >> 5; - vga.crtc.underline_loc = (data & 0x1f); - break; - case 0x15: - vga.crtc.vert_blank_start &= ~0xff; - vga.crtc.vert_blank_start |= data & 0xff; - break; - case 0x16: - vga.crtc.vert_blank_end = data & 0x7f; - break; - case 0x17: - vga.crtc.sync_en = (data & 0x80) >> 7; - vga.crtc.word_mode = (data & 0x40) >> 6; - vga.crtc.aw = (data & 0x20) >> 5; - vga.crtc.div2 = (data & 0x08) >> 3; - vga.crtc.sldiv = (data & 0x04) >> 2; - vga.crtc.map14 = (data & 0x02) >> 1; - vga.crtc.map13 = (data & 0x01) >> 0; - break; - case 0x18: - vga.crtc.line_compare &= ~0xff; - vga.crtc.line_compare |= data & 0xff; - break; - default: - logerror("Unhandled CRTC reg w %02x %02x\n",index,data); - break; - } -} - -void vga_device::seq_reg_write(uint8_t index, uint8_t data) -{ - switch(index) - { - case 0x02: - vga.sequencer.map_mask = data & 0xf; - break; - case 0x03: - /* --2- 84-- character select A - ---2 --84 character select B */ - vga.sequencer.char_sel.A = (((data & 0xc) >> 2)<<1) | ((data & 0x20) >> 5); - vga.sequencer.char_sel.B = (((data & 0x3) >> 0)<<1) | ((data & 0x10) >> 4); - if(data) - popmessage("Char SEL checker, contact MAMEdev (%02x %02x)\n",vga.sequencer.char_sel.A,vga.sequencer.char_sel.B); - break; - } -} - uint8_t vga_device::vga_vblank() { uint8_t res; @@ -1619,490 +1683,48 @@ uint8_t vga_device::vga_vblank() return res; } -READ8_MEMBER(vga_device::vga_crtc_r) -{ - uint8_t data = 0xff; - - switch (offset) { - case 4: - data = vga.crtc.index; - break; - case 5: - data = crtc_reg_read(vga.crtc.index); - break; - case 0xa: - uint8_t hsync,vsync; - vga.attribute.state = 0; - data = 0; - - hsync = screen().hblank() & 1; - vsync = vga_vblank(); //screen().vblank() & 1; - - data |= (hsync | vsync) & 1; // DD - display disable register - data |= (vsync & 1) << 3; // VRetrace register - - /* ega diagnostic readback enough for oak bios */ - switch (vga.attribute.data[0x12]&0x30) { - case 0: - if (vga.attribute.data[0x11]&1) data|=0x10; - if (vga.attribute.data[0x11]&4) data|=0x20; - break; - case 0x10: - data|=(vga.attribute.data[0x11]&0x30); - break; - case 0x20: - if (vga.attribute.data[0x11]&2) data|=0x10; - if (vga.attribute.data[0x11]&8) data|=0x20; - break; - case 0x30: - data|=(vga.attribute.data[0x11]&0xc0)>>2; - break; - } - break; - case 0xf: - /* oak test */ - //data=0; - /* pega bios on/off */ - data=0x80; - break; - } - return data; -} - -WRITE8_MEMBER(vga_device::vga_crtc_w) -{ - switch (offset) - { - case 4: - vga.crtc.index = data; - break; - - case 5: - if (LOG_REGISTERS) - { - logerror("vga_crtc_w(): CRTC[0x%02X%s] = 0x%02X\n", - vga.crtc.index, - (vga.crtc.index < vga.svga_intf.crtc_regcount) ? "" : "?", - data); - } - - crtc_reg_write(vga.crtc.index,data); - //screen().update_partial(screen().vpos()); - #if 0 - if((vga.crtc.index & 0xfe) != 0x0e) - printf("%02x %02x %d\n",vga.crtc.index,data,screen().vpos()); - #endif - break; - - case 0xa: - vga.feature_control = data; - break; - } -} - - - -READ8_MEMBER(vga_device::port_03b0_r) -{ - uint8_t data = 0xff; - if (CRTC_PORT_ADDR==0x3b0) - data=vga_crtc_r(space, offset, mem_mask); - return data; -} - -uint8_t vga_device::gc_reg_read(uint8_t index) -{ - uint8_t res; - - switch(index) - { - case 0x00: - res = vga.gc.set_reset & 0xf; - break; - case 0x01: - res = vga.gc.enable_set_reset & 0xf; - break; - case 0x02: - res = vga.gc.color_compare & 0xf; - break; - case 0x03: - res = (vga.gc.logical_op & 3) << 3; - res |= (vga.gc.rotate_count & 7); - break; - case 0x04: - res = vga.gc.read_map_sel & 3; - break; - case 0x05: - res = (vga.gc.shift256 & 1) << 6; - res |= (vga.gc.shift_reg & 1) << 5;; - res |= (vga.gc.host_oe & 1) << 4; - res |= (vga.gc.read_mode & 1) << 3; - res |= (vga.gc.write_mode & 3); - break; - case 0x06: - res = (vga.gc.memory_map_sel & 3) << 2; - res |= (vga.gc.chain_oe & 1) << 1; - res |= (vga.gc.alpha_dis & 1); - break; - case 0x07: - res = vga.gc.color_dont_care & 0xf; - break; - case 0x08: - res = vga.gc.bit_mask & 0xff; - break; - default: - res = 0xff; - break; - } - - return res; -} - -READ8_MEMBER(vga_device::port_03c0_r) -{ - uint8_t data = 0xff; - - switch (offset) - { - case 0: - data = vga.attribute.index; - break; - case 1: - if((vga.attribute.index&0x20) - && ((vga.attribute.index&0x1f)<0x10)) - data = 0; // palette access is disabled in this mode - else if ((vga.attribute.index&0x1f)<sizeof(vga.attribute.data)) - data=vga.attribute.data[vga.attribute.index&0x1f]; - break; - - case 2: - // TODO: in VGA bit 4 is actually always on? - data = 0x60; // is VGA - switch ((vga.miscellaneous_output>>2)&3) - { - case 3: - if (!vga.read_dipswitch.isnull() && vga.read_dipswitch(space, 0, mem_mask) & 0x01) - data |= 0x10; - else - data |= 0x10; - break; - case 2: - if (!vga.read_dipswitch.isnull() && vga.read_dipswitch(space, 0, mem_mask) & 0x02) - data |= 0x10; - else - data |= 0x10; - break; - case 1: - if (!vga.read_dipswitch.isnull() && vga.read_dipswitch(space, 0, mem_mask) & 0x04) - data |= 0x10; - else - data |= 0x10; - break; - case 0: - if (!vga.read_dipswitch.isnull() && vga.read_dipswitch(space, 0, mem_mask) & 0x08) - data |= 0x10; - else - data |= 0x10; - break; - } - break; - - case 3: - data = vga.oak.reg; - break; - - case 4: - data = vga.sequencer.index; - break; - - case 5: - if (vga.sequencer.index < vga.svga_intf.seq_regcount) - data = vga.sequencer.data[vga.sequencer.index]; - break; - - case 6: - data = vga.dac.mask; - break; - - case 7: - data = (vga.dac.read) ? 3 : 0; - break; - - case 8: - data = vga.dac.write_index; - break; - - case 9: - if (vga.dac.read) - { - switch (vga.dac.state++) - { - case 0: - data = vga.dac.color[3*vga.dac.read_index]; - break; - case 1: - data = vga.dac.color[3*vga.dac.read_index + 1]; - break; - case 2: - data = vga.dac.color[3*vga.dac.read_index + 2]; - break; - } - - if (vga.dac.state==3) - { - vga.dac.state = 0; - vga.dac.read_index++; - } - } - break; - - case 0xa: - data = vga.feature_control; - break; - - case 0xc: - data = vga.miscellaneous_output; - break; - - case 0xe: - data = vga.gc.index; - break; - - case 0xf: - data = gc_reg_read(vga.gc.index); - break; - } - return data; -} - -READ8_MEMBER(vga_device::port_03d0_r) -{ - uint8_t data = 0xff; - if (CRTC_PORT_ADDR == 0x3d0) - data = vga_crtc_r(space, offset, mem_mask); - if(offset == 8) - { - logerror("VGA: 0x3d8 read %s\n", machine().describe_context()); - data = 0; // TODO: PC-200 reads back CGA register here, everything else returns open bus OR CGA emulation of register 0x3d8 - } - - return data; -} - -WRITE8_MEMBER(vga_device::port_03b0_w) -{ - if (LOG_ACCESSES) - logerror("vga_port_03b0_w(): port=0x%04x data=0x%02x\n", offset + 0x3b0, data); - - if (CRTC_PORT_ADDR == 0x3b0) - vga_crtc_w(space, offset, data, mem_mask); -} - -void vga_device::attribute_reg_write(uint8_t index, uint8_t data) -{ - if((index & 0x30) == 0) - { - //if(vga.sequencer.data[1]&0x20) // ok? - vga.attribute.data[index & 0x1f] = data & 0x3f; - } - else - { - switch(index & 0x1f) - { - /* TODO: intentional dirtiness, variable names to be properly changed */ - case 0x10: vga.attribute.data[0x10] = data; break; - case 0x11: vga.attribute.data[0x11] = data; break; - case 0x12: vga.attribute.data[0x12] = data; break; - case 0x13: vga.attribute.pel_shift_latch = vga.attribute.data[0x13] = data; break; - case 0x14: vga.attribute.data[0x14] = data; break; - } - } -} - -void vga_device::gc_reg_write(uint8_t index,uint8_t data) -{ - switch(index) - { - case 0x00: - vga.gc.set_reset = data & 0xf; - break; - case 0x01: - vga.gc.enable_set_reset = data & 0xf; - break; - case 0x02: - vga.gc.color_compare = data & 0xf; - break; - case 0x03: - vga.gc.logical_op = (data & 0x18) >> 3; - vga.gc.rotate_count = data & 7; - break; - case 0x04: - vga.gc.read_map_sel = data & 3; - break; - case 0x05: - vga.gc.shift256 = (data & 0x40) >> 6; - vga.gc.shift_reg = (data & 0x20) >> 5; - vga.gc.host_oe = (data & 0x10) >> 4; - vga.gc.read_mode = (data & 8) >> 3; - vga.gc.write_mode = data & 3; - //if(data & 0x10 && vga.gc.alpha_dis) - // popmessage("Host O/E enabled, contact MAMEdev"); - break; - case 0x06: - vga.gc.memory_map_sel = (data & 0xc) >> 2; - vga.gc.chain_oe = (data & 2) >> 1; - vga.gc.alpha_dis = (data & 1); - //if(data & 2 && vga.gc.alpha_dis) - // popmessage("Chain O/E enabled, contact MAMEdev"); - break; - case 0x07: - vga.gc.color_dont_care = data & 0xf; - break; - case 0x08: - vga.gc.bit_mask = data & 0xff; - break; - } -} - -WRITE8_MEMBER(vga_device::port_03c0_w) -{ - if (LOG_ACCESSES) - logerror("vga_port_03c0_w(): port=0x%04x data=0x%02x\n", offset + 0x3c0, data); - - switch (offset) { - case 0: - if (vga.attribute.state==0) - { - vga.attribute.index=data; - } - else - { - attribute_reg_write(vga.attribute.index,data); - } - vga.attribute.state=!vga.attribute.state; - break; - case 2: - vga.miscellaneous_output=data; - recompute_params(); - break; - case 3: - vga.oak.reg = data; - break; - case 4: - vga.sequencer.index = data; - break; - case 5: - if (LOG_REGISTERS) - { - logerror("vga_port_03c0_w(): SEQ[0x%02X%s] = 0x%02X\n", - vga.sequencer.index, - (vga.sequencer.index < vga.svga_intf.seq_regcount) ? "" : "?", - data); - } - if (vga.sequencer.index < vga.svga_intf.seq_regcount) - { - vga.sequencer.data[vga.sequencer.index] = data; - } - - seq_reg_write(vga.sequencer.index,data); - recompute_params(); - break; - case 6: - vga.dac.mask=data; - vga.dac.dirty=1; - break; - case 7: - vga.dac.read_index=data; - vga.dac.state=0; - vga.dac.read=1; - break; - case 8: - vga.dac.write_index=data; - vga.dac.state=0; - vga.dac.read=0; - break; - case 9: - if (!vga.dac.read) - { - switch (vga.dac.state++) { - case 0: - vga.dac.color[3*vga.dac.write_index]=data; - break; - case 1: - vga.dac.color[3*vga.dac.write_index + 1]=data; - break; - case 2: - vga.dac.color[3*vga.dac.write_index + 2]=data; - break; - } - vga.dac.dirty=1; - if (vga.dac.state==3) { - vga.dac.state=0; vga.dac.write_index++; - } - } - break; - case 0xe: - vga.gc.index=data; - break; - case 0xf: - gc_reg_write(vga.gc.index,data); - break; - } -} - - - -WRITE8_MEMBER(vga_device::port_03d0_w) -{ - if (LOG_ACCESSES) - logerror("vga_port_03d0_w(): port=0x%04x data=0x%02x\n", offset + 0x3d0, data); - - if (CRTC_PORT_ADDR == 0x3d0) - vga_crtc_w(space, offset, data, mem_mask); -} - -void vga_device::device_reset() -{ - /* clear out the VGA structure */ - memset(vga.pens, 0, sizeof(vga.pens)); - vga.miscellaneous_output = 0; - vga.feature_control = 0; - vga.sequencer.index = 0; - memset(vga.sequencer.data, 0, sizeof(vga.sequencer.data)); - vga.crtc.index = 0; - memset(vga.crtc.data, 0, sizeof(vga.crtc.data)); - vga.gc.index = 0; - memset(vga.gc.latch, 0, sizeof(vga.gc.latch)); - memset(&vga.attribute, 0, sizeof(vga.attribute)); - memset(&vga.dac, 0, sizeof(vga.dac)); - memset(&vga.cursor, 0, sizeof(vga.cursor)); - memset(&vga.oak, 0, sizeof(vga.oak)); - - vga.gc.memory_map_sel = 0x3; /* prevent xtbios excepting vga ram as system ram */ -/* amstrad pc1640 bios relies on the position of - the video memory area, - so I introduced the reset to switch to b8000 area */ - vga.sequencer.data[4] = 0; - - /* TODO: real defaults */ - vga.crtc.line_compare = 0x3ff; - /* indiana.c boot PROM doesn't set this and assumes it's 0xff */ - vga.dac.mask = 0xff; -} +/* + 4 additional dipswitches + seems to have emulation modes at register level + (mda/hgc lines bit 8 not identical to ega/vga) + + standard ega/vga dipswitches + 00000000 320x200 + 00000001 640x200 hanging + 00000010 640x200 hanging + 00000011 640x200 hanging + + 00000100 640x350 hanging + 00000101 640x350 hanging EGA mono + 00000110 320x200 + 00000111 640x200 + + 00001000 640x200 + 00001001 640x200 + 00001010 720x350 partial visible + 00001011 720x350 partial visible + + 00001100 320x200 + 00001101 320x200 + 00001110 320x200 + 00001111 320x200 +*/ +static INPUT_PORTS_START(vga_sense) + PORT_START("VGA_SENSE") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNKNOWN ) +INPUT_PORTS_END -void s3_vga_device::device_reset() +ioport_constructor vga_device::device_input_ports() const { - vga_device::device_reset(); - // Power-on strapping bits. Sampled at reset, but can be modified later. - // These are just assumed defaults. - s3.strapping = 0x000f0b1e; - s3.sr10 = 0x42; - s3.sr11 = 0x41; + return INPUT_PORTS_NAME(vga_sense); } -READ8_MEMBER(vga_device::mem_r) +// TODO: convert to mapped space +uint8_t vga_device::mem_r(offs_t offset) { - /* TODO: check me */ switch(vga.gc.memory_map_sel & 0x03) { case 0: break; @@ -2124,20 +1746,22 @@ READ8_MEMBER(vga_device::mem_r) if (vga.gc.read_mode) { - uint8_t byte,layer; - uint8_t fill_latch; - data=0; + // In Read Mode 1 latch is checked against this + // cfr. lombrall & intsocch where they RMW sprite-like objects + // and anything outside this formula goes transparent. + const u8 target_color = (vga.gc.color_compare & vga.gc.color_dont_care); + data = 0; - for(byte=0;byte<8;byte++) + for(u8 byte = 0; byte < 8; byte++) { - fill_latch = 0; - for(layer=0;layer<4;layer++) + u8 fill_latch = 0; + for(u8 layer = 0; layer < 4; layer++) { if(vga.gc.latch[layer] & 1 << byte) fill_latch |= 1 << layer; } fill_latch &= vga.gc.color_dont_care; - if(fill_latch == vga.gc.color_compare) + if(fill_latch == target_color) data |= 1 << byte; } } @@ -2148,7 +1772,6 @@ READ8_MEMBER(vga_device::mem_r) } else { - // TODO: Guesswork, probably not right uint8_t i,data; data = 0; @@ -2167,7 +1790,7 @@ READ8_MEMBER(vga_device::mem_r) //return 0; } -WRITE8_MEMBER(vga_device::mem_w) +void vga_device::mem_w(offs_t offset, uint8_t data) { //Inside each case must prevent writes to non-mapped VGA memory regions, not only mask the offset. switch(vga.gc.memory_map_sel & 0x03) @@ -2205,3693 +1828,382 @@ WRITE8_MEMBER(vga_device::mem_w) } } -READ8_MEMBER(vga_device::mem_linear_r) +// TODO: is there any non-SVGA capable board capable of linear access? +uint8_t vga_device::mem_linear_r(offs_t offset) { return vga.memory[offset % vga.svga_intf.vram_size]; } -WRITE8_MEMBER(vga_device::mem_linear_w) +void vga_device::mem_linear_w(offs_t offset, uint8_t data) { vga.memory[offset % vga.svga_intf.vram_size] = data; } - -//------------------------------------------------- -// device_add_mconfig - add device configuration -//------------------------------------------------- - -void ati_vga_device::device_add_mconfig(machine_config &config) -{ - MACH8(config, "8514a", 0).set_vga_owner(); - EEPROM_93C46_16BIT(config, "ati_eeprom"); -} - -void s3_vga_device::device_add_mconfig(machine_config &config) -{ - IBM8514A(config, "8514a", 0).set_vga_owner(); -} - -/****************************************** - -Tseng ET4000k implementation - -******************************************/ - -void tseng_vga_device::tseng_define_video_mode() -{ - int divisor; - int xtal = 0; - svga.rgb8_en = 0; - svga.rgb15_en = 0; - svga.rgb16_en = 0; - svga.rgb24_en = 0; - switch(((et4k.aux_ctrl << 1) & 4)|(vga.miscellaneous_output & 0xc)>>2) - { - case 0: - xtal = XTAL(25'174'800).value(); - break; - case 1: - xtal = XTAL(28'636'363).value(); - break; - case 2: - xtal = 16257000*2; //2xEGA clock - break; - case 3: - xtal = XTAL(40'000'000).value(); - break; - case 4: - xtal = XTAL(36'000'000).value(); - break; - case 5: - xtal = XTAL(45'000'000).value(); - break; - case 6: - xtal = 31000000; - break; - case 7: - xtal = 38000000; - break; - } - switch(et4k.dac_ctrl & 0xe0) - { - case 0xa0: - svga.rgb15_en = 1; - divisor = 2; - break; - case 0xe0: - svga.rgb16_en = 1; - divisor = 2; - break; - case 0x60: - svga.rgb24_en = 1; - divisor = 3; - xtal *= 2.0f/3.0f; - break; - default: - svga.rgb8_en = (!(vga.sequencer.data[1] & 8) && (vga.sequencer.data[4] & 8) && vga.gc.shift256 && vga.crtc.div2 && GRAPHIC_MODE); - divisor = 1; - break; - } - recompute_params_clock(divisor, xtal); -} - -uint8_t tseng_vga_device::tseng_crtc_reg_read(uint8_t index) -{ - uint8_t res; - - if(index <= 0x18) - res = crtc_reg_read(index); - else - { - switch(index) - { - case 0x34: - res = et4k.aux_ctrl; - break; - case 0x3f: - res = et4k.horz_overflow; - break; - default: - res = vga.crtc.data[index]; - //printf("%02x\n",index); - break; - } - } - - return res; -} - -void tseng_vga_device::tseng_crtc_reg_write(uint8_t index, uint8_t data) -{ - if(index <= 0x18) - crtc_reg_write(index,data); - else - { - switch(index) - { - case 0x34: - et4k.aux_ctrl = data; - break; - case 0x3f: - et4k.horz_overflow = data; - vga.crtc.horz_total = (vga.crtc.horz_total & 0xff) | ((data & 1) << 8); - break; - default: - //printf("%02x %02x\n",index,data); - break; - } - } -} - -uint8_t tseng_vga_device::tseng_seq_reg_read(uint8_t index) -{ - uint8_t res; - - res = 0xff; - - if(index <= 0x04) - res = vga.sequencer.data[index]; - else - { - switch(index) - { - case 0x06: - case 0x07: - //printf("%02x\n",index); - break; - } - } - - return res; -} - -void tseng_vga_device::tseng_seq_reg_write(uint8_t index, uint8_t data) -{ - if(index <= 0x04) - { - vga.sequencer.data[vga.sequencer.index] = data; - seq_reg_write(vga.sequencer.index,data); - } - else - { - switch(index) - { - case 0x06: - case 0x07: - //printf("%02x %02x\n",index,data); - break; - } - } -} - -READ8_MEMBER(tseng_vga_device::port_03b0_r) +/* VBLANK callback, start address definitely updates AT vblank, not before. */ +TIMER_CALLBACK_MEMBER(vga_device::vblank_timer_cb) { - uint8_t res = 0xff; + vga.crtc.start_addr = latch_start_addr(); + vga.attribute.pel_shift = vga.attribute.pel_shift_latch; - if (CRTC_PORT_ADDR == 0x3b0) + if (vga.crtc.irq_latch == 0 && vga.crtc.irq_disable == 0) { - switch(offset) - { - case 5: - res = tseng_crtc_reg_read(vga.crtc.index); - break; - case 8: - res = et4k.reg_3d8; - break; - default: - res = vga_device::port_03b0_r(space,offset,mem_mask); - break; - } + vga.crtc.irq_latch = 1; + m_vsync_cb(1); } - return res; + m_vblank_timer->adjust( screen().time_until_pos(vga.crtc.vert_blank_start + vga.crtc.vert_blank_end) ); } -WRITE8_MEMBER(tseng_vga_device::port_03b0_w) -{ - if (CRTC_PORT_ADDR == 0x3b0) - { - switch(offset) - { - case 5: - vga.crtc.data[vga.crtc.index] = data; - tseng_crtc_reg_write(vga.crtc.index,data); - break; - case 8: - et4k.reg_3d8 = data; - if(data == 0xa0) - et4k.ext_reg_ena = true; - else if(data == 0x29) - et4k.ext_reg_ena = false; - break; - default: - vga_device::port_03b0_w(space,offset,data,mem_mask); - break; - } - } - tseng_define_video_mode(); -} +// ISA bus bindings -void tseng_vga_device::tseng_attribute_reg_write(uint8_t index, uint8_t data) +void vga_device::enter_setup_mode() { - switch(index) - { - case 0x16: - et4k.misc1 = data; - #if 0 - svga.rgb8_en = 0; - svga.rgb15_en = 0; - svga.rgb16_en = 0; - svga.rgb32_en = 0; - /* TODO: et4k and w32 are different here */ - switch(et4k.misc1 & 0x30) - { - case 0: - // normal power-up mode - break; - case 0x10: - svga.rgb8_en = 1; - break; - case 0x20: - case 0x30: - popmessage("Tseng 15/16 bit HiColor mode, contact MAMEdev"); - break; - } - #endif - break; - case 0x17: et4k.misc2 = data; break; - default: - attribute_reg_write(index,data); - } - + // ... } -READ8_MEMBER(tseng_vga_device::port_03c0_r) +/* + * ---x ---- setup mode (only $102 accessible if this is on) + * ---- x--- Enable $03xx I/O and memory accesses + * ---- -xxx BIOS ROM page select for lowest 4 Kbyte range + * + * The generic ISA sequence is: + * $46e8 0x10 (setup mode) + * $0102 0x01 (wakeup core) + * $46e8 0x0e + * + */ +void vga_device::mode_setup_w(offs_t offset, u8 data) { - uint8_t res; - - switch(offset) + LOG("mode_setup_w %02x\n", data); + if (BIT(data, 4)) { - case 0x01: - switch(vga.attribute.index) - { - case 0x16: res = et4k.misc1; break; - case 0x17: res = et4k.misc2; break; - default: - res = vga_device::port_03c0_r(space,offset,mem_mask); - break; - } - - break; - - case 0x05: - res = tseng_seq_reg_read(vga.sequencer.index); - break; - case 0x0d: - res = svga.bank_w & 0xf; - res |= (svga.bank_r & 0xf) << 4; - break; - case 0x06: - if(et4k.dac_state == 4) - { - if(!et4k.dac_ctrl) - et4k.dac_ctrl = 0x80; - res = et4k.dac_ctrl; - break; - } - et4k.dac_state++; - res = vga_device::port_03c0_r(space,offset,mem_mask); - break; - case 0x08: - et4k.dac_state = 0; - default: - res = vga_device::port_03c0_r(space,offset,mem_mask); - break; + enter_setup_mode(); } - - return res; } -WRITE8_MEMBER(tseng_vga_device::port_03c0_w) -{ - switch(offset) - { - case 0: - if (vga.attribute.state==0) - { - vga.attribute.index=data; - } - else - { - tseng_attribute_reg_write(vga.attribute.index,data); - } - vga.attribute.state=!vga.attribute.state; - break; +/************************************** + * + * SVGA overrides + * + *************************************/ - case 0x05: - tseng_seq_reg_write(vga.sequencer.index,data); - break; - case 0x0d: - svga.bank_w = data & 0xf; - svga.bank_r = (data & 0xf0) >> 4; - break; - case 0x06: - if(et4k.dac_state == 4) - { - et4k.dac_ctrl = data; - break; - } - default: - vga_device::port_03c0_w(space,offset,data,mem_mask); - break; - } - tseng_define_video_mode(); -} - -READ8_MEMBER(tseng_vga_device::port_03d0_r) +svga_device::svga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : vga_device(mconfig, type, tag, owner, clock) { - uint8_t res = 0xff; - - if (CRTC_PORT_ADDR == 0x3d0) - { - switch(offset) - { - case 5: - res = tseng_crtc_reg_read(vga.crtc.index); - break; - case 8: - res = et4k.reg_3d8; - break; - default: - res = vga_device::port_03d0_r(space,offset,mem_mask); - break; - } - } - - return res; } -WRITE8_MEMBER(tseng_vga_device::port_03d0_w) -{ - if (CRTC_PORT_ADDR == 0x3d0) - { - switch(offset) - { - case 5: - vga.crtc.data[vga.crtc.index] = data; - tseng_crtc_reg_write(vga.crtc.index,data); - //if((vga.crtc.index & 0xfe) != 0x0e) - // printf("%02x %02x %d\n",vga.crtc.index,data,screen().vpos()); - break; - case 8: - et4k.reg_3d8 = data; - if(data == 0xa0) - et4k.ext_reg_ena = true; - else if(data == 0x29) - et4k.ext_reg_ena = false; - break; - default: - vga_device::port_03d0_w(space,offset,data,mem_mask); - break; - } - } - tseng_define_video_mode(); -} - -READ8_MEMBER(tseng_vga_device::mem_r) +void svga_device::zero() { - if(svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en) - { - offset &= 0xffff; - return vga.memory[(offset+svga.bank_r*0x10000)]; - } - - return vga_device::mem_r(space,offset,mem_mask); + vga_device::zero(); + memset(&svga, 0, sizeof(svga)); } -WRITE8_MEMBER(tseng_vga_device::mem_w) +void svga_device::device_start() { - if(svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en) - { - offset &= 0xffff; - vga.memory[(offset+svga.bank_w*0x10000)] = data; - } - else - vga_device::mem_w(space,offset,data,mem_mask); -} - -/****************************************** - -S3 implementation - -******************************************/ + vga_device::device_start(); + memset(&svga, 0, sizeof(svga)); -uint16_t s3_vga_device::offset() -{ - //popmessage("Offset: %04x %s %s %s",vga.crtc.offset,vga.crtc.dw?"DW":"--",vga.crtc.word_mode?"BYTE":"WORD",(s3.memory_config & 0x08)?"31":"--"); - if(s3.memory_config & 0x08) - return vga.crtc.offset << 3; - return vga_device::offset(); + save_item(NAME(svga.bank_r)); + save_item(NAME(svga.bank_w)); + save_item(NAME(svga.rgb8_en)); + save_item(NAME(svga.rgb15_en)); + save_item(NAME(svga.rgb16_en)); + save_item(NAME(svga.rgb24_en)); + save_item(NAME(svga.rgb32_en)); + save_item(NAME(svga.id)); } -uint8_t s3_vga_device::s3_crtc_reg_read(uint8_t index) +u16 svga_device::line_compare_mask() { - uint8_t res; - - if(index <= 0x18) - res = crtc_reg_read(index); - else - { - switch(index) - { - case 0x2d: - res = s3.id_high; - break; - case 0x2e: - res = s3.id_low; - break; - case 0x2f: - res = s3.revision; - break; - case 0x30: // CR30 Chip ID/REV register - res = s3.id_cr30; - break; - case 0x31: - res = s3.memory_config; - break; - case 0x35: - res = s3.crt_reg_lock; - break; - case 0x36: // Configuration register 1 - res = s3.strapping & 0x000000ff; // PCI (not really), Fast Page Mode DRAM - break; - case 0x37: // Configuration register 2 - res = (s3.strapping & 0x0000ff00) >> 8; // enable chipset, 64k BIOS size, internal DCLK/MCLK - break; - case 0x38: - res = s3.reg_lock1; - break; - case 0x39: - res = s3.reg_lock2; - break; - case 0x42: // CR42 Mode Control - res = s3.cr42 & 0x0f; // bit 5 set if interlaced, leave it unset for now. - break; - case 0x43: - res = s3.cr43; - break; - case 0x45: - res = s3.cursor_mode; - s3.cursor_fg_ptr = 0; - s3.cursor_bg_ptr = 0; - break; - case 0x46: - res = (s3.cursor_x & 0xff00) >> 8; - break; - case 0x47: - res = s3.cursor_x & 0x00ff; - break; - case 0x48: - res = (s3.cursor_y & 0xff00) >> 8; - break; - case 0x49: - res = s3.cursor_y & 0x00ff; - break; - case 0x4a: - res = s3.cursor_fg[s3.cursor_fg_ptr++]; - s3.cursor_fg_ptr %= 4; - break; - case 0x4b: - res = s3.cursor_bg[s3.cursor_bg_ptr++]; - s3.cursor_bg_ptr %= 4; - break; - case 0x4c: - res = (s3.cursor_start_addr & 0xff00) >> 8; - break; - case 0x4d: - res = s3.cursor_start_addr & 0x00ff; - break; - case 0x4e: - res = s3.cursor_pattern_x; - break; - case 0x4f: - res = s3.cursor_pattern_y; - break; - case 0x51: - res = (vga.crtc.start_addr_latch & 0x0c0000) >> 18; - res |= ((svga.bank_w & 0x30) >> 2); - res |= ((vga.crtc.offset & 0x0300) >> 4); - break; - case 0x53: - res = s3.cr53; - break; - case 0x55: - res = s3.extended_dac_ctrl; - break; - case 0x5c: - // if VGA dot clock is set to 3 (misc reg bits 2-3), then selected dot clock is read, otherwise read VGA clock select - if((vga.miscellaneous_output & 0xc) == 0x0c) - res = s3.cr42 & 0x0f; - else - res = (vga.miscellaneous_output & 0xc) >> 2; - break; - case 0x67: - res = s3.ext_misc_ctrl_2; - break; - case 0x68: // Configuration register 3 - res = (s3.strapping & 0x00ff0000) >> 16; // no /CAS,/OE stretch time, 32-bit data bus size - break; - case 0x69: - res = vga.crtc.start_addr_latch >> 16; - break; - case 0x6a: - res = svga.bank_r & 0x7f; - break; - case 0x6f: // Configuration register 4 (Trio64V+) - res = (s3.strapping & 0xff000000) >> 24; // LPB(?) mode, Serial port I/O at port 0xe8, Serial port I/O disabled (MMIO only), no WE delay - break; - default: - res = vga.crtc.data[index]; - //machine().debug_break(); - //printf("%02x\n",index); - break; - } - } - - return res; + return 0x3ff; } -void s3_vga_device::s3_define_video_mode() +void svga_device::svga_vh_rgb8(bitmap_rgb32 &bitmap, const rectangle &cliprect) { - int divisor = 1; - int xtal = ((vga.miscellaneous_output & 0xc) ? XTAL(28'636'363) : XTAL(25'174'800)).value(); - double freq; - - if((vga.miscellaneous_output & 0xc) == 0x0c) - { - // DCLK calculation - freq = ((double)(s3.clk_pll_m+2) / (double)((s3.clk_pll_n+2)*(pow(2.0,s3.clk_pll_r)))) * 14.318; // clock between XIN and XOUT - xtal = freq * 1000000; - } + int height = vga.crtc.maximum_scan_line * (vga.crtc.scan_doubling + 1); - if((s3.ext_misc_ctrl_2) >> 4) - { - svga.rgb8_en = 0; - svga.rgb15_en = 0; - svga.rgb16_en = 0; - svga.rgb32_en = 0; - switch((s3.ext_misc_ctrl_2) >> 4) - { - case 0x01: svga.rgb8_en = 1; break; - case 0x03: svga.rgb15_en = 1; divisor = 2; break; - case 0x05: svga.rgb16_en = 1; divisor = 2; break; - case 0x0d: svga.rgb32_en = 1; divisor = 1; break; - default: fatalerror("TODO: S3 colour mode not implemented %02x\n",((s3.ext_misc_ctrl_2) >> 4)); - } - } - else - { - svga.rgb8_en = (s3.memory_config & 8) >> 3; - svga.rgb15_en = 0; - svga.rgb16_en = 0; - svga.rgb32_en = 0; - } - recompute_params_clock(divisor, xtal); -} + uint16_t mask_comp = line_compare_mask(); + int curr_addr = 0; +// uint16_t line_length; +// if(vga.crtc.dw) +// line_length = vga.crtc.offset << 3; // doubleword mode +// else +// { +// line_length = vga.crtc.offset << 4; +// } -void s3_vga_device::s3_crtc_reg_write(uint8_t index, uint8_t data) -{ - if(index <= 0x18) - crtc_reg_write(index,data); - else + uint8_t start_shift = (!(vga.sequencer.data[4] & 0x08) || svga.ignore_chain4) ? 2 : 0; + for (int addr = vga.crtc.start_addr << start_shift, line=0; line<LINES; line+=height, addr += offset(), curr_addr+=offset()) { - switch(index) + for (int yi = 0;yi < height; yi++) { - case 0x31: // CR31 Memory Configuration Register - s3.memory_config = data; - vga.crtc.start_addr_latch &= ~0x30000; - vga.crtc.start_addr_latch |= ((data & 0x30) << 12); - s3_define_video_mode(); - break; - case 0x35: - if((s3.reg_lock1 & 0xc) != 8 || ((s3.reg_lock1 & 0xc0) == 0)) // lock register + if((line + yi) < (vga.crtc.line_compare & mask_comp)) + curr_addr = addr; + if((line + yi) == (vga.crtc.line_compare & mask_comp)) + curr_addr = 0; + uint32_t *const bitmapline = &bitmap.pix(line + yi); + addr %= vga.svga_intf.vram_size; + for (int pos=curr_addr, c=0, column=0; column<VGA_COLUMNS; column++, c+=8, pos+=0x8) + { + if(pos + 0x08 >= vga.svga_intf.vram_size) return; - s3.crt_reg_lock = data; - svga.bank_w = data & 0xf; - svga.bank_r = svga.bank_w; - break; - case 0x36: - if(s3.reg_lock2 == 0xa5) - { - s3.strapping = (s3.strapping & 0xffffff00) | data; - logerror("CR36: Strapping data = %08x\n",s3.strapping); - } - break; - case 0x37: - if(s3.reg_lock2 == 0xa5) - { - s3.strapping = (s3.strapping & 0xffff00ff) | (data << 8); - logerror("CR37: Strapping data = %08x\n",s3.strapping); - } - break; - case 0x38: - s3.reg_lock1 = data; - break; - case 0x39: - /* TODO: reg lock mechanism */ - s3.reg_lock2 = data; - break; - case 0x40: - s3.enable_8514 = data & 0x01; // enable 8514/A registers (x2e8, x6e8, xae8, xee8) - break; - case 0x42: - s3.cr42 = data; // bit 5 = interlace, bits 0-3 = dot clock (seems to be undocumented) - break; - case 0x43: - s3.cr43 = data; // bit 2 = bit 8 of offset register, but only if bits 4-5 of CR51 are 00h. - vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((data & 0x04) << 6); - s3_define_video_mode(); - break; -/* -3d4h index 45h (R/W): CR45 Hardware Graphics Cursor Mode -bit 0 HWGC ENB. Hardware Graphics Cursor Enable. Set to enable the - HardWare Cursor in VGA and enhanced modes. - 1 (911/24) Delay Timing for Pattern Data Fetch - 2 (801/5,928) Hardware Cursor Horizontal Stretch 2. If set the cursor - pixels are stretched horizontally to two bytes and items 0 and 1 of - the fore/background stacks in 3d4h index 4Ah/4Bh are used. - 3 (801/5,928) Hardware Cursor Horizontal Stretch 3. If set the cursor - pixels are stretched horizontally to three bytes and items 0,1 and - 2 of the fore/background stacks in 3d4h index 4Ah/4Bh are used. - 2-3 (805i,864/964) HWC-CSEL. Hardware Cursor Color Select. - 0: 4/8bit, 1: 15/16bt, 2: 24bit, 3: 32bit - Note: So far I've had better luck with: 0: 8/15/16bit, 1: 32bit?? - 4 (80x +) Hardware Cursor Right Storage. If set the cursor data is - stored in the last 256 bytes of 4 1Kyte lines (4bits/pixel) or the - last 512 bytes of 2 2Kbyte lines (8bits/pixel). Intended for - 1280x1024 modes where there are no free lines at the bottom. - 5 (928) Cursor Control Enable for Brooktree Bt485 DAC. If set and 3d4h - index 55h bit 5 is set the HC1 output becomes the ODF and the HC0 - output becomes the CDE - (964) BT485 ODF Selection for Bt485A RAMDAC. If set pin 185 (RS3 - /ODF) is the ODF output to a Bt485A compatible RamDAC (low for even - fields and high for odd fields), if clear pin185 is the RS3 output. - */ - case 0x45: - s3.cursor_mode = data; - break; -/* -3d4h index 46h M(R/W): CR46/7 Hardware Graphics Cursor Origin-X -bit 0-10 The HardWare Cursor X position. For 64k modes this value should be - twice the actual X co-ordinate. - */ - case 0x46: - s3.cursor_x = (s3.cursor_x & 0x00ff) | (data << 8); - break; - case 0x47: - s3.cursor_x = (s3.cursor_x & 0xff00) | data; - break; -/* -3d4h index 48h M(R/W): CR48/9 Hardware Graphics Cursor Origin-Y -bit 0-9 (911/24) The HardWare Cursor Y position. - 0-10 (80x +) The HardWare Cursor Y position. -Note: The position is activated when the high byte of the Y coordinate (index - 48h) is written, so this byte should be written last (not 911/924 ?) - */ - case 0x48: - s3.cursor_y = (s3.cursor_y & 0x00ff) | (data << 8); - break; - case 0x49: - s3.cursor_y = (s3.cursor_y & 0xff00) | data; - break; -/* -3d4h index 4Ah (R/W): Hardware Graphics Cursor Foreground Stack (80x +) -bit 0-7 The Foreground Cursor color. Three bytes (4 for the 864/964) are - stacked here. When the Cursor Mode register (3d4h index 45h) is read - the stackpointer is reset. When a byte is written the byte is - written into the current top of stack and the stackpointer is - increased. The first byte written (item 0) is allways used, the - other two(3) only when Hardware Cursor Horizontal Stretch (3d4h - index 45h bit 2-3) is enabled. - */ - case 0x4a: - s3.cursor_fg[s3.cursor_fg_ptr++] = data; - s3.cursor_fg_ptr %= 4; - break; -/* -3d4h index 4Bh (R/W): Hardware Graphics Cursor Background Stack (80x +) -bit 0-7 The Background Cursor color. Three bytes (4 for the 864/964) are - stacked here. When the Cursor Mode register (3d4h index 45h) is read - the stackpointer is reset. When a byte is written the byte is - written into the current top of stack and the stackpointer is - increased. The first byte written (item 0) is allways used, the - other two(3) only when Hardware Cursor Horizontal Stretch (3d4h - index 45h bit 2-3) is enabled. - */ - case 0x4b: - s3.cursor_bg[s3.cursor_bg_ptr++] = data; - s3.cursor_bg_ptr %= 4; - break; -/* -3d4h index 4Ch M(R/W): CR4C/D Hardware Graphics Cursor Storage Start Address -bit 0-9 (911,924) HCS_STADR. Hardware Graphics Cursor Storage Start Address - 0-11 (80x,928) HWGC_STA. Hardware Graphics Cursor Storage Start Address - 0-12 (864,964) HWGC_STA. Hardware Graphics Cursor Storage Start Address - Address of the HardWare Cursor Map in units of 1024 bytes (256 bytes - for planar modes). The cursor map is a 64x64 bitmap with 2 bits (A - and B) per pixel. The map is stored as one word (16 bits) of bit A, - followed by one word with the corresponding 16 B bits. - The bits are interpreted as: - A B MS-Windows: X-11: - 0 0 Background Screen data - 0 1 Foreground Screen data - 1 0 Screen data Background - 1 1 Inverted screen Foreground - The Windows/X11 switch is only available for the 80x +. - (911/24) For 64k color modes the cursor is stored as one byte (8 - bits) of A bits, followed by the 8 B-bits, and each bit in the - cursor should be doubled to provide a consistent cursor image. - (801/5,928) For Hi/True color modes use the Horizontal Stretch bits - (3d4h index 45h bits 2 and 3). - */ - case 0x4c: - s3.cursor_start_addr = (s3.cursor_start_addr & 0x00ff) | (data << 8); - popmessage("HW Cursor Data Address %04x\n",s3.cursor_start_addr); - break; - case 0x4d: - s3.cursor_start_addr = (s3.cursor_start_addr & 0xff00) | data; - popmessage("HW Cursor Data Address %04x\n",s3.cursor_start_addr); - break; -/* -3d4h index 4Eh (R/W): CR4E HGC Pattern Disp Start X-Pixel Position -bit 0-5 Pattern Display Start X-Pixel Position. - */ - case 0x4e: - s3.cursor_pattern_x = data; - break; -/* -3d4h index 4Fh (R/W): CR4F HGC Pattern Disp Start Y-Pixel Position -bit 0-5 Pattern Display Start Y-Pixel Position. - */ - case 0x4f: - s3.cursor_pattern_y = data; - break; - case 0x51: - vga.crtc.start_addr_latch &= ~0xc0000; - vga.crtc.start_addr_latch |= ((data & 0x3) << 18); - svga.bank_w = (svga.bank_w & 0xcf) | ((data & 0x0c) << 2); - svga.bank_r = svga.bank_w; - if((data & 0x30) != 0x00) - vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((data & 0x30) << 4); - else - vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((s3.cr43 & 0x04) << 6); - s3_define_video_mode(); - break; - case 0x53: - s3.cr53 = data; - break; -/* -3d4h index 55h (R/W): Extended Video DAC Control Register (80x +) -bit 0-1 DAC Register Select Bits. Passed to the RS2 and RS3 pins on the - RAMDAC, allowing access to all 8 or 16 registers on advanced RAMDACs. - If this field is 0, 3d4h index 43h bit 1 is active. - 2 Enable General Input Port Read. If set DAC reads are disabled and the - STRD strobe for reading the General Input Port is enabled for reading - while DACRD is active, if clear DAC reads are enabled. - 3 (928) Enable External SID Operation if set. If set video data is - passed directly from the VRAMs to the DAC rather than through the - VGA chip - 4 Hardware Cursor MS/X11 Mode. If set the Hardware Cursor is in X11 - mode, if clear in MS-Windows mode - 5 (80x,928) Hardware Cursor External Operation Mode. If set the two - bits of cursor data ,is output on the HC[0-1] pins for the video DAC - The SENS pin becomes HC1 and the MID2 pin becomes HC0. - 6 ?? - 7 (80x,928) Disable PA Output. If set PA[0-7] and VCLK are tristated. - (864/964) TOFF VCLK. Tri-State Off VCLK Output. VCLK output tri - -stated if set - */ - case 0x55: - s3.extended_dac_ctrl = data; - break; -/* -3d4h index 5Dh (R/W): Extended Horizontal Overflow Register (80x +) -bit 0 Horizontal Total bit 8. Bit 8 of the Horizontal Total register (3d4h - index 0) - 1 Horizontal Display End bit 8. Bit 8 of the Horizontal Display End - register (3d4h index 1) - 2 Start Horizontal Blank bit 8. Bit 8 of the Horizontal Start Blanking - register (3d4h index 2). - 3 (864,964) EHB+64. End Horizontal Blank +64. If set the /BLANK pulse - is extended by 64 DCLKs. Note: Is this bit 6 of 3d4h index 3 or - does it really extend by 64 ? - 4 Start Horizontal Sync Position bit 8. Bit 8 of the Horizontal Start - Retrace register (3d4h index 4). - 5 (864,964) EHS+32. End Horizontal Sync +32. If set the HSYNC pulse - is extended by 32 DCLKs. Note: Is this bit 5 of 3d4h index 5 or - does it really extend by 32 ? - 6 (928,964) Data Transfer Position bit 8. Bit 8 of the Data Transfer - Position register (3d4h index 3Bh) - 7 (928,964) Bus-Grant Terminate Position bit 8. Bit 8 of the Bus Grant - Termination register (3d4h index 5Fh). -*/ - case 0x5d: - vga.crtc.horz_total = (vga.crtc.horz_total & 0xfeff) | ((data & 0x01) << 8); - vga.crtc.horz_disp_end = (vga.crtc.horz_disp_end & 0xfeff) | ((data & 0x02) << 7); - vga.crtc.horz_blank_start = (vga.crtc.horz_blank_start & 0xfeff) | ((data & 0x04) << 6); - vga.crtc.horz_blank_end = (vga.crtc.horz_blank_end & 0xffbf) | ((data & 0x08) << 3); - vga.crtc.horz_retrace_start = (vga.crtc.horz_retrace_start & 0xfeff) | ((data & 0x10) << 4); - vga.crtc.horz_retrace_end = (vga.crtc.horz_retrace_end & 0xffdf) | (data & 0x20); - s3_define_video_mode(); - break; -/* -3d4h index 5Eh (R/W): Extended Vertical Overflow Register (80x +) -bit 0 Vertical Total bit 10. Bit 10 of the Vertical Total register (3d4h - index 6). Bits 8 and 9 are in 3d4h index 7 bit 0 and 5. - 1 Vertical Display End bit 10. Bit 10 of the Vertical Display End - register (3d4h index 12h). Bits 8 and 9 are in 3d4h index 7 bit 1 - and 6 - 2 Start Vertical Blank bit 10. Bit 10 of the Vertical Start Blanking - register (3d4h index 15h). Bit 8 is in 3d4h index 7 bit 3 and bit 9 - in 3d4h index 9 bit 5 - 4 Vertical Retrace Start bit 10. Bit 10 of the Vertical Start Retrace - register (3d4h index 10h). Bits 8 and 9 are in 3d4h index 7 bit 2 - and 7. - 6 Line Compare Position bit 10. Bit 10 of the Line Compare register - (3d4h index 18h). Bit 8 is in 3d4h index 7 bit 4 and bit 9 in 3d4h - index 9 bit 6. - */ - case 0x5e: - vga.crtc.vert_total = (vga.crtc.vert_total & 0xfbff) | ((data & 0x01) << 10); - vga.crtc.vert_disp_end = (vga.crtc.vert_disp_end & 0xfbff) | ((data & 0x02) << 9); - vga.crtc.vert_blank_start = (vga.crtc.vert_blank_start & 0xfbff) | ((data & 0x04) << 8); - vga.crtc.vert_retrace_start = (vga.crtc.vert_retrace_start & 0xfbff) | ((data & 0x10) << 6); - vga.crtc.line_compare = (vga.crtc.line_compare & 0xfbff) | ((data & 0x40) << 4); - s3_define_video_mode(); - break; - case 0x67: - s3.ext_misc_ctrl_2 = data; - s3_define_video_mode(); - break; - case 0x68: - if(s3.reg_lock2 == 0xa5) - { - s3.strapping = (s3.strapping & 0xff00ffff) | (data << 16); - logerror("CR68: Strapping data = %08x\n",s3.strapping); - } - break; - case 0x69: - vga.crtc.start_addr_latch &= ~0x1f0000; - vga.crtc.start_addr_latch |= ((data & 0x1f) << 16); - s3_define_video_mode(); - break; - case 0x6a: - svga.bank_w = data & 0x3f; - svga.bank_r = svga.bank_w; - break; - case 0x6f: - if(s3.reg_lock2 == 0xa5) + for (int xi=0;xi<8;xi++) { - s3.strapping = (s3.strapping & 0x00ffffff) | (data << 24); - logerror("CR6F: Strapping data = %08x\n",s3.strapping); + if(!screen().visible_area().contains(c+xi, line + yi)) + continue; + bitmapline[c+xi] = pen(vga.memory[(pos+(xi))]); } - break; - default: - if(LOG_8514) logerror("S3: 3D4 index %02x write %02x\n",index,data); - break; - } - } -} - -uint8_t s3_vga_device::s3_seq_reg_read(uint8_t index) -{ - uint8_t res = 0xff; - - if(index <= 0x0c) - res = vga.sequencer.data[index]; - else - { - switch(index) - { - case 0x10: - res = s3.sr10; - break; - case 0x11: - res = s3.sr11; - break; - case 0x12: - res = s3.sr12; - break; - case 0x13: - res = s3.sr13; - break; - case 0x15: - res = s3.sr15; - break; - case 0x17: - res = s3.sr17; // CLKSYN test register - s3.sr17--; // who knows what it should return, docs only say it defaults to 0, and is reserved for testing of the clock synthesiser - break; - } - } - - return res; -} - -void s3_vga_device::s3_seq_reg_write(uint8_t index, uint8_t data) -{ - if(index <= 0x0c) - { - vga.sequencer.data[vga.sequencer.index] = data; - seq_reg_write(vga.sequencer.index,data); - } - else - { - switch(index) - { - // Memory CLK PLL - case 0x10: - s3.sr10 = data; - break; - case 0x11: - s3.sr11 = data; - break; - // Video CLK PLL - case 0x12: - s3.sr12 = data; - break; - case 0x13: - s3.sr13 = data; - break; - case 0x15: - if(data & 0x02) // load DCLK frequency (would normally have a small variable delay) - { - s3.clk_pll_n = s3.sr12 & 0x1f; - s3.clk_pll_r = (s3.sr12 & 0x60) >> 5; - s3.clk_pll_m = s3.sr13 & 0x7f; - s3_define_video_mode(); - } - if(data & 0x20) // immediate DCLK/MCLK load - { - s3.clk_pll_n = s3.sr12 & 0x1f; - s3.clk_pll_r = (s3.sr12 & 0x60) >> 5; - s3.clk_pll_m = s3.sr13 & 0x7f; - s3_define_video_mode(); } - s3.sr15 = data; } } } - - -READ8_MEMBER(s3_vga_device::port_03b0_r) -{ - uint8_t res = 0xff; - - if (CRTC_PORT_ADDR == 0x3b0) - { - switch(offset) - { - case 5: - res = s3_crtc_reg_read(vga.crtc.index); - break; - default: - res = vga_device::port_03b0_r(space,offset,mem_mask); - break; - } - } - - return res; -} - -WRITE8_MEMBER(s3_vga_device::port_03b0_w) -{ - if (CRTC_PORT_ADDR == 0x3b0) - { - switch(offset) - { - case 5: - vga.crtc.data[vga.crtc.index] = data; - s3_crtc_reg_write(vga.crtc.index,data); - break; - default: - vga_device::port_03b0_w(space,offset,data,mem_mask); - break; - } - } -} - -READ8_MEMBER(s3_vga_device::port_03c0_r) -{ - uint8_t res; - - switch(offset) - { - case 5: - res = s3_seq_reg_read(vga.sequencer.index); - break; - default: - res = vga_device::port_03c0_r(space,offset,mem_mask); - break; - } - - return res; -} - -WRITE8_MEMBER(s3_vga_device::port_03c0_w) -{ - switch(offset) - { - case 5: - s3_seq_reg_write(vga.sequencer.index,data); - break; - default: - vga_device::port_03c0_w(space,offset,data,mem_mask); - break; - } -} - -READ8_MEMBER(s3_vga_device::port_03d0_r) +void svga_device::svga_vh_rgb15(bitmap_rgb32 &bitmap, const rectangle &cliprect) { - uint8_t res = 0xff; - - if (CRTC_PORT_ADDR == 0x3d0) - { - switch(offset) - { - case 5: - res = s3_crtc_reg_read(vga.crtc.index); - break; - default: - res = vga_device::port_03d0_r(space,offset,mem_mask); - break; - } - } - - return res; -} + #define MV(x) (vga.memory[x]+(vga.memory[x+1]<<8)) + constexpr uint32_t IV = 0xff000000; + int height = vga.crtc.maximum_scan_line * (vga.crtc.scan_doubling + 1); -WRITE8_MEMBER(s3_vga_device::port_03d0_w) -{ - if (CRTC_PORT_ADDR == 0x3d0) + /* line compare is screen sensitive */ +// uint16_t mask_comp = 0xff | (TLINES & 0x300); + int curr_addr = 0; + int yi=0; + for (int addr = vga.crtc.start_addr << 2, line=0; line<TLINES; line+=height, addr+=offset(), curr_addr+=offset()) { - switch(offset) + uint32_t *const bitmapline = &bitmap.pix(line); + addr %= vga.svga_intf.vram_size; + for (int pos=addr, c=0, column=0; column<TGA_COLUMNS; column++, c+=8, pos+=0x10) { - case 5: - vga.crtc.data[vga.crtc.index] = data; - s3_crtc_reg_write(vga.crtc.index,data); - break; - default: - vga_device::port_03d0_w(space,offset,data,mem_mask); - break; - } - } -} - -READ8_MEMBER(ati_vga_device::port_03c0_r) -{ - uint8_t data = 0xff; - - switch(offset) - { - case 1: - if ((vga.attribute.index&0x1f) < sizeof(vga.attribute.data)) - data = vga.attribute.data[vga.attribute.index&0x1f]; - break; - default: - data = vga_device::port_03c0_r(space,offset,mem_mask); - break; - } - return data; -} - - -/* accelerated ports, TBD ... */ - -void ibm8514a_device::ibm8514_write_fg(uint32_t offset) -{ - address_space &space = machine().dummy_space(); - offset %= m_vga->vga.svga_intf.vram_size; - uint8_t dst = m_vga->mem_linear_r(space,offset,0xff); - uint8_t src = 0; - - // check clipping rectangle - if((ibm8514.current_cmd & 0xe000) == 0xc000) // BitBLT writes to the destination X/Y, so check that instead - { - if(ibm8514.dest_x < ibm8514.scissors_left || ibm8514.dest_x > ibm8514.scissors_right || ibm8514.dest_y < ibm8514.scissors_top || ibm8514.dest_y > ibm8514.scissors_bottom) - return; // do nothing - } - else - if(ibm8514.curr_x < ibm8514.scissors_left || ibm8514.curr_x > ibm8514.scissors_right || ibm8514.curr_y < ibm8514.scissors_top || ibm8514.curr_y > ibm8514.scissors_bottom) - return; // do nothing - - // determine source - switch(ibm8514.fgmix & 0x0060) - { - case 0x0000: - src = ibm8514.bgcolour; - break; - case 0x0020: - src = ibm8514.fgcolour; - break; - case 0x0040: - src = ibm8514.pixel_xfer; - break; - case 0x0060: - // video memory - presume the memory is sourced from the current X/Y co-ords - src = m_vga->mem_linear_r(space,((ibm8514.curr_y * IBM8514_LINE_LENGTH) + ibm8514.curr_x),0xff); - break; - } - - // write the data - switch(ibm8514.fgmix & 0x000f) - { - case 0x0000: - m_vga->mem_linear_w(space,offset,~dst,0xff); - break; - case 0x0001: - m_vga->mem_linear_w(space,offset,0x00,0xff); - break; - case 0x0002: - m_vga->mem_linear_w(space,offset,0xff,0xff); - break; - case 0x0003: - m_vga->mem_linear_w(space,offset,dst,0xff); - break; - case 0x0004: - m_vga->mem_linear_w(space,offset,~src,0xff); - break; - case 0x0005: - m_vga->mem_linear_w(space,offset,src ^ dst,0xff); - break; - case 0x0006: - m_vga->mem_linear_w(space,offset,~(src ^ dst),0xff); - break; - case 0x0007: - m_vga->mem_linear_w(space,offset,src,0xff); - break; - case 0x0008: - m_vga->mem_linear_w(space,offset,~(src & dst),0xff); - break; - case 0x0009: - m_vga->mem_linear_w(space,offset,(~src) | dst,0xff); - break; - case 0x000a: - m_vga->mem_linear_w(space,offset,src | (~dst),0xff); - break; - case 0x000b: - m_vga->mem_linear_w(space,offset,src | dst,0xff); - break; - case 0x000c: - m_vga->mem_linear_w(space,offset,src & dst,0xff); - break; - case 0x000d: - m_vga->mem_linear_w(space,offset,src & (~dst),0xff); - break; - case 0x000e: - m_vga->mem_linear_w(space,offset,(~src) & dst,0xff); - break; - case 0x000f: - m_vga->mem_linear_w(space,offset,~(src | dst),0xff); - break; - } -} - -void ibm8514a_device::ibm8514_write_bg(uint32_t offset) -{ - address_space &space = machine().dummy_space(); - offset %= m_vga->vga.svga_intf.vram_size; - uint8_t dst = m_vga->mem_linear_r(space,offset,0xff); - uint8_t src = 0; - - // check clipping rectangle - if((ibm8514.current_cmd & 0xe000) == 0xc000) // BitBLT writes to the destination X/Y, so check that instead - { - if(ibm8514.dest_x < ibm8514.scissors_left || ibm8514.dest_x > ibm8514.scissors_right || ibm8514.dest_y < ibm8514.scissors_top || ibm8514.dest_y > ibm8514.scissors_bottom) - return; // do nothing - } - else - if(ibm8514.curr_x < ibm8514.scissors_left || ibm8514.curr_x > ibm8514.scissors_right || ibm8514.curr_y < ibm8514.scissors_top || ibm8514.curr_y > ibm8514.scissors_bottom) - return; // do nothing - - // determine source - switch(ibm8514.bgmix & 0x0060) - { - case 0x0000: - src = ibm8514.bgcolour; - break; - case 0x0020: - src = ibm8514.fgcolour; - break; - case 0x0040: - src = ibm8514.pixel_xfer; - break; - case 0x0060: - // video memory - presume the memory is sourced from the current X/Y co-ords - src = m_vga->mem_linear_r(space,((ibm8514.curr_y * IBM8514_LINE_LENGTH) + ibm8514.curr_x),0xff); - break; - } - - // write the data - switch(ibm8514.bgmix & 0x000f) - { - case 0x0000: - m_vga->mem_linear_w(space,offset,~dst,0xff); - break; - case 0x0001: - m_vga->mem_linear_w(space,offset,0x00,0xff); - break; - case 0x0002: - m_vga->mem_linear_w(space,offset,0xff,0xff); - break; - case 0x0003: - m_vga->mem_linear_w(space,offset,dst,0xff); - break; - case 0x0004: - m_vga->mem_linear_w(space,offset,~src,0xff); - break; - case 0x0005: - m_vga->mem_linear_w(space,offset,src ^ dst,0xff); - break; - case 0x0006: - m_vga->mem_linear_w(space,offset,~(src ^ dst),0xff); - break; - case 0x0007: - m_vga->mem_linear_w(space,offset,src,0xff); - break; - case 0x0008: - m_vga->mem_linear_w(space,offset,~(src & dst),0xff); - break; - case 0x0009: - m_vga->mem_linear_w(space,offset,(~src) | dst,0xff); - break; - case 0x000a: - m_vga->mem_linear_w(space,offset,src | (~dst),0xff); - break; - case 0x000b: - m_vga->mem_linear_w(space,offset,src | dst,0xff); - break; - case 0x000c: - m_vga->mem_linear_w(space,offset,src & dst,0xff); - break; - case 0x000d: - m_vga->mem_linear_w(space,offset,src & (~dst),0xff); - break; - case 0x000e: - m_vga->mem_linear_w(space,offset,(~src) & dst,0xff); - break; - case 0x000f: - m_vga->mem_linear_w(space,offset,~(src | dst),0xff); - break; - } -} - -void ibm8514a_device::ibm8514_write(uint32_t offset, uint32_t src) -{ - int data_size = 8; - uint32_t xfer; + if(pos + 0x10 >= vga.svga_intf.vram_size) + return; + for(int xi=0,xm=0;xi<8;xi++,xm+=2) + { + if(!screen().visible_area().contains(c+xi, line + yi)) + continue; - switch(ibm8514.pixel_control & 0x00c0) - { - case 0x0000: // Foreground Mix only - ibm8514_write_fg(offset); - break; - case 0x0040: // fixed pattern (?) - // TODO - break; - case 0x0080: // use pixel transfer register - if(ibm8514.bus_size == 0) // 8-bit - data_size = 8; - if(ibm8514.bus_size == 1) // 16-bit - data_size = 16; - if(ibm8514.bus_size == 2) // 32-bit - data_size = 32; - if((ibm8514.current_cmd & 0x1000) && (data_size != 8)) - { - xfer = ((ibm8514.pixel_xfer & 0x000000ff) << 8) | ((ibm8514.pixel_xfer & 0x0000ff00) >> 8) - | ((ibm8514.pixel_xfer & 0x00ff0000) << 8) | ((ibm8514.pixel_xfer & 0xff000000) >> 8); - } - else - xfer = ibm8514.pixel_xfer; - if(ibm8514.current_cmd & 0x0002) - { - if((xfer & ((1<<(data_size-1))>>ibm8514.src_x)) != 0) - ibm8514_write_fg(offset); - else - ibm8514_write_bg(offset); - } - else - { - ibm8514_write_fg(offset); + int r = (MV(pos+xm)&0x7c00)>>10; + int g = (MV(pos+xm)&0x03e0)>>5; + int b = (MV(pos+xm)&0x001f)>>0; + r = (r << 3) | (r & 0x7); + g = (g << 3) | (g & 0x7); + b = (b << 3) | (b & 0x7); + bitmapline[c+xi] = IV|(r<<16)|(g<<8)|(b<<0); + } } - ibm8514.src_x++; - if(ibm8514.src_x >= data_size) - ibm8514.src_x = 0; - break; - case 0x00c0: // use source plane - if (m_vga->mem_linear_r(machine().dummy_space(), src, 0xff) != 0x00) - ibm8514_write_fg(offset); - else - ibm8514_write_bg(offset); - break; } } -/* -92E8h W(R/W): Line Error Term Read/Write Register (ERR_TERM). -bit 0-12 (911/924) LINE PARAMETER/ERROR TERM. For Line Drawing this is the - Bresenham Initial Error Term 2*dminor-dmajor (one less if the - starting X is less than the ending X) in two's complement format. - (dminor is the length of the line projected onto the minor or - dependent axis, dmajor is the length of the line projected onto - the major or independent axis). - 0-13 (80x +) LINE PARAMETER/ERROR TERM. See above. - */ -READ16_MEMBER(ibm8514a_device::ibm8514_line_error_r) -{ - return ibm8514.line_errorterm; -} - -WRITE16_MEMBER(ibm8514a_device::ibm8514_line_error_w) -{ - ibm8514.line_errorterm = data; - if(LOG_8514) logerror("8514/A: Line Parameter/Error Term write %04x\n",data); -} - -/* - 9AE8h W(R): Graphics Processor Status Register (GP_STAT) -bit 0-7 Queue State. - 00h = 8 words available - queue is empty - 01h = 7 words available - 03h = 6 words available - 07h = 5 words available - 0Fh = 4 words available - 1Fh = 3 words available - 3Fh = 2 words available - 7Fh = 1 word available - FFh = 0 words available - queue is full - 8 (911-928) DTA AVA. Read Data Available. If set data is ready to be - read from the PIX_TRANS register (E2E8h). - 9 HDW BSY. Hardware Graphics Processor Busy - If set the Graphics Processor is busy. - 10 (928 +) AE. All FIFO Slots Empty. If set all FIFO slots are empty. - 11-15 (864/964) (R) Queue State bits 8-12. 1Fh if 8 words or less - available, Fh for 9 words, 7 for 10 words, 3 for 11 words, 1 for - 12 words and 0 for 13 words available. - */ -READ16_MEMBER(ibm8514a_device::ibm8514_gpstatus_r) -{ - uint16_t ret = 0x0000; - - //if(LOG_8514) logerror("S3: 9AE8 read\n"); - if(ibm8514.gpbusy == true) - ret |= 0x0200; - if(ibm8514.data_avail == true) - ret |= 0x0100; - return ret; -} - -void ibm8514a_device::ibm8514_draw_vector(uint8_t len, uint8_t dir, bool draw) +void svga_device::svga_vh_rgb16(bitmap_rgb32 &bitmap, const rectangle &cliprect) { - uint32_t offset; - int x = 0; - - while(x <= len) - { - offset = (ibm8514.curr_y * IBM8514_LINE_LENGTH) + ibm8514.curr_x; - if(draw) - ibm8514_write(offset,offset); - switch(dir) - { - case 0: // 0 degrees - ibm8514.curr_x++; - break; - case 1: // 45 degrees - ibm8514.curr_x++; - ibm8514.curr_y--; - break; - case 2: // 90 degrees - ibm8514.curr_y--; - break; - case 3: // 135 degrees - ibm8514.curr_y--; - ibm8514.curr_x--; - break; - case 4: // 180 degrees - ibm8514.curr_x--; - break; - case 5: // 225 degrees - ibm8514.curr_x--; - ibm8514.curr_y++; - break; - case 6: // 270 degrees - ibm8514.curr_y++; - break; - case 7: // 315 degrees - ibm8514.curr_y++; - ibm8514.curr_x++; - break; - } - x++; - } -} + #define MV(x) (vga.memory[x]+(vga.memory[x+1]<<8)) + constexpr uint32_t IV = 0xff000000; + int height = vga.crtc.maximum_scan_line * (vga.crtc.scan_doubling + 1); -/* -9AE8h W(W): Drawing Command Register (CMD) -bit 0 (911-928) ~RD/WT. Read/Write Data. If set VRAM write operations are - enabled. If clear operations execute normally but writes are - disabled. - 1 PX MD. Pixel Mode. Defines the orientation of the display bitmap. - 0 = Through plane mode (Single pixel transferred at a time) - 1 = Across plane mode (Multiple pixels transferred at a time). - 2 LAST PXOF. Last Pixel Off. If set the last pixel of a line command - (CMD_LINE, SSV or LINEAF) is not drawn. This is used for mixes such - as XOR where drawing the same pixel twice would give the wrong - color. - 3 DIR TYP. Direction Type. - 0: Bresenham line drawing (X-Y Axial) - CMD_LINE draws a line using the Bresenham algorithm as - specified in the DESTY_AXSTP (8AE8h), DESTX_DIASTP (8EE8h), - ERR_TERM (92E8h) and MAJ_AXIS_PCNT (96E8h) registers - INC_X, INC_Y and YMAJAXIS determines the direction. - 1: Vector line draws (Radial). - CMD_NOP allows drawing of Short Stroke Vectors (SSVs) by - writing to the Short Stroke register (9EE8h). - CMD_LINE draws a vector of length MAJ_AXIS_PCNT (96E8h) - in the direction specified by LINEDIR (bits 5-7). - DRWG-DIR determines the direction of the line. - 4 DRAW YES. If clear the current position is moved, but no pixels - are modified. This bit should be set when attempting read or - write of bitmap data. - 5-7 DRWG-DIR. Drawing Direction. When a line draw command (CMD_LINE) - with DIR TYP=1 (Radial) is issued, these bits define the direction - of the line counter clockwise relative to the positive X-axis. - 0 = 000 degrees - 1 = 045 degrees - 2 = 090 degrees - 3 = 135 degrees - 4 = 180 degrees - 5 = 225 degrees - 6 = 270 degrees - 7 = 315 degrees - 5 INC_X. This bit together with INC_Y determines which quadrant - the slope of a line lies within. They also determine the - orientation of rectangle draw commands. - If set lines are drawn in the positive X direction (left to right). - 6 YMAJAXIS. For Bresenham line drawing commands this bit determines - which axis is the independent or major axis. INC_X and INC_Y - determines which quadrant the slope falls within. This bit further - defines the slope to within an octant. - If set Y is the major (independent) axis. - 7 INC_Y. This bit together with INC_X determines which quadrant - the slope of a line lies within. They also determine the - orientation of rectangle draw commands. - If set lines are drawn in the positive Y direction (down). - 8 WAIT YES. If set the drawing engine waits for read/write of the - PIX_TRANS register (E2E8h) for each pixel during a draw operation. - 9 (911-928) BUS SIZE. If set the PIX_TRANS register (E2E8h) is - processed internally as two bytes in the order specified by BYTE - SWAP. If clear all accesses to E2E8h are 8bit. - 9-10 (864,964) BUS SIZE. Select System Bus Size. Controls the width of - the Pixel Data Transfer registers (E2E8h,E2EAh) and the memory - mapped I/O. 0: 8bit, 1: 16bit, 2: 32bit - 12 BYTE SWAP. Affects both reads and writes of SHORT_STROKE (9EE8h) - and PIX_TRANS (E2E8h) when 16bit=1. - If set take low byte first, if clear take high byte first. - 13-15 Draw Command: - 0 = NOP. Used for Short Stroke Vectors. - 1 = Draw Line. If bit 3 is set the line is drawn to the angle in - bits 5-7 and the length in the Major Axis Pixel Count register - (96E8h), if clear the line is drawn from the Bresenham - constants in the Axial Step Constant register(8AE8h), Diagonal - Step Constant register (8EE8h), Line Error Term register - (92E8h) and bits 5-7 of this register. - 2 = Rectangle Fill. The Current X (86E8h) and Y (82E8h) - registers holds the coordinates of the rectangle to fill and - the Major Axis Pixel Count register (96E8h) holds the - horizontal width (in pixels) fill and the Minor Axis Pixel - Count register (BEE8h index 0) holds the height of the - rectangle. - 6 = BitBLT. Copies the source rectangle specified by the Current X - (86E8h) and Y (8AE8h) registers to the destination rectangle, - specified as for the Rectangle Fills. - 7 = (80x +) Pattern Fill. The source rectangle is an 8x8 pattern - rectangle, which is copied repeatably to the destination - rectangle. - */ -WRITE16_MEMBER(ibm8514a_device::ibm8514_cmd_w) -{ - int x,y; - int pattern_x,pattern_y; - uint32_t off,src; - uint8_t readmask; - - ibm8514.current_cmd = data; - ibm8514.src_x = 0; - ibm8514.src_y = 0; - ibm8514.bus_size = (data & 0x0600) >> 9; - switch(data & 0xe000) + /* line compare is screen sensitive */ +// uint16_t mask_comp = 0xff | (TLINES & 0x300); + int curr_addr = 0; + int yi=0; + for (int addr = vga.crtc.start_addr << 2, line=0; line<TLINES; line+=height, addr+=offset(), curr_addr+=offset()) { - case 0x0000: // NOP (for "Short Stroke Vectors") - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - if(LOG_8514) logerror("8514/A: Command (%04x) - NOP (Short Stroke Vector)\n",ibm8514.current_cmd); - break; - case 0x2000: // Line - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - if(data & 0x0008) - { - if(data & 0x0100) - { - ibm8514.state = IBM8514_DRAWING_LINE; - ibm8514.data_avail = true; - if(LOG_8514) logerror("8514/A: Command (%04x) - Vector Line (WAIT) %i,%i \n",ibm8514.current_cmd,ibm8514.curr_x,ibm8514.curr_y); - } - else - { - ibm8514_draw_vector(ibm8514.rect_width,(data & 0x00e0) >> 5,(data & 0010) ? true : false); - if(LOG_8514) logerror("8514/A: Command (%04x) - Vector Line - %i,%i \n",ibm8514.current_cmd,ibm8514.curr_x,ibm8514.curr_y); - } - } - else - { - // Not perfect, but will do for now. - int16_t dx = ibm8514.rect_width; - int16_t dy = ibm8514.line_axial_step >> 1; - int16_t err = ibm8514.line_errorterm; - int sx = (data & 0x0020) ? 1 : -1; - int sy = (data & 0x0080) ? 1 : -1; - int count = 0; - int16_t temp; - - if(LOG_8514) logerror("8514/A: Command (%04x) - Line (Bresenham) - %i,%i Axial %i, Diagonal %i, Error %i, Major Axis %i, Minor Axis %i\n",ibm8514.current_cmd, - ibm8514.curr_x,ibm8514.curr_y,ibm8514.line_axial_step,ibm8514.line_diagonal_step,ibm8514.line_errorterm,ibm8514.rect_width,ibm8514.rect_height); - - if((data & 0x0040)) - { - temp = dx; dx = dy; dy = temp; - } - for(;;) - { - ibm8514_write(ibm8514.curr_x + (ibm8514.curr_y * IBM8514_LINE_LENGTH),ibm8514.curr_x + (ibm8514.curr_y * IBM8514_LINE_LENGTH)); - if (count > ibm8514.rect_width) break; - count++; - if((err*2) > -dy) - { - err -= dy; - ibm8514.curr_x += sx; - } - if((err*2) < dx) - { - err += dx; - ibm8514.curr_y += sy; - } - } - } - break; - case 0x4000: // Rectangle Fill - if(data & 0x0100) // WAIT (for read/write of PIXEL TRANSFER (E2E8)) - { - ibm8514.state = IBM8514_DRAWING_RECT; - //ibm8514.gpbusy = true; // DirectX 5 keeps waiting for the busy bit to be clear... - ibm8514.bus_size = (data & 0x0600) >> 9; - ibm8514.data_avail = true; - if(LOG_8514) logerror("8514/A: Command (%04x) - Rectangle Fill (WAIT) %i,%i Width: %i Height: %i Colour: %08x\n",ibm8514.current_cmd,ibm8514.curr_x, - ibm8514.curr_y,ibm8514.rect_width,ibm8514.rect_height,ibm8514.fgcolour); - break; - } - if(LOG_8514) logerror("8514/A: Command (%04x) - Rectangle Fill %i,%i Width: %i Height: %i Colour: %08x\n",ibm8514.current_cmd,ibm8514.curr_x, - ibm8514.curr_y,ibm8514.rect_width,ibm8514.rect_height,ibm8514.fgcolour); - off = 0; - off += (IBM8514_LINE_LENGTH * ibm8514.curr_y); - off += ibm8514.curr_x; - for(y=0;y<=ibm8514.rect_height;y++) - { - for(x=0;x<=ibm8514.rect_width;x++) - { - if(data & 0x0020) // source pattern is always based on current X/Y? - ibm8514_write((off+x) % m_vga->vga.svga_intf.vram_size,(off+x) % m_vga->vga.svga_intf.vram_size); - else - ibm8514_write((off-x) % m_vga->vga.svga_intf.vram_size,(off-x) % m_vga->vga.svga_intf.vram_size); - if(ibm8514.current_cmd & 0x0020) - { - ibm8514.curr_x++; - if(ibm8514.curr_x > ibm8514.prev_x + ibm8514.rect_width) - { - ibm8514.curr_x = ibm8514.prev_x; - ibm8514.src_x = 0; - if(ibm8514.current_cmd & 0x0080) - ibm8514.curr_y++; - else - ibm8514.curr_y--; - } - } - else - { - ibm8514.curr_x--; - if(ibm8514.curr_x < ibm8514.prev_x - ibm8514.rect_width) - { - ibm8514.curr_x = ibm8514.prev_x; - ibm8514.src_x = 0; - if(ibm8514.current_cmd & 0x0080) - ibm8514.curr_y++; - else - ibm8514.curr_y--; - } - } - } - if(data & 0x0080) - off += IBM8514_LINE_LENGTH; - else - off -= IBM8514_LINE_LENGTH; - } - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - break; - case 0xc000: // BitBLT - // TODO: a10cuba sets up blantantly invalid parameters here, CPU core bug maybe? - if(LOG_8514) logerror("8514/A: Command (%04x) - BitBLT from %i,%i to %i,%i Width: %i Height: %i\n",ibm8514.current_cmd, - ibm8514.curr_x,ibm8514.curr_y,ibm8514.dest_x,ibm8514.dest_y,ibm8514.rect_width,ibm8514.rect_height); - off = 0; - off += (IBM8514_LINE_LENGTH * ibm8514.dest_y); - off += ibm8514.dest_x; - src = 0; - src += (IBM8514_LINE_LENGTH * ibm8514.curr_y); - src += ibm8514.curr_x; - readmask = ((ibm8514.read_mask & 0x01) << 7) | ((ibm8514.read_mask & 0xfe) >> 1); - for(y=0;y<=ibm8514.rect_height;y++) - { - for(x=0;x<=ibm8514.rect_width;x++) - { - if((ibm8514.pixel_control & 0xc0) == 0xc0) - { - // only check read mask if Mix Select is set to 11 (VRAM determines mix) - if(m_vga->mem_linear_r(space,(src+x),0xff) & ~readmask) - { - // presumably every program is going to be smart enough to set the FG mix to use VRAM (0x6x) - if(data & 0x0020) - ibm8514_write(off+x,src+x); - else - ibm8514_write(off-x,src-x); - } - } - else - { - // presumably every program is going to be smart enough to set the FG mix to use VRAM (0x6x) - if(data & 0x0020) - ibm8514_write(off+x,src+x); - else - ibm8514_write(off-x,src-x); - } - if(ibm8514.current_cmd & 0x0020) - { - ibm8514.curr_x++; - if(ibm8514.curr_x > ibm8514.prev_x + ibm8514.rect_width) - { - ibm8514.curr_x = ibm8514.prev_x; - ibm8514.src_x = 0; - if(ibm8514.current_cmd & 0x0080) - ibm8514.curr_y++; - else - ibm8514.curr_y--; - } - } - else - { - ibm8514.curr_x--; - if(ibm8514.curr_x < ibm8514.prev_x - ibm8514.rect_width) - { - ibm8514.curr_x = ibm8514.prev_x; - ibm8514.src_x = 0; - if(ibm8514.current_cmd & 0x0080) - ibm8514.curr_y++; - else - ibm8514.curr_y--; - } - } - } - if(data & 0x0080) - { - src += IBM8514_LINE_LENGTH; - off += IBM8514_LINE_LENGTH; - } - else - { - src -= IBM8514_LINE_LENGTH; - off -= IBM8514_LINE_LENGTH; - } - } - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - ibm8514.curr_x = ibm8514.prev_x; - ibm8514.curr_y = ibm8514.prev_y; - break; - case 0xe000: // Pattern Fill - if(LOG_8514) logerror("8514/A: Command (%04x) - Pattern Fill - source %i,%i dest %i,%i Width: %i Height: %i\n",ibm8514.current_cmd, - ibm8514.curr_x,ibm8514.curr_y,ibm8514.dest_x,ibm8514.dest_y,ibm8514.rect_width,ibm8514.rect_height); - off = 0; - off += (IBM8514_LINE_LENGTH * ibm8514.dest_y); - off += ibm8514.dest_x; - src = 0; - src += (IBM8514_LINE_LENGTH * ibm8514.curr_y); - src += ibm8514.curr_x; - if(data & 0x0020) - pattern_x = 0; - else - pattern_x = 7; - if(data & 0x0080) - pattern_y = 0; - else - pattern_y = 7; - - for(y=0;y<=ibm8514.rect_height;y++) + uint32_t *const bitmapline = &bitmap.pix(line); + addr %= vga.svga_intf.vram_size; + for (int pos=addr, c=0, column=0; column<TGA_COLUMNS; column++, c+=8, pos+=0x10) { - for(x=0;x<=ibm8514.rect_width;x++) + if(pos + 0x10 >= vga.svga_intf.vram_size) + return; + for (int xi=0,xm=0;xi<8;xi++,xm+=2) { - if(data & 0x0020) - { - ibm8514_write(off+x,src+pattern_x); - pattern_x++; - if(pattern_x >= 8) - pattern_x = 0; - } - else - { - ibm8514_write(off-x,src-pattern_x); - pattern_x--; - if(pattern_x < 0) - pattern_x = 7; - } - } + if(!screen().visible_area().contains(c+xi, line + yi)) + continue; - // for now, presume that INC_X and INC_Y affect both src and dest, at is would for a bitblt. - if(data & 0x0020) - pattern_x = 0; - else - pattern_x = 7; - if(data & 0x0080) - { - pattern_y++; - src += IBM8514_LINE_LENGTH; - if(pattern_y >= 8) - { - pattern_y = 0; - src -= (IBM8514_LINE_LENGTH * 8); // move src pointer back to top of pattern - } - off += IBM8514_LINE_LENGTH; - } - else - { - pattern_y--; - src -= IBM8514_LINE_LENGTH; - if(pattern_y < 0) - { - pattern_y = 7; - src += (IBM8514_LINE_LENGTH * 8); // move src pointer back to bottom of pattern - } - off -= IBM8514_LINE_LENGTH; + int r = (MV(pos+xm)&0xf800)>>11; + int g = (MV(pos+xm)&0x07e0)>>5; + int b = (MV(pos+xm)&0x001f)>>0; + r = (r << 3) | (r & 0x7); + g = (g << 2) | (g & 0x3); + b = (b << 3) | (b & 0x7); + bitmapline[c+xi] = IV|(r<<16)|(g<<8)|(b<<0); } } - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - break; - default: - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - if(LOG_8514) logerror("8514/A: Unknown command: %04x\n",data); } } -/* -8AE8h W(R/W): Destination Y Position & Axial Step Constant Register - (DESTY_AXSTP) -bit 0-11 DESTINATION Y-POSITION. During BITBLT operations this is the Y - co-ordinate of the destination in pixels. - 0-12 (911/924) LINE PARAMETER AXIAL STEP CONSTANT. During Line Drawing, - this is the Bresenham constant 2*dminor in two's complement - format. (dminor is the length of the line projected onto the minor - or dependent axis). - 0-13 (80 x+) LINE PARAMETER AXIAL STEP CONSTANT. Se above - - */ -READ16_MEMBER(ibm8514a_device::ibm8514_desty_r) -{ - return ibm8514.line_axial_step; -} - -WRITE16_MEMBER(ibm8514a_device::ibm8514_desty_w) -{ - ibm8514.line_axial_step = data; - ibm8514.dest_y = data; - if(LOG_8514) logerror("8514/A: Line Axial Step / Destination Y write %04x\n",data); -} - -/* -8EE8h W(R/W): Destination X Position & Diagonal Step Constant Register - (DESTX_DISTP) -bit 0-11 DESTINATION X-POSITION. During BITBLT operations this is the X - co-ordinate of the destination in pixels. - 0-12 (911/924) LINE PARAMETER DIAGONAL STEP CONSTANT. During Line - Drawing this is the Bresenham constant 2*dminor-2*dmajor in two's - complement format. (dminor is the length of the line projected - onto the minor or dependent axis, dmajor is the length of the line - projected onto the major or independent axis) - 0-13 (80x +) LINE PARAMETER DIAGONAL STEP CONSTANT. Se above - - */ -READ16_MEMBER(ibm8514a_device::ibm8514_destx_r) -{ - return ibm8514.line_diagonal_step; -} - -WRITE16_MEMBER(ibm8514a_device::ibm8514_destx_w) -{ - ibm8514.line_diagonal_step = data; - ibm8514.dest_x = data; - if(LOG_8514) logerror("8514/A: Line Diagonal Step / Destination X write %04x\n",data); -} - -/* -9EE8h W(R/W): Short Stroke Vector Transfer Register (SHORT_STROKE) -bit 0-3 Length of vector projected onto the major axis. - This is also the number of pixels drawn. - 4 Must be set for pixels to be written. - 5-7 VECDIR. The angle measured counter-clockwise from horizontal - right) at which the line is drawn, - 0 = 000 degrees - 1 = 045 degrees - 2 = 090 degrees - 3 = 135 degrees - 4 = 180 degrees - 5 = 225 degrees - 6 = 270 degrees - 7 = 315 degrees - 8-15 The lower 8 bits are duplicated in the upper 8 bits so two - short stroke vectors can be drawn with one command. -Note: The upper byte must be written for the SSV command to be executed. - Thus if a byte is written to 9EE8h another byte must be written to - 9EE9h before execution starts. A single 16bit write will do. - If only one SSV is desired the other byte can be set to 0. - */ -void ibm8514a_device::ibm8514_wait_draw_ssv() +void svga_device::svga_vh_rgb24(bitmap_rgb32 &bitmap, const rectangle &cliprect) { - uint8_t len = ibm8514.wait_vector_len; - uint8_t dir = ibm8514.wait_vector_dir; - bool draw = ibm8514.wait_vector_draw; - uint8_t count = ibm8514.wait_vector_count; - uint32_t offset; - int x; - int data_size; - - switch(ibm8514.bus_size) - { - case 0: - data_size = 8; - break; - case 1: - data_size = 16; - break; - case 2: - data_size = 32; - break; - default: - data_size = 8; - break; - } + #define MD(x) (vga.memory[x]+(vga.memory[x+1]<<8)+(vga.memory[x+2]<<16)) + constexpr uint32_t ID = 0xff000000; + int height = vga.crtc.maximum_scan_line * (vga.crtc.scan_doubling + 1); - for(x=0;x<data_size;x++) + /* line compare is screen sensitive */ +// uint16_t mask_comp = 0xff | (TLINES & 0x300); + int curr_addr = 0; + int yi=0; + for (int addr = vga.crtc.start_addr << 3, line=0; line<TLINES; line+=height, addr+=offset(), curr_addr+=offset()) { - if(len > count) + uint32_t *const bitmapline = &bitmap.pix(line); + addr %= vga.svga_intf.vram_size; + for (int pos=addr, c=0, column=0; column<TGA_COLUMNS; column++, c+=8, pos+=24) { - if(ibm8514.state == IBM8514_DRAWING_SSV_1) - { - ibm8514.state = IBM8514_DRAWING_SSV_2; - ibm8514.wait_vector_len = (ibm8514.ssv & 0x0f00) >> 8; - ibm8514.wait_vector_dir = (ibm8514.ssv & 0xe000) >> 13; - ibm8514.wait_vector_draw = (ibm8514.ssv & 0x1000) ? true : false; - ibm8514.wait_vector_count = 0; + if(pos + 24 >= vga.svga_intf.vram_size) return; - } - else if(ibm8514.state == IBM8514_DRAWING_SSV_2) + for (int xi=0,xm=0;xi<8;xi++,xm+=3) { - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - ibm8514.data_avail = false; - return; - } - } + if(!screen().visible_area().contains(c+xi, line + yi)) + continue; - if(ibm8514.state == IBM8514_DRAWING_SSV_1 || ibm8514.state == IBM8514_DRAWING_SSV_2) - { - offset = (ibm8514.curr_y * IBM8514_LINE_LENGTH) + ibm8514.curr_x; - if(draw) - ibm8514_write(offset,offset); - switch(dir) - { - case 0: // 0 degrees - ibm8514.curr_x++; - break; - case 1: // 45 degrees - ibm8514.curr_x++; - ibm8514.curr_y--; - break; - case 2: // 90 degrees - ibm8514.curr_y--; - break; - case 3: // 135 degrees - ibm8514.curr_y--; - ibm8514.curr_x--; - break; - case 4: // 180 degrees - ibm8514.curr_x--; - break; - case 5: // 225 degrees - ibm8514.curr_x--; - ibm8514.curr_y++; - break; - case 6: // 270 degrees - ibm8514.curr_y++; - break; - case 7: // 315 degrees - ibm8514.curr_y++; - ibm8514.curr_x++; - break; + int r = (MD(pos+xm)&0xff0000)>>16; + int g = (MD(pos+xm)&0x00ff00)>>8; + int b = (MD(pos+xm)&0x0000ff)>>0; + bitmapline[c+xi] = ID|(r<<16)|(g<<8)|(b<<0); } } } } -void ibm8514a_device::ibm8514_draw_ssv(uint8_t data) -{ - uint8_t len = data & 0x0f; - uint8_t dir = (data & 0xe0) >> 5; - bool draw = (data & 0x10) ? true : false; - - ibm8514_draw_vector(len,dir,draw); -} - -READ16_MEMBER(ibm8514a_device::ibm8514_ssv_r) -{ - return ibm8514.ssv; -} - -WRITE16_MEMBER(ibm8514a_device::ibm8514_ssv_w) +void svga_device::svga_vh_rgb32(bitmap_rgb32 &bitmap, const rectangle &cliprect) { - ibm8514.ssv = data; - - if(ibm8514.current_cmd & 0x0100) - { - ibm8514.state = IBM8514_DRAWING_SSV_1; - ibm8514.data_avail = true; - ibm8514.wait_vector_len = ibm8514.ssv & 0x0f; - ibm8514.wait_vector_dir = (ibm8514.ssv & 0xe0) >> 5; - ibm8514.wait_vector_draw = (ibm8514.ssv & 0x10) ? true : false; - ibm8514.wait_vector_count = 0; - return; - } + #define MD(x) (vga.memory[x]+(vga.memory[x+1]<<8)+(vga.memory[x+2]<<16)) + constexpr uint32_t ID = 0xff000000; + int height = vga.crtc.maximum_scan_line * (vga.crtc.scan_doubling + 1); - if(ibm8514.current_cmd & 0x1000) // byte sequence - { - ibm8514_draw_ssv(data & 0xff); - ibm8514_draw_ssv(data >> 8); - } - else - { - ibm8514_draw_ssv(data >> 8); - ibm8514_draw_ssv(data & 0xff); - } - if(LOG_8514) logerror("8514/A: Short Stroke Vector write %04x\n",data); -} +// uint16_t mask_comp; -void ibm8514a_device::ibm8514_wait_draw_vector() -{ - uint8_t len = ibm8514.wait_vector_len; - uint8_t dir = ibm8514.wait_vector_dir; - bool draw = ibm8514.wait_vector_draw; - uint8_t count = ibm8514.wait_vector_count; - uint32_t offset; - uint8_t data_size = 0; - int x; - - if(ibm8514.bus_size == 0) // 8-bit - data_size = 8; - if(ibm8514.bus_size == 1) // 16-bit - data_size = 16; - if(ibm8514.bus_size == 2) // 32-bit - data_size = 32; - - for(x=0;x<data_size;x++) + /* line compare is screen sensitive */ +// mask_comp = 0xff | (TLINES & 0x300); + int curr_addr = 0; + int yi=0; + for (int addr = vga.crtc.start_addr << 2, line=0; line<TLINES; line+=height, addr+=(offset()), curr_addr+=(offset())) { - if(len > count) + uint32_t *const bitmapline = &bitmap.pix(line); + addr %= vga.svga_intf.vram_size; + for (int pos=addr, c=0, column=0; column<TGA_COLUMNS; column++, c+=8, pos+=0x20) { - if(ibm8514.state == IBM8514_DRAWING_LINE) - { - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - ibm8514.data_avail = false; + if(pos + 0x20 >= vga.svga_intf.vram_size) return; - } - } - - if(ibm8514.state == IBM8514_DRAWING_LINE) - { - offset = (ibm8514.curr_y * IBM8514_LINE_LENGTH) + ibm8514.curr_x; - if(draw) - ibm8514_write(offset,offset); - switch(dir) + for (int xi=0,xm=0;xi<8;xi++,xm+=4) { - case 0: // 0 degrees - ibm8514.curr_x++; - break; - case 1: // 45 degrees - ibm8514.curr_x++; - ibm8514.curr_y--; - break; - case 2: // 90 degrees - ibm8514.curr_y--; - break; - case 3: // 135 degrees - ibm8514.curr_y--; - ibm8514.curr_x--; - break; - case 4: // 180 degrees - ibm8514.curr_x--; - break; - case 5: // 225 degrees - ibm8514.curr_x--; - ibm8514.curr_y++; - break; - case 6: // 270 degrees - ibm8514.curr_y++; - break; - case 7: // 315 degrees - ibm8514.curr_y++; - ibm8514.curr_x++; - break; + if(!screen().visible_area().contains(c+xi, line + yi)) + continue; + + int r = (MD(pos+xm)&0xff0000)>>16; + int g = (MD(pos+xm)&0x00ff00)>>8; + int b = (MD(pos+xm)&0x0000ff)>>0; + bitmapline[c+xi] = ID|(r<<16)|(g<<8)|(b<<0); } } } } -/* -96E8h W(R/W): Major Axis Pixel Count/Rectangle Width Register (MAJ_AXIS_PCNT) -bit 0-10 (911/924) RECTANGLE WIDTH/LINE PARAMETER MAX. For BITBLT and - rectangle commands this is the width of the area. For Line Drawing - this is the Bresenham constant dmajor in two's complement format. - (dmajor is the length of the line projected onto the major or - independent axis). Must be positive. - 0-11 (80x +) RECTANGLE WIDTH/LINE PARAMETER MAX. See above - */ -READ16_MEMBER(ibm8514a_device::ibm8514_width_r) -{ - return ibm8514.rect_width; -} - -WRITE16_MEMBER(ibm8514a_device::ibm8514_width_w) -{ - ibm8514.rect_width = data & 0x1fff; - if(LOG_8514) logerror("8514/A: Major Axis Pixel Count / Rectangle Width write %04x\n",data); -} - -READ16_MEMBER(ibm8514a_device::ibm8514_currentx_r) -{ - return ibm8514.curr_x; -} - -WRITE16_MEMBER(ibm8514a_device::ibm8514_currentx_w) -{ - ibm8514.curr_x = data; - ibm8514.prev_x = data; - if(LOG_8514) logerror("8514/A: Current X set to %04x (%i)\n",data,ibm8514.curr_x); -} - -READ16_MEMBER(ibm8514a_device::ibm8514_currenty_r) -{ - return ibm8514.curr_y; -} - -WRITE16_MEMBER(ibm8514a_device::ibm8514_currenty_w) -{ - ibm8514.curr_y = data; - ibm8514.prev_y = data; - if(LOG_8514) logerror("8514/A: Current Y set to %04x (%i)\n",data,ibm8514.curr_y); -} - -READ16_MEMBER(ibm8514a_device::ibm8514_fgcolour_r) -{ - return ibm8514.fgcolour; -} - -WRITE16_MEMBER(ibm8514a_device::ibm8514_fgcolour_w) -{ - ibm8514.fgcolour = data; - if(LOG_8514) logerror("8514/A: Foreground Colour write %04x\n",data); -} - -READ16_MEMBER(ibm8514a_device::ibm8514_bgcolour_r) -{ - return ibm8514.bgcolour; -} - -WRITE16_MEMBER(ibm8514a_device::ibm8514_bgcolour_w) -{ - ibm8514.bgcolour = data; - if(LOG_8514) logerror("8514/A: Background Colour write %04x\n",data); -} - -/* -AEE8h W(R/W): Read Mask Register (RD_MASK) -bit 0-7 (911/924) Read Mask affects the following commands: CMD_RECT, - CMD_BITBLT and reading data in Across Plane Mode. - Each bit set prevents the plane from being read. - 0-15 (801/5) Readmask. See above. - 0-31 (928 +) Readmask. See above. In 32 bits per pixel modes there are - two 16bit registers at this address. BEE8h index 0Eh bit 4 selects - which 16 bits are accessible and each access toggles to the other - 16 bits. - */ -READ16_MEMBER(ibm8514a_device::ibm8514_read_mask_r) -{ - return ibm8514.read_mask & 0xffff; -} - -WRITE16_MEMBER(ibm8514a_device::ibm8514_read_mask_w) -{ - ibm8514.read_mask = (ibm8514.read_mask & 0xffff0000) | data; - if(LOG_8514) logerror("8514/A: Read Mask (Low) write = %08x\n",ibm8514.read_mask); -} - -/* -AAE8h W(R/W): Write Mask Register (WRT_MASK) -bit 0-7 (911/924) Writemask. A plane can only be modified if the - corresponding bit is set. - 0-15 (801/5) Writemask. See above. - 0-31 (928 +) Writemask. See above. In 32 bits per pixel modes there are - two 16bit registers at this address. BEE8h index 0Eh bit 4 selects - which 16 bits are accessible and each access toggles to the other - 16 bits. - */ -READ16_MEMBER(ibm8514a_device::ibm8514_write_mask_r) -{ - return ibm8514.write_mask & 0xffff; -} - -WRITE16_MEMBER(ibm8514a_device::ibm8514_write_mask_w) -{ - ibm8514.write_mask = (ibm8514.write_mask & 0xffff0000) | data; - if(LOG_8514) logerror("8514/A: Write Mask (Low) write = %08x\n",ibm8514.write_mask); -} - -READ16_MEMBER(ibm8514a_device::ibm8514_multifunc_r ) -{ - switch(ibm8514.multifunc_sel) - { - case 0: - return ibm8514.rect_height; - case 1: - return ibm8514.scissors_top; - case 2: - return ibm8514.scissors_left; - case 3: - return ibm8514.scissors_bottom; - case 4: - return ibm8514.scissors_right; - // TODO: remaining functions - default: - if(LOG_8514) logerror("8514/A: Unimplemented multifunction register %i selected\n",ibm8514.multifunc_sel); - return 0xff; - } -} - -WRITE16_MEMBER(ibm8514a_device::ibm8514_multifunc_w ) -{ - switch(data & 0xf000) - { -/* -BEE8h index 00h W(R/W): Minor Axis Pixel Count Register (MIN_AXIS_PCNT). -bit 0-10 (911/924) Rectangle Height. Height of BITBLT or rectangle command. - Actual height is one larger. - 0-11 (80x +) Rectangle Height. See above -*/ - case 0x0000: - ibm8514.rect_height = data & 0x0fff; - if(LOG_8514) logerror("8514/A: Minor Axis Pixel Count / Rectangle Height write %04x\n",data); - break; -/* -BEE8h index 01h W(R/W): Top Scissors Register (SCISSORS_T). -bit 0-10 (911/924) Clipping Top Limit. Defines the upper bound of the - Clipping Rectangle (Lowest Y coordinate). - 0-11 (80x +) Clipping Top Limit. See above - -BEE8h index 02h W(R/W): Left Scissors Registers (SCISSORS_L). -bit 0-10 (911,924) Clipping Left Limit. Defines the left bound of the - Clipping Rectangle (Lowest X coordinate). - 0-11 (80x +) Clipping Left Limit. See above. - -BEE8h index 03h W(R/W): Bottom Scissors Register (SCISSORS_B). -bit 0-10 (911,924) Clipping Bottom Limit. Defines the bottom bound of the - Clipping Rectangle (Highest Y coordinate). - 0-11 (80x +) Clipping Bottom Limit. See above. - -BEE8h index 04h W(R/W): Right Scissors Register (SCISSORS_R). -bit 0-10 (911,924) Clipping Right Limit. Defines the right bound of the - Clipping Rectangle (Highest X coordinate). - 0-11 (80x +) Clipping Bottom Limit. See above. - */ - case 0x1000: - ibm8514.scissors_top = data & 0x0fff; - if(LOG_8514) logerror("S3: Scissors Top write %04x\n",data); - break; - case 0x2000: - ibm8514.scissors_left = data & 0x0fff; - if(LOG_8514) logerror("S3: Scissors Left write %04x\n",data); - break; - case 0x3000: - ibm8514.scissors_bottom = data & 0x0fff; - if(LOG_8514) logerror("S3: Scissors Bottom write %04x\n",data); - break; - case 0x4000: - ibm8514.scissors_right = data & 0x0fff; - if(LOG_8514) logerror("S3: Scissors Right write %04x\n",data); - break; -/* -BEE8h index 0Ah W(R/W): Pixel Control Register (PIX_CNTL). -BIT 2 (911-928) Pack Data. If set image read data is a monochrome bitmap, - if clear it is a bitmap of the current pixel depth - 6-7 DT-EX-DRC. Select Mix Select. - 0 Foreground Mix is always used. - 1 use fixed pattern to decide which mix setting to use on a pixel - 2 CPU Data (Pixel Transfer register) determines the Mix register used. - 3 Video memory determines the Mix register used. - */ - case 0xa000: - ibm8514.pixel_control = data; - if(LOG_8514) logerror("S3: Pixel control write %04x\n",data); - break; - case 0xe000: - ibm8514.multifunc_misc = data; - if(LOG_8514) logerror("S3: Multifunction Miscellaneous write %04x\n",data); - break; -/* -BEE8h index 0Fh W(W): Read Register Select Register (READ_SEL) (801/5,928) -bit 0-2 (911-928) READ-REG-SEL. Read Register Select. Selects the register - that is actually read when a read of BEE8h happens. Each read of - BEE8h increments this register by one. - 0: Read will return contents of BEE8h index 0. - 1: Read will return contents of BEE8h index 1. - 2: Read will return contents of BEE8h index 2. - 3: Read will return contents of BEE8h index 3. - 4: Read will return contents of BEE8h index 4. - 5: Read will return contents of BEE8h index 0Ah. - 6: Read will return contents of BEE8h index 0Eh. - 7: Read will return contents of 9AE8h (Bits 13-15 will be 0). - 0-3 (864,964) READ-REG-SEL. See above plus: - 8: Read will return contents of 42E8h (Bits 12-15 will be 0) - 9: Read will return contents of 46E8h - 10: Read will return contents of BEE8h index 0Dh - */ - case 0xf000: - ibm8514.multifunc_sel = data & 0x000f; - if(LOG_8514) logerror("S3: Multifunction select write %04x\n",data); - default: - if(LOG_8514) logerror("S3: Unimplemented multifunction register %i write %03x\n",data >> 12,data & 0x0fff); - } -} - -void ibm8514a_device::ibm8514_wait_draw() +// TODO: inherit from base class +uint8_t svga_device::pc_vga_choosevideomode() { - int x, data_size = 8; - uint32_t off; - - // the data in the pixel transfer register or written to VRAM masks the rectangle output - if(ibm8514.bus_size == 0) // 8-bit - data_size = 8; - if(ibm8514.bus_size == 1) // 16-bit - data_size = 16; - if(ibm8514.bus_size == 2) // 32-bit - data_size = 32; - off = 0; - off += (IBM8514_LINE_LENGTH * ibm8514.curr_y); - off += ibm8514.curr_x; - if(ibm8514.current_cmd & 0x02) // "across plane mode" + if (vga.crtc.sync_en) { - for(x=0;x<data_size;x++) + if (vga.dac.dirty) { - ibm8514_write(off,off); - if(ibm8514.current_cmd & 0x0020) - { - off++; - ibm8514.curr_x++; - if(ibm8514.curr_x > ibm8514.prev_x + ibm8514.rect_width) - { - ibm8514.curr_x = ibm8514.prev_x; - ibm8514.src_x = 0; - if(ibm8514.current_cmd & 0x0080) - { - ibm8514.curr_y++; - if(ibm8514.curr_y > ibm8514.prev_y + ibm8514.rect_height) - { - ibm8514.state = IBM8514_IDLE; - ibm8514.data_avail = false; - ibm8514.gpbusy = false; - } - } - else - { - ibm8514.curr_y--; - if(ibm8514.curr_y < ibm8514.prev_y - ibm8514.rect_height) - { - ibm8514.state = IBM8514_IDLE; - ibm8514.data_avail = false; - ibm8514.gpbusy = false; - } - } - return; - } - } - else - { - off--; - ibm8514.curr_x--; - if(ibm8514.curr_x < ibm8514.prev_x - ibm8514.rect_width) - { - ibm8514.curr_x = ibm8514.prev_x; - ibm8514.src_x = 0; - if(ibm8514.current_cmd & 0x0080) - { - ibm8514.curr_y++; - if(ibm8514.curr_y > ibm8514.prev_y + ibm8514.rect_height) - { - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - ibm8514.data_avail = false; - } - } - else - { - ibm8514.curr_y--; - if(ibm8514.curr_y < ibm8514.prev_y - ibm8514.rect_height) - { - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - ibm8514.data_avail = false; - } - } - return; - } - } + palette_update(); + vga.dac.dirty = 0; } - } - else - { - // "through plane" mode (single pixel) - for(x=0;x<data_size;x+=8) - { - ibm8514_write(off,off); - if(ibm8514.current_cmd & 0x0020) - { - off++; - ibm8514.curr_x++; - if(ibm8514.curr_x > ibm8514.prev_x + ibm8514.rect_width) - { - ibm8514.curr_x = ibm8514.prev_x; - ibm8514.src_x = 0; - if(ibm8514.current_cmd & 0x0080) - { - ibm8514.curr_y++; - if(ibm8514.curr_y > ibm8514.prev_y + ibm8514.rect_height) - { - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - ibm8514.data_avail = false; - } - } - else - { - ibm8514.curr_y--; - if(ibm8514.curr_y < ibm8514.prev_y - ibm8514.rect_height) - { - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - ibm8514.data_avail = false; - } - } - return; - } - } - else + if (vga.attribute.data[0x10] & 0x80) + { + for (int i=0; i<16;i++) { - off--; - ibm8514.curr_x--; - if(ibm8514.curr_x < ibm8514.prev_x - ibm8514.rect_width) - { - ibm8514.curr_x = ibm8514.prev_x; - ibm8514.src_x = 0; - if(ibm8514.current_cmd & 0x0080) - { - ibm8514.curr_y++; - if(ibm8514.curr_y > ibm8514.prev_y + ibm8514.rect_height) - { - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - ibm8514.data_avail = false; - } - } - else - { - ibm8514.curr_y--; - if(ibm8514.curr_y < ibm8514.prev_y - ibm8514.rect_height) - { - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - ibm8514.data_avail = false; - } - } - return; - } + vga.pens[i] = pen((vga.attribute.data[i]&0x0f) + |((vga.attribute.data[0x14]&0xf)<<4)); } } - } -} - -/* -B6E8h W(R/W): Background Mix Register (BKGD_MIX) -bit 0-3 Background MIX (BACKMIX). - 00 not DST - 01 0 (false) - 02 1 (true) - 03 2 DST - 04 not SRC - 05 SRC xor DST - 06 not (SRC xor DST) - 07 SRC - 08 not (SRC and DST) - 09 (not SRC) or DST - 0A SRC or (not DST) - 0B SRC or DST - 0C SRC and DST - 0D SRC and (not DST) - 0E (not SRC) and DST - 0F not (SRC or DST) - DST is always the destination bitmap, bit SRC has four - possible sources selected by the BSS bits. - 5-6 Background Source Select (BSS) - 0 BSS is Background Color - 1 BSS is Foreground Color - 2 BSS is Pixel Data from the PIX_TRANS register (E2E8h) - 3 BSS is Bitmap Data (Source data from display buffer). - */ -READ16_MEMBER(ibm8514a_device::ibm8514_backmix_r) -{ - return ibm8514.bgmix; -} - -WRITE16_MEMBER(ibm8514a_device::ibm8514_backmix_w) -{ - ibm8514.bgmix = data; - if(LOG_8514) logerror("8514/A: BG Mix write %04x\n",data); -} - -READ16_MEMBER(ibm8514a_device::ibm8514_foremix_r) -{ - return ibm8514.fgmix; -} - -WRITE16_MEMBER(ibm8514a_device::ibm8514_foremix_w) -{ - ibm8514.fgmix = data; - if(LOG_8514) logerror("8514/A: FG Mix write %04x\n",data); -} - -READ16_MEMBER(ibm8514a_device::ibm8514_pixel_xfer_r) -{ - if(offset == 1) - return (ibm8514.pixel_xfer & 0xffff0000) >> 16; - else - return ibm8514.pixel_xfer & 0x0000ffff; -} - -WRITE16_MEMBER(ibm8514a_device::ibm8514_pixel_xfer_w) -{ - if(offset == 1) - ibm8514.pixel_xfer = (ibm8514.pixel_xfer & 0x0000ffff) | (data << 16); - else - ibm8514.pixel_xfer = (ibm8514.pixel_xfer & 0xffff0000) | data; - - if(ibm8514.state == IBM8514_DRAWING_RECT) - ibm8514_wait_draw(); - - if(ibm8514.state == IBM8514_DRAWING_SSV_1 || ibm8514.state == IBM8514_DRAWING_SSV_2) - ibm8514_wait_draw_ssv(); - - if(ibm8514.state == IBM8514_DRAWING_LINE) - ibm8514_wait_draw_vector(); - - if(LOG_8514) logerror("8514/A: Pixel Transfer = %08x\n",ibm8514.pixel_xfer); -} - -READ8_MEMBER(s3_vga_device::mem_r) -{ - if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb32_en) - { - int data; - if(offset & 0x10000) - return 0; - data = 0; - if(vga.sequencer.data[4] & 0x8) - { - if((offset + (svga.bank_r*0x10000)) < vga.svga_intf.vram_size) - data = vga.memory[(offset + (svga.bank_r*0x10000))]; - } else { - int i; - - for(i=0;i<4;i++) + for (int i=0; i<16;i++) { - if(vga.sequencer.map_mask & 1 << i) - { - if((offset*4+i+(svga.bank_r*0x10000)) < vga.svga_intf.vram_size) - data |= vga.memory[(offset*4+i+(svga.bank_r*0x10000))]; - } + vga.pens[i] = pen((vga.attribute.data[i]&0x3f) + |((vga.attribute.data[0x14]&0xc)<<4)); } } - return data; - } - if((offset + (svga.bank_r*0x10000)) < vga.svga_intf.vram_size) - return vga_device::mem_r(space,offset,mem_mask); - else - return 0xff; -} -WRITE8_MEMBER(s3_vga_device::mem_w) -{ - ibm8514a_device* dev = get_8514(); - // bit 4 of CR53 enables memory-mapped I/O - // 0xA0000-0xA7fff maps to port 0xE2E8 (pixel transfer) - if(s3.cr53 & 0x10) - { - if(offset < 0x8000) + if (svga.rgb32_en) { - // pass through to the pixel transfer register (DirectX 5 wants this) - if(dev->ibm8514.bus_size == 0) - { - dev->ibm8514.pixel_xfer = (dev->ibm8514.pixel_xfer & 0xffffff00) | data; - dev->ibm8514_wait_draw(); - } - if(dev->ibm8514.bus_size == 1) - { - switch(offset & 0x0001) - { - case 0: - default: - dev->ibm8514.pixel_xfer = (dev->ibm8514.pixel_xfer & 0xffffff00) | data; - break; - case 1: - dev->ibm8514.pixel_xfer = (dev->ibm8514.pixel_xfer & 0xffff00ff) | (data << 8); - dev->ibm8514_wait_draw(); - break; - } - } - if(dev->ibm8514.bus_size == 2) - { - switch(offset & 0x0003) - { - case 0: - default: - dev->ibm8514.pixel_xfer = (dev->ibm8514.pixel_xfer & 0xffffff00) | data; - break; - case 1: - dev->ibm8514.pixel_xfer = (dev->ibm8514.pixel_xfer & 0xffff00ff) | (data << 8); - break; - case 2: - dev->ibm8514.pixel_xfer = (dev->ibm8514.pixel_xfer & 0xff00ffff) | (data << 16); - break; - case 3: - dev->ibm8514.pixel_xfer = (dev->ibm8514.pixel_xfer & 0x00ffffff) | (data << 24); - dev->ibm8514_wait_draw(); - break; - } - } - return; + return RGB32_MODE; } - switch(offset) + else if (svga.rgb24_en) { - case 0x8100: - case 0x82e8: - dev->ibm8514.curr_y = (dev->ibm8514.curr_y & 0xff00) | data; - dev->ibm8514.prev_y = (dev->ibm8514.prev_y & 0xff00) | data; - break; - case 0x8101: - case 0x82e9: - dev->ibm8514.curr_y = (dev->ibm8514.curr_y & 0x00ff) | (data << 8); - dev->ibm8514.prev_y = (dev->ibm8514.prev_y & 0x00ff) | (data << 8); - break; - case 0x8102: - case 0x86e8: - dev->ibm8514.curr_x = (dev->ibm8514.curr_x & 0xff00) | data; - dev->ibm8514.prev_x = (dev->ibm8514.prev_x & 0xff00) | data; - break; - case 0x8103: - case 0x86e9: - dev->ibm8514.curr_x = (dev->ibm8514.curr_x & 0x00ff) | (data << 8); - dev->ibm8514.prev_x = (dev->ibm8514.prev_x & 0x00ff) | (data << 8); - break; - case 0x8108: - case 0x8ae8: - dev->ibm8514.line_axial_step = (dev->ibm8514.line_axial_step & 0xff00) | data; - dev->ibm8514.dest_y = (dev->ibm8514.dest_y & 0xff00) | data; - break; - case 0x8109: - case 0x8ae9: - dev->ibm8514.line_axial_step = (dev->ibm8514.line_axial_step & 0x00ff) | ((data & 0x3f) << 8); - dev->ibm8514.dest_y = (dev->ibm8514.dest_y & 0x00ff) | (data << 8); - break; - case 0x810a: - case 0x8ee8: - dev->ibm8514.line_diagonal_step = (dev->ibm8514.line_diagonal_step & 0xff00) | data; - dev->ibm8514.dest_x = (dev->ibm8514.dest_x & 0xff00) | data; - break; - case 0x810b: - case 0x8ee9: - dev->ibm8514.line_diagonal_step = (dev->ibm8514.line_diagonal_step & 0x00ff) | ((data & 0x3f) << 8); - dev->ibm8514.dest_x = (dev->ibm8514.dest_x & 0x00ff) | (data << 8); - break; - case 0x8118: - case 0x9ae8: - s3.mmio_9ae8 = (s3.mmio_9ae8 & 0xff00) | data; - break; - case 0x8119: - case 0x9ae9: - s3.mmio_9ae8 = (s3.mmio_9ae8 & 0x00ff) | (data << 8); - dev->ibm8514_cmd_w(space,0,s3.mmio_9ae8,0xffff); - break; - case 0x8120: - case 0xa2e8: - dev->ibm8514.bgcolour = (dev->ibm8514.bgcolour & 0xff00) | data; - break; - case 0x8121: - case 0xa2e9: - dev->ibm8514.bgcolour = (dev->ibm8514.bgcolour & 0x00ff) | (data << 8); - break; - case 0x8124: - case 0xa6e8: - dev->ibm8514.fgcolour = (dev->ibm8514.fgcolour & 0xff00) | data; - break; - case 0x8125: - case 0xa6e9: - dev->ibm8514.fgcolour = (dev->ibm8514.fgcolour & 0x00ff) | (data << 8); - break; - case 0x8128: - case 0xaae8: - dev->ibm8514.write_mask = (dev->ibm8514.write_mask & 0xff00) | data; - break; - case 0x8129: - case 0xaae9: - dev->ibm8514.write_mask = (dev->ibm8514.write_mask & 0x00ff) | (data << 8); - break; - case 0x812c: - case 0xaee8: - dev->ibm8514.read_mask = (dev->ibm8514.read_mask & 0xff00) | data; - break; - case 0x812d: - case 0xaee9: - dev->ibm8514.read_mask = (dev->ibm8514.read_mask & 0x00ff) | (data << 8); - break; - case 0xb6e8: - case 0x8134: - dev->ibm8514.bgmix = (dev->ibm8514.bgmix & 0xff00) | data; - break; - case 0x8135: - case 0xb6e9: - dev->ibm8514.bgmix = (dev->ibm8514.bgmix & 0x00ff) | (data << 8); - break; - case 0x8136: - case 0xbae8: - dev->ibm8514.fgmix = (dev->ibm8514.fgmix & 0xff00) | data; - break; - case 0x8137: - case 0xbae9: - dev->ibm8514.fgmix = (dev->ibm8514.fgmix & 0x00ff) | (data << 8); - break; - case 0x8138: - dev->ibm8514.scissors_top = (dev->ibm8514.scissors_top & 0xff00) | data; - break; - case 0x8139: - dev->ibm8514.scissors_top = (dev->ibm8514.scissors_top & 0x00ff) | (data << 8); - break; - case 0x813a: - dev->ibm8514.scissors_left = (dev->ibm8514.scissors_left & 0xff00) | data; - break; - case 0x813b: - dev->ibm8514.scissors_left = (dev->ibm8514.scissors_left & 0x00ff) | (data << 8); - break; - case 0x813c: - dev->ibm8514.scissors_bottom = (dev->ibm8514.scissors_bottom & 0xff00) | data; - break; - case 0x813d: - dev->ibm8514.scissors_bottom = (dev->ibm8514.scissors_bottom & 0x00ff) | (data << 8); - break; - case 0x813e: - dev->ibm8514.scissors_right = (dev->ibm8514.scissors_right & 0xff00) | data; - break; - case 0x813f: - dev->ibm8514.scissors_right = (dev->ibm8514.scissors_right & 0x00ff) | (data << 8); - break; - case 0x8140: - dev->ibm8514.pixel_control = (dev->ibm8514.pixel_control & 0xff00) | data; - break; - case 0x8141: - dev->ibm8514.pixel_control = (dev->ibm8514.pixel_control & 0x00ff) | (data << 8); - break; - case 0x8146: - dev->ibm8514.multifunc_sel = (dev->ibm8514.multifunc_sel & 0xff00) | data; - break; - case 0x8148: - dev->ibm8514.rect_height = (dev->ibm8514.rect_height & 0xff00) | data; - break; - case 0x8149: - dev->ibm8514.rect_height = (dev->ibm8514.rect_height & 0x00ff) | (data << 8); - break; - case 0x814a: - dev->ibm8514.rect_width = (dev->ibm8514.rect_width & 0xff00) | data; - break; - case 0x814b: - dev->ibm8514.rect_width = (dev->ibm8514.rect_width & 0x00ff) | (data << 8); - break; - case 0x8150: - dev->ibm8514.pixel_xfer = (dev->ibm8514.pixel_xfer & 0xffffff00) | data; - if(dev->ibm8514.state == IBM8514_DRAWING_RECT) - dev->ibm8514_wait_draw(); - break; - case 0x8151: - dev->ibm8514.pixel_xfer = (dev->ibm8514.pixel_xfer & 0xffff00ff) | (data << 8); - if(dev->ibm8514.state == IBM8514_DRAWING_RECT) - dev->ibm8514_wait_draw(); - break; - case 0x8152: - dev->ibm8514.pixel_xfer = (dev->ibm8514.pixel_xfer & 0xff00ffff) | (data << 16); - if(dev->ibm8514.state == IBM8514_DRAWING_RECT) - dev->ibm8514_wait_draw(); - break; - case 0x8153: - dev->ibm8514.pixel_xfer = (dev->ibm8514.pixel_xfer & 0x00ffffff) | (data << 24); - if(dev->ibm8514.state == IBM8514_DRAWING_RECT) - dev->ibm8514_wait_draw(); - break; - case 0xbee8: - s3.mmio_bee8 = (s3.mmio_bee8 & 0xff00) | data; - break; - case 0xbee9: - s3.mmio_bee8 = (s3.mmio_bee8 & 0x00ff) | (data << 8); - dev->ibm8514_multifunc_w(space,0,s3.mmio_bee8,0xffff); - break; - case 0x96e8: - s3.mmio_96e8 = (s3.mmio_96e8 & 0xff00) | data; - break; - case 0x96e9: - s3.mmio_96e8 = (s3.mmio_96e8 & 0x00ff) | (data << 8); - dev->ibm8514_width_w(space,0,s3.mmio_96e8,0xffff); - break; - case 0xe2e8: - dev->ibm8514.pixel_xfer = (dev->ibm8514.pixel_xfer & 0xffffff00) | data; - dev->ibm8514_wait_draw(); - break; - default: - if(LOG_8514) logerror("S3: MMIO offset %05x write %02x\n",offset+0xa0000,data); + return RGB24_MODE; } - return; - } - - if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb32_en) - { - //printf("%08x %02x (%02x %02x) %02X\n",offset,data,vga.sequencer.map_mask,svga.bank_w,(vga.sequencer.data[4] & 0x08)); - if(offset & 0x10000) - return; - if(vga.sequencer.data[4] & 0x8) + else if (svga.rgb16_en) { - if((offset + (svga.bank_w*0x10000)) < vga.svga_intf.vram_size) - vga.memory[(offset + (svga.bank_w*0x10000))] = data; + return RGB16_MODE; } - else + else if (svga.rgb15_en) { - int i; - for(i=0;i<4;i++) - { - if(vga.sequencer.map_mask & 1 << i) - { - if((offset*4+i+(svga.bank_w*0x10000)) < vga.svga_intf.vram_size) - vga.memory[(offset*4+i+(svga.bank_w*0x10000))] = data; - } - } + return RGB15_MODE; } - return; - } - - if((offset + (svga.bank_w*0x10000)) < vga.svga_intf.vram_size) - vga_device::mem_w(space,offset,data,mem_mask); -} - -/****************************************** - -gamtor.c implementation (TODO: identify the video card) - -******************************************/ - -READ8_MEMBER(gamtor_vga_device::mem_r) -{ - return vga.memory[offset]; -} - -WRITE8_MEMBER(gamtor_vga_device::mem_w) -{ - vga.memory[offset] = data; -} - - -READ8_MEMBER(gamtor_vga_device::port_03b0_r) -{ - uint8_t res; - - switch(offset) - { - default: - res = vga_device::port_03b0_r(space,offset ^ 3,mem_mask); - break; - } - - return res; -} - -WRITE8_MEMBER(gamtor_vga_device::port_03b0_w) -{ - switch(offset) - { - default: - vga_device::port_03b0_w(space,offset ^ 3,data,mem_mask); - break; - } -} - -READ8_MEMBER(gamtor_vga_device::port_03c0_r) -{ - uint8_t res; - - switch(offset) - { - default: - res = vga_device::port_03c0_r(space,offset ^ 3,mem_mask); - break; - } - - return res; -} - -WRITE8_MEMBER(gamtor_vga_device::port_03c0_w) -{ - switch(offset) - { - default: - vga_device::port_03c0_w(space,offset ^ 3,data,mem_mask); - break; - } -} - -READ8_MEMBER(gamtor_vga_device::port_03d0_r) -{ - uint8_t res; - - switch(offset) - { - default: - res = vga_device::port_03d0_r(space,offset ^ 3,mem_mask); - break; - } - - return res; -} - -WRITE8_MEMBER(gamtor_vga_device::port_03d0_w) -{ - switch(offset) - { - default: - vga_device::port_03d0_w(space,offset ^ 3,data,mem_mask); - break; - } -} - -uint16_t ati_vga_device::offset() -{ - //popmessage("Offset: %04x %s %s %s %s",vga.crtc.offset,vga.crtc.dw?"DW":"--",vga.crtc.word_mode?"BYTE":"WORD",(ati.ext_reg[0x33] & 0x40) ? "PEL" : "---",(ati.ext_reg[0x30] & 0x20) ? "256" : "---"); - if(ati.ext_reg[0x30] & 0x20) // likely wrong, gets 640x400/480 SVGA and tweaked 256 colour modes displaying correctly in Fractint. - return vga_device::offset() << 3; - if(ati.ext_reg[0x33] & 0x40) - return vga_device::offset() << 2; - return vga_device::offset(); -} - - -void ati_vga_device::set_dot_clock() -{ - int clock; - uint8_t clock_type; - int div = ((ati.ext_reg[0x38] & 0xc0) >> 6) + 1; - int divisor = 1; - - clock_type = ((ati.ext_reg[0x3e] & 0x10)>>1) | ((ati.ext_reg[0x39] & 0x02)<<1) | ((vga.miscellaneous_output & 0x0c)>>2); - switch(clock_type) - { - case 0: - clock = XTAL(42'954'545).value(); - break; - case 1: - clock = 48771000; - break; - case 2: - clock = 16657000; - break; - case 3: - clock = XTAL(36'000'000).value(); - break; - case 4: - clock = 50350000; - break; - case 5: - clock = 56640000; - break; - case 6: - clock = 28322000; - break; - case 7: - clock = 44900000; - break; - case 8: - clock = 30240000; - break; - case 9: - clock = XTAL(32'000'000).value(); - break; - case 10: - clock = 37500000; - break; - case 11: - clock = 39000000; - break; - case 12: - clock = XTAL(40'000'000).value(); - break; - case 13: - clock = 56644000; - break; - case 14: - clock = 75000000; - break; - case 15: - clock = 65000000; - break; - default: - clock = XTAL(42'954'545).value(); - logerror("Invalid dot clock %i selected.\n",clock_type); - } -// logerror("ATI: Clock select type %i (%iHz / %i)\n",clock_type,clock,div); - recompute_params_clock(divisor,clock / div); - -} - -void ati_vga_device::ati_define_video_mode() -{ - svga.rgb8_en = 0; - svga.rgb15_en = 0; - svga.rgb16_en = 0; - svga.rgb32_en = 0; - - if(ati.ext_reg[0x30] & 0x20) - svga.rgb8_en = 1; - - set_dot_clock(); -} - -READ8_MEMBER(ati_vga_device::mem_r) -{ - if(svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en) - { - if(ati.ext_reg[0x3d] & 0x04) + else if (svga.rgb8_en) { - offset &= 0x1ffff; - return vga.memory[(offset+svga.bank_r*0x20000) % vga.svga_intf.vram_size]; + return RGB8_MODE; } - else + else if (!GRAPHIC_MODE) { - offset &= 0xffff; - return vga.memory[(offset+svga.bank_r*0x10000) % vga.svga_intf.vram_size]; + return TEXT_MODE; } - } - - return vga_device::mem_r(space,offset,mem_mask); -} - -WRITE8_MEMBER(ati_vga_device::mem_w) -{ - if(svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en) - { - if(ati.ext_reg[0x3d] & 0x04) + else if (vga.gc.shift256) { - offset &= 0x1ffff; - vga.memory[(offset+svga.bank_w*0x20000) % vga.svga_intf.vram_size] = data; + return VGA_MODE; } - else + else if (vga.gc.shift_reg) { - offset &= 0xffff; - vga.memory[(offset+svga.bank_w*0x10000) % vga.svga_intf.vram_size] = data; + return CGA_MODE; } - } - else - vga_device::mem_w(space,offset,data,mem_mask); -} - - -READ8_MEMBER(ati_vga_device::ati_port_ext_r) -{ - uint8_t ret = 0xff; - - switch(offset) - { - case 0: - break; - case 1: - switch(ati.ext_reg_select) + else if (vga.gc.memory_map_sel == 0x03) { - case 0x20: - ret = 0x10; // 16-bit ROM access - logerror("ATI20 read\n"); - break; - case 0x28: // Vertical line counter (high) - ret = (screen().vpos() >> 8) & 0x03; - logerror("ATI28 (vertical line high) read\n"); - break; - case 0x29: // Vertical line counter (low) - ret = screen().vpos() & 0xff; // correct? - logerror("ATI29 (vertical line low) read\n"); - break; - case 0x2a: - ret = ati.vga_chip_id; // Chip revision (6 for the 28800-6, 5 for the 28800-5) This register is not listed in ATI's mach32 docs - logerror("ATI2A (VGA ID) read\n"); - break; - case 0x37: - { - eeprom_serial_93cxx_device* eep = subdevice<eeprom_serial_93cxx_device>("ati_eeprom"); - ret = 0x00; - ret |= eep->do_read() << 3; - } - break; - case 0x3d: - ret = ati.ext_reg[ati.ext_reg_select] & 0x0f; - ret |= 0x10; // EGA DIP switch emulation - logerror("ATI3D (EGA DIP emulation) read\n"); - break; - default: - ret = ati.ext_reg[ati.ext_reg_select]; - logerror("ATI: Extended VGA register 0x01CE index %02x read\n",ati.ext_reg_select); + return MONO_MODE; } - break; - } - return ret; -} - -WRITE8_MEMBER(ati_vga_device::ati_port_ext_w) -{ - switch(offset) - { - case 0: - ati.ext_reg_select = data & 0x3f; - break; - case 1: - ati.ext_reg[ati.ext_reg_select] = data; - switch(ati.ext_reg_select) + else { - case 0x23: - vga.crtc.start_addr_latch = (vga.crtc.start_addr_latch & 0xfffdffff) | ((data & 0x10) << 13); - vga.crtc.cursor_addr = (vga.crtc.cursor_addr & 0xfffdffff) | ((data & 0x08) << 14); - ati.ext_reg[ati.ext_reg_select] = data & 0x1f; - logerror("ATI: ATI23 write %02x\n",data); - break; - case 0x26: - ati.ext_reg[ati.ext_reg_select] = data & 0xc9; - logerror("ATI: ATI26 write %02x\n",data); - break; - case 0x2b: - ati.ext_reg[ati.ext_reg_select] = data & 0xdf; - logerror("ATI: ATI2B write %02x\n",data); - break; - case 0x2d: - if(data & 0x08) - { - vga.crtc.horz_total = (vga.crtc.horz_total & 0x00ff) | (data & 0x01) << 8; - // bit 1 = bit 8 of horizontal blank start - // bit 2 = bit 8 of horizontal retrace start - } - logerror("ATI: ATI2D (extensions) write %02x\n",data); - break; - case 0x30: - vga.crtc.start_addr_latch = (vga.crtc.start_addr_latch & 0xfffeffff) | ((data & 0x40) << 10); - vga.crtc.cursor_addr = (vga.crtc.cursor_addr & 0xfffeffff) | ((data & 0x04) << 14); - ati.ext_reg[ati.ext_reg_select] = data & 0x7d; - logerror("ATI: ATI30 write %02x\n",data); - break; - case 0x31: - ati.ext_reg[ati.ext_reg_select] = data & 0x7f; - logerror("ATI: ATI31 write %02x\n",data); - break; - case 0x32: // memory page select - if(ati.ext_reg[0x3e] & 0x08) - { - svga.bank_r = ((data & 0x01) << 3) | ((data & 0xe0) >> 5); - svga.bank_w = ((data & 0x1e) >> 1); - } - else - { - svga.bank_r = ((data & 0x1e) >> 1); - svga.bank_w = ((data & 0x1e) >> 1); - } - //logerror("ATI: Memory Page Select write %02x (read: %i write %i)\n",data,svga.bank_r,svga.bank_w); - break; - case 0x33: // EEPROM - ati.ext_reg[ati.ext_reg_select] = data & 0xef; - if(data & 0x04) - { - eeprom_serial_93cxx_device* eep = subdevice<eeprom_serial_93cxx_device>("ati_eeprom"); - if(eep != nullptr) - { - eep->di_write((data & 0x01) ? ASSERT_LINE : CLEAR_LINE); - eep->clk_write((data & 0x02) ? ASSERT_LINE : CLEAR_LINE); - eep->cs_write((data & 0x08) ? ASSERT_LINE : CLEAR_LINE); - } - } - else - logerror("ATI: ATI33 write %02x\n",data); - break; - case 0x38: - ati.ext_reg[ati.ext_reg_select] = data & 0xef; - logerror("ATI: ATI38 write %02x\n",data); - break; - case 0x39: - ati.ext_reg[ati.ext_reg_select] = data & 0xfe; - logerror("ATI: ATI39 write %02x\n",data); - break; - case 0x3a: // General purpose read-write bits - ati.ext_reg[ati.ext_reg_select] = data & 0x07; - logerror("ATI: ATI3A write %02x\n",data); - break; - case 0x3c: // Reserved, should be 0 - ati.ext_reg[ati.ext_reg_select] = 0; - logerror("ATI: ATI3C write %02x\n",data); - break; - case 0x3d: - ati.ext_reg[ati.ext_reg_select] = data & 0xfd; - logerror("ATI: ATI3D write %02x\n",data); - break; - case 0x3e: - ati.ext_reg[ati.ext_reg_select] = data & 0x1f; - logerror("ATI: ATI3E write %02x\n",data); - break; - case 0x3f: - ati.ext_reg[ati.ext_reg_select] = data & 0x0f; - logerror("ATI: ATI3F write %02x\n",data); - break; - default: - logerror("ATI: Extended VGA register 0x01CE index %02x write %02x\n",ati.ext_reg_select,data); + return EGA_MODE; } - break; - } - ati_define_video_mode(); -} - -/* -02E8h W(R): Display Status Register -bit 0 SENSE is the result of a wired-OR of 3 comparators, one - for each of the RGB video signal. - By programming the RAMDAC for various values - and patterns and then reading the SENSE, the monitor type - (color, monochrome or none) can be determined. - 1 VBLANK. Vertical Blank State - If Vertical Blank is active this bit is set. - 2 HORTOG. Horizontal Toggle - This bit toggles every time a HSYNC pulse starts - 3-15 Reserved(0) - */ -READ8_MEMBER(ibm8514a_device::ibm8514_status_r) -{ - switch(offset) - { - case 0: - return m_vga->vga_vblank() << 1; - case 2: - return m_vga->port_03c0_r(space,6,mem_mask); - case 3: - return m_vga->port_03c0_r(space,7,mem_mask); - case 4: - return m_vga->port_03c0_r(space,8,mem_mask); - case 5: - return m_vga->port_03c0_r(space,9,mem_mask); } - return 0; -} - -WRITE8_MEMBER(ibm8514a_device::ibm8514_htotal_w) -{ - switch(offset) - { - case 0: - ibm8514.htotal = data & 0xff; - break; - case 2: - m_vga->port_03c0_w(space,6,data,mem_mask); - break; - case 3: - m_vga->port_03c0_w(space,7,data,mem_mask); - break; - case 4: - m_vga->port_03c0_w(space,8,data,mem_mask); - break; - case 5: - m_vga->port_03c0_w(space,9,data,mem_mask); - break; - } - //vga.crtc.horz_total = data & 0x01ff; - if(LOG_8514) logerror("8514/A: Horizontal total write %04x\n",data); -} - -/* -42E8h W(R): Subsystem Status Register (SUBSYS_STAT) -bit 0-3 Interrupt requests. These bits show the state of internal interrupt - requests. An interrupt will only occur if the corresponding bit(s) - in SUBSYS_CNTL is set. Interrupts can only be reset by writing a 1 - to the corresponding Interrupt Clear bit in SUBSYS_CNTL. - Bit 0: VBLNKFLG - 1: PICKFLAG - 2: INVALIDIO - 3: GPIDLE - 4-6 MONITORID. - 1: IBM 8507 (1024x768) Monochrome - 2: IBM 8514 (1024x768) Color - 5: IBM 8503 (640x480) Monochrome - 6: IBM 8512/13 (640x480) Color - 7 8PLANE. - (CT82c480) This bit is latched on reset from pin P4D7. - 8-11 CHIP_REV. Chip revision number. - 12-15 (CT82c480) CHIP_ID. 0=CT 82c480. - */ -READ16_MEMBER(ibm8514a_device::ibm8514_substatus_r) -{ - // TODO: - if(m_vga->vga_vblank() != 0) // not correct, but will do for now - ibm8514.substatus |= 0x01; - return ibm8514.substatus; -} - -/* -42E8h W(W): Subsystem Control Register (SUBSYS_CNTL) -bit 0-3 Interrupt Reset. Write 1 to a bit to reset the interrupt. - Bit 0 RVBLNKFLG Write 1 to reset Vertical Blank interrupt. - 1 RPICKFLAG Write 1 to reset PICK interrupt. - 2 RINVALIDIO Write 1 to reset Queue Overflow/Data - Underflow interrupt. - 3 RGPIDLE Write 1 to reset GPIDLE interrupt. - 4-7 Reserved(0) - 8 IBLNKFLG. If set Vertical Blank Interrupts are enabled. - 9 IPICKFLAG. If set PICK Interrupts are enabled. - 10 IINVALIDIO. If set Queue Overflow/Data Underflow Interrupts are - enabled. - 11 IGPIDLE. If set Graphics Engine Idle Interrupts are enabled. - 12-13 CHPTEST. Used for chip testing. - 14-15 Graphics Processor Control (GPCTRL). - */ -WRITE16_MEMBER(ibm8514a_device::ibm8514_subcontrol_w) -{ - ibm8514.subctrl = data; - ibm8514.substatus &= ~(data & 0x0f); // reset interrupts -// if(LOG_8514) logerror("8514/A: Subsystem control write %04x\n",data); -} - -READ16_MEMBER(ibm8514a_device::ibm8514_subcontrol_r) -{ - return ibm8514.subctrl; -} - -/* 22E8 (W) - * Display Control - * bits 1-2: Line skip control - 0=bits 1-2 skipped, 1=bit 2 skipped - * bit 3: Double scan - * bit 4: Interlace - * bits 5-6: Emable Display - 0=no change, 1=enable 8514/A, 2 or 3=8514/A reset - */ -WRITE16_MEMBER(ibm8514a_device::ibm8514_display_ctrl_w) -{ - ibm8514.display_ctrl = data & 0x7e; - switch(data & 0x60) - { - case 0x00: - break; // do nothing - case 0x20: - ibm8514.enabled = true; // enable 8514/A - break; - case 0x40: - case 0x60: // reset (does this disable the 8514/A?) - ibm8514.enabled = false; - break; - } -} - -WRITE16_MEMBER(ibm8514a_device::ibm8514_advfunc_w) -{ - ibm8514.advfunction_ctrl = data; - ibm8514.passthrough = data & 0x0001; -} - -READ16_MEMBER(ibm8514a_device::ibm8514_htotal_r) -{ - return ibm8514.htotal; -} - -READ16_MEMBER(ibm8514a_device::ibm8514_vtotal_r) -{ - return ibm8514.vtotal; -} - -WRITE16_MEMBER(ibm8514a_device::ibm8514_vtotal_w) -{ - ibm8514.vtotal = data; -// vga.crtc.vert_total = data; - if(LOG_8514) logerror("8514/A: Vertical total write %04x\n",data); -} - -READ16_MEMBER(ibm8514a_device::ibm8514_vdisp_r) -{ - return ibm8514.vdisp; -} - -WRITE16_MEMBER(ibm8514a_device::ibm8514_vdisp_w) -{ - ibm8514.vdisp = data; -// vga.crtc.vert_disp_end = data >> 3; - if(LOG_8514) logerror("8514/A: Vertical Displayed write %04x\n",data); -} - -READ16_MEMBER(ibm8514a_device::ibm8514_vsync_r) -{ - return ibm8514.vsync; -} -WRITE16_MEMBER(ibm8514a_device::ibm8514_vsync_w) -{ - ibm8514.vsync = data; - if(LOG_8514) logerror("8514/A: Vertical Sync write %04x\n",data); -} - -void ibm8514a_device::enabled() -{ - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; -} - -READ16_MEMBER(mach8_device::mach8_ec0_r) -{ - return ibm8514.ec0; -} - -WRITE16_MEMBER(mach8_device::mach8_ec0_w) -{ - ibm8514.ec0 = data; - if(LOG_8514) logerror("8514/A: Extended configuration 0 write %04x\n",data); -} - -READ16_MEMBER(mach8_device::mach8_ec1_r) -{ - return ibm8514.ec1; -} - -WRITE16_MEMBER(mach8_device::mach8_ec1_w) -{ - ibm8514.ec1 = data; - if(LOG_8514) logerror("8514/A: Extended configuration 1 write %04x\n",data); -} - -READ16_MEMBER(mach8_device::mach8_ec2_r) -{ - return ibm8514.ec2; -} - -WRITE16_MEMBER(mach8_device::mach8_ec2_w) -{ - ibm8514.ec2 = data; - if(LOG_8514) logerror("8514/A: Extended configuration 2 write %04x\n",data); -} - -READ16_MEMBER(mach8_device::mach8_ec3_r) -{ - return ibm8514.ec3; -} - -WRITE16_MEMBER(mach8_device::mach8_ec3_w) -{ - ibm8514.ec3 = data; - if(LOG_8514) logerror("8514/A: Extended configuration 3 write %04x\n",data); -} - -READ16_MEMBER(mach8_device::mach8_ext_fifo_r) -{ - return 0x00; // for now, report all FIFO slots as free -} - -WRITE16_MEMBER(mach8_device::mach8_linedraw_index_w) -{ - mach8.linedraw = data & 0x07; - if(LOG_8514) logerror("Mach8: Line Draw Index write %04x\n",data); -} - -READ16_MEMBER(mach8_device::mach8_bresenham_count_r) -{ - return ibm8514.rect_width & 0x1fff; -} - -WRITE16_MEMBER(mach8_device::mach8_bresenham_count_w) -{ - ibm8514.rect_width = data & 0x1fff; - if(LOG_8514) logerror("Mach8: Bresenham count write %04x\n",data); -} - -READ16_MEMBER(mach8_device::mach8_linedraw_r) -{ - return 0xff; -} - -WRITE16_MEMBER(mach8_device::mach8_linedraw_w) -{ - // TODO: actually draw the lines - switch(mach8.linedraw) - { - case 0: // Set current X - ibm8514.curr_x = data; - mach8.linedraw++; - break; - case 1: // Set current Y - ibm8514.curr_y = data; - mach8.linedraw++; - break; - case 2: // Line end X - ibm8514.curr_x = data; - mach8.linedraw++; - break; - case 3: // Line end Y - ibm8514.curr_y = data; - mach8.linedraw = 2; - break; - case 4: // Set current X - ibm8514.curr_x = data; - mach8.linedraw++; - break; - case 5: // Set current Y - ibm8514.curr_y = data; - mach8.linedraw = 4; - break; - } - logerror("ATI: Linedraw register write %04x, mode %i\n",data,mach8.linedraw); -} - -READ16_MEMBER(mach8_device::mach8_sourcex_r) -{ - return ibm8514.dest_x & 0x07ff; -} - -READ16_MEMBER(mach8_device::mach8_sourcey_r) -{ - return ibm8514.dest_y & 0x07ff; -} - -WRITE16_MEMBER(mach8_device::mach8_ext_leftscissor_w) -{ - // TODO -} - -WRITE16_MEMBER(mach8_device::mach8_ext_topscissor_w) -{ - // TODO -} - -READ16_MEMBER(mach8_device::mach8_scratch0_r) -{ - return mach8.scratch0; -} - -WRITE16_MEMBER(mach8_device::mach8_scratch0_w) -{ - mach8.scratch0 = data; - if(LOG_8514) logerror("Mach8: Scratch Pad 0 write %04x\n",data); -} - -READ16_MEMBER(mach8_device::mach8_scratch1_r) -{ - return mach8.scratch1; -} - -WRITE16_MEMBER(mach8_device::mach8_scratch1_w) -{ - mach8.scratch1 = data; - if(LOG_8514) logerror("Mach8: Scratch Pad 1 write %04x\n",data); -} - -WRITE16_MEMBER(mach8_device::mach8_crt_pitch_w) -{ - mach8.crt_pitch = data & 0x00ff; - m_vga->set_offset(mach8.crt_pitch); - if(LOG_8514) logerror("Mach8: CRT pitch write %04x\n",mach8.crt_pitch); -} - -WRITE16_MEMBER(mach8_device::mach8_ge_offset_l_w) -{ - mach8.ge_offset = (mach8.ge_offset & 0x0f0000) | data; - if(LOG_8514) logerror("Mach8: Graphics Engine Offset (Low) write %05x\n",mach8.ge_offset); -} - -WRITE16_MEMBER(mach8_device::mach8_ge_offset_h_w) -{ - mach8.ge_offset = (mach8.ge_offset & 0x00ffff) | ((data & 0x000f) << 16); - if(LOG_8514) logerror("Mach8: Graphics Engine Offset (High) write %05x\n",mach8.ge_offset); -} - -WRITE16_MEMBER(mach8_device::mach8_ge_pitch_w) -{ - mach8.ge_pitch = data & 0x00ff; - if(LOG_8514) logerror("Mach8: Graphics Engine pitch write %04x\n",mach8.ge_pitch); + return SCREEN_OFF; } -WRITE16_MEMBER(mach8_device::mach8_scan_x_w) +uint8_t svga_device::get_video_depth() { - mach8.scan_x = data & 0x07ff; - - if((mach8.dp_config & 0xe000) == 0x4000) // foreground source is the Pixel Transfer register + switch(pc_vga_choosevideomode()) { - ibm8514.state = MACH8_DRAWING_SCAN; - ibm8514.bus_size = (mach8.dp_config & 0x0200) >> 9; - ibm8514.data_avail = true; + case VGA_MODE: + case RGB8_MODE: + return 8; + case RGB15_MODE: + case RGB16_MODE: + return 16; + case RGB24_MODE: + case RGB32_MODE: + return 32; } - // TODO: non-wait version of Scan To X - if(LOG_8514) logerror("Mach8: Scan To X write %04x\n",mach8.scan_x); -} - -WRITE16_MEMBER(mach8_device::mach8_pixel_xfer_w) -{ - ibm8514_pixel_xfer_w(space,offset,data,mem_mask); - - if(ibm8514.state == MACH8_DRAWING_SCAN) - mach8_wait_scan(); + return 0; } -void mach8_device::mach8_wait_scan() +// TODO: inherit from base class +uint32_t svga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { - uint32_t offset = mach8.ge_offset << 2; - uint32_t addr = (ibm8514.prev_y * (mach8.ge_pitch * 8)) + ibm8514.prev_x; + uint8_t cur_mode = pc_vga_choosevideomode(); - // TODO: support reverse direction - if(mach8.dp_config & 0x0010) // drawing enabled + switch(cur_mode) { - if(mach8.dp_config & 0x0200) // 16-bit - { - ibm8514_write_fg(offset + addr); - ibm8514.pixel_xfer >>= 8; - ibm8514.prev_x++; - ibm8514_write_fg(offset + addr + 1); - ibm8514.prev_x++; - mach8.scan_x -= 2; - if(mach8.scan_x <= 0) - { - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - ibm8514.data_avail = false; - ibm8514.curr_x = ibm8514.prev_x; - } - } - else // 8-bit - { - ibm8514_write_fg(offset + addr); - ibm8514.prev_x++; - mach8.scan_x--; - if(mach8.scan_x <= 0) - { - ibm8514.state = IBM8514_IDLE; - ibm8514.gpbusy = false; - ibm8514.data_avail = false; - ibm8514.curr_x = ibm8514.prev_x; - } - } + case SCREEN_OFF: bitmap.fill (black_pen(), cliprect);break; + case TEXT_MODE: vga_vh_text (bitmap, cliprect); break; + case VGA_MODE: vga_vh_vga (bitmap, cliprect); break; + case EGA_MODE: vga_vh_ega (bitmap, cliprect); break; + case CGA_MODE: vga_vh_cga (bitmap, cliprect); break; + case MONO_MODE: vga_vh_mono (bitmap, cliprect); break; + case RGB8_MODE: svga_vh_rgb8 (bitmap, cliprect); break; + case RGB15_MODE: svga_vh_rgb15(bitmap, cliprect); break; + case RGB16_MODE: svga_vh_rgb16(bitmap, cliprect); break; + case RGB24_MODE: svga_vh_rgb24(bitmap, cliprect); break; + case RGB32_MODE: svga_vh_rgb32(bitmap, cliprect); break; } -} -/* - * CEEE (Write): Data Path Configuration - * bit 0: Read/Write data - * 1: Polygon-fill blit mode - * 2: Read host data - 0=colour, 1=monochrome - * 4: Enable Draw - * 5-6: Monochrome Data Source (0=always 1, 1=Mono pattern register, 2=Pixel Transfer register, 3=VRAM blit source) - * 7-8: Background Colour Source (0=Foreground Colour register, 1=Background Colour register, 2=Pixel Transfer register, 3=VRAM blit source) - * 9: Data width - 0=8-bit, 1=16-bit - * 12: LSB First (ignored in mach8 mode when data width is not set) - * 13-15: Foreground Colour Source (as Background Source, plus 5=Colour pattern shift register) - */ -WRITE16_MEMBER(mach8_device::mach8_dp_config_w) -{ - mach8.dp_config = data; - if(LOG_8514) logerror("Mach8: Data Path Configuration write %04x\n",mach8.dp_config); -} - -/* -12EEh W(R): Configuration Status 1 Register (Mach8) -bit 0 CLK_MODE. Set to use clock chip, clear to use crystals. - 1 BUS_16. Set for 16bit bus, clear for 8bit bus - 2 MC_BUS. Set for MicroChannel bus, clear for ISA/EISA bus - 3 EEPROM_ENA. EEPROM enabled if set - 4 DRAM_ENA. Set for DRAM, clear for VRAM. - 5-6 MEM_INSTALLED. Video memory. 0: 512K, 1: 1024K - 7 ROM_ENA. Set is ROM is enabled - 8 ROM_PAGE_ENA. Set if ROM paging enabled - 9-15 ROM_LOCATION. If bit 2 and 3 are 0 the ROM will be at this location: - 0: C000h, 1: C080h, 2: C100h, .. 127: FF80h (unlikely) - */ -READ16_MEMBER(mach8_device::mach8_config1_r) -{ - return 0x0082; -} - -/* -16EEh (R): Configuration Status 2 Register (Mach8) -bit 0 SHARE_CLOCK. If set the Mach8 shares clock with the VGA - 1 HIRES_BOOT. Boot in hi-res mode if set - 2 EPROM_16_ENA. Adapter configured for 16bit ROM if set - 3 WRITE_PER_BIT. Write masked VRAM operations supported if set - 4 FLASH_ENA. Flash page writes supported if set - */ -READ16_MEMBER(mach8_device::mach8_config2_r) -{ - return 0x0002; -} - -/* 7AEE (W) Mach 8 (16-bit) - * bits 0-2 Monitor Alias - Monitor ID - * bit 3 Enable reporting of Monitor Alias - * bit 12 EEPROM Data Out - * bit 13 EEPROM Clock - * bit 14 EEPROM Chip Select - * bit 15 EEPROM Select (Enables read/write of external EEPROM) - */ -WRITE16_MEMBER(mach8_device::mach8_ge_ext_config_w) -{ - mach8.ge_ext_config = data; - if(data & 0x8000) - popmessage("EEPROM enabled via 7AEE"); + return 0; } |